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"
@@ -1255,7 +1256,7 @@ IRBuilder::EnsureLoopBodyForInEnumeratorArrayOpnd()
12551256}
12561257
12571258IR::Opnd *
1258- IRBuilder::BuildForInEnumeratorOpnd (uint forInLoopLevel)
1259+ IRBuilder::BuildForInEnumeratorOpnd (uint forInLoopLevel, uint32 offset )
12591260{
12601261 Assert (forInLoopLevel < this ->m_func ->GetJITFunctionBody ()->GetForInLoopDepth ());
12611262 if (this ->IsLoopBody ())
@@ -1270,7 +1271,7 @@ IRBuilder::BuildForInEnumeratorOpnd(uint forInLoopLevel)
12701271 else if (this ->m_func ->GetJITFunctionBody ()->IsCoroutine ())
12711272 {
12721273 return IR::IndirOpnd::New (
1273- this ->m_generatorJumpTable .EnsureForInEnumeratorArrayOpnd ( ),
1274+ this ->m_generatorJumpTable .BuildForInEnumeratorArrayOpnd (offset ),
12741275 forInLoopLevel * sizeof (Js::ForInObjectEnumerator),
12751276 TyMachPtr,
12761277 this ->m_func
@@ -2949,7 +2950,7 @@ IRBuilder::BuildProfiledReg1Unsigned1(Js::OpCode newOpcode, uint32 offset, Js::R
29492950 if (newOpcode == Js::OpCode::InitForInEnumerator)
29502951 {
29512952 IR::RegOpnd * src1Opnd = this ->BuildSrcOpnd (R0);
2952- IR::Opnd * src2Opnd = this ->BuildForInEnumeratorOpnd (C1);
2953+ IR::Opnd * src2Opnd = this ->BuildForInEnumeratorOpnd (C1, offset );
29532954 IR::Instr *instr = IR::ProfiledInstr::New (Js::OpCode::InitForInEnumerator, nullptr , src1Opnd, src2Opnd, m_func);
29542955 instr->AsProfiledInstr ()->u .profileId = profileId;
29552956 this ->AddInstr (instr, offset);
@@ -3084,7 +3085,7 @@ IRBuilder::BuildReg1Unsigned1(Js::OpCode newOpcode, uint offset, Js::RegSlot R0,
30843085 {
30853086 IR::Instr *instr = IR::Instr::New (Js::OpCode::InitForInEnumerator, m_func);
30863087 instr->SetSrc1 (this ->BuildSrcOpnd (R0));
3087- instr->SetSrc2 (this ->BuildForInEnumeratorOpnd (C1));
3088+ instr->SetSrc2 (this ->BuildForInEnumeratorOpnd (C1, offset ));
30883089 this ->AddInstr (instr, offset);
30893090 return ;
30903091 }
@@ -6935,7 +6936,7 @@ IRBuilder::BuildBrReg1Unsigned1(Js::OpCode newOpcode, uint32 offset)
69356936void
69366937IRBuilder::BuildBrBReturn (Js::OpCode newOpcode, uint32 offset, Js::RegSlot DestRegSlot, uint32 forInLoopLevel, uint32 targetOffset)
69376938{
6938- IR::Opnd *srcOpnd = this ->BuildForInEnumeratorOpnd (forInLoopLevel);
6939+ IR::Opnd *srcOpnd = this ->BuildForInEnumeratorOpnd (forInLoopLevel, offset );
69396940 IR::RegOpnd * destOpnd = this ->BuildDstOpnd (DestRegSlot);
69406941 IR::BranchInstr * branchInstr = IR::BranchInstr::New (newOpcode, destOpnd, nullptr , srcOpnd, m_func);
69416942 this ->AddBranchInstr (branchInstr, offset, targetOffset);
@@ -7922,14 +7923,12 @@ IRBuilder::GeneratorJumpTable::BuildJumpTable()
79227923 //
79237924 // s1 = Ld_A prm1
79247925 // s2 = Ld_A s1[offset of JavascriptGenerator::frame]
7925- // BrNotAddr_A s2 !nullptr $initializationCode
7926+ // BrNotAddr_A s2 !nullptr $jumpTable
79267927 //
79277928 // $createInterpreterStackFrame:
79287929 // call helper
79297930 //
7930- // $initializationCode:
7931- // load for-in enumerator address from interpreter stack frame
7932- //
7931+ // Br $startOfFunc
79337932 //
79347933 // $jumpTable:
79357934 //
@@ -7963,23 +7962,25 @@ IRBuilder::GeneratorJumpTable::BuildJumpTable()
79637962 IR::LabelInstr* functionBegin = IR::LabelInstr::New (Js::OpCode::Label, this ->m_func );
79647963 LABELNAMESET (functionBegin, " GeneratorFunctionBegin" );
79657964
7966- IR::LabelInstr* initCode = IR::LabelInstr::New (Js::OpCode::Label, this ->m_func );
7967- LABELNAMESET (initCode , " GeneratorInitializationAndJumpTable " );
7965+ IR::LabelInstr* jumpTable = IR::LabelInstr::New (Js::OpCode::Label, this ->m_func );
7966+ LABELNAMESET (jumpTable , " GeneratorJumpTable " );
79687967
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 );
7968+ // If there is already a stack frame, generator function has previously begun execution - don't recreate, skip down to jump table
7969+ // BrNotAddr_A s2 nullptr $jumpTable
7970+ IR::BranchInstr* skipCreateInterpreterFrame = IR::BranchInstr::New (Js::OpCode::BrNotAddr_A, jumpTable, genFrameOpnd, IR::AddrOpnd::NewNull (this ->m_func ), this ->m_func );
79717971 this ->m_irBuilder ->AddInstr (skipCreateInterpreterFrame, this ->m_irBuilder ->m_functionStartOffset );
79727972
79737973 // Create interpreter stack frame
79747974 IR::Instr* createInterpreterFrame = IR::Instr::New (Js::OpCode::GeneratorCreateInterpreterStackFrame, genFrameOpnd /* dst */ , genRegOpnd /* src */ , this ->m_func );
79757975 this ->m_irBuilder ->AddInstr (createInterpreterFrame, this ->m_irBuilder ->m_functionStartOffset );
79767976
7977+ // Having created the frame, skip over the jump table and start executing from the beginning of the function
79777978 IR::BranchInstr* skipJumpTable = IR::BranchInstr::New (Js::OpCode::Br, functionBegin, this ->m_func );
79787979 this ->m_irBuilder ->AddInstr (skipJumpTable, this ->m_irBuilder ->m_functionStartOffset );
79797980
7980- // Label to insert any initialization code
7981- // $initializationCode :
7982- this ->m_irBuilder ->AddInstr (initCode , this ->m_irBuilder ->m_functionStartOffset );
7981+ // Label for start of jumpTable - where we look for the correct Yield resume point
7982+ // $jumpTable :
7983+ this ->m_irBuilder ->AddInstr (jumpTable , this ->m_irBuilder ->m_functionStartOffset );
79837984
79847985 // s3 = Ld_A s2[offset of InterpreterStackFrame::m_reader.m_currentLocation]
79857986 IR::RegOpnd* curLocOpnd = IR::RegOpnd::New (TyMachPtr, this ->m_func );
@@ -8015,46 +8016,24 @@ IRBuilder::GeneratorJumpTable::BuildJumpTable()
80158016
80168017 this ->m_irBuilder ->AddInstr (functionBegin, this ->m_irBuilder ->m_functionStartOffset );
80178018
8018- // Save these values for later use
8019- this ->m_initLabel = initCode;
8019+ // Save this value for later use
80208020 this ->m_generatorFrameOpnd = genFrameOpnd;
8021+ this ->m_func ->SetGeneratorFrameSym (genFrameOpnd->GetStackSym ());
80218022
80228023 return this ->m_irBuilder ->m_lastInstr ;
80238024}
80248025
8025- IR::LabelInstr*
8026- IRBuilder::GeneratorJumpTable::GetInitLabel () const
8027- {
8028- Assert (this ->m_initLabel != nullptr );
8029- return this ->m_initLabel ;
8030- }
8031-
80328026IR::RegOpnd*
8033- IRBuilder::GeneratorJumpTable::CreateForInEnumeratorArrayOpnd ()
8034- {
8035- Assert (this ->m_initLabel != nullptr );
8027+ IRBuilder::GeneratorJumpTable::BuildForInEnumeratorArrayOpnd (uint32 offset)
8028+ {
80368029 Assert (this ->m_generatorFrameOpnd != nullptr );
80378030
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,
8031+ IR::RegOpnd* forInEnumeratorArrayOpnd = IR::RegOpnd::New (TyMachPtr, this ->m_func );
8032+ IR::Instr* instr = IR::Instr::New (Js::OpCode::Ld_A, forInEnumeratorArrayOpnd,
80428033 POINTER_OFFSET (this ->m_generatorFrameOpnd , Js::InterpreterStackFrame::GetOffsetOfForInEnumerators (), ForInEnumerators),
80438034 this ->m_func
80448035 );
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- }
8036+ this ->m_irBuilder ->AddInstr (instr, offset);
80588037
8059- return this -> m_forInEnumeratorArrayOpnd ;
8038+ return forInEnumeratorArrayOpnd ;
80608039}
0 commit comments