Optimize InstanceOfD when rhs is unique interface

We would normally have to load the class and do
a whole bunch of other noise. Now we don't.
Esse commit está contido em:
Eric Caruso
2013-07-08 12:05:39 -07:00
commit de Sara Golemon
commit c3d067f65c
9 arquivos alterados com 45 adições e 26 exclusões
+8 -5
Ver Arquivo
@@ -534,14 +534,17 @@ D:Bool = OpNSame S0:Gen S1:Gen
Perform comparisons with PHP semantics on S0 and S1, and put the
result in D.
D:Bool = InstanceOf S0:Cls S1:Cls S2:ConstBool
D:Bool = InstanceOf S0:Cls S1:Cls
Sets D based on whether S0 is a descendant of the class, interface,
or trait in S1. (Note that this is always false for a trait). S1
may be null at runtime if the class is not defined. The flag S2 is
just a hint that is true if we should assume S1 might be an
interface---the instruction must still handle it correctly if this
hint is wrong at runtime.
may be null at runtime if the class is not defined.
D:Bool = InstanceOfIface S0:Cls S1:Cls
Fast path for interface checks. Sets D based on whether S0 implements
S1, but S1 must be a unique interface. This should only be used in
repo-authoritative mode.
D:Bool = ExtendsClass S0:Cls S1:Cls
+3
Ver Arquivo
@@ -510,6 +510,9 @@ public:
}
return false;
}
bool ifaceofDirect(const StringData* name) const {
return m_interfaces.lookupDefault(name, nullptr) != nullptr;
}
const StringData* name() const {
return m_preClass->name();
}
+3 -15
Ver Arquivo
@@ -465,6 +465,9 @@ CALL_OPCODE(StableMapIsset)
CALL_OPCODE(IssetElem)
CALL_OPCODE(EmptyElem)
CALL_OPCODE(InstanceOf)
CALL_OPCODE(InstanceOfIface)
#undef NOOP_OPCODE
// Thread chain of patch locations using the 4 byte space in each jmp/jcc
@@ -1951,21 +1954,6 @@ void CodeGenerator::cgIsNTypeMem(IRInstruction* inst) {
///////////////////////////////////////////////////////////////////////////////
HOT_FUNC_VM static bool instanceOfHelper(const Class* objClass,
const Class* testClass) {
return testClass && objClass->classof(testClass);
}
void CodeGenerator::cgInstanceOf(IRInstruction* inst) {
cgCallHelper(m_as,
TCA(instanceOfHelper),
inst->dst(),
SyncOptions::kNoSyncPoint,
ArgGroup(m_regs)
.ssa(inst->src(0))
.ssa(inst->src(1)));
}
/*
* Check instanceof using instance bitmasks.
*
+16 -2
Ver Arquivo
@@ -57,6 +57,11 @@ bool classIsUniqueNormalClass(const Class* cls) {
!(cls->attrs() & (AttrInterface | AttrTrait));
}
bool classIsUniqueInterface(const Class* cls) {
return classIsUnique(cls) &&
(cls->attrs() & AttrInterface);
}
}
//////////////////////////////////////////////////////////////////////
@@ -2908,6 +2913,16 @@ void HhbcTranslator::emitInstanceOfD(int classNameStrId) {
const bool isNormalClass = classIsUniqueNormalClass(maybeCls);
const bool isUnique = classIsUnique(maybeCls);
/*
* If the class is a unique interface, we can just hit the class's
* interfaces map and call it a day.
*/
if (!haveBit && classIsUniqueInterface(maybeCls)) {
push(gen(InstanceOfIface, objClass, ssaClassName));
gen(DecRef, src);
return;
}
/*
* If the class is unique or a parent of the current context, we
* don't need to load it out of target cache because it must
@@ -2930,8 +2945,7 @@ void HhbcTranslator::emitInstanceOfD(int classNameStrId) {
checkClass) :
gen(InstanceOf,
objClass,
checkClass,
cns(maybeCls && !isNormalClass))
checkClass)
);
gen(DecRef, src);
}
+2 -1
Ver Arquivo
@@ -255,7 +255,8 @@ O(ConvObjToStr, D(Str), S(Obj), N|Er|CRc|K) \
O(ConvCellToStr, D(Str), S(Cell), N|Er|CRc|K) \
\
O(ExtendsClass, D(Bool), S(Cls) C(Cls), C) \
O(InstanceOf, D(Bool), S(Cls) S(Cls) C(Bool), C|N) \
O(InstanceOf, D(Bool), S(Cls) S(Cls), C|N) \
O(InstanceOfIface, D(Bool), S(Cls) CStr, C|N) \
O(IsTypeMem, D(Bool), S(PtrToGen), NA) \
O(IsNTypeMem, D(Bool), S(PtrToGen), NA) \
/* name dstinfo srcinfo flags */ \
-3
Ver Arquivo
@@ -845,9 +845,6 @@ void LinearScan::computePreColoringHint() {
m_preColoringHint.add(inst->src(0), 0, 1);
}
break;
case InstanceOf:
normalHint(2, 0, 0);
break;
case LdSSwitchDestFast:
normalHint(1, 0, 0);
break;
+5
Ver Arquivo
@@ -258,6 +258,11 @@ static CallMap s_callMap({
{EmptyElem,{FSSA, 0}, DSSA, SSync,
{{SSA, 1}, {VecKeyIS, 2}, {SSA, 3}}},
/* instanceof checks */
{InstanceOf, (TCA)instanceOfHelper, DSSA, SNone, {{SSA, 0}, {SSA, 1}}},
{InstanceOfIface, (TCA)Util::getMethodPtr(&Class::ifaceofDirect), DSSA,
SNone, {{SSA, 0}, {SSA, 1}}},
/* debug assert helpers */
{DbgAssertPtr, (TCA)assertTv, DNone, SNone, {{SSA, 0}}},
});
+6
Ver Arquivo
@@ -326,4 +326,10 @@ RefData* staticLocInitCached(StringData* name, ActRec* fp, TypedValue val,
return staticLocInitImpl<true>(name, fp, val, ch);
}
HOT_FUNC_VM
bool instanceOfHelper(const Class* objClass,
const Class* testClass) {
return testClass && objClass->classof(testClass);
}
} }
+2
Ver Arquivo
@@ -117,6 +117,8 @@ RefData* staticLocInit(StringData* name, ActRec* fp, TypedValue val);
RefData* staticLocInitCached(StringData* name, ActRec* fp, TypedValue val,
TargetCache::CacheHandle ch);
bool instanceOfHelper(const Class* objClass, const Class* testClass);
} }
#endif