11// -------------------------------------------------------------------------------------------------------
22// Copyright (C) Microsoft. All rights reserved.
3+ // Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
34// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45// -------------------------------------------------------------------------------------------------------
56#include " Backend.h"
@@ -117,6 +118,11 @@ IRBuilder::DoBailOnNoProfile()
117118 return false ;
118119 }
119120
121+ if (m_func->GetTopFunc ()->GetJITFunctionBody ()->IsCoroutine ())
122+ {
123+ return false ;
124+ }
125+
120126 return true ;
121127}
122128
@@ -1255,7 +1261,7 @@ IRBuilder::EnsureLoopBodyForInEnumeratorArrayOpnd()
12551261}
12561262
12571263IR ::Opnd *
1258- IRBuilder::BuildForInEnumeratorOpnd (uint forInLoopLevel)
1264+ IRBuilder::BuildForInEnumeratorOpnd (uint forInLoopLevel, uint32 offset )
12591265{
12601266 Assert (forInLoopLevel < this ->m_func ->GetJITFunctionBody ()->GetForInLoopDepth ());
12611267 if (this ->IsLoopBody ())
@@ -1270,7 +1276,7 @@ IRBuilder::BuildForInEnumeratorOpnd(uint forInLoopLevel)
12701276 else if (this ->m_func ->GetJITFunctionBody ()->IsCoroutine ())
12711277 {
12721278 return IR::IndirOpnd::New (
1273- this ->m_generatorJumpTable .EnsureForInEnumeratorArrayOpnd ( ),
1279+ this ->m_generatorJumpTable .BuildForInEnumeratorArrayOpnd (offset ),
12741280 forInLoopLevel * sizeof (Js::ForInObjectEnumerator),
12751281 TyMachPtr,
12761282 this ->m_func
@@ -2949,7 +2955,7 @@ IRBuilder::BuildProfiledReg1Unsigned1(Js::OpCode newOpcode, uint32 offset, Js::R
29492955 if (newOpcode == Js::OpCode::InitForInEnumerator)
29502956 {
29512957 IR ::RegOpnd * src1Opnd = this ->BuildSrcOpnd (R0 );
2952- IR ::Opnd * src2Opnd = this ->BuildForInEnumeratorOpnd (C1 );
2958+ IR ::Opnd * src2Opnd = this ->BuildForInEnumeratorOpnd (C1 , offset );
29532959 IR ::Instr *instr = IR::ProfiledInstr::New (Js::OpCode::InitForInEnumerator, nullptr , src1Opnd, src2Opnd, m_func);
29542960 instr->AsProfiledInstr ()->u .profileId = profileId;
29552961 this ->AddInstr (instr, offset);
@@ -3084,7 +3090,7 @@ IRBuilder::BuildReg1Unsigned1(Js::OpCode newOpcode, uint offset, Js::RegSlot R0,
30843090 {
30853091 IR ::Instr *instr = IR::Instr::New (Js::OpCode::InitForInEnumerator, m_func);
30863092 instr->SetSrc1 (this ->BuildSrcOpnd (R0 ));
3087- instr->SetSrc2 (this ->BuildForInEnumeratorOpnd (C1 ));
3093+ instr->SetSrc2 (this ->BuildForInEnumeratorOpnd (C1 , offset ));
30883094 this ->AddInstr (instr, offset);
30893095 return ;
30903096 }
@@ -6935,7 +6941,7 @@ IRBuilder::BuildBrReg1Unsigned1(Js::OpCode newOpcode, uint32 offset)
69356941void
69366942IRBuilder::BuildBrBReturn (Js::OpCode newOpcode, uint32 offset, Js::RegSlot DestRegSlot, uint32 forInLoopLevel, uint32 targetOffset)
69376943{
6938- IR ::Opnd *srcOpnd = this ->BuildForInEnumeratorOpnd (forInLoopLevel);
6944+ IR ::Opnd *srcOpnd = this ->BuildForInEnumeratorOpnd (forInLoopLevel, offset );
69396945 IR ::RegOpnd * destOpnd = this ->BuildDstOpnd (DestRegSlot);
69406946 IR ::BranchInstr * branchInstr = IR::BranchInstr::New (newOpcode, destOpnd, nullptr , srcOpnd, m_func);
69416947 this ->AddBranchInstr (branchInstr, offset, targetOffset);
@@ -7922,14 +7928,12 @@ IRBuilder::GeneratorJumpTable::BuildJumpTable()
79227928 //
79237929 // s1 = Ld_A prm1
79247930 // s2 = Ld_A s1[offset of JavascriptGenerator::frame]
7925- // BrNotAddr_A s2 !nullptr $initializationCode
7931+ // BrNotAddr_A s2 !nullptr $jumpTable
79267932 //
79277933 // $createInterpreterStackFrame:
79287934 // call helper
79297935 //
7930- // $initializationCode:
7931- // load for-in enumerator address from interpreter stack frame
7932- //
7936+ // Br $startOfFunc
79337937 //
79347938 // $jumpTable:
79357939 //
@@ -7963,23 +7967,25 @@ IRBuilder::GeneratorJumpTable::BuildJumpTable()
79637967 IR ::LabelInstr* functionBegin = IR::LabelInstr::New (Js::OpCode::Label, this ->m_func );
79647968 LABELNAMESET (functionBegin, " GeneratorFunctionBegin" );
79657969
7966- IR ::LabelInstr* initCode = IR::LabelInstr::New (Js::OpCode::Label, this ->m_func );
7967- LABELNAMESET (initCode , " GeneratorInitializationAndJumpTable " );
7970+ IR ::LabelInstr* jumpTable = IR::LabelInstr::New (Js::OpCode::Label, this ->m_func );
7971+ LABELNAMESET (jumpTable , " GeneratorJumpTable " );
79687972
7969- // BrNotAddr_A s2 nullptr $initializationCode
7970- IR ::BranchInstr* skipCreateInterpreterFrame = IR::BranchInstr::New (Js::OpCode::BrNotAddr_A, initCode, genFrameOpnd, IR::AddrOpnd::NewNull (this ->m_func ), this ->m_func );
7973+ // If there is already a stack frame, generator function has previously begun execution - don't recreate, skip down to jump table
7974+ // BrNotAddr_A s2 nullptr $jumpTable
7975+ IR ::BranchInstr* skipCreateInterpreterFrame = IR::BranchInstr::New (Js::OpCode::BrNotAddr_A, jumpTable, genFrameOpnd, IR::AddrOpnd::NewNull (this ->m_func ), this ->m_func );
79717976 this ->m_irBuilder ->AddInstr (skipCreateInterpreterFrame, this ->m_irBuilder ->m_functionStartOffset );
79727977
79737978 // Create interpreter stack frame
79747979 IR ::Instr* createInterpreterFrame = IR::Instr::New (Js::OpCode::GeneratorCreateInterpreterStackFrame, genFrameOpnd /* dst */ , genRegOpnd /* src */ , this ->m_func );
79757980 this ->m_irBuilder ->AddInstr (createInterpreterFrame, this ->m_irBuilder ->m_functionStartOffset );
79767981
7982+ // Having created the frame, skip over the jump table and start executing from the beginning of the function
79777983 IR ::BranchInstr* skipJumpTable = IR::BranchInstr::New (Js::OpCode::Br, functionBegin, this ->m_func );
79787984 this ->m_irBuilder ->AddInstr (skipJumpTable, this ->m_irBuilder ->m_functionStartOffset );
79797985
7980- // Label to insert any initialization code
7981- // $initializationCode :
7982- this ->m_irBuilder ->AddInstr (initCode , this ->m_irBuilder ->m_functionStartOffset );
7986+ // Label for start of jumpTable - where we look for the correct Yield resume point
7987+ // $jumpTable :
7988+ this ->m_irBuilder ->AddInstr (jumpTable , this ->m_irBuilder ->m_functionStartOffset );
79837989
79847990 // s3 = Ld_A s2[offset of InterpreterStackFrame::m_reader.m_currentLocation]
79857991 IR ::RegOpnd* curLocOpnd = IR::RegOpnd::New (TyMachPtr, this ->m_func );
@@ -8015,46 +8021,24 @@ IRBuilder::GeneratorJumpTable::BuildJumpTable()
80158021
80168022 this ->m_irBuilder ->AddInstr (functionBegin, this ->m_irBuilder ->m_functionStartOffset );
80178023
8018- // Save these values for later use
8019- this ->m_initLabel = initCode;
8024+ // Save this value for later use
80208025 this ->m_generatorFrameOpnd = genFrameOpnd;
8026+ this ->m_func ->SetGeneratorFrameSym (genFrameOpnd->GetStackSym ());
80218027
80228028 return this ->m_irBuilder ->m_lastInstr ;
80238029}
80248030
8025- IR ::LabelInstr*
8026- IRBuilder::GeneratorJumpTable::GetInitLabel () const
8027- {
8028- Assert (this ->m_initLabel != nullptr );
8029- return this ->m_initLabel ;
8030- }
8031-
80328031IR ::RegOpnd*
8033- IRBuilder::GeneratorJumpTable::CreateForInEnumeratorArrayOpnd ()
8034- {
8035- Assert (this ->m_initLabel != nullptr );
8032+ IRBuilder::GeneratorJumpTable::BuildForInEnumeratorArrayOpnd (uint32 offset)
8033+ {
80368034 Assert (this ->m_generatorFrameOpnd != nullptr );
80378035
8038- IR ::RegOpnd* forInEnumeratorOpnd = IR::RegOpnd::New (TyMachPtr, this ->m_func );
8039- IR ::Instr* instr = IR::Instr::New (
8040- Js::OpCode::Ld_A,
8041- forInEnumeratorOpnd,
8036+ IR ::RegOpnd* forInEnumeratorArrayOpnd = IR::RegOpnd::New (TyMachPtr, this ->m_func );
8037+ IR ::Instr* instr = IR::Instr::New (Js::OpCode::Ld_A, forInEnumeratorArrayOpnd,
80428038 POINTER_OFFSET (this ->m_generatorFrameOpnd , Js::InterpreterStackFrame::GetOffsetOfForInEnumerators (), ForInEnumerators),
80438039 this ->m_func
80448040 );
8045- this ->m_initLabel ->InsertAfter (instr);
8046-
8047- return forInEnumeratorOpnd;
8048- }
8049-
8050- IR ::RegOpnd*
8051- IRBuilder::GeneratorJumpTable::EnsureForInEnumeratorArrayOpnd ()
8052- {
8053- if (this ->m_forInEnumeratorArrayOpnd == nullptr )
8054- {
8055- this ->m_forInEnumeratorArrayOpnd = this ->CreateForInEnumeratorArrayOpnd ();
8056- this ->m_func ->SetForInEnumeratorSymForGeneratorSym (m_forInEnumeratorArrayOpnd->GetStackSym ());
8057- }
8041+ this ->m_irBuilder ->AddInstr (instr, offset);
80588042
8059- return this -> m_forInEnumeratorArrayOpnd ;
8043+ return forInEnumeratorArrayOpnd ;
80608044}
0 commit comments