Skip to content

Commit fc907f2

Browse files
committed
Change the way the JIT renumbers byte code temps
1 parent 8595cce commit fc907f2

23 files changed

+23966
-23741
lines changed

lib/Backend/FlowGraph.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,7 @@ FlowGraph::RunPeeps()
835835
case Js::OpCode::BrSrNeq_A:
836836
case Js::OpCode::BrOnHasProperty:
837837
case Js::OpCode::BrOnNoProperty:
838+
case Js::OpCode::BrOnHasLocalProperty:
838839
case Js::OpCode::BrOnNoLocalProperty:
839840
case Js::OpCode::BrHasSideEffects:
840841
case Js::OpCode::BrNotHasSideEffects:

lib/Backend/GlobOpt.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3418,6 +3418,7 @@ GlobOpt::OptSrc(IR::Opnd *opnd, IR::Instr * *pInstr, Value **indirIndexValRef, I
34183418
case Js::OpCode::BrOnNoProperty:
34193419
case Js::OpCode::BrOnNoLocalProperty:
34203420
case Js::OpCode::BrOnHasProperty:
3421+
case Js::OpCode::BrOnHasLocalProperty:
34213422
case Js::OpCode::LdMethodFldPolyInlineMiss:
34223423
case Js::OpCode::StSlotChkUndecl:
34233424
case Js::OpCode::ScopedLdInst:

lib/Backend/IR.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1906,6 +1906,14 @@ BranchInstr::Invert()
19061906
this->m_opcode = Js::OpCode::BrOnNoProperty;
19071907
break;
19081908

1909+
case Js::OpCode::BrOnHasLocalProperty:
1910+
this->m_opcode = Js::OpCode::BrOnNoLocalProperty;
1911+
break;
1912+
1913+
case Js::OpCode::BrOnNoLocalProperty:
1914+
this->m_opcode = Js::OpCode::BrOnHasLocalProperty;
1915+
break;
1916+
19091917
case Js::OpCode::BrOnNoProperty:
19101918
this->m_opcode = Js::OpCode::BrOnHasProperty;
19111919
break;

lib/Backend/IRBuilder.cpp

Lines changed: 75 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -353,12 +353,10 @@ IRBuilder::Build()
353353
if (tempCount > 0)
354354
{
355355
this->tempMap = AnewArrayZ(m_tempAlloc, SymID, tempCount);
356-
this->fbvTempUsed = BVFixed::New<JitArenaAllocator>(tempCount, m_tempAlloc);
357356
}
358357
else
359358
{
360359
this->tempMap = nullptr;
361-
this->fbvTempUsed = nullptr;
362360
}
363361

364362
m_func->m_headInstr = IR::EntryInstr::New(Js::OpCode::FunctionEntry, m_func);
@@ -1224,7 +1222,6 @@ IRBuilder::BuildSrcStackSymID(Js::RegSlot regSlot)
12241222
this->SetMappedTemp(regSlot, symID);
12251223
this->EnsureLoopBodyLoadSlot(symID);
12261224
}
1227-
this->SetTempUsed(regSlot, TRUE);
12281225
}
12291226
else
12301227
{
@@ -1315,7 +1312,7 @@ IRBuilder::BuildSrcOpnd(Js::RegSlot srcRegSlot, IRType type)
13151312
///----------------------------------------------------------------------------
13161313

13171314
IR::RegOpnd *
1318-
IRBuilder::BuildDstOpnd(Js::RegSlot dstRegSlot, IRType type, bool isCatchObjectSym)
1315+
IRBuilder::BuildDstOpnd(Js::RegSlot dstRegSlot, IRType type, bool isCatchObjectSym, bool reuseTemp)
13191316
{
13201317
StackSym * symDst;
13211318
SymID symID;
@@ -1336,24 +1333,20 @@ IRBuilder::BuildDstOpnd(Js::RegSlot dstRegSlot, IRType type, bool isCatchObjectS
13361333

13371334
// This is a def of a temp. Create a new sym ID for it if it's been used since its last def.
13381335
// !!!NOTE: always process an instruction's temp uses before its temp defs!!!
1339-
if (this->GetTempUsed(dstRegSlot))
1336+
1337+
symID = this->GetMappedTemp(dstRegSlot);
1338+
if (symID == 0)
13401339
{
1341-
symID = m_func->m_symTable->NewID();
1342-
this->SetTempUsed(dstRegSlot, FALSE);
1340+
// First time we've seen the temp. Just use the number that the front end gave it.
1341+
symID = static_cast<SymID>(dstRegSlot);
13431342
this->SetMappedTemp(dstRegSlot, symID);
13441343
}
1345-
else
1344+
else if (!reuseTemp)
13461345
{
1347-
symID = this->GetMappedTemp(dstRegSlot);
1348-
// The temp hasn't been used since its last def. There are 2 possibilities:
1349-
if (symID == 0)
1350-
{
1351-
// First time we've seen the temp. Just use the number that the front end gave it.
1352-
symID = static_cast<SymID>(dstRegSlot);
1353-
this->SetMappedTemp(dstRegSlot, symID);
1354-
}
1346+
// Byte code has not told us to reuse the mapped temp at this def, so don't. Make a new one.
1347+
symID = m_func->m_symTable->NewID();
1348+
this->SetMappedTemp(dstRegSlot, symID);
13551349
}
1356-
13571350
}
13581351
else
13591352
{
@@ -1506,6 +1499,7 @@ IRBuilder::BuildReg1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0)
15061499
IR::Opnd * srcOpnd = nullptr;
15071500
bool isNotInt = false;
15081501
bool dstIsCatchObject = false;
1502+
bool reuseLoc = false;
15091503
ValueType dstValueType;
15101504
switch (newOpcode)
15111505
{
@@ -1560,6 +1554,9 @@ IRBuilder::BuildReg1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0)
15601554
isNotInt = true;
15611555
break;
15621556

1557+
case Js::OpCode::LdLocalObj_ReuseLoc:
1558+
reuseLoc = true;
1559+
// fall through
15631560
case Js::OpCode::LdLocalObj:
15641561
if (!m_func->GetJITFunctionBody()->HasScopeObject())
15651562
{
@@ -1636,6 +1633,9 @@ IRBuilder::BuildReg1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0)
16361633
break;
16371634
}
16381635

1636+
case Js::OpCode::LdFalse_ReuseLoc:
1637+
reuseLoc = true;
1638+
// fall through
16391639
case Js::OpCode::LdFalse:
16401640
{
16411641
const auto addrOpnd = IR::AddrOpnd::New(m_func->GetScriptContextInfo()->GetFalseAddr(), IR::AddrOpndKindDynamicVar, m_func, true);
@@ -1645,6 +1645,9 @@ IRBuilder::BuildReg1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0)
16451645
break;
16461646
}
16471647

1648+
case Js::OpCode::LdTrue_ReuseLoc:
1649+
reuseLoc = true;
1650+
// fall through
16481651
case Js::OpCode::LdTrue:
16491652
{
16501653
const auto addrOpnd = IR::AddrOpnd::New(m_func->GetScriptContextInfo()->GetTrueAddr(), IR::AddrOpndKindDynamicVar, m_func, true);
@@ -1666,12 +1669,6 @@ IRBuilder::BuildReg1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0)
16661669
isNotInt = TRUE;
16671670
break;
16681671

1669-
case Js::OpCode::Unused:
1670-
// Don't generate anything. Just indicate that the temp reg is used.
1671-
Assert(this->RegIsTemp(dstRegSlot));
1672-
this->SetTempUsed(dstRegSlot, TRUE);
1673-
return;
1674-
16751672
case Js::OpCode::InitUndecl:
16761673
srcOpnd = IR::AddrOpnd::New(m_func->GetScriptContextInfo()->GetUndeclBlockVarAddr(), IR::AddrOpndKindDynamicVar, m_func, true);
16771674
srcOpnd->SetValueType(ValueType::PrimitiveOrObject);
@@ -1705,7 +1702,7 @@ IRBuilder::BuildReg1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0)
17051702
}
17061703
}
17071704

1708-
IR::RegOpnd * dstOpnd = this->BuildDstOpnd(dstRegSlot, TyVar, dstIsCatchObject);
1705+
IR::RegOpnd * dstOpnd = this->BuildDstOpnd(dstRegSlot, TyVar, dstIsCatchObject, reuseLoc);
17091706
dstOpnd->SetValueType(dstValueType);
17101707
StackSym * dstSym = dstOpnd->m_sym;
17111708
dstSym->m_isCatchObjectSym = dstIsCatchObject;
@@ -1773,9 +1770,25 @@ IRBuilder::BuildReg2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::Re
17731770
{
17741771
IR::RegOpnd * src1Opnd = this->BuildSrcOpnd(R1);
17751772
StackSym * symSrc1 = src1Opnd->m_sym;
1773+
bool reuseLoc = false;
17761774

17771775
switch (newOpcode)
17781776
{
1777+
case Js::OpCode::Ld_A_ReuseLoc:
1778+
newOpcode = Js::OpCode::Ld_A;
1779+
reuseLoc = true;
1780+
break;
1781+
1782+
case Js::OpCode::Typeof_ReuseLoc:
1783+
newOpcode = Js::OpCode::Typeof;
1784+
reuseLoc = true;
1785+
break;
1786+
1787+
case Js::OpCode::UnwrapWithObj_ReuseLoc:
1788+
newOpcode = Js::OpCode::UnwrapWithObj;
1789+
reuseLoc = true;
1790+
break;
1791+
17791792
case Js::OpCode::SpreadObjectLiteral:
17801793
// fall through
17811794
case Js::OpCode::SetComputedNameVar:
@@ -1807,7 +1820,7 @@ IRBuilder::BuildReg2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::Re
18071820
}
18081821
}
18091822

1810-
IR::RegOpnd * dstOpnd = this->BuildDstOpnd(R0);
1823+
IR::RegOpnd * dstOpnd = this->BuildDstOpnd(R0, TyVar, false, reuseLoc);
18111824
StackSym * dstSym = dstOpnd->m_sym;
18121825

18131826
IR::Instr * instr = nullptr;
@@ -2380,7 +2393,7 @@ IRBuilder::BuildReg2B1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSl
23802393

23812394
IR::Instr * instr;
23822395
IR::RegOpnd * srcOpnd = this->BuildSrcOpnd(srcRegSlot);
2383-
IR::RegOpnd * dstOpnd = this->BuildDstOpnd(dstRegSlot);
2396+
IR::RegOpnd * dstOpnd = this->BuildDstOpnd(dstRegSlot, TyVar, false, true);
23842397

23852398
IR::IndirOpnd * indir1Opnd = IR::IndirOpnd::New(dstOpnd, index, TyVar, m_func);
23862399

@@ -2417,22 +2430,23 @@ IRBuilder::BuildReg3B1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSl
24172430
IR::Instr * instr;
24182431
IR::RegOpnd * src1Opnd = this->BuildSrcOpnd(src1RegSlot);
24192432
IR::RegOpnd * src2Opnd = this->BuildSrcOpnd(src2RegSlot);
2420-
IR::RegOpnd * dstOpnd = this->BuildDstOpnd(dstRegSlot);
2421-
dstOpnd->SetValueType(ValueType::String);
2433+
IR::RegOpnd * dstOpnd = nullptr;
24222434

24232435
IR::Instr * newConcatStrMulti = nullptr;
24242436
switch (newOpcode)
24252437
{
24262438
case Js::OpCode::NewConcatStrMulti:
2427-
2439+
dstOpnd = this->BuildDstOpnd(dstRegSlot);
24282440
newConcatStrMulti = IR::Instr::New(Js::OpCode::NewConcatStrMulti, dstOpnd, IR::IntConstOpnd::New(index, TyUint32, m_func), m_func);
24292441
index = 0;
24302442
break;
24312443
case Js::OpCode::SetConcatStrMultiItem2:
2444+
dstOpnd = this->BuildDstOpnd(dstRegSlot, TyVar, false, true);
24322445
break;
24332446
default:
24342447
Assert(false);
24352448
};
2449+
dstOpnd->SetValueType(ValueType::String);
24362450
IR::IndirOpnd * indir1Opnd = IR::IndirOpnd::New(dstOpnd, index, TyVar, m_func);
24372451
IR::IndirOpnd * indir2Opnd = IR::IndirOpnd::New(dstOpnd, index + 1, TyVar, m_func);
24382452

@@ -3152,15 +3166,20 @@ IRBuilder::BuildElementC(Js::OpCode newOpcode, uint32 offset, Js::RegSlot fieldR
31523166
PropertyKind propertyKind = PropertyKindData;
31533167
IR::SymOpnd * fieldSymOpnd = this->BuildFieldOpnd(newOpcode, fieldRegSlot, propertyId, propertyIdIndex, propertyKind);
31543168
IR::RegOpnd * regOpnd;
3169+
bool reuseLoc = false;
31553170

31563171
switch (newOpcode)
31573172
{
3173+
case Js::OpCode::DeleteFld_ReuseLoc:
3174+
newOpcode = Js::OpCode::DeleteFld;
3175+
reuseLoc = true;
3176+
// fall through
31583177
case Js::OpCode::DeleteFld:
31593178
case Js::OpCode::DeleteRootFld:
31603179
case Js::OpCode::DeleteFldStrict:
31613180
case Js::OpCode::DeleteRootFldStrict:
31623181
// Load
3163-
regOpnd = this->BuildDstOpnd(regSlot);
3182+
regOpnd = this->BuildDstOpnd(regSlot, TyVar, false, reuseLoc);
31643183
instr = IR::Instr::New(newOpcode, regOpnd, fieldSymOpnd, m_func);
31653184
break;
31663185

@@ -3482,6 +3501,7 @@ IRBuilder::BuildElementSlotI1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
34823501
StackSym * stackFuncPtrSym = nullptr;
34833502
SymID symID = m_func->GetJITFunctionBody()->GetLocalClosureReg();
34843503
bool isLdSlotThatWasNotProfiled = false;
3504+
bool reuseLoc = false;
34853505
StackSym* closureSym = m_func->GetLocalClosureSym();
34863506

34873507
uint scopeSlotSize = this->IsParamScopeDone() ? m_func->GetJITFunctionBody()->GetScopeSlotArraySize() : m_func->GetJITFunctionBody()->GetParamScopeSlotArraySize();
@@ -3679,9 +3699,12 @@ IRBuilder::BuildElementSlotI1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
36793699
this->AddInstr(instr, offset);
36803700
break;
36813701

3702+
case Js::OpCode::LdEnvObj_ReuseLoc:
3703+
reuseLoc = true;
3704+
// fall through
36823705
case Js::OpCode::LdEnvObj:
36833706
fieldOpnd = this->BuildFieldOpnd(Js::OpCode::LdSlotArr, this->GetEnvReg(), slotId, (Js::PropertyIdIndexType)-1, PropertyKindSlotArray);
3684-
regOpnd = this->BuildDstOpnd(regSlot);
3707+
regOpnd = this->BuildDstOpnd(regSlot, TyVar, false, reuseLoc);
36853708
instr = IR::Instr::New(Js::OpCode::LdSlotArr, regOpnd, fieldOpnd, m_func);
36863709
this->AddInstr(instr, offset);
36873710

@@ -4255,9 +4278,14 @@ IRBuilder::BuildElementP(Js::OpCode newOpcode, uint32 offset, Js::RegSlot regSlo
42554278
propertyId = this->m_func->GetJITFunctionBody()->GetPropertyIdFromCacheId(inlineCacheIndex);
42564279

42574280
Js::RegSlot instance = this->GetEnvRegForEvalCode();
4281+
bool reuseLoc = false;
42584282

42594283
switch (newOpcode)
42604284
{
4285+
case Js::OpCode::LdLocalFld_ReuseLoc:
4286+
reuseLoc = true;
4287+
newOpcode = Js::OpCode::LdLocalFld;
4288+
// fall through
42614289
case Js::OpCode::LdLocalFld:
42624290
if (m_func->GetLocalClosureSym()->HasByteCodeRegSlot())
42634291
{
@@ -4272,7 +4300,7 @@ IRBuilder::BuildElementP(Js::OpCode newOpcode, uint32 offset, Js::RegSlot regSlo
42724300
{
42734301
fieldSymOpnd->AsPropertySymOpnd()->TryDisableRuntimePolymorphicCache();
42744302
}
4275-
regOpnd = this->BuildDstOpnd(regSlot);
4303+
regOpnd = this->BuildDstOpnd(regSlot, TyVar, false, reuseLoc);
42764304

42774305
instr = nullptr;
42784306
if (isProfiled)
@@ -4485,8 +4513,13 @@ IRBuilder::BuildElementCP(Js::OpCode newOpcode, uint32 offset, Js::RegSlot insta
44854513

44864514
IR::Instr * instr = nullptr;
44874515
bool isLdFldThatWasNotProfiled = false;
4516+
bool reuseLoc = false;
44884517
switch (newOpcode)
44894518
{
4519+
case Js::OpCode::LdFld_ReuseLoc:
4520+
reuseLoc = true;
4521+
newOpcode = Js::OpCode::LdFld;
4522+
// fall through
44904523
case Js::OpCode::LdFldForTypeOf:
44914524
case Js::OpCode::LdFld:
44924525
case Js::OpCode::LdLen_A:
@@ -4502,7 +4535,7 @@ IRBuilder::BuildElementCP(Js::OpCode newOpcode, uint32 offset, Js::RegSlot insta
45024535
case Js::OpCode::ScopedLdMethodFld:
45034536
// Load
45044537
// LdMethodFromFlags is backend only. Don't need to be added here.
4505-
regOpnd = this->BuildDstOpnd(regSlot);
4538+
regOpnd = this->BuildDstOpnd(regSlot, TyVar, false, reuseLoc);
45064539

45074540
if (isProfiled)
45084541
{
@@ -4879,6 +4912,7 @@ IRBuilder::BuildElementU(Js::OpCode newOpcode, uint32 offset, Js::RegSlot instan
48794912
IR::RegOpnd * regOpnd;
48804913
IR::SymOpnd * fieldSymOpnd;
48814914
Js::PropertyId propertyId = m_func->GetJITFunctionBody()->GetReferencedPropertyId(propertyIdIndex);
4915+
bool reuseLoc = false;
48824916

48834917
switch (newOpcode)
48844918
{
@@ -4926,10 +4960,14 @@ IRBuilder::BuildElementU(Js::OpCode newOpcode, uint32 offset, Js::RegSlot instan
49264960
instr = IR::Instr::New(newOpcode, fieldSymOpnd, regOpnd, m_func);
49274961
break;
49284962

4963+
case Js::OpCode::DeleteLocalFld_ReuseLoc:
4964+
newOpcode = Js::OpCode::DeleteLocalFld;
4965+
reuseLoc = true;
4966+
// fall through
49294967
case Js::OpCode::DeleteLocalFld:
49304968
newOpcode = Js::OpCode::DeleteFld;
49314969
fieldSymOpnd = BuildFieldOpnd(newOpcode, m_func->GetJITFunctionBody()->GetLocalClosureReg(), propertyId, propertyIdIndex, PropertyKindData);
4932-
regOpnd = BuildDstOpnd(instance);
4970+
regOpnd = BuildDstOpnd(instance, TyVar, false, reuseLoc);
49334971
instr = IR::Instr::New(newOpcode, regOpnd, fieldSymOpnd, m_func);
49344972
break;
49354973

@@ -7278,7 +7316,7 @@ void
72787316
IRBuilder::BuildBrLocalProperty(Js::OpCode newOpcode, uint32 offset)
72797317
{
72807318
Assert(!OpCodeAttr::HasMultiSizeLayout(newOpcode));
7281-
Assert(newOpcode == Js::OpCode::BrOnNoLocalProperty);
7319+
Assert(newOpcode == Js::OpCode::BrOnHasLocalProperty);
72827320

72837321
const unaligned Js::OpLayoutBrLocalProperty *branchInsn = m_jnReader.BrLocalProperty();
72847322

@@ -7322,7 +7360,8 @@ IRBuilder::BuildBrEnvProperty(Js::OpCode newOpcode, uint32 offset)
73227360
fieldSym = PropertySym::New(regOpnd->m_sym, propertyId, branchInsn->PropertyIdIndex, (uint)-1, PropertyKindData, m_func);
73237361
fieldOpnd = IR::SymOpnd::New(fieldSym, TyVar, m_func);
73247362

7325-
branchInstr = IR::BranchInstr::New(newOpcode == Js::OpCode::BrOnNoEnvProperty ? Js::OpCode::BrOnNoProperty : Js::OpCode::BrOnNoLocalProperty, nullptr, fieldOpnd, m_func);
7363+
Assert(newOpcode == Js::OpCode::BrOnHasEnvProperty || newOpcode == Js::OpCode::BrOnHasLocalEnvProperty);
7364+
branchInstr = IR::BranchInstr::New(newOpcode == Js::OpCode::BrOnHasEnvProperty ? Js::OpCode::BrOnHasProperty : Js::OpCode::BrOnHasLocalProperty, nullptr, fieldOpnd, m_func);
73267365
this->AddBranchInstr(branchInstr, offset, targetOffset);
73277366
}
73287367

0 commit comments

Comments
 (0)