@@ -3528,19 +3528,34 @@ IRBuilder::BuildElementSlotI1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
35283528 StackSym * stackFuncPtrSym = nullptr ;
35293529 SymID symID = m_func->GetJITFunctionBody ()->GetLocalClosureReg ();
35303530 bool isLdSlotThatWasNotProfiled = false ;
3531+ bool stableSlot = false ;
35313532 StackSym* closureSym = m_func->GetLocalClosureSym ();
35323533
35333534 uint scopeSlotSize = this ->IsParamScopeDone () ? m_func->GetJITFunctionBody ()->GetScopeSlotArraySize () : m_func->GetJITFunctionBody ()->GetParamScopeSlotArraySize ();
35343535
35353536 switch (newOpcode)
35363537 {
3538+ case Js::OpCode::LdStableParamSlot:
3539+ stableSlot = true ;
3540+ goto ParamSlotCommon;
3541+
35373542 case Js::OpCode::LdParamSlot:
3543+ stableSlot = false ;
3544+
3545+ ParamSlotCommon:
35383546 scopeSlotSize = m_func->GetJITFunctionBody ()->GetParamScopeSlotArraySize ();
35393547 closureSym = m_func->GetParamClosureSym ();
35403548 symID = m_func->GetJITFunctionBody ()->GetParamClosureReg ();
3541- // Fall through
3549+ goto LocalSlotCommon;
3550+
3551+ case Js::OpCode::LdStableLocalSlot:
3552+ stableSlot = true ;
3553+ goto LocalSlotCommon;
35423554
35433555 case Js::OpCode::LdLocalSlot:
3556+ stableSlot = false ;
3557+
3558+ LocalSlotCommon:
35443559 if (!PHASE_OFF (Js::ClosureRangeCheckPhase, m_func))
35453560 {
35463561 if ((uint32)slotId >= scopeSlotSize + Js::ScopeSlots::FirstSlotIndex)
@@ -3580,7 +3595,7 @@ IRBuilder::BuildElementSlotI1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
35803595 this ->EnsureLoopBodyLoadSlot (symID);
35813596 }
35823597
3583- fieldSym = PropertySym::FindOrCreate (symID, slotId, (uint32)-1 , (uint)-1 , PropertyKindSlots, m_func);
3598+ fieldSym = PropertySym::FindOrCreate (symID, slotId, (uint32)-1 , (uint)-1 , PropertyKindSlots, m_func, stableSlot );
35843599 fieldOpnd = IR::SymOpnd::New (fieldSym, TyVar, m_func);
35853600 regOpnd = this ->BuildDstOpnd (regSlot);
35863601 instr = nullptr ;
@@ -3637,16 +3652,32 @@ IRBuilder::BuildElementSlotI1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
36373652 this ->AddInstr (instr, offset);
36383653 break ;
36393654
3655+ case Js::OpCode::StStableParamSlot:
3656+ case Js::OpCode::StStableParamSlotChkUndecl:
3657+ stableSlot = true ;
3658+ goto StParamSlotCommon;
3659+
36403660 case Js::OpCode::StParamSlot:
36413661 case Js::OpCode::StParamSlotChkUndecl:
3662+ stableSlot = false ;
3663+
3664+ StParamSlotCommon:
36423665 scopeSlotSize = m_func->GetJITFunctionBody ()->GetParamScopeSlotArraySize ();
36433666 closureSym = m_func->GetParamClosureSym ();
36443667 symID = m_func->GetJITFunctionBody ()->GetParamClosureReg ();
3645- newOpcode = newOpcode == Js::OpCode::StParamSlot ? Js::OpCode::StLocalSlot : Js::OpCode::StLocalSlotChkUndecl;
3646- // Fall through
3668+ newOpcode = newOpcode == Js::OpCode::StParamSlot || newOpcode == Js::OpCode::StStableParamSlot ? Js::OpCode::StLocalSlot : Js::OpCode::StLocalSlotChkUndecl;
3669+ goto StLocalSlotCommon;
3670+
3671+ case Js::OpCode::StStableLocalSlot:
3672+ case Js::OpCode::StStableLocalSlotChkUndecl:
3673+ stableSlot = true ;
3674+ goto StLocalSlotCommon;
36473675
36483676 case Js::OpCode::StLocalSlot:
36493677 case Js::OpCode::StLocalSlotChkUndecl:
3678+ stableSlot = false ;
3679+
3680+ StLocalSlotCommon:
36503681 if (!PHASE_OFF (Js::ClosureRangeCheckPhase, m_func))
36513682 {
36523683 if ((uint32)slotId >= scopeSlotSize + Js::ScopeSlots::FirstSlotIndex)
@@ -3662,7 +3693,7 @@ IRBuilder::BuildElementSlotI1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
36623693 this ->AddInstr (byteCodeUse, offset);
36633694 }
36643695
3665- newOpcode = newOpcode == Js::OpCode::StLocalSlot ? Js::OpCode::StSlot : Js::OpCode::StSlotChkUndecl;
3696+ newOpcode = newOpcode == Js::OpCode::StLocalSlot || newOpcode == Js::OpCode::StStableLocalSlot ? Js::OpCode::StSlot : Js::OpCode::StSlotChkUndecl;
36663697 if (m_func->DoStackFrameDisplay ())
36673698 {
36683699 regOpnd = IR::RegOpnd::New (TyVar, m_func);
@@ -3687,7 +3718,7 @@ IRBuilder::BuildElementSlotI1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
36873718 this ->EnsureLoopBodyLoadSlot (symID);
36883719 }
36893720 }
3690- fieldSym = PropertySym::FindOrCreate (symID, slotId, (uint32)-1 , (uint)-1 , PropertyKindSlots, m_func);
3721+ fieldSym = PropertySym::FindOrCreate (symID, slotId, (uint32)-1 , (uint)-1 , PropertyKindSlots, m_func, stableSlot );
36913722 fieldOpnd = IR::SymOpnd::New (fieldSym, TyVar, m_func);
36923723 regOpnd = this ->BuildSrcOpnd (regSlot);
36933724 instr = IR::Instr::New (newOpcode, fieldOpnd, regOpnd, m_func);
@@ -3882,7 +3913,8 @@ IRBuilder::BuildElementSlotI2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
38823913 IR::Instr *instr;
38833914 PropertySym *fieldSym;
38843915 bool isLdSlotThatWasNotProfiled = false ;
3885- bool stableSlots = false ;
3916+ bool stableSlotArray = false ;
3917+ bool stableSlot = false ;
38863918
38873919 switch (newOpcode)
38883920 {
@@ -3916,19 +3948,26 @@ IRBuilder::BuildElementSlotI2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
39163948 break ;
39173949 }
39183950
3951+ case Js::OpCode::LdStableEnvSlot:
3952+ stableSlotArray = true ;
3953+ stableSlot = true ;
3954+ goto EnvSlotCommon;
3955+
39193956 case Js::OpCode::LdEnvSlot:
39203957 case Js::OpCode::StEnvSlot:
39213958 case Js::OpCode::StEnvSlotChkUndecl:
3922- stableSlots = true ;
3923- goto SlotsCommon;
3959+ stableSlotArray = true ;
3960+ stableSlot = false ;
3961+ goto EnvSlotCommon;
39243962
39253963 case Js::OpCode::LdEnvObjSlot:
39263964 case Js::OpCode::StEnvObjSlot:
39273965 case Js::OpCode::StEnvObjSlotChkUndecl:
3928- stableSlots = false ;
3966+ stableSlotArray = false ;
3967+ stableSlot = false ;
39293968
3930- SlotsCommon :
3931- fieldOpnd = this ->BuildFieldOpnd (Js::OpCode::LdSlotArr, this ->GetEnvReg (), slotId1, (Js::PropertyIdIndexType)-1 , PropertyKindSlotArray, (uint)-1 , stableSlots );
3969+ EnvSlotCommon :
3970+ fieldOpnd = this ->BuildFieldOpnd (Js::OpCode::LdSlotArr, this ->GetEnvReg (), slotId1, (Js::PropertyIdIndexType)-1 , PropertyKindSlotArray, (uint)-1 , stableSlotArray );
39323971 regOpnd = IR::RegOpnd::New (TyVar, m_func);
39333972 instr = IR::Instr::New (Js::OpCode::LdSlotArr, regOpnd, fieldOpnd, m_func);
39343973 this ->AddInstr (instr, offset);
@@ -3953,12 +3992,13 @@ IRBuilder::BuildElementSlotI2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
39533992 break ;
39543993 }
39553994
3956- fieldSym = PropertySym::New (regOpnd->m_sym , slotId2, (uint32)-1 , (uint)-1 , PropertyKindSlots, m_func);
3995+ fieldSym = PropertySym::New (regOpnd->m_sym , slotId2, (uint32)-1 , (uint)-1 , PropertyKindSlots, m_func, stableSlot );
39573996 fieldOpnd = IR::SymOpnd::New (fieldSym, TyVar, m_func);
39583997
39593998 switch (newOpcode)
39603999 {
39614000 case Js::OpCode::LdEnvSlot:
4001+ case Js::OpCode::LdStableEnvSlot:
39624002 case Js::OpCode::LdEnvObjSlot:
39634003 newOpcode = Js::OpCode::LdSlot;
39644004 regOpnd = this ->BuildDstOpnd (regSlot);
@@ -3992,10 +4032,18 @@ IRBuilder::BuildElementSlotI2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
39924032 }
39934033 break ;
39944034
4035+ case Js::OpCode::StStableInnerSlot:
4036+ case Js::OpCode::StStableInnerSlotChkUndecl:
4037+ stableSlot = true ;
4038+ goto StInnerSlotCommon;
4039+
39954040 case Js::OpCode::StInnerObjSlot:
39964041 case Js::OpCode::StInnerObjSlotChkUndecl:
39974042 case Js::OpCode::StInnerSlot:
39984043 case Js::OpCode::StInnerSlotChkUndecl:
4044+ stableSlot = false ;
4045+
4046+ StInnerSlotCommon:
39994047 if ((uint)slotId1 >= m_func->GetJITFunctionBody ()->GetInnerScopeCount ())
40004048 {
40014049 Js::Throw::FatalInternalError ();
@@ -4018,15 +4066,15 @@ IRBuilder::BuildElementSlotI2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
40184066 }
40194067 else
40204068 {
4021- fieldOpnd = this ->BuildFieldOpnd (Js::OpCode::StSlot, slotId1, slotId2, (Js::PropertyIdIndexType)-1 , PropertyKindSlots);
4069+ fieldOpnd = this ->BuildFieldOpnd (Js::OpCode::StSlot, slotId1, slotId2, (Js::PropertyIdIndexType)-1 , PropertyKindSlots, (uint)- 1 , stableSlot );
40224070 if (!this ->DoSlotArrayCheck (fieldOpnd, IsLoopBody ()))
40234071 {
40244072 // Need a dynamic check on the size of the local slot array.
40254073 m_func->GetTopFunc ()->AddSlotArrayCheck (fieldOpnd);
40264074 }
40274075 }
40284076 newOpcode =
4029- newOpcode == Js::OpCode::StInnerObjSlot || newOpcode == Js::OpCode::StInnerSlot ?
4077+ newOpcode == Js::OpCode::StInnerObjSlot || newOpcode == Js::OpCode::StInnerSlot || newOpcode == Js::OpCode::StStableInnerSlot ?
40304078 Js::OpCode::StSlot : Js::OpCode::StSlotChkUndecl;
40314079 instr = IR::Instr::New (newOpcode, fieldOpnd, regOpnd, m_func);
40324080 if (newOpcode == Js::OpCode::StSlotChkUndecl)
@@ -4038,8 +4086,15 @@ IRBuilder::BuildElementSlotI2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
40384086
40394087 break ;
40404088
4089+ case Js::OpCode::LdStableInnerSlot:
4090+ stableSlot = true ;
4091+ goto LdInnerSlotCommon;
4092+
40414093 case Js::OpCode::LdInnerSlot:
40424094 case Js::OpCode::LdInnerObjSlot:
4095+ stableSlot = false ;
4096+
4097+ LdInnerSlotCommon:
40434098 if ((uint)slotId1 >= m_func->GetJITFunctionBody ()->GetInnerScopeCount ())
40444099 {
40454100 Js::Throw::FatalInternalError ();
@@ -4061,7 +4116,7 @@ IRBuilder::BuildElementSlotI2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
40614116 }
40624117 else
40634118 {
4064- fieldOpnd = this ->BuildFieldOpnd (Js::OpCode::LdSlot, slotId1, slotId2, (Js::PropertyIdIndexType)-1 , PropertyKindSlots);
4119+ fieldOpnd = this ->BuildFieldOpnd (Js::OpCode::LdSlot, slotId1, slotId2, (Js::PropertyIdIndexType)-1 , PropertyKindSlots, (uint)- 1 , stableSlot );
40654120 if (!this ->DoSlotArrayCheck (fieldOpnd, IsLoopBody ()))
40664121 {
40674122 // Need a dynamic check on the size of the local slot array.
0 commit comments