Skip to content

Commit aeb54d8

Browse files
committed
[MERGE #5019 @pleath] Support polymorphic type checks for equivalent objtypespec
Merge pull request #5019 from pleath:polyequiv For type checks where we have a set of multiple equivalent types, create a property guard that is structured like a polymorphic inline cache, with an underlying array of types indexed by a hash of the type pointer.
2 parents 0f689f7 + 7cb51bf commit aeb54d8

23 files changed

+446
-142
lines changed

lib/Backend/Chakra.Backend.vcxproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,6 @@
475475
<ClInclude Include="NativeCodeGenerator.h" />
476476
<ClInclude Include="Opnd.h" />
477477
<ClInclude Include="Peeps.h" />
478-
<ClInclude Include="PropertyGuard.h" />
479478
<ClInclude Include="QueuedFullJitWorkItem.h" />
480479
<ClInclude Include="Region.h" />
481480
<ClInclude Include="SccLiveness.h" />

lib/Backend/Chakra.Backend.vcxproj.filters

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,6 @@
372372
<ClInclude Include="ValueInfo.h" />
373373
<ClInclude Include="JITThunkEmitter.h" />
374374
<ClInclude Include="IntConstMath.h" />
375-
<ClInclude Include="PropertyGuard.h" />
376375
<ClInclude Include="JavascriptNativeOperators.h" />
377376
<ClInclude Include="EquivalentTypeSet.h" />
378377
<ClInclude Include="arm64\MdOpCodes.h">

lib/Backend/Func.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,6 +1585,26 @@ Func::CreateEquivalentTypeGuard(JITTypeHolder type, uint32 objTypeSpecFldId)
15851585

15861586
Js::JitEquivalentTypeGuard* guard = NativeCodeDataNewNoFixup(GetNativeCodeDataAllocator(), Js::JitEquivalentTypeGuard, type->GetAddr(), this->indexedPropertyGuardCount++, objTypeSpecFldId);
15871587

1588+
this->InitializeEquivalentTypeGuard(guard);
1589+
1590+
return guard;
1591+
}
1592+
1593+
Js::JitPolyEquivalentTypeGuard*
1594+
Func::CreatePolyEquivalentTypeGuard(uint32 objTypeSpecFldId)
1595+
{
1596+
EnsureEquivalentTypeGuards();
1597+
1598+
Js::JitPolyEquivalentTypeGuard* guard = NativeCodeDataNewNoFixup(GetNativeCodeDataAllocator(), Js::JitPolyEquivalentTypeGuard, this->indexedPropertyGuardCount++, objTypeSpecFldId);
1599+
1600+
this->InitializeEquivalentTypeGuard(guard);
1601+
1602+
return guard;
1603+
}
1604+
1605+
void
1606+
Func::InitializeEquivalentTypeGuard(Js::JitEquivalentTypeGuard * guard)
1607+
{
15881608
// If we want to hard code the address of the cache, we will need to go back to allocating it from the native code data allocator.
15891609
// We would then need to maintain consistency (double write) to both the recycler allocated cache and the one on the heap.
15901610
Js::EquivalentTypeCache* cache = nullptr;
@@ -1601,8 +1621,6 @@ Func::CreateEquivalentTypeGuard(JITTypeHolder type, uint32 objTypeSpecFldId)
16011621
// Give the cache a back-pointer to the guard so that the guard can be cleared at runtime if necessary.
16021622
cache->SetGuard(guard);
16031623
this->equivalentTypeGuards->Prepend(guard);
1604-
1605-
return guard;
16061624
}
16071625

16081626
void

lib/Backend/Func.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,8 +449,10 @@ static const unsigned __int64 c_debugFillPattern8 = 0xcececececececece;
449449
void EnsureSingleTypeGuards();
450450
Js::JitTypePropertyGuard* GetOrCreateSingleTypeGuard(intptr_t typeAddr);
451451

452-
void EnsureEquivalentTypeGuards();
452+
void EnsureEquivalentTypeGuards();
453+
void InitializeEquivalentTypeGuard(Js::JitEquivalentTypeGuard * guard);
453454
Js::JitEquivalentTypeGuard * CreateEquivalentTypeGuard(JITTypeHolder type, uint32 objTypeSpecFldId);
455+
Js::JitPolyEquivalentTypeGuard * CreatePolyEquivalentTypeGuard(uint32 objTypeSpecFldId);
454456

455457
void ThrowIfScriptClosed();
456458
void EnsurePropertyGuardsByPropertyId();

lib/Backend/JITTimeConstructorCache.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ JITTimeConstructorCache::JITTimeConstructorCache(const Js::JavascriptFunction* c
2222
m_data.guardedPropOps = 0;
2323
if (runtimeCache->IsNormal())
2424
{
25-
JITType::BuildFromJsType(runtimeCache->content.type, (JITType*)&m_data.type);
25+
JITType::BuildFromJsType(reinterpret_cast<Js::DynamicType*>(runtimeCache->GetValue()), (JITType*)&m_data.type);
2626
}
2727
}
2828

lib/Backend/JavascriptNativeOperators.cpp

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,16 +101,47 @@ namespace Js
101101
return CheckIfTypeIsEquivalent(type, guard);
102102
}
103103

104+
bool JavascriptNativeOperators::CheckIfPolyTypeIsEquivalentForFixedField(Type* type, JitPolyEquivalentTypeGuard* guard, uint8 index)
105+
{
106+
if (guard->GetPolyValue(index) == PropertyGuard::GuardValue::Invalidated_DuringSweep)
107+
{
108+
return false;
109+
}
110+
return CheckIfPolyTypeIsEquivalent(type, guard, index);
111+
}
112+
104113
bool JavascriptNativeOperators::CheckIfTypeIsEquivalent(Type* type, JitEquivalentTypeGuard* guard)
105114
{
106-
if (guard->GetValue() == PropertyGuard::GuardValue::Invalidated)
115+
bool result = EquivalenceCheckHelper(type, guard, guard->GetValue());
116+
if (result)
117+
{
118+
guard->SetTypeAddr((intptr_t)type);
119+
}
120+
return result;
121+
}
122+
123+
bool JavascriptNativeOperators::CheckIfPolyTypeIsEquivalent(Type* type, JitPolyEquivalentTypeGuard* guard, uint8 index)
124+
{
125+
bool result = EquivalenceCheckHelper(type, guard, guard->GetPolyValue(index));
126+
if (result)
127+
{
128+
guard->SetPolyValue((intptr_t)type, index);
129+
}
130+
return result;
131+
}
132+
133+
bool JavascriptNativeOperators::EquivalenceCheckHelper(Type* type, JitEquivalentTypeGuard* guard, intptr_t guardValue)
134+
{
135+
if (guardValue == PropertyGuard::GuardValue::Invalidated)
107136
{
108137
return false;
109138
}
110139

111-
AssertMsg(type && type->GetScriptContext(), "type and it's ScriptContext should be valid.");
140+
AssertMsg(type && type->GetScriptContext(), "type and its ScriptContext should be valid.");
112141

113-
if (!guard->IsInvalidatedDuringSweep() && ((Js::Type*)guard->GetTypeAddr())->GetScriptContext() != type->GetScriptContext())
142+
if (guardValue != PropertyGuard::GuardValue::Invalidated_DuringSweep &&
143+
guardValue != PropertyGuard::GuardValue::Uninitialized &&
144+
((Js::Type*)guardValue)->GetScriptContext() != type->GetScriptContext())
114145
{
115146
// For valid guard value, can't cache cross-context objects
116147
return false;
@@ -158,7 +189,6 @@ namespace Js
158189
}
159190
}
160191
#endif
161-
guard->SetTypeAddr((intptr_t)type);
162192
return true;
163193
}
164194

@@ -326,7 +356,6 @@ namespace Js
326356
}
327357

328358
type->SetHasBeenCached();
329-
guard->SetTypeAddr((intptr_t)type);
330359
return true;
331360
}
332361
#endif

lib/Backend/JavascriptNativeOperators.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ namespace Js
133133
#endif
134134
static bool CheckIfTypeIsEquivalent(Type* type, JitEquivalentTypeGuard* guard);
135135
static bool CheckIfTypeIsEquivalentForFixedField(Type* type, JitEquivalentTypeGuard* guard);
136+
static bool CheckIfPolyTypeIsEquivalent(Type* type, JitPolyEquivalentTypeGuard* guard, uint8 index);
137+
static bool CheckIfPolyTypeIsEquivalentForFixedField(Type* type, JitPolyEquivalentTypeGuard* guard, uint8 index);
138+
static bool EquivalenceCheckHelper(Type* type, JitEquivalentTypeGuard* guard, intptr_t value);
136139

137140
static Var OP_GetElementI_JIT_ExpectingNativeFloatArray(Var instance, Var index, ScriptContext *scriptContext);
138141
static Var OP_GetElementI_JIT_ExpectingVarArray(Var instance, Var index, ScriptContext *scriptContext);

lib/Backend/JnHelperMethodList.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@ HELPERCALL(Op_ScopedGetMethodPolymorphic, ((Js::Var (*)(Js::FunctionBody *const,
252252

253253
HELPERCALL(CheckIfTypeIsEquivalent, Js::JavascriptNativeOperators::CheckIfTypeIsEquivalent, 0)
254254
HELPERCALL(CheckIfTypeIsEquivalentForFixedField, Js::JavascriptNativeOperators::CheckIfTypeIsEquivalentForFixedField, 0)
255+
HELPERCALL(CheckIfPolyTypeIsEquivalent, Js::JavascriptNativeOperators::CheckIfPolyTypeIsEquivalent, 0)
256+
HELPERCALL(CheckIfPolyTypeIsEquivalentForFixedField, Js::JavascriptNativeOperators::CheckIfPolyTypeIsEquivalentForFixedField, 0)
255257

256258
HELPERCALL(Op_Delete, Js::JavascriptOperators::Delete, AttrCanThrow)
257259
HELPERCALL(OP_InitSetter, Js::JavascriptOperators::OP_InitSetter, AttrCanThrow)

0 commit comments

Comments
 (0)