Implement IsObject in IR

It turns out is_object actually shouldn't be calling isResource, so this
really wasn't as bad as everyone thought. I cleaned up the simplifier
logic for this instruction (even though is_object is weird, we can still
optimize it away when the src isn't even KindOfObject).

A more elegant solution might be to introduce Type::Resource, but that
would be more complex and I just want to get something working for the
purposes of lockdown.
Esse commit está contido em:
Owen Yamauchi
2013-05-08 15:10:23 -07:00
commit de Sara Golemon
commit c2e56ad8f3
2 arquivos alterados com 46 adições e 16 exclusões
+29 -5
Ver Arquivo
@@ -1596,20 +1596,44 @@ void CodeGenerator::emitSetCc(IRInstruction* inst, ConditionCode cc) {
}
ConditionCode CodeGenerator::emitIsTypeTest(IRInstruction* inst, bool negate) {
if (inst->getTypeParam().subtypeOf(Type::Obj)) {
// Task #2094715: Handle isType tests for Type::Obj, which
// requires checking that checked object is not a resource
CG_PUNT(cgIsTypeObject);
auto const src = inst->getSrc(0);
if (inst->getTypeParam().equals(Type::Obj)) {
auto const srcReg = m_regs[src].getReg();
if (src->isA(Type::PtrToGen)) {
emitTestTVType(m_as, KindOfObject, srcReg[TVOFF(m_type)]);
TCA toPatch = m_as.code.frontier;
m_as. jne8(toPatch); // 1
// Get the ObjectData*
emitDeref(m_as, srcReg, rScratch);
m_as. cmpq(SystemLib::s_resourceClass,
rScratch[ObjectData::getVMClassOffset()]);
// 1:
m_as.patchJcc8(toPatch, m_as.code.frontier);
} else {
// Cases where src isn't an Obj should have been simplified away
if (!src->isA(Type::Obj)) {
CG_PUNT(IsType-KnownWrongType);
}
m_as. cmpq(SystemLib::s_resourceClass,
srcReg[ObjectData::getVMClassOffset()]);
}
// At this point, the flags say "equal" if is_object is false.
return negate ? CC_E : CC_NE;
}
SSATmp* src = inst->getSrc(0);
if (src->isA(Type::PtrToGen)) {
PhysReg base = m_regs[src].getReg();
return emitTypeTest(inst, base[TVOFF(m_type)], negate);
}
assert(src->isA(Type::Gen));
assert(!src->isConst());
PhysReg srcReg = m_regs[src].getReg(1); // type register
if (srcReg == InvalidReg) {
CG_PUNT(IsType-KnownType);
}
return emitTypeTest(inst, srcReg, negate);
}
+17 -11
Ver Arquivo
@@ -1178,20 +1178,26 @@ SSATmp* Simplifier::simplifyIsType(IRInstruction* inst) {
// The comparisons below won't work for these cases covered by this
// assert, and we currently don't generate these types.
assert(type.isKnownUnboxedDataType() && type != Type::StaticStr);
if (type != Type::Obj) {
if (srcType.subtypeOf(type) || (type.isString() && srcType.isString())) {
return cns(trueSense);
}
if (srcType != Type::Cell) {
return cns(!trueSense);
}
// CountedStr and StaticStr are disjoint, but compatible for this purpose.
if (type.isString() && srcType.isString()) {
return cns(trueSense);
}
if (srcType != Type::Obj) {
// Note: for IsObject*, we need to emit a call to ObjectData::isResource
// (or equivalent), so we can't fold away the case where we know we are
// checking an object.
// The types are disjoint; the result must be false.
if ((srcType & type).equals(Type::Bottom)) {
return cns(!trueSense);
}
// The src type is a subtype of the tested type. You'd think the result would
// always be true, but it's not for is_object.
if (!type.subtypeOf(Type::Obj) && srcType.subtypeOf(type)) {
return cns(trueSense);
}
// At this point, either the tested type is a subtype of the src type, or they
// are non-disjoint but neither is a subtype of the other. (Or it's the weird
// Obj case.) We can't simplify this away.
return nullptr;
}