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"
@@ -117,6 +118,11 @@ IRBuilder::DoBailOnNoProfile()
117
118
return false ;
118
119
}
119
120
121
+ if (m_func->GetTopFunc ()->GetJITFunctionBody ()->IsCoroutine ())
122
+ {
123
+ return false ;
124
+ }
125
+
120
126
return true ;
121
127
}
122
128
@@ -1255,7 +1261,7 @@ IRBuilder::EnsureLoopBodyForInEnumeratorArrayOpnd()
1255
1261
}
1256
1262
1257
1263
IR::Opnd *
1258
- IRBuilder::BuildForInEnumeratorOpnd (uint forInLoopLevel)
1264
+ IRBuilder::BuildForInEnumeratorOpnd (uint forInLoopLevel, uint32 offset )
1259
1265
{
1260
1266
Assert (forInLoopLevel < this ->m_func ->GetJITFunctionBody ()->GetForInLoopDepth ());
1261
1267
if (this ->IsLoopBody ())
@@ -1270,7 +1276,7 @@ IRBuilder::BuildForInEnumeratorOpnd(uint forInLoopLevel)
1270
1276
else if (this ->m_func ->GetJITFunctionBody ()->IsCoroutine ())
1271
1277
{
1272
1278
return IR::IndirOpnd::New (
1273
- this ->m_generatorJumpTable .EnsureForInEnumeratorArrayOpnd ( ),
1279
+ this ->m_generatorJumpTable .BuildForInEnumeratorArrayOpnd (offset ),
1274
1280
forInLoopLevel * sizeof (Js::ForInObjectEnumerator),
1275
1281
TyMachPtr,
1276
1282
this ->m_func
@@ -2949,7 +2955,7 @@ IRBuilder::BuildProfiledReg1Unsigned1(Js::OpCode newOpcode, uint32 offset, Js::R
2949
2955
if (newOpcode == Js::OpCode::InitForInEnumerator)
2950
2956
{
2951
2957
IR::RegOpnd * src1Opnd = this ->BuildSrcOpnd (R0);
2952
- IR::Opnd * src2Opnd = this ->BuildForInEnumeratorOpnd (C1);
2958
+ IR::Opnd * src2Opnd = this ->BuildForInEnumeratorOpnd (C1, offset );
2953
2959
IR::Instr *instr = IR::ProfiledInstr::New (Js::OpCode::InitForInEnumerator, nullptr , src1Opnd, src2Opnd, m_func);
2954
2960
instr->AsProfiledInstr ()->u .profileId = profileId;
2955
2961
this ->AddInstr (instr, offset);
@@ -3084,7 +3090,7 @@ IRBuilder::BuildReg1Unsigned1(Js::OpCode newOpcode, uint offset, Js::RegSlot R0,
3084
3090
{
3085
3091
IR::Instr *instr = IR::Instr::New (Js::OpCode::InitForInEnumerator, m_func);
3086
3092
instr->SetSrc1 (this ->BuildSrcOpnd (R0));
3087
- instr->SetSrc2 (this ->BuildForInEnumeratorOpnd (C1));
3093
+ instr->SetSrc2 (this ->BuildForInEnumeratorOpnd (C1, offset ));
3088
3094
this ->AddInstr (instr, offset);
3089
3095
return ;
3090
3096
}
@@ -6935,7 +6941,7 @@ IRBuilder::BuildBrReg1Unsigned1(Js::OpCode newOpcode, uint32 offset)
6935
6941
void
6936
6942
IRBuilder::BuildBrBReturn (Js::OpCode newOpcode, uint32 offset, Js::RegSlot DestRegSlot, uint32 forInLoopLevel, uint32 targetOffset)
6937
6943
{
6938
- IR::Opnd *srcOpnd = this ->BuildForInEnumeratorOpnd (forInLoopLevel);
6944
+ IR::Opnd *srcOpnd = this ->BuildForInEnumeratorOpnd (forInLoopLevel, offset );
6939
6945
IR::RegOpnd * destOpnd = this ->BuildDstOpnd (DestRegSlot);
6940
6946
IR::BranchInstr * branchInstr = IR::BranchInstr::New (newOpcode, destOpnd, nullptr , srcOpnd, m_func);
6941
6947
this ->AddBranchInstr (branchInstr, offset, targetOffset);
@@ -7922,14 +7928,12 @@ IRBuilder::GeneratorJumpTable::BuildJumpTable()
7922
7928
//
7923
7929
// s1 = Ld_A prm1
7924
7930
// s2 = Ld_A s1[offset of JavascriptGenerator::frame]
7925
- // BrNotAddr_A s2 !nullptr $initializationCode
7931
+ // BrNotAddr_A s2 !nullptr $jumpTable
7926
7932
//
7927
7933
// $createInterpreterStackFrame:
7928
7934
// call helper
7929
7935
//
7930
- // $initializationCode:
7931
- // load for-in enumerator address from interpreter stack frame
7932
- //
7936
+ // Br $startOfFunc
7933
7937
//
7934
7938
// $jumpTable:
7935
7939
//
@@ -7963,23 +7967,25 @@ IRBuilder::GeneratorJumpTable::BuildJumpTable()
7963
7967
IR::LabelInstr* functionBegin = IR::LabelInstr::New (Js::OpCode::Label, this ->m_func );
7964
7968
LABELNAMESET (functionBegin, " GeneratorFunctionBegin" );
7965
7969
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 " );
7968
7972
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 );
7971
7976
this ->m_irBuilder ->AddInstr (skipCreateInterpreterFrame, this ->m_irBuilder ->m_functionStartOffset );
7972
7977
7973
7978
// Create interpreter stack frame
7974
7979
IR::Instr* createInterpreterFrame = IR::Instr::New (Js::OpCode::GeneratorCreateInterpreterStackFrame, genFrameOpnd /* dst */ , genRegOpnd /* src */ , this ->m_func );
7975
7980
this ->m_irBuilder ->AddInstr (createInterpreterFrame, this ->m_irBuilder ->m_functionStartOffset );
7976
7981
7982
+ // Having created the frame, skip over the jump table and start executing from the beginning of the function
7977
7983
IR::BranchInstr* skipJumpTable = IR::BranchInstr::New (Js::OpCode::Br, functionBegin, this ->m_func );
7978
7984
this ->m_irBuilder ->AddInstr (skipJumpTable, this ->m_irBuilder ->m_functionStartOffset );
7979
7985
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 );
7983
7989
7984
7990
// s3 = Ld_A s2[offset of InterpreterStackFrame::m_reader.m_currentLocation]
7985
7991
IR::RegOpnd* curLocOpnd = IR::RegOpnd::New (TyMachPtr, this ->m_func );
@@ -8015,46 +8021,24 @@ IRBuilder::GeneratorJumpTable::BuildJumpTable()
8015
8021
8016
8022
this ->m_irBuilder ->AddInstr (functionBegin, this ->m_irBuilder ->m_functionStartOffset );
8017
8023
8018
- // Save these values for later use
8019
- this ->m_initLabel = initCode;
8024
+ // Save this value for later use
8020
8025
this ->m_generatorFrameOpnd = genFrameOpnd;
8026
+ this ->m_func ->SetGeneratorFrameSym (genFrameOpnd->GetStackSym ());
8021
8027
8022
8028
return this ->m_irBuilder ->m_lastInstr ;
8023
8029
}
8024
8030
8025
- IR::LabelInstr*
8026
- IRBuilder::GeneratorJumpTable::GetInitLabel () const
8027
- {
8028
- Assert (this ->m_initLabel != nullptr );
8029
- return this ->m_initLabel ;
8030
- }
8031
-
8032
8031
IR::RegOpnd*
8033
- IRBuilder::GeneratorJumpTable::CreateForInEnumeratorArrayOpnd ()
8034
- {
8035
- Assert (this ->m_initLabel != nullptr );
8032
+ IRBuilder::GeneratorJumpTable::BuildForInEnumeratorArrayOpnd (uint32 offset)
8033
+ {
8036
8034
Assert (this ->m_generatorFrameOpnd != nullptr );
8037
8035
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,
8042
8038
POINTER_OFFSET (this ->m_generatorFrameOpnd , Js::InterpreterStackFrame::GetOffsetOfForInEnumerators (), ForInEnumerators),
8043
8039
this ->m_func
8044
8040
);
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);
8058
8042
8059
- return this -> m_forInEnumeratorArrayOpnd ;
8043
+ return forInEnumeratorArrayOpnd ;
8060
8044
}
0 commit comments