1
1
// -------------------------------------------------------------------------------------------------------
2
2
// Copyright (C) Microsoft. All rights reserved.
3
+ // Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
3
4
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
4
5
// -------------------------------------------------------------------------------------------------------
5
6
#include " Backend.h"
@@ -1255,7 +1256,7 @@ IRBuilder::EnsureLoopBodyForInEnumeratorArrayOpnd()
1255
1256
}
1256
1257
1257
1258
IR::Opnd *
1258
- IRBuilder::BuildForInEnumeratorOpnd (uint forInLoopLevel)
1259
+ IRBuilder::BuildForInEnumeratorOpnd (uint forInLoopLevel, uint32 offset )
1259
1260
{
1260
1261
Assert (forInLoopLevel < this ->m_func ->GetJITFunctionBody ()->GetForInLoopDepth ());
1261
1262
if (this ->IsLoopBody ())
@@ -1270,7 +1271,7 @@ IRBuilder::BuildForInEnumeratorOpnd(uint forInLoopLevel)
1270
1271
else if (this ->m_func ->GetJITFunctionBody ()->IsCoroutine ())
1271
1272
{
1272
1273
return IR::IndirOpnd::New (
1273
- this ->m_generatorJumpTable .EnsureForInEnumeratorArrayOpnd ( ),
1274
+ this ->m_generatorJumpTable .BuildForInEnumeratorArrayOpnd (offset ),
1274
1275
forInLoopLevel * sizeof (Js::ForInObjectEnumerator),
1275
1276
TyMachPtr,
1276
1277
this ->m_func
@@ -2949,7 +2950,7 @@ IRBuilder::BuildProfiledReg1Unsigned1(Js::OpCode newOpcode, uint32 offset, Js::R
2949
2950
if (newOpcode == Js::OpCode::InitForInEnumerator)
2950
2951
{
2951
2952
IR::RegOpnd * src1Opnd = this ->BuildSrcOpnd (R0);
2952
- IR::Opnd * src2Opnd = this ->BuildForInEnumeratorOpnd (C1);
2953
+ IR::Opnd * src2Opnd = this ->BuildForInEnumeratorOpnd (C1, offset );
2953
2954
IR::Instr *instr = IR::ProfiledInstr::New (Js::OpCode::InitForInEnumerator, nullptr , src1Opnd, src2Opnd, m_func);
2954
2955
instr->AsProfiledInstr ()->u .profileId = profileId;
2955
2956
this ->AddInstr (instr, offset);
@@ -3084,7 +3085,7 @@ IRBuilder::BuildReg1Unsigned1(Js::OpCode newOpcode, uint offset, Js::RegSlot R0,
3084
3085
{
3085
3086
IR::Instr *instr = IR::Instr::New (Js::OpCode::InitForInEnumerator, m_func);
3086
3087
instr->SetSrc1 (this ->BuildSrcOpnd (R0));
3087
- instr->SetSrc2 (this ->BuildForInEnumeratorOpnd (C1));
3088
+ instr->SetSrc2 (this ->BuildForInEnumeratorOpnd (C1, offset ));
3088
3089
this ->AddInstr (instr, offset);
3089
3090
return ;
3090
3091
}
@@ -6935,7 +6936,7 @@ IRBuilder::BuildBrReg1Unsigned1(Js::OpCode newOpcode, uint32 offset)
6935
6936
void
6936
6937
IRBuilder::BuildBrBReturn (Js::OpCode newOpcode, uint32 offset, Js::RegSlot DestRegSlot, uint32 forInLoopLevel, uint32 targetOffset)
6937
6938
{
6938
- IR::Opnd *srcOpnd = this ->BuildForInEnumeratorOpnd (forInLoopLevel);
6939
+ IR::Opnd *srcOpnd = this ->BuildForInEnumeratorOpnd (forInLoopLevel, offset );
6939
6940
IR::RegOpnd * destOpnd = this ->BuildDstOpnd (DestRegSlot);
6940
6941
IR::BranchInstr * branchInstr = IR::BranchInstr::New (newOpcode, destOpnd, nullptr , srcOpnd, m_func);
6941
6942
this ->AddBranchInstr (branchInstr, offset, targetOffset);
@@ -7922,14 +7923,12 @@ IRBuilder::GeneratorJumpTable::BuildJumpTable()
7922
7923
//
7923
7924
// s1 = Ld_A prm1
7924
7925
// s2 = Ld_A s1[offset of JavascriptGenerator::frame]
7925
- // BrNotAddr_A s2 !nullptr $initializationCode
7926
+ // BrNotAddr_A s2 !nullptr $jumpTable
7926
7927
//
7927
7928
// $createInterpreterStackFrame:
7928
7929
// call helper
7929
7930
//
7930
- // $initializationCode:
7931
- // load for-in enumerator address from interpreter stack frame
7932
- //
7931
+ // Br $startOfFunc
7933
7932
//
7934
7933
// $jumpTable:
7935
7934
//
@@ -7963,23 +7962,25 @@ IRBuilder::GeneratorJumpTable::BuildJumpTable()
7963
7962
IR::LabelInstr* functionBegin = IR::LabelInstr::New (Js::OpCode::Label, this ->m_func );
7964
7963
LABELNAMESET (functionBegin, " GeneratorFunctionBegin" );
7965
7964
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 " );
7968
7967
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 );
7971
7971
this ->m_irBuilder ->AddInstr (skipCreateInterpreterFrame, this ->m_irBuilder ->m_functionStartOffset );
7972
7972
7973
7973
// Create interpreter stack frame
7974
7974
IR::Instr* createInterpreterFrame = IR::Instr::New (Js::OpCode::GeneratorCreateInterpreterStackFrame, genFrameOpnd /* dst */ , genRegOpnd /* src */ , this ->m_func );
7975
7975
this ->m_irBuilder ->AddInstr (createInterpreterFrame, this ->m_irBuilder ->m_functionStartOffset );
7976
7976
7977
+ // Having created the frame, skip over the jump table and start executing from the beginning of the function
7977
7978
IR::BranchInstr* skipJumpTable = IR::BranchInstr::New (Js::OpCode::Br, functionBegin, this ->m_func );
7978
7979
this ->m_irBuilder ->AddInstr (skipJumpTable, this ->m_irBuilder ->m_functionStartOffset );
7979
7980
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 );
7983
7984
7984
7985
// s3 = Ld_A s2[offset of InterpreterStackFrame::m_reader.m_currentLocation]
7985
7986
IR::RegOpnd* curLocOpnd = IR::RegOpnd::New (TyMachPtr, this ->m_func );
@@ -8015,46 +8016,24 @@ IRBuilder::GeneratorJumpTable::BuildJumpTable()
8015
8016
8016
8017
this ->m_irBuilder ->AddInstr (functionBegin, this ->m_irBuilder ->m_functionStartOffset );
8017
8018
8018
- // Save these values for later use
8019
- this ->m_initLabel = initCode;
8019
+ // Save this value for later use
8020
8020
this ->m_generatorFrameOpnd = genFrameOpnd;
8021
+ this ->m_func ->SetGeneratorFrameSym (genFrameOpnd->GetStackSym ());
8021
8022
8022
8023
return this ->m_irBuilder ->m_lastInstr ;
8023
8024
}
8024
8025
8025
- IR::LabelInstr*
8026
- IRBuilder::GeneratorJumpTable::GetInitLabel () const
8027
- {
8028
- Assert (this ->m_initLabel != nullptr );
8029
- return this ->m_initLabel ;
8030
- }
8031
-
8032
8026
IR::RegOpnd*
8033
- IRBuilder::GeneratorJumpTable::CreateForInEnumeratorArrayOpnd ()
8034
- {
8035
- Assert (this ->m_initLabel != nullptr );
8027
+ IRBuilder::GeneratorJumpTable::BuildForInEnumeratorArrayOpnd (uint32 offset)
8028
+ {
8036
8029
Assert (this ->m_generatorFrameOpnd != nullptr );
8037
8030
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,
8042
8033
POINTER_OFFSET (this ->m_generatorFrameOpnd , Js::InterpreterStackFrame::GetOffsetOfForInEnumerators (), ForInEnumerators),
8043
8034
this ->m_func
8044
8035
);
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);
8058
8037
8059
- return this -> m_forInEnumeratorArrayOpnd ;
8038
+ return forInEnumeratorArrayOpnd ;
8060
8039
}
0 commit comments