Skip to content

Commit 100d3ec

Browse files
committed
Allow LdSlotArr to be hoisted across calls when the result is known to be invariant
1 parent 34b8876 commit 100d3ec

File tree

7 files changed

+55
-20
lines changed

7 files changed

+55
-20
lines changed

lib/Backend/Func.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ Func::Func(JitArenaAllocator *alloc, JITTimeWorkItem * workItem,
126126
#endif
127127
, m_funcStartLabel(nullptr)
128128
, m_funcEndLabel(nullptr)
129+
, bvStableSlotSyms(nullptr)
129130
#if DBG
130131
, hasCalledSetDoFastPaths(false)
131132
, allowRemoveBailOutArgInstr(false)
@@ -172,6 +173,8 @@ Func::Func(JitArenaAllocator *alloc, JITTimeWorkItem * workItem,
172173
outputData->hasJittedStackClosure = false;
173174
outputData->localVarSlotsOffset = m_localVarSlotsOffset;
174175
outputData->localVarChangedOffset = m_hasLocalVarChangedOffset;
176+
177+
this->bvStableSlotSyms = Anew(this->m_alloc, BVSparse<JitArenaAllocator>, this->m_alloc);
175178
}
176179

177180
if (this->IsInlined())
@@ -808,6 +811,21 @@ void Func::OnAddSym(Sym* sym)
808811
}
809812
}
810813

814+
void Func::AddStableSlotSym(PropertySym *sym)
815+
{
816+
this->GetTopFunc()->bvStableSlotSyms->Set(sym->m_id);
817+
}
818+
819+
bool Func::IsStableSlotSym(PropertySym *sym) const
820+
{
821+
return this->GetTopFunc()->bvStableSlotSyms->Test(sym->m_id);
822+
}
823+
824+
BVSparse<JitArenaAllocator> *Func::GetStableSlotSyms() const
825+
{
826+
return this->GetTopFunc()->bvStableSlotSyms;
827+
}
828+
811829
///
812830
/// Returns offset of the flag (1 byte) whether any local was changed (in debugger).
813831
/// If the function does not have any locals, returns -1.

lib/Backend/Func.h

+5
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,10 @@ static const unsigned __int64 c_debugFillPattern8 = 0xcececececececece;
442442
StackSym *GetLocalFrameDisplaySym() const { return m_localFrameDisplaySym; }
443443
void SetLocalFrameDisplaySym(StackSym *sym) { m_localFrameDisplaySym = sym; }
444444

445+
void AddStableSlotSym(PropertySym *sym);
446+
bool IsStableSlotSym(PropertySym *sym) const;
447+
BVSparse<JitArenaAllocator> *GetStableSlotSyms() const;
448+
445449
intptr_t GetJittedLoopIterationsSinceLastBailoutAddress() const;
446450
void EnsurePinnedTypeRefs();
447451
void PinTypeRef(void* typeRef);
@@ -724,6 +728,7 @@ static const unsigned __int64 c_debugFillPattern8 = 0xcececececececece;
724728
BitVector m_regsUsed;
725729
StackSym * tempSymDouble;
726730
StackSym * tempSymBool;
731+
BVSparse<JitArenaAllocator> * bvStableSlotSyms;
727732
uint32 loopCount;
728733
uint32 unoptimizableArgumentsObjReference;
729734
Js::ProfileId callSiteIdInParentFunc;

lib/Backend/GlobOptFields.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ GlobOpt::KillLiveElems(IR::IndirOpnd * indirOpnd, BVSparse<JitArenaAllocator> *
242242
void
243243
GlobOpt::KillAllFields(BVSparse<JitArenaAllocator> * bv)
244244
{
245-
bv->ClearAll();
245+
bv->And(func->GetStableSlotSyms());
246246
if (this->IsLoopPrePass())
247247
{
248248
for (Loop * loop = this->rootLoopPrePass; loop != nullptr; loop = loop->parent)
@@ -447,9 +447,8 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
447447
void
448448
GlobOpt::ProcessFieldKills(IR::Instr * instr)
449449
{
450-
if (!this->DoFieldCopyProp() && !this->DoFieldRefOpts() && !DoCSE())
450+
if (this->currentBlock->globOptData.liveFields->IsEmpty())
451451
{
452-
Assert(this->currentBlock->globOptData.liveFields->IsEmpty());
453452
return;
454453
}
455454

@@ -1808,7 +1807,7 @@ GlobOpt::CopyPropPropertySymObj(IR::SymOpnd *symOpnd, IR::Instr *instr)
18081807
if (copySym != nullptr)
18091808
{
18101809
PropertySym *newProp = PropertySym::FindOrCreate(
1811-
copySym->m_id, propertySym->m_propertyId, propertySym->GetPropertyIdIndex(), propertySym->GetInlineCacheIndex(), propertySym->m_fieldKind, this->func);
1810+
copySym->m_id, propertySym->m_propertyId, propertySym->GetPropertyIdIndex(), propertySym->GetInlineCacheIndex(), propertySym->m_fieldKind, this->func, this->func->IsStableSlotSym(propertySym));
18121811

18131812
if (!this->IsLoopPrePass() || SafeToCopyPropInPrepass(objSym, copySym, val))
18141813
{

lib/Backend/IRBuilder.cpp

+12-6
Original file line numberDiff line numberDiff line change
@@ -1212,10 +1212,10 @@ IRBuilder::BuildIndirOpnd(IR::RegOpnd *baseReg, uint32 offset, const char16 *des
12121212
#endif
12131213

12141214
IR::SymOpnd *
1215-
IRBuilder::BuildFieldOpnd(Js::OpCode newOpcode, Js::RegSlot reg, Js::PropertyId propertyId, Js::PropertyIdIndexType propertyIdIndex, PropertyKind propertyKind, uint inlineCacheIndex)
1215+
IRBuilder::BuildFieldOpnd(Js::OpCode newOpcode, Js::RegSlot reg, Js::PropertyId propertyId, Js::PropertyIdIndexType propertyIdIndex, PropertyKind propertyKind, uint inlineCacheIndex, bool stableSlotSym)
12161216
{
12171217
AssertOrFailFast(inlineCacheIndex < m_func->GetJITFunctionBody()->GetInlineCacheCount() || inlineCacheIndex == Js::Constants::NoInlineCacheIndex);
1218-
PropertySym * propertySym = BuildFieldSym(reg, propertyId, propertyIdIndex, inlineCacheIndex, propertyKind);
1218+
PropertySym * propertySym = BuildFieldSym(reg, propertyId, propertyIdIndex, inlineCacheIndex, propertyKind, stableSlotSym);
12191219
IR::SymOpnd * symOpnd;
12201220

12211221
// If we plan to apply object type optimization to this instruction or if we intend to emit a fast path using an inline
@@ -1243,14 +1243,14 @@ IRBuilder::BuildFieldOpnd(Js::OpCode newOpcode, Js::RegSlot reg, Js::PropertyId
12431243
}
12441244

12451245
PropertySym *
1246-
IRBuilder::BuildFieldSym(Js::RegSlot reg, Js::PropertyId propertyId, Js::PropertyIdIndexType propertyIdIndex, uint inlineCacheIndex, PropertyKind propertyKind)
1246+
IRBuilder::BuildFieldSym(Js::RegSlot reg, Js::PropertyId propertyId, Js::PropertyIdIndexType propertyIdIndex, uint inlineCacheIndex, PropertyKind propertyKind, bool stableSlotSym)
12471247
{
12481248
PropertySym * propertySym;
12491249
SymID symId = this->BuildSrcStackSymID(reg);
12501250

12511251
AssertMsg(m_func->m_symTable->FindStackSym(symId), "Tried to use an undefined stacksym?");
12521252

1253-
propertySym = PropertySym::FindOrCreate(symId, propertyId, propertyIdIndex, inlineCacheIndex, propertyKind, m_func);
1253+
propertySym = PropertySym::FindOrCreate(symId, propertyId, propertyIdIndex, inlineCacheIndex, propertyKind, m_func, stableSlotSym);
12541254

12551255
return propertySym;
12561256
}
@@ -3882,6 +3882,7 @@ IRBuilder::BuildElementSlotI2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
38823882
IR::Instr *instr;
38833883
PropertySym *fieldSym;
38843884
bool isLdSlotThatWasNotProfiled = false;
3885+
bool stableSlots = false;
38853886

38863887
switch (newOpcode)
38873888
{
@@ -3916,13 +3917,18 @@ IRBuilder::BuildElementSlotI2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
39163917
}
39173918

39183919
case Js::OpCode::LdEnvSlot:
3919-
case Js::OpCode::LdEnvObjSlot:
39203920
case Js::OpCode::StEnvSlot:
39213921
case Js::OpCode::StEnvSlotChkUndecl:
3922+
stableSlots = true;
3923+
goto SlotsCommon;
3924+
3925+
case Js::OpCode::LdEnvObjSlot:
39223926
case Js::OpCode::StEnvObjSlot:
39233927
case Js::OpCode::StEnvObjSlotChkUndecl:
3928+
stableSlots = false;
39243929

3925-
fieldOpnd = this->BuildFieldOpnd(Js::OpCode::LdSlotArr, this->GetEnvReg(), slotId1, (Js::PropertyIdIndexType)-1, PropertyKindSlotArray);
3930+
SlotsCommon:
3931+
fieldOpnd = this->BuildFieldOpnd(Js::OpCode::LdSlotArr, this->GetEnvReg(), slotId1, (Js::PropertyIdIndexType)-1, PropertyKindSlotArray, (uint)-1, stableSlots);
39263932
regOpnd = IR::RegOpnd::New(TyVar, m_func);
39273933
instr = IR::Instr::New(Js::OpCode::LdSlotArr, regOpnd, fieldOpnd, m_func);
39283934
this->AddInstr(instr, offset);

lib/Backend/IRBuilder.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,8 @@ class IRBuilder
211211
#if DBG_DUMP || defined(ENABLE_IR_VIEWER)
212212
IR::IndirOpnd * BuildIndirOpnd(IR::RegOpnd *baseReg, uint32 offset, const char16 *desc);
213213
#endif
214-
IR::SymOpnd * BuildFieldOpnd(Js::OpCode newOpCode, Js::RegSlot reg, Js::PropertyId propertyId, Js::PropertyIdIndexType propertyIdIndex, PropertyKind propertyKind, uint inlineCacheIndex = -1);
215-
PropertySym * BuildFieldSym(Js::RegSlot reg, Js::PropertyId propertyId, Js::PropertyIdIndexType propertyIdIndex, uint inlineCacheIndex, PropertyKind propertyKind);
214+
IR::SymOpnd * BuildFieldOpnd(Js::OpCode newOpCode, Js::RegSlot reg, Js::PropertyId propertyId, Js::PropertyIdIndexType propertyIdIndex, PropertyKind propertyKind, uint inlineCacheIndex = -1, bool stableSlotSym = false);
215+
PropertySym * BuildFieldSym(Js::RegSlot reg, Js::PropertyId propertyId, Js::PropertyIdIndexType propertyIdIndex, uint inlineCacheIndex, PropertyKind propertyKind, bool stableSlotSym = false);
216216
SymID BuildSrcStackSymID(Js::RegSlot regSlot);
217217
IR::RegOpnd * BuildDstOpnd(Js::RegSlot dstRegSlot, IRType type = TyVar, bool isCatchObjectSym = false);
218218
IR::RegOpnd * BuildSrcOpnd(Js::RegSlot srcRegSlot, IRType type = TyVar);

lib/Backend/Sym.cpp

+12-5
Original file line numberDiff line numberDiff line change
@@ -949,18 +949,18 @@ StackSym *StackSym::EnsureAuxSlotPtrSym(Func * func)
949949
///----------------------------------------------------------------------------
950950

951951
PropertySym *
952-
PropertySym::New(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func)
952+
PropertySym::New(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func, bool stableSlotSym)
953953
{
954954
StackSym * stackSym;
955955

956956
stackSym = func->m_symTable->FindStackSym(stackSymID);
957957
AssertMsg(stackSym != nullptr, "Adding propertySym to non-existing stackSym... Can this happen??");
958958

959-
return PropertySym::New(stackSym, propertyId, propertyIdIndex, inlineCacheIndex, fieldKind, func);
959+
return PropertySym::New(stackSym, propertyId, propertyIdIndex, inlineCacheIndex, fieldKind, func, stableSlotSym);
960960
}
961961

962962
PropertySym *
963-
PropertySym::New(StackSym *stackSym, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func)
963+
PropertySym::New(StackSym *stackSym, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func, bool stableSlotSym)
964964
{
965965
PropertySym * propertySym;
966966

@@ -989,6 +989,12 @@ PropertySym::New(StackSym *stackSym, int32 propertyId, uint32 propertyIdIndex, u
989989

990990
func->m_symTable->Add(propertySym);
991991

992+
if (stableSlotSym)
993+
{
994+
Assert(fieldKind == PropertyKindSlots || fieldKind == PropertyKindLocalSlots || fieldKind == PropertyKindSlotArray);
995+
func->AddStableSlotSym(propertySym);
996+
}
997+
992998
// Keep track of all the property we use from this sym so we can invalidate
993999
// the value in glob opt
9941000
ObjectSymInfo * objectSymInfo = stackSym->EnsureObjectInfo(func);
@@ -1022,18 +1028,19 @@ PropertySym::Find(SymID stackSymID, int32 propertyId, Func *func)
10221028
///----------------------------------------------------------------------------
10231029

10241030
PropertySym *
1025-
PropertySym::FindOrCreate(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func)
1031+
PropertySym::FindOrCreate(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func, bool stableSlotSym)
10261032
{
10271033
PropertySym * propertySym;
10281034

10291035
propertySym = Find(stackSymID, propertyId, func);
10301036

10311037
if (propertySym)
10321038
{
1039+
Assert(stableSlotSym == func->IsStableSlotSym(propertySym));
10331040
return propertySym;
10341041
}
10351042

1036-
return PropertySym::New(stackSymID, propertyId, propertyIdIndex, inlineCacheIndex, fieldKind, func);
1043+
return PropertySym::New(stackSymID, propertyId, propertyIdIndex, inlineCacheIndex, fieldKind, func, stableSlotSym);
10371044
}
10381045
#if DBG_DUMP || defined(ENABLE_IR_VIEWER)
10391046

lib/Backend/Sym.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -304,10 +304,10 @@ class PropertySym: public Sym
304304
{
305305
friend class Sym;
306306
public:
307-
static PropertySym * New(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func);
308-
static PropertySym * New(StackSym *stackSym, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func);
307+
static PropertySym * New(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func, bool stableSlotSym = false);
308+
static PropertySym * New(StackSym *stackSym, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func, bool stableSlotSym = false);
309309
static PropertySym * Find(SymID stackSymID, int32 propertyId, Func *func);
310-
static PropertySym * FindOrCreate(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func);
310+
static PropertySym * FindOrCreate(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func, bool stableSlotSym = false);
311311

312312
Func *GetFunc() { return m_func; }
313313
bool HasPropertyIdIndex() { return m_propertyIdIndex != -1; }

0 commit comments

Comments
 (0)