Properly patch exit traces ending with JmpZero and JmpNZero

The hoistConditionalJumps pass was not handling traces ending with
JmpZero and JmpNZero.  This was resulting in spurious jumps to
'astubs' instead of patching the jcc+jump pair in 'a'.
Esse commit está contido em:
ottoni
2013-03-14 05:21:27 -07:00
commit de Sara Golemon
commit ba2cf21ec9
3 arquivos alterados com 50 adições e 27 exclusões
+2 -22
Ver Arquivo
@@ -222,26 +222,6 @@ pathloop:
}
}
ConditionCode cmpOpToCC(Opcode opc) {
switch (opc) {
case OpGt: return CC_G;
case OpGte: return CC_GE;
case OpLt: return CC_L;
case OpLte: return CC_LE;
case OpEq: return CC_E;
case OpNeq: return CC_NE;
case OpSame: return CC_E;
case OpNSame: return CC_NE;
case InstanceOf: return CC_NZ;
case NInstanceOf: return CC_Z;
case InstanceOfBitmask: return CC_NZ;
case NInstanceOfBitmask: return CC_Z;
case IsType: return CC_NZ;
case IsNType: return CC_Z;
default: always_assert(0);
}
}
const char* getContextName(Class* ctx) {
return ctx ? ctx->name()->data() : ":anonymous:";
}
@@ -534,7 +514,7 @@ void CodeGenerator::cgJcc(IRInstruction* inst) {
SSATmp* src1 = inst->getSrc(0);
SSATmp* src2 = inst->getSrc(1);
Opcode opc = inst->getOpcode();
ConditionCode cc = cmpOpToCC(queryJmpToQueryOp(opc));
ConditionCode cc = queryJmpToCC(opc);
Type src1Type = src1->getType();
Type src2Type = src2->getType();
@@ -2253,7 +2233,7 @@ void CodeGenerator::cgExitTrace(IRInstruction* inst) {
// Patch the original jcc;jmp, don't emit another
IRInstruction* jcc = toSmash->getInstruction();
Opcode opc = jcc->getOpcode();
ConditionCode cc = cmpOpToCC(queryJmpToQueryOp(opc));
ConditionCode cc = queryJmpToCC(opc);
uint64_t taken = pc->getValInt();
uint64_t notTaken = notTakenPC->getValInt();
+47 -1
Ver Arquivo
@@ -629,14 +629,60 @@ inline Opcode queryToJmpOp(Opcode opc) {
}
inline bool isQueryJmpOp(Opcode opc) {
return opc >= JmpGt && opc <= JmpIsNType;
switch (opc) {
case JmpGt:
case JmpGte:
case JmpLt:
case JmpLte:
case JmpEq:
case JmpNeq:
case JmpSame:
case JmpNSame:
case JmpInstanceOf:
case JmpNInstanceOf:
case JmpInstanceOfBitmask:
case JmpNInstanceOfBitmask:
case JmpIsType:
case JmpIsNType:
case JmpZero:
case JmpNZero:
return true;
default:
return false;
}
}
inline Opcode queryJmpToQueryOp(Opcode opc) {
assert(isQueryJmpOp(opc));
assert(opc != JmpZero && opc != JmpNZero);
return Opcode(OpGt + (opc - JmpGt));
}
inline ConditionCode queryJmpToCC(Opcode opc) {
assert(isQueryJmpOp(opc));
switch (opc) {
case JmpGt: return CC_G;
case JmpGte: return CC_GE;
case JmpLt: return CC_L;
case JmpLte: return CC_LE;
case JmpEq: return CC_E;
case JmpNeq: return CC_NE;
case JmpSame: return CC_E;
case JmpNSame: return CC_NE;
case JmpInstanceOf: return CC_NZ;
case JmpNInstanceOf: return CC_Z;
case JmpInstanceOfBitmask: return CC_NZ;
case JmpNInstanceOfBitmask: return CC_Z;
case JmpIsType: return CC_NZ;
case JmpIsNType: return CC_Z;
case JmpZero: return CC_Z;
case JmpNZero: return CC_NZ;
default:
not_reached();
}
}
/*
* Right now branch fusion is too indiscriminate to handle fusing
* with potentially expensive-to-repeat operations. TODO(#2053369)
+1 -4
Ver Arquivo
@@ -23,10 +23,7 @@ namespace HPHP { namespace VM { namespace JIT {
// These are the conditional branches supported for direct branch
// to their target trace at TraceExit, TraceExitType::NormalCc
static bool jccCanBeDirectExit(Opcode opc) {
// JmpGt .. JmpNSame are contiguous and all use cgJcc
return (JmpGt <= opc && opc <= JmpNSame) ||
opc == JmpInstanceOf || opc == JmpNInstanceOf ||
opc == JmpInstanceOfBitmask || opc == JmpNInstanceOfBitmask;
return isQueryJmpOp(opc) && (opc != JmpIsType) && (opc != JmpIsNType);
// TODO(#2053369): JmpIsType, etc
}