convert enums to enum classes, part 1
C++11 cleanup (clean up easy enums) Since sandcastle is failing:
Esse commit está contido em:
@@ -1614,7 +1614,7 @@ resume:
|
||||
return;
|
||||
|
||||
} catch (...) {
|
||||
always_assert(Transl::tl_regState == Transl::REGSTATE_CLEAN);
|
||||
always_assert(Transl::tl_regState == Transl::VMRegState::CLEAN);
|
||||
auto const action = exception_handler();
|
||||
if (action == UnwindAction::ResumeVM) {
|
||||
goto resume;
|
||||
@@ -7048,7 +7048,7 @@ VMExecutionContext::prettyStack(const string& prefix) const {
|
||||
}
|
||||
|
||||
void VMExecutionContext::checkRegStateWork() const {
|
||||
assert(Transl::tl_regState == Transl::REGSTATE_CLEAN);
|
||||
assert(Transl::tl_regState == Transl::VMRegState::CLEAN);
|
||||
}
|
||||
|
||||
void VMExecutionContext::DumpStack() {
|
||||
|
||||
@@ -28,7 +28,7 @@ TRACE_SET_MOD(trans);
|
||||
* A mapping from FCall instructions to the statically-known StringData*
|
||||
* that they're calling. Used to accelerate our FCall translations.
|
||||
*/
|
||||
enum CallRecordType {
|
||||
enum class CallRecordType {
|
||||
EncodedNameAndArgs,
|
||||
Function
|
||||
};
|
||||
@@ -67,7 +67,7 @@ static void recordNameAndArgs(const SrcKey& sk,
|
||||
const StringData* name,
|
||||
int numArgs) {
|
||||
CallRecord cr;
|
||||
cr.m_type = EncodedNameAndArgs;
|
||||
cr.m_type = CallRecordType::EncodedNameAndArgs;
|
||||
cr.m_encodedName = encodeCallAndArgs(name, numArgs);
|
||||
s_callDB.insert(std::make_pair(sk, cr));
|
||||
}
|
||||
@@ -81,7 +81,7 @@ static void recordFunc(NormalizedInstruction& i,
|
||||
func->fullName()->data());
|
||||
|
||||
CallRecord cr;
|
||||
cr.m_type = Function;
|
||||
cr.m_type = CallRecordType::Function;
|
||||
cr.m_func = func;
|
||||
s_callDB.insert(std::make_pair(sk, cr));
|
||||
}
|
||||
@@ -184,10 +184,10 @@ void annotate(NormalizedInstruction* i) {
|
||||
case OpFCallArray: {
|
||||
CallRecord callRec;
|
||||
if (mapGet(s_callDB, i->source, &callRec)) {
|
||||
if (callRec.m_type == Function) {
|
||||
if (callRec.m_type == CallRecordType::Function) {
|
||||
i->funcd = callRec.m_func;
|
||||
} else {
|
||||
assert(callRec.m_type == EncodedNameAndArgs);
|
||||
assert(callRec.m_type == CallRecordType::EncodedNameAndArgs);
|
||||
i->funcName = callRec.m_encodedName;
|
||||
}
|
||||
} else {
|
||||
@@ -202,7 +202,7 @@ const StringData*
|
||||
fcallToFuncName(const NormalizedInstruction* i) {
|
||||
CallRecord callRec;
|
||||
if (mapGet(s_callDB, i->source, &callRec)) {
|
||||
if (callRec.m_type == Function) {
|
||||
if (callRec.m_type == CallRecordType::Function) {
|
||||
return callRec.m_func->name();
|
||||
}
|
||||
string name;
|
||||
|
||||
@@ -39,14 +39,14 @@ struct Block : boost::noncopyable {
|
||||
typedef InstructionList::const_iterator const_iterator;
|
||||
|
||||
// Execution frequency hint; codegen will put Unlikely blocks in astubs.
|
||||
enum Hint { Neither, Likely, Unlikely };
|
||||
enum class Hint { Neither, Likely, Unlikely };
|
||||
|
||||
Block(unsigned id, const Func* func)
|
||||
: m_trace(nullptr)
|
||||
, m_func(func)
|
||||
, m_next(this, nullptr)
|
||||
, m_id(id)
|
||||
, m_hint(Neither)
|
||||
, m_hint(Hint::Neither)
|
||||
{}
|
||||
|
||||
const IRInstruction* beginCatch() const {
|
||||
|
||||
@@ -103,7 +103,7 @@ struct CycleInfo {
|
||||
};
|
||||
|
||||
struct MoveInfo {
|
||||
enum Kind { Move, Xchg };
|
||||
enum class Kind { Move, Xchg };
|
||||
|
||||
MoveInfo(Kind kind, int reg1, int reg2):
|
||||
m_kind(kind), m_reg1(reg1), m_reg2(reg2) {}
|
||||
@@ -188,7 +188,7 @@ pathloop:
|
||||
int node = q[i];
|
||||
if (moves[node] >= 0) {
|
||||
int nextNode = moves[node];
|
||||
howTo.push_back(MoveInfo(MoveInfo::Move, nextNode, node));
|
||||
howTo.push_back(MoveInfo(MoveInfo::Kind::Move, nextNode, node));
|
||||
--outDegree[nextNode];
|
||||
if (outDegree[nextNode] == 0) {
|
||||
q[qBack] = nextNode;
|
||||
@@ -204,24 +204,24 @@ pathloop:
|
||||
if (cycles[i].length == 2 && !hasXMMReg) {
|
||||
int v = cycles[i].node;
|
||||
int w = moves[v];
|
||||
howTo.push_back(MoveInfo(MoveInfo::Xchg, w, v));
|
||||
howTo.push_back(MoveInfo(MoveInfo::Kind::Xchg, w, v));
|
||||
} else if (cycles[i].length == 3 && !hasXMMReg) {
|
||||
int v = cycles[i].node;
|
||||
int w = moves[v];
|
||||
howTo.push_back(MoveInfo(MoveInfo::Xchg, w, v));
|
||||
howTo.push_back(MoveInfo(MoveInfo::Kind::Xchg, w, v));
|
||||
int x = moves[w];
|
||||
howTo.push_back(MoveInfo(MoveInfo::Xchg, x, w));
|
||||
howTo.push_back(MoveInfo(MoveInfo::Kind::Xchg, x, w));
|
||||
} else {
|
||||
int v = cycles[i].node;
|
||||
howTo.push_back(MoveInfo(MoveInfo::Move, v, rTmp));
|
||||
howTo.push_back(MoveInfo(MoveInfo::Kind::Move, v, rTmp));
|
||||
int w = v;
|
||||
int x = moves[w];
|
||||
while (x != v) {
|
||||
howTo.push_back(MoveInfo(MoveInfo::Move, x, w));
|
||||
howTo.push_back(MoveInfo(MoveInfo::Kind::Move, x, w));
|
||||
w = x;
|
||||
x = moves[w];
|
||||
}
|
||||
howTo.push_back(MoveInfo(MoveInfo::Move, rTmp, w));
|
||||
howTo.push_back(MoveInfo(MoveInfo::Kind::Move, rTmp, w));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -238,7 +238,7 @@ ArgDesc::ArgDesc(SSATmp* tmp, const RegisterInfo& info, bool val)
|
||||
: m_imm(-1), m_zeroExtend(false), m_done(false) {
|
||||
if (tmp->type() == Type::None) {
|
||||
assert(val);
|
||||
m_kind = None;
|
||||
m_kind = Kind::None;
|
||||
return;
|
||||
}
|
||||
if (tmp->inst()->op() == DefConst) {
|
||||
@@ -248,7 +248,7 @@ ArgDesc::ArgDesc(SSATmp* tmp, const RegisterInfo& info, bool val)
|
||||
} else {
|
||||
m_imm = toDataTypeForCall(tmp->type());
|
||||
}
|
||||
m_kind = Imm;
|
||||
m_kind = Kind::Imm;
|
||||
return;
|
||||
}
|
||||
if (tmp->type().isNull()) {
|
||||
@@ -258,7 +258,7 @@ ArgDesc::ArgDesc(SSATmp* tmp, const RegisterInfo& info, bool val)
|
||||
} else {
|
||||
m_imm = toDataTypeForCall(tmp->type());
|
||||
}
|
||||
m_kind = Imm;
|
||||
m_kind = Kind::Imm;
|
||||
return;
|
||||
}
|
||||
if (val || tmp->numNeededRegs() > 1) {
|
||||
@@ -269,7 +269,7 @@ ArgDesc::ArgDesc(SSATmp* tmp, const RegisterInfo& info, bool val)
|
||||
// If val is false then we're passing tmp's type. TypeReg lets
|
||||
// CodeGenerator know that the value might require some massaging
|
||||
// to be in the right format for the call.
|
||||
m_kind = val ? Reg : TypeReg;
|
||||
m_kind = val ? Kind::Reg : Kind::TypeReg;
|
||||
// zero extend any boolean value that we pass to the helper in case
|
||||
// the helper expects it (e.g., as TypedValue)
|
||||
if (val && tmp->isA(Type::Bool)) m_zeroExtend = true;
|
||||
@@ -278,7 +278,7 @@ ArgDesc::ArgDesc(SSATmp* tmp, const RegisterInfo& info, bool val)
|
||||
}
|
||||
m_srcReg = InvalidReg;
|
||||
m_imm = toDataTypeForCall(tmp->type());
|
||||
m_kind = Imm;
|
||||
m_kind = Kind::Imm;
|
||||
}
|
||||
|
||||
const Func* CodeGenerator::curFunc() const {
|
||||
@@ -774,7 +774,7 @@ void CodeGenerator::emitReqBindJcc(ConditionCode cc,
|
||||
assert(&m_as != &m_astubs &&
|
||||
"ReqBindJcc only makes sense outside of astubs");
|
||||
|
||||
prepareForTestAndSmash(a, 0, kAlignJccAndJmp);
|
||||
prepareForTestAndSmash(a, 0, TestAndSmashFlags::kAlignJccAndJmp);
|
||||
auto const patchAddr = a.code.frontier;
|
||||
|
||||
auto const jccStub = m_astubs.code.frontier;
|
||||
@@ -901,9 +901,9 @@ static int64_t shuffleArgs(Asm& a, ArgGroup& args) {
|
||||
memset(argDescs, 0, sizeof argDescs);
|
||||
for (size_t i = 0; i < args.numRegArgs(); ++i) {
|
||||
auto kind = args[i].kind();
|
||||
if (!(kind == ArgDesc::Reg ||
|
||||
kind == ArgDesc::Addr ||
|
||||
kind == ArgDesc::TypeReg)) {
|
||||
if (!(kind == ArgDesc::Kind::Reg ||
|
||||
kind == ArgDesc::Kind::Addr ||
|
||||
kind == ArgDesc::Kind::TypeReg)) {
|
||||
continue;
|
||||
}
|
||||
auto dstReg = args[i].dstReg();
|
||||
@@ -918,13 +918,13 @@ static int64_t shuffleArgs(Asm& a, ArgGroup& args) {
|
||||
|
||||
// Execute the plan
|
||||
for (size_t i = 0; i < howTo.size(); ++i) {
|
||||
if (howTo[i].m_kind == MoveInfo::Move) {
|
||||
if (howTo[i].m_kind == MoveInfo::Kind::Move) {
|
||||
if (howTo[i].m_reg2 == rCgGP) {
|
||||
emitMovRegReg(a, howTo[i].m_reg1, howTo[i].m_reg2);
|
||||
} else {
|
||||
ArgDesc* argDesc = argDescs[int(howTo[i].m_reg2)];
|
||||
ArgDesc::Kind kind = argDesc->kind();
|
||||
if (kind == ArgDesc::Reg || kind == ArgDesc::TypeReg) {
|
||||
if (kind == ArgDesc::Kind::Reg || kind == ArgDesc::Kind::TypeReg) {
|
||||
if (argDesc->isZeroExtend()) {
|
||||
assert(howTo[i].m_reg1.isGP());
|
||||
assert(howTo[i].m_reg2.isGP());
|
||||
@@ -933,13 +933,13 @@ static int64_t shuffleArgs(Asm& a, ArgGroup& args) {
|
||||
emitMovRegReg(a, howTo[i].m_reg1, howTo[i].m_reg2);
|
||||
}
|
||||
} else {
|
||||
assert(kind == ArgDesc::Addr);
|
||||
assert(kind == ArgDesc::Kind::Addr);
|
||||
assert(howTo[i].m_reg1.isGP());
|
||||
assert(howTo[i].m_reg2.isGP());
|
||||
a. lea (howTo[i].m_reg1[argDesc->imm().q()],
|
||||
howTo[i].m_reg2);
|
||||
}
|
||||
if (kind != ArgDesc::TypeReg) {
|
||||
if (kind != ArgDesc::Kind::TypeReg) {
|
||||
argDesc->markDone();
|
||||
}
|
||||
}
|
||||
@@ -958,16 +958,16 @@ static int64_t shuffleArgs(Asm& a, ArgGroup& args) {
|
||||
ArgDesc::Kind kind = args[i].kind();
|
||||
PhysReg dst = args[i].dstReg();
|
||||
assert(dst.isGP());
|
||||
if (kind == ArgDesc::Imm) {
|
||||
if (kind == ArgDesc::Kind::Imm) {
|
||||
a.emitImmReg(args[i].imm().q(), dst);
|
||||
} else if (kind == ArgDesc::TypeReg) {
|
||||
} else if (kind == ArgDesc::Kind::TypeReg) {
|
||||
a. shlq (kTypeShiftBits, dst);
|
||||
} else if (kind == ArgDesc::Addr) {
|
||||
} else if (kind == ArgDesc::Kind::Addr) {
|
||||
a. addq (args[i].imm(), dst);
|
||||
} else if (args[i].isZeroExtend()) {
|
||||
a. movzbl (rbyte(dst), r32(dst));
|
||||
} else if (RuntimeOption::EvalHHIRGenerateAsserts &&
|
||||
kind == ArgDesc::None) {
|
||||
kind == ArgDesc::Kind::None) {
|
||||
a.emitImmReg(0xbadbadbadbadbad, dst);
|
||||
}
|
||||
}
|
||||
@@ -979,7 +979,7 @@ static int64_t shuffleArgs(Asm& a, ArgGroup& args) {
|
||||
auto srcReg = arg.srcReg();
|
||||
assert(arg.dstReg() == InvalidReg);
|
||||
switch (arg.kind()) {
|
||||
case ArgDesc::Reg:
|
||||
case ArgDesc::Kind::Reg:
|
||||
if (arg.isZeroExtend()) {
|
||||
a. movzbl(rbyte(srcReg), r32(rCgGP));
|
||||
a. push(rCgGP);
|
||||
@@ -993,7 +993,7 @@ static int64_t shuffleArgs(Asm& a, ArgGroup& args) {
|
||||
}
|
||||
break;
|
||||
|
||||
case ArgDesc::TypeReg:
|
||||
case ArgDesc::Kind::TypeReg:
|
||||
static_assert(kTypeWordOffset == 4 || kTypeWordOffset == 1,
|
||||
"kTypeWordOffset value not supported");
|
||||
assert(srcReg.isGP());
|
||||
@@ -1012,15 +1012,15 @@ static int64_t shuffleArgs(Asm& a, ArgGroup& args) {
|
||||
}
|
||||
break;
|
||||
|
||||
case ArgDesc::Imm:
|
||||
case ArgDesc::Kind::Imm:
|
||||
a. emitImmReg(arg.imm(), rCgGP);
|
||||
a. push(rCgGP);
|
||||
break;
|
||||
|
||||
case ArgDesc::Addr:
|
||||
case ArgDesc::Kind::Addr:
|
||||
not_implemented();
|
||||
|
||||
case ArgDesc::None:
|
||||
case ArgDesc::Kind::None:
|
||||
a. push(rax);
|
||||
if (RuntimeOption::EvalHHIRGenerateAsserts) {
|
||||
a. storeq(0xbadbadbadbadbad, *rsp);
|
||||
@@ -1146,7 +1146,7 @@ void CodeGenerator::cgCallHelper(Asm& a,
|
||||
|
||||
// do the call; may use a trampoline
|
||||
m_tx64->emitCall(a, call);
|
||||
if (sync != kNoSyncPoint) {
|
||||
if (sync != SyncOptions::kNoSyncPoint) {
|
||||
recordSyncPoint(a, sync);
|
||||
}
|
||||
|
||||
@@ -1598,7 +1598,7 @@ void CodeGenerator::cgOpCmpHelper(
|
||||
if (type1.isString() && type2.isString()) {
|
||||
ArgGroup args(m_regs);
|
||||
args.ssa(src1).ssa(src2);
|
||||
cgCallHelper(m_as, (TCA)str_cmp_str, dst, kSyncPoint, args);
|
||||
cgCallHelper(m_as, (TCA)str_cmp_str, dst, SyncOptions::kSyncPoint, args);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1649,11 +1649,13 @@ void CodeGenerator::cgOpCmpHelper(
|
||||
if (type2 == Type::Int) {
|
||||
ArgGroup args(m_regs);
|
||||
args.ssa(src1).ssa(src2);
|
||||
cgCallHelper(m_as, (TCA)str_cmp_int, dst, kSyncPoint, args);
|
||||
cgCallHelper(m_as, (TCA)str_cmp_int, dst,
|
||||
SyncOptions::kSyncPoint, args);
|
||||
} else if (type2 == Type::Obj) {
|
||||
ArgGroup args(m_regs);
|
||||
args.ssa(src1).ssa(src2);
|
||||
cgCallHelper(m_as, (TCA)str_cmp_obj, dst, kSyncPoint, args);
|
||||
cgCallHelper(m_as, (TCA)str_cmp_obj, dst,
|
||||
SyncOptions::kSyncPoint, args);
|
||||
} else {
|
||||
CG_PUNT(cgOpCmpHelper_sx);
|
||||
}
|
||||
@@ -1666,11 +1668,13 @@ void CodeGenerator::cgOpCmpHelper(
|
||||
if (type2 == Type::Obj) {
|
||||
ArgGroup args(m_regs);
|
||||
args.ssa(src1).ssa(src2);
|
||||
cgCallHelper(m_as, (TCA)obj_cmp_obj, dst, kSyncPoint, args);
|
||||
cgCallHelper(m_as, (TCA)obj_cmp_obj, dst,
|
||||
SyncOptions::kSyncPoint, args);
|
||||
} else if (type2 == Type::Int) {
|
||||
ArgGroup args(m_regs);
|
||||
args.ssa(src1).ssa(src2);
|
||||
cgCallHelper(m_as, (TCA)obj_cmp_int, dst, kSyncPoint, args);
|
||||
cgCallHelper(m_as, (TCA)obj_cmp_int, dst,
|
||||
SyncOptions::kSyncPoint, args);
|
||||
} else {
|
||||
CG_PUNT(cgOpCmpHelper_ox);
|
||||
}
|
||||
@@ -1684,7 +1688,7 @@ void CodeGenerator::cgOpCmpHelper(
|
||||
else if (type1.isArray() && type2.isArray()) {
|
||||
ArgGroup args(m_regs);
|
||||
args.ssa(src1).ssa(src2);
|
||||
cgCallHelper(m_as, (TCA)arr_cmp_arr, dst, kSyncPoint, args);
|
||||
cgCallHelper(m_as, (TCA)arr_cmp_arr, dst, SyncOptions::kSyncPoint, args);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1930,7 +1934,7 @@ void CodeGenerator::cgInstanceOf(IRInstruction* inst) {
|
||||
cgCallHelper(m_as,
|
||||
TCA(instanceOfHelper),
|
||||
inst->dst(),
|
||||
kNoSyncPoint,
|
||||
SyncOptions::kNoSyncPoint,
|
||||
ArgGroup(m_regs)
|
||||
.ssa(inst->src(0))
|
||||
.ssa(inst->src(1)));
|
||||
@@ -2243,7 +2247,8 @@ void CodeGenerator::cgLdFunc(IRInstruction* inst) {
|
||||
|
||||
TargetCache::CacheHandle ch = TargetCache::FuncCache::alloc();
|
||||
// raises an error if function not found
|
||||
cgCallHelper(m_as, (TCA)FuncCache::lookup, m_regs[dst].reg(), kSyncPoint,
|
||||
cgCallHelper(m_as, (TCA)FuncCache::lookup, m_regs[dst].reg(),
|
||||
SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).imm(ch).ssa(methodName));
|
||||
}
|
||||
|
||||
@@ -2287,7 +2292,7 @@ void CodeGenerator::cgLdObjMethod(IRInstruction *inst) {
|
||||
},
|
||||
[&] { // else call slow path helper
|
||||
cgCallHelper(m_as, (TCA)methodCacheSlowPath, InvalidReg,
|
||||
kSyncPoint,
|
||||
SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).addr(rVmTl, handle)
|
||||
.ssa(actRec)
|
||||
.ssa(name)
|
||||
@@ -2451,7 +2456,7 @@ void CodeGenerator::cgLdSSwitchDestFast(IRInstruction* inst) {
|
||||
cgCallHelper(m_as,
|
||||
TCA(sswitchHelperFast),
|
||||
inst->dst(),
|
||||
kNoSyncPoint,
|
||||
SyncOptions::kNoSyncPoint,
|
||||
ArgGroup(m_regs)
|
||||
.ssa(inst->src(0))
|
||||
.immPtr(table)
|
||||
@@ -2484,7 +2489,7 @@ void CodeGenerator::cgLdSSwitchDestSlow(IRInstruction* inst) {
|
||||
cgCallHelper(m_as,
|
||||
TCA(sswitchHelperSlow),
|
||||
inst->dst(),
|
||||
kSyncPoint,
|
||||
SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs)
|
||||
.typedValue(inst->src(0))
|
||||
.immPtr(strtab)
|
||||
@@ -3046,7 +3051,7 @@ void CodeGenerator::cgDecRefStaticType(Type type,
|
||||
unlikelyIfBlock(CC_Z, [&] (Asm& a) {
|
||||
// Emit the call to release in m_astubs
|
||||
cgCallHelper(a, m_tx64->getDtorCall(type.toDataType()),
|
||||
InvalidReg, InvalidReg, kSyncPoint,
|
||||
InvalidReg, InvalidReg, SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).reg(dataReg));
|
||||
});
|
||||
}
|
||||
@@ -3079,7 +3084,7 @@ void CodeGenerator::cgDecRefDynamicType(PhysReg typeReg,
|
||||
// Emit jump to m_astubs (to call release) if count got down to zero
|
||||
unlikelyIfBlock(CC_Z, [&] (Asm& a) {
|
||||
// Emit call to release in m_astubs
|
||||
cgCallHelper(a, getDtorTyped(), InvalidReg, kSyncPoint,
|
||||
cgCallHelper(a, getDtorTyped(), InvalidReg, SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).reg(dataReg).reg(typeReg));
|
||||
});
|
||||
}
|
||||
@@ -3150,7 +3155,7 @@ void CodeGenerator::cgDecRefDynamicTypeMem(PhysReg baseReg,
|
||||
unlikelyIfBlock(CC_Z, [&] (Asm& a) {
|
||||
// Emit call to release in m_astubs
|
||||
a.lea(baseReg[offset], scratchReg);
|
||||
cgCallHelper(a, getDtorGeneric(), InvalidReg, kSyncPoint,
|
||||
cgCallHelper(a, getDtorGeneric(), InvalidReg, SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).reg(scratchReg));
|
||||
});
|
||||
}
|
||||
@@ -3394,7 +3399,7 @@ void CodeGenerator::cgAllocObjFast(IRInstruction* inst) {
|
||||
cgCallHelper(a,
|
||||
(TCA)getMethodPtr(&Class::initProps),
|
||||
InvalidReg,
|
||||
kSyncPoint,
|
||||
SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).imm((uint64_t)cls));
|
||||
});
|
||||
}
|
||||
@@ -3405,7 +3410,7 @@ void CodeGenerator::cgAllocObjFast(IRInstruction* inst) {
|
||||
cgCallHelper(a,
|
||||
(TCA)getMethodPtr(&Class::initSProps),
|
||||
InvalidReg,
|
||||
kSyncPoint,
|
||||
SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).imm((uint64_t)cls));
|
||||
});
|
||||
}
|
||||
@@ -3416,7 +3421,7 @@ void CodeGenerator::cgAllocObjFast(IRInstruction* inst) {
|
||||
cgCallHelper(m_as,
|
||||
(TCA)cls->instanceCtor(),
|
||||
dstReg,
|
||||
kSyncPoint,
|
||||
SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).imm((uint64_t)cls));
|
||||
} else {
|
||||
size_t size = Instance::sizeForNProps(cls->numDeclProperties());
|
||||
@@ -3425,7 +3430,7 @@ void CodeGenerator::cgAllocObjFast(IRInstruction* inst) {
|
||||
cgCallHelper(m_as,
|
||||
(TCA)getMethodPtr(&Instance::newInstanceRaw),
|
||||
dstReg,
|
||||
kSyncPoint,
|
||||
SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).imm((uint64_t)cls).imm(allocator));
|
||||
}
|
||||
|
||||
@@ -3451,7 +3456,7 @@ void CodeGenerator::cgAllocObjFast(IRInstruction* inst) {
|
||||
cgCallHelper(m_as,
|
||||
(TCA)memcpy,
|
||||
InvalidReg,
|
||||
kNoSyncPoint,
|
||||
SyncOptions::kNoSyncPoint,
|
||||
args);
|
||||
} else {
|
||||
// Slower case: we have to load the src address from the targetcache
|
||||
@@ -3468,7 +3473,7 @@ void CodeGenerator::cgAllocObjFast(IRInstruction* inst) {
|
||||
cgCallHelper(m_as,
|
||||
(TCA)memcpy,
|
||||
InvalidReg,
|
||||
kNoSyncPoint,
|
||||
SyncOptions::kNoSyncPoint,
|
||||
args);
|
||||
} else {
|
||||
ArgGroup args = ArgGroup(m_regs)
|
||||
@@ -3478,7 +3483,7 @@ void CodeGenerator::cgAllocObjFast(IRInstruction* inst) {
|
||||
cgCallHelper(m_as,
|
||||
(TCA)deepInitHelper,
|
||||
InvalidReg,
|
||||
kNoSyncPoint,
|
||||
SyncOptions::kNoSyncPoint,
|
||||
args);
|
||||
}
|
||||
}
|
||||
@@ -3490,7 +3495,7 @@ void CodeGenerator::cgAllocObjFast(IRInstruction* inst) {
|
||||
cgCallHelper(m_as,
|
||||
(TCA)getMethodPtr(&Instance::callCustomInstanceInit),
|
||||
dstReg,
|
||||
kSyncPoint,
|
||||
SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).reg(dstReg));
|
||||
}
|
||||
}
|
||||
@@ -3504,7 +3509,7 @@ void CodeGenerator::cgCallArray(IRInstruction* inst) {
|
||||
|
||||
// fCallArrayHelper makes the actual call by smashing its return address.
|
||||
cgCallHelper(m_as, (TCA)TranslatorX64::fCallArrayHelper,
|
||||
nullptr, kSyncPoint, args);
|
||||
nullptr, SyncOptions::kSyncPoint, args);
|
||||
}
|
||||
|
||||
void CodeGenerator::cgCall(IRInstruction* inst) {
|
||||
@@ -3570,7 +3575,7 @@ void CodeGenerator::cgCastStk(IRInstruction *inst) {
|
||||
not_reached();
|
||||
}
|
||||
cgCallHelper(m_as, tvCastHelper, nullptr,
|
||||
kSyncPoint, args, DestType::None);
|
||||
SyncOptions::kSyncPoint, args, DestType::None);
|
||||
}
|
||||
|
||||
void CodeGenerator::cgCoerceStk(IRInstruction *inst) {
|
||||
@@ -3662,7 +3667,7 @@ void CodeGenerator::cgCallBuiltin(IRInstruction* inst) {
|
||||
// return value from this call since we know where the value is.
|
||||
cgCallHelper(m_as, Transl::CppCall((TCA)func->nativeFuncPtr()),
|
||||
isCppByRef(funcReturnType) ? InvalidReg : dstReg,
|
||||
kSyncPoint, callArgs);
|
||||
SyncOptions::kSyncPoint, callArgs);
|
||||
|
||||
// load return value from builtin
|
||||
// for primitive return types (int, bool), the return value
|
||||
@@ -4095,12 +4100,12 @@ void CodeGenerator::recordSyncPoint(Asm& as,
|
||||
|
||||
Offset stackOff = m_state.lastMarker->stackOff;
|
||||
switch (sync) {
|
||||
case kSyncPointAdjustOne:
|
||||
case SyncOptions::kSyncPointAdjustOne:
|
||||
stackOff -= 1;
|
||||
break;
|
||||
case kSyncPoint:
|
||||
case SyncOptions::kSyncPoint:
|
||||
break;
|
||||
case kNoSyncPoint:
|
||||
case SyncOptions::kNoSyncPoint:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
@@ -4454,7 +4459,7 @@ void CodeGenerator::cgLdClsMethodCache(IRInstruction* inst) {
|
||||
cgCallHelper(a,
|
||||
(TCA)StaticMethodCache::lookupIR,
|
||||
funcDestReg,
|
||||
kSyncPoint,
|
||||
SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).imm(ch) // Handle ch
|
||||
.immPtr(ne) // NamedEntity* np.second
|
||||
.immPtr(cls) // className
|
||||
@@ -4568,7 +4573,7 @@ void CodeGenerator::cgLdClsMethodFCache(IRInstruction* inst) {
|
||||
RegSet toSave = m_state.liveRegs[inst] | RegSet(destCtxReg);
|
||||
cgCallHelper(a, Transl::CppCall((TCA)lookup),
|
||||
funcDestReg, InvalidReg,
|
||||
kSyncPoint,
|
||||
SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).imm(ch)
|
||||
.immPtr(cls)
|
||||
.immPtr(methName)
|
||||
@@ -4637,7 +4642,7 @@ void CodeGenerator::cgLdClsPropAddrCached(IRInstruction* inst) {
|
||||
target ? (TCA)SPropCache::lookupIR<false>
|
||||
: (TCA)SPropCache::lookupIR<true>, // raise on error
|
||||
tmpReg,
|
||||
kSyncPoint, // could re-enter to initialize properties
|
||||
SyncOptions::kSyncPoint, // could re-enter to init properties
|
||||
ArgGroup(m_regs).imm(ch).ssa(cls).ssa(propName).ssa(cxt));
|
||||
if (target) {
|
||||
a.testq(tmpReg, tmpReg);
|
||||
@@ -4669,7 +4674,7 @@ void CodeGenerator::cgLdClsPropAddr(IRInstruction* inst) {
|
||||
target ? (TCA)SPropCache::lookupSProp<false>
|
||||
: (TCA)SPropCache::lookupSProp<true>, // raise on error
|
||||
dstReg,
|
||||
kSyncPoint, // could re-enter to initialize properties
|
||||
SyncOptions::kSyncPoint, // could re-enter to init properties
|
||||
ArgGroup(m_regs).ssa(cls).ssa(prop).ssa(ctx));
|
||||
if (target) {
|
||||
m_as.testq(dstReg, dstReg);
|
||||
@@ -4701,7 +4706,7 @@ void CodeGenerator::cgLdClsCached(IRInstruction* inst) {
|
||||
cgCallHelper(a,
|
||||
(TCA)TargetCache::lookupKnownClass<false>,
|
||||
inst->dst(),
|
||||
kSyncPoint,
|
||||
SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).addr(rVmTl, intptr_t(ch)).ssas(inst, 0));
|
||||
});
|
||||
}
|
||||
@@ -4718,7 +4723,7 @@ void CodeGenerator::cgLdCls(IRInstruction* inst) {
|
||||
SSATmp* className = inst->src(0);
|
||||
|
||||
CacheHandle ch = ClassCache::alloc();
|
||||
cgCallHelper(m_as, (TCA)ClassCache::lookup, dst, kSyncPoint,
|
||||
cgCallHelper(m_as, (TCA)ClassCache::lookup, dst, SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).imm(ch).ssa(className));
|
||||
}
|
||||
|
||||
@@ -4744,7 +4749,7 @@ void CodeGenerator::cgLookupClsCns(IRInstruction* inst) {
|
||||
m_as,
|
||||
TCA(TargetCache::lookupClassConstantTv),
|
||||
inst->dst(),
|
||||
kSyncPoint,
|
||||
SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs)
|
||||
.addr(rVmTl, ch)
|
||||
.immPtr(Unit::GetNamedEntity(extra->clsName))
|
||||
@@ -4804,7 +4809,7 @@ void CodeGenerator::cgLookupCns(IRInstruction* inst) {
|
||||
.immPtr(cnsName);
|
||||
|
||||
cgCallHelper(m_as, TCA(lookupCnsHelper),
|
||||
inst->dst(), kSyncPoint, args, DestType::TV);
|
||||
inst->dst(), SyncOptions::kSyncPoint, args, DestType::TV);
|
||||
}
|
||||
|
||||
HOT_FUNC_VM
|
||||
@@ -4857,7 +4862,7 @@ void CodeGenerator::cgAKExists(IRInstruction* inst) {
|
||||
cgCallHelper(m_as,
|
||||
(TCA)ak_exist_string,
|
||||
inst->dst(),
|
||||
kNoSyncPoint,
|
||||
SyncOptions::kNoSyncPoint,
|
||||
ArgGroup(m_regs).immPtr(empty_string.get()).ssa(arr));
|
||||
} else {
|
||||
m_as.mov_imm64_reg(0, m_regs[inst->dst()].reg());
|
||||
@@ -4873,7 +4878,7 @@ void CodeGenerator::cgAKExists(IRInstruction* inst) {
|
||||
cgCallHelper(m_as,
|
||||
helper_func,
|
||||
inst->dst(),
|
||||
kNoSyncPoint,
|
||||
SyncOptions::kNoSyncPoint,
|
||||
ArgGroup(m_regs).ssa(key).ssa(arr));
|
||||
}
|
||||
|
||||
@@ -4889,14 +4894,16 @@ HOT_FUNC_VM static TypedValue* ldGblAddrDefHelper(StringData* name) {
|
||||
|
||||
void CodeGenerator::cgLdGblAddr(IRInstruction* inst) {
|
||||
auto dstReg = m_regs[inst->dst()].reg();
|
||||
cgCallHelper(m_as, (TCA)ldGblAddrHelper, dstReg, kNoSyncPoint,
|
||||
cgCallHelper(m_as, (TCA)ldGblAddrHelper, dstReg,
|
||||
SyncOptions::kNoSyncPoint,
|
||||
ArgGroup(m_regs).ssa(inst->src(0)));
|
||||
m_as.testq(dstReg, dstReg);
|
||||
emitFwdJcc(CC_Z, inst->taken());
|
||||
}
|
||||
|
||||
void CodeGenerator::cgLdGblAddrDef(IRInstruction* inst) {
|
||||
cgCallHelper(m_as, (TCA)ldGblAddrDefHelper, inst->dst(), kNoSyncPoint,
|
||||
cgCallHelper(m_as, (TCA)ldGblAddrDefHelper, inst->dst(),
|
||||
SyncOptions::kNoSyncPoint,
|
||||
ArgGroup(m_regs).ssa(inst->src(0)));
|
||||
}
|
||||
|
||||
@@ -5047,7 +5054,7 @@ void CodeGenerator::cgReleaseVVOrExit(IRInstruction* inst) {
|
||||
a,
|
||||
TCA(static_cast<void (*)(ActRec*)>(ExtraArgs::deallocate)),
|
||||
nullptr,
|
||||
kSyncPoint,
|
||||
SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).reg(rFp),
|
||||
DestType::None
|
||||
);
|
||||
@@ -5064,7 +5071,7 @@ void CodeGenerator::cgBoxPtr(IRInstruction* inst) {
|
||||
base[TVOFF(m_data)],
|
||||
[&](ConditionCode cc) {
|
||||
ifThen(m_as, ccNegate(cc), [&] {
|
||||
cgCallHelper(m_as, (TCA)tvBox, dstReg, kNoSyncPoint,
|
||||
cgCallHelper(m_as, (TCA)tvBox, dstReg, SyncOptions::kNoSyncPoint,
|
||||
ArgGroup(m_regs).ssa(addr));
|
||||
});
|
||||
});
|
||||
@@ -5093,14 +5100,14 @@ void CodeGenerator::cgConcat(IRInstruction* inst) {
|
||||
fptr = (void*)concat_is;
|
||||
}
|
||||
if (fptr) {
|
||||
cgCallHelper(m_as, (TCA)fptr, dst, kNoSyncPoint,
|
||||
cgCallHelper(m_as, (TCA)fptr, dst, SyncOptions::kNoSyncPoint,
|
||||
ArgGroup(m_regs).ssa(tl).ssa(tr));
|
||||
} else {
|
||||
if (lType.subtypeOf(Type::Obj) || lType.needsReg() ||
|
||||
rType.subtypeOf(Type::Obj) || rType.needsReg()) {
|
||||
CG_PUNT(cgConcat);
|
||||
}
|
||||
cgCallHelper(m_as, (TCA)concat_value, dst, kNoSyncPoint,
|
||||
cgCallHelper(m_as, (TCA)concat_value, dst, SyncOptions::kNoSyncPoint,
|
||||
ArgGroup(m_regs).typedValue(tl).typedValue(tr));
|
||||
}
|
||||
}
|
||||
@@ -5116,7 +5123,7 @@ void CodeGenerator::cgInterpOne(IRInstruction* inst) {
|
||||
void* interpOneHelper = interpOneEntryPoints[opc];
|
||||
|
||||
auto dstReg = InvalidReg;
|
||||
cgCallHelper(m_as, (TCA)interpOneHelper, dstReg, kSyncPoint,
|
||||
cgCallHelper(m_as, (TCA)interpOneHelper, dstReg, SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).ssa(fp).ssa(sp).imm(pcOff));
|
||||
|
||||
auto newSpReg = m_regs[inst->dst()].reg();
|
||||
@@ -5137,7 +5144,7 @@ void CodeGenerator::cgInterpOneCF(IRInstruction* inst) {
|
||||
void* interpOneHelper = interpOneEntryPoints[opc];
|
||||
|
||||
auto dstReg = InvalidReg;
|
||||
cgCallHelper(m_as, (TCA)interpOneHelper, dstReg, kSyncPoint,
|
||||
cgCallHelper(m_as, (TCA)interpOneHelper, dstReg, SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).ssa(fp).ssa(sp).imm(pcOff));
|
||||
|
||||
// The interpOne method returns a pointer to the current ExecutionContext
|
||||
@@ -5170,7 +5177,7 @@ void CodeGenerator::emitContVarEnvHelperCall(SSATmp* fp, TCA helper) {
|
||||
m_as. loadq (m_regs[fp].reg()[AROFF(m_varEnv)], scratch);
|
||||
m_as. testq (scratch, scratch);
|
||||
unlikelyIfBlock(CC_NZ, [&] (Asm& a) {
|
||||
cgCallHelper(a, helper, InvalidReg, kNoSyncPoint,
|
||||
cgCallHelper(a, helper, InvalidReg, SyncOptions::kNoSyncPoint,
|
||||
ArgGroup(m_regs).ssa(fp));
|
||||
});
|
||||
}
|
||||
@@ -5244,7 +5251,7 @@ void CodeGenerator::cgIterInitCommon(IRInstruction* inst) {
|
||||
}
|
||||
TCA helperAddr = isWInit ? (TCA)new_iter_array_key<true> :
|
||||
isInitK ? (TCA)new_iter_array_key<false> : (TCA)new_iter_array;
|
||||
cgCallHelper(m_as, helperAddr, inst->dst(), kSyncPoint, args);
|
||||
cgCallHelper(m_as, helperAddr, inst->dst(), SyncOptions::kSyncPoint, args);
|
||||
} else {
|
||||
assert(src->type() == Type::Obj);
|
||||
args.imm(uintptr_t(curClass())).addr(fpReg, valLocalOffset);
|
||||
@@ -5258,7 +5265,7 @@ void CodeGenerator::cgIterInitCommon(IRInstruction* inst) {
|
||||
// stack pointer by 1 stack element on an unwind, skipping over
|
||||
// the src object.
|
||||
cgCallHelper(m_as, (TCA)new_iter_object, inst->dst(),
|
||||
kSyncPointAdjustOne, args);
|
||||
SyncOptions::kSyncPointAdjustOne, args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5292,7 +5299,7 @@ void CodeGenerator::cgIterNextCommon(IRInstruction* inst) {
|
||||
}
|
||||
TCA helperAddr = isWNext ? (TCA)iter_next_key<true> :
|
||||
isNextK ? (TCA)iter_next_key<false> : (TCA)iter_next;
|
||||
cgCallHelper(m_as, helperAddr, inst->dst(), kSyncPoint, args);
|
||||
cgCallHelper(m_as, helperAddr, inst->dst(), SyncOptions::kSyncPoint, args);
|
||||
}
|
||||
|
||||
void iterFreeHelper(Iter* iter) {
|
||||
@@ -5306,21 +5313,22 @@ void citerFreeHelper(Iter* iter) {
|
||||
void CodeGenerator::cgIterFree(IRInstruction* inst) {
|
||||
PhysReg fpReg = m_regs[inst->src(0)].reg();
|
||||
int64_t offset = iterOffset(inst->extra<IterFree>()->iterId);
|
||||
cgCallHelper(m_as, (TCA)iterFreeHelper, InvalidReg, kSyncPoint,
|
||||
cgCallHelper(m_as, (TCA)iterFreeHelper, InvalidReg, SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).addr(fpReg, offset));
|
||||
}
|
||||
|
||||
void CodeGenerator::cgDecodeCufIter(IRInstruction* inst) {
|
||||
PhysReg fpReg = m_regs[inst->src(1)].reg();
|
||||
int64_t offset = iterOffset(inst->extra<DecodeCufIter>()->iterId);
|
||||
cgCallHelper(m_as, (TCA)decodeCufIterHelper, inst->dst(), kSyncPoint,
|
||||
cgCallHelper(m_as, (TCA)decodeCufIterHelper, inst->dst(),
|
||||
SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).addr(fpReg, offset).typedValue(inst->src(0)));
|
||||
}
|
||||
|
||||
void CodeGenerator::cgCIterFree(IRInstruction* inst) {
|
||||
PhysReg fpReg = m_regs[inst->src(0)].reg();
|
||||
int64_t offset = iterOffset(inst->extra<CIterFree>()->iterId);
|
||||
cgCallHelper(m_as, (TCA)citerFreeHelper, InvalidReg, kSyncPoint,
|
||||
cgCallHelper(m_as, (TCA)citerFreeHelper, InvalidReg, SyncOptions::kSyncPoint,
|
||||
ArgGroup(m_regs).addr(fpReg, offset));
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ enum class DestType : unsigned {
|
||||
TV // return a TypedValue packed in two registers
|
||||
};
|
||||
|
||||
enum SyncOptions {
|
||||
enum class SyncOptions {
|
||||
kNoSyncPoint,
|
||||
kSyncPoint,
|
||||
kSyncPointAdjustOne,
|
||||
@@ -329,7 +329,7 @@ private:
|
||||
void emitContVarEnvHelperCall(SSATmp* fp, TCA helper);
|
||||
const Func* curFunc() const;
|
||||
Class* curClass() const { return curFunc()->cls(); }
|
||||
void recordSyncPoint(Asm& as, SyncOptions sync = kSyncPoint);
|
||||
void recordSyncPoint(Asm& as, SyncOptions sync = SyncOptions::kSyncPoint);
|
||||
Address getDtorGeneric();
|
||||
Address getDtorTyped();
|
||||
int iterOffset(SSATmp* tmp);
|
||||
@@ -393,7 +393,7 @@ private:
|
||||
|
||||
class ArgDesc {
|
||||
public:
|
||||
enum Kind {
|
||||
enum class Kind {
|
||||
Reg, // Normal register
|
||||
TypeReg, // TypedValue's m_type field. Might need arch-specific
|
||||
// mangling before call depending on TypedValue's layout.
|
||||
@@ -469,7 +469,7 @@ struct ArgGroup {
|
||||
}
|
||||
|
||||
ArgGroup& imm(uintptr_t imm) {
|
||||
push_arg(ArgDesc(ArgDesc::Imm, InvalidReg, imm));
|
||||
push_arg(ArgDesc(ArgDesc::Kind::Imm, InvalidReg, imm));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -480,12 +480,12 @@ struct ArgGroup {
|
||||
ArgGroup& immPtr(std::nullptr_t) { return imm(0); }
|
||||
|
||||
ArgGroup& reg(PhysReg reg) {
|
||||
push_arg(ArgDesc(ArgDesc::Reg, PhysReg(reg), -1));
|
||||
push_arg(ArgDesc(ArgDesc::Kind::Reg, PhysReg(reg), -1));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArgGroup& addr(PhysReg base, intptr_t off) {
|
||||
push_arg(ArgDesc(ArgDesc::Addr, base, off));
|
||||
push_arg(ArgDesc(ArgDesc::Kind::Addr, base, off));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -544,7 +544,7 @@ private:
|
||||
}
|
||||
|
||||
ArgGroup& none() {
|
||||
push_arg(ArgDesc(ArgDesc::None, InvalidReg, -1));
|
||||
push_arg(ArgDesc(ArgDesc::Kind::None, InvalidReg, -1));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -548,7 +548,7 @@ void HhbcTranslator::emitCns(uint32_t id) {
|
||||
return c1;
|
||||
},
|
||||
[&] { // Taken: miss in TC, do lookup & init
|
||||
m_tb->hint(Block::Unlikely);
|
||||
m_tb->hint(Block::Hint::Unlikely);
|
||||
return gen(LookupCns, getCatchTrace(), cnsType, cnsNameTmp);
|
||||
}
|
||||
);
|
||||
@@ -824,7 +824,7 @@ void HhbcTranslator::emitStaticLocInit(uint32_t locId, uint32_t litStrId) {
|
||||
return gen(IncRef, cachedBox);
|
||||
},
|
||||
[&] { // taken: We missed in the cache
|
||||
m_tb->hint(Block::Unlikely);
|
||||
m_tb->hint(Block::Hint::Unlikely);
|
||||
return gen(StaticLocInitCached,
|
||||
cns(name), m_tb->fp(), value, ch);
|
||||
}
|
||||
@@ -2751,7 +2751,7 @@ void HhbcTranslator::emitVerifyParamType(int32_t paramId) {
|
||||
gen(JmpZero, taken, isInstance);
|
||||
},
|
||||
[&] { // taken: the param type does not match
|
||||
m_tb->hint(Block::Unlikely);
|
||||
m_tb->hint(Block::Hint::Unlikely);
|
||||
gen(VerifyParamFail, getCatchTrace(), cns(paramId));
|
||||
}
|
||||
);
|
||||
|
||||
@@ -86,13 +86,13 @@ static const bool debug = false;
|
||||
|
||||
bool isInferredType(const NormalizedInstruction& i) {
|
||||
return (i.getOutputUsage(i.outStack) ==
|
||||
NormalizedInstruction::OutputInferred);
|
||||
NormalizedInstruction::OutputUse::Inferred);
|
||||
}
|
||||
|
||||
JIT::Type getInferredOrPredictedType(const NormalizedInstruction& i) {
|
||||
NormalizedInstruction::OutputUse u = i.getOutputUsage(i.outStack);
|
||||
if (u == NormalizedInstruction::OutputInferred ||
|
||||
(u == NormalizedInstruction::OutputUsed && i.outputPredicted)) {
|
||||
if (u == NormalizedInstruction::OutputUse::Inferred ||
|
||||
(u == NormalizedInstruction::OutputUse::Used && i.outputPredicted)) {
|
||||
return JIT::Type::fromRuntimeType(i.outStack->rtt);
|
||||
}
|
||||
return JIT::Type::None;
|
||||
@@ -1521,12 +1521,12 @@ Translator::passPredictedAndInferredTypes(const NormalizedInstruction& i) {
|
||||
NormalizedInstruction::OutputUse u = i.getOutputUsage(i.outStack);
|
||||
JIT::Type jitType = JIT::Type::fromRuntimeType(i.outStack->rtt);
|
||||
|
||||
if (u == NormalizedInstruction::OutputInferred) {
|
||||
if (u == NormalizedInstruction::OutputUse::Inferred) {
|
||||
TRACE(1, "irPassPredictedAndInferredTypes: output inferred as %s\n",
|
||||
jitType.toString().c_str());
|
||||
m_hhbcTrans->assertTypeStack(0, jitType);
|
||||
|
||||
} else if ((u == NormalizedInstruction::OutputUsed && i.outputPredicted)) {
|
||||
} else if (u == NormalizedInstruction::OutputUse::Used && i.outputPredicted) {
|
||||
// If the value was predicted statically by the front-end, it
|
||||
// means that it's either the predicted type or null. In this
|
||||
// case, if the predicted value is not ref-counted and it's simply
|
||||
|
||||
@@ -74,7 +74,7 @@ LayoutInfo layoutBlocks(IRTrace* trace, const IRFactory& irFactory) {
|
||||
ret.astubsIt = std::stable_partition(
|
||||
ret.blocks.begin(), ret.blocks.end(),
|
||||
[&] (Block* b) {
|
||||
return b->isMain() && b->hint() != Block::Unlikely;
|
||||
return b->isMain() && b->hint() != Block::Hint::Unlikely;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -879,7 +879,7 @@ static RegNumber findLabelSrcReg(const RegAllocInfo& regs, IRInstruction* label,
|
||||
assert(label->op() == DefLabel);
|
||||
SSATmp* withReg = label->block()->findSrc(dstIdx, [&](SSATmp* src) {
|
||||
return regs[src].reg(regIndex) != InvalidReg &&
|
||||
src->inst()->block()->hint() != Block::Unlikely;
|
||||
src->inst()->block()->hint() != Block::Hint::Unlikely;
|
||||
});
|
||||
return withReg ? regs[withReg].reg(regIndex) : reg::noreg;
|
||||
}
|
||||
|
||||
@@ -27,13 +27,13 @@ namespace HPHP { namespace JIT { namespace NativeCalls {
|
||||
using namespace HPHP::Transl;
|
||||
using namespace HPHP::Transl::TargetCache;
|
||||
|
||||
static const SyncOptions SNone = kNoSyncPoint;
|
||||
static const SyncOptions SSync = kSyncPoint;
|
||||
static const SyncOptions SSyncAdj1 = kSyncPointAdjustOne;
|
||||
const SyncOptions SNone = SyncOptions::kNoSyncPoint;
|
||||
const SyncOptions SSync = SyncOptions::kSyncPoint;
|
||||
const SyncOptions SSyncAdj1 = SyncOptions::kSyncPointAdjustOne;
|
||||
|
||||
static const DestType DSSA = DestType::SSA;
|
||||
static const DestType DTV = DestType::TV;
|
||||
static const DestType DNone = DestType::None;
|
||||
const DestType DSSA = DestType::SSA;
|
||||
const DestType DTV = DestType::TV;
|
||||
const DestType DNone = DestType::None;
|
||||
|
||||
/*
|
||||
* The table passed to s_callMap's constructor describes helpers calls
|
||||
|
||||
@@ -119,8 +119,8 @@ void printLabel(std::ostream& os, const Block* block) {
|
||||
os << color(ANSI_COLOR_MAGENTA);
|
||||
os << "L" << block->id();
|
||||
switch (block->hint()) {
|
||||
case Block::Unlikely: os << "<Unlikely>"; break;
|
||||
case Block::Likely: os << "<Likely>"; break;
|
||||
case Block::Hint::Unlikely: os << "<Unlikely>"; break;
|
||||
case Block::Hint::Likely: os << "<Likely>"; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -276,7 +276,7 @@ static smart::vector<Block*> blocks(const IRTrace* trace,
|
||||
if (!asmInfo) {
|
||||
smart::vector<Block*> unlikely;
|
||||
for (Block* block : trace->blocks()) {
|
||||
if (block->hint() == Block::Unlikely) {
|
||||
if (block->hint() == Block::Hint::Unlikely) {
|
||||
unlikely.push_back(block);
|
||||
} else {
|
||||
blocks.push_back(block);
|
||||
|
||||
@@ -66,7 +66,7 @@ void SrcRec::emitFallbackJump(TCA from, int cc /* = -1 */) {
|
||||
if (cc < 0) {
|
||||
a.jmp(a.code.frontier);
|
||||
} else {
|
||||
assert(incoming.type() == IncomingBranch::JCC);
|
||||
assert(incoming.type() == IncomingBranch::Tag::JCC);
|
||||
a.jcc((ConditionCode)cc, a.code.frontier);
|
||||
}
|
||||
|
||||
@@ -181,14 +181,14 @@ void SrcRec::replaceOldTranslations() {
|
||||
|
||||
void SrcRec::patch(IncomingBranch branch, TCA dest) {
|
||||
switch (branch.type()) {
|
||||
case IncomingBranch::JMP: {
|
||||
case IncomingBranch::Tag::JMP: {
|
||||
auto& a = tx64->getAsmFor(branch.toSmash());
|
||||
CodeCursor cg(a, branch.toSmash());
|
||||
TranslatorX64::smashJmp(a, branch.toSmash(), dest);
|
||||
break;
|
||||
}
|
||||
|
||||
case IncomingBranch::JCC: {
|
||||
case IncomingBranch::Tag::JCC: {
|
||||
// patch destination, but preserve the condition code
|
||||
int32_t delta = safe_cast<int32_t>((dest - branch.toSmash()) - kJmpccLen);
|
||||
int32_t* addr = (int32_t*)(branch.toSmash() + kJmpccLen - 4);
|
||||
@@ -196,7 +196,7 @@ void SrcRec::patch(IncomingBranch branch, TCA dest) {
|
||||
break;
|
||||
}
|
||||
|
||||
case IncomingBranch::ADDR:
|
||||
case IncomingBranch::Tag::ADDR:
|
||||
// Note that this effectively ignores a
|
||||
atomic_release_store(reinterpret_cast<TCA*>(branch.toSmash()), dest);
|
||||
}
|
||||
|
||||
@@ -42,28 +42,32 @@ namespace Transl {
|
||||
* intact.
|
||||
*/
|
||||
struct IncomingBranch {
|
||||
enum BranchType {
|
||||
enum class Tag {
|
||||
JMP,
|
||||
JCC,
|
||||
ADDR,
|
||||
};
|
||||
|
||||
static IncomingBranch jmpFrom(TCA from) { return IncomingBranch(JMP, from); }
|
||||
static IncomingBranch jccFrom(TCA from) { return IncomingBranch(JCC, from); }
|
||||
static IncomingBranch jmpFrom(TCA from) {
|
||||
return IncomingBranch(Tag::JMP, from);
|
||||
}
|
||||
static IncomingBranch jccFrom(TCA from) {
|
||||
return IncomingBranch(Tag::JCC, from);
|
||||
}
|
||||
static IncomingBranch addr(TCA* from) {
|
||||
return IncomingBranch(ADDR, TCA(from));
|
||||
return IncomingBranch(Tag::ADDR, TCA(from));
|
||||
}
|
||||
|
||||
BranchType type() const { return m_type; }
|
||||
Tag type() const { return m_type; }
|
||||
TCA toSmash() const { return m_toSmash; }
|
||||
|
||||
private:
|
||||
explicit IncomingBranch(BranchType type, TCA toSmash)
|
||||
explicit IncomingBranch(Tag type, TCA toSmash)
|
||||
: m_type(type)
|
||||
, m_toSmash(toSmash)
|
||||
{}
|
||||
|
||||
BranchType m_type;
|
||||
Tag m_type;
|
||||
TCA m_toSmash;
|
||||
};
|
||||
|
||||
|
||||
@@ -93,9 +93,9 @@ struct VMRegAnchor : private boost::noncopyable {
|
||||
explicit VMRegAnchor(ActRec* ar) {
|
||||
// Some C++ entry points have an ActRec prepared from after a call
|
||||
// instruction. This syncs us to right after the call instruction.
|
||||
assert(tl_regState == REGSTATE_DIRTY);
|
||||
m_old = REGSTATE_DIRTY;
|
||||
tl_regState = REGSTATE_CLEAN;
|
||||
assert(tl_regState == VMRegState::DIRTY);
|
||||
m_old = VMRegState::DIRTY;
|
||||
tl_regState = VMRegState::CLEAN;
|
||||
|
||||
auto prevAr = g_vmContext->getOuterVMFrame(ar);
|
||||
const Func* prevF = prevAr->m_func;
|
||||
@@ -122,7 +122,7 @@ struct EagerVMRegAnchor {
|
||||
assert(vmfp() == fp && vmsp() == sp && vmpc() == pc);
|
||||
}
|
||||
m_old = tl_regState;
|
||||
tl_regState = REGSTATE_CLEAN;
|
||||
tl_regState = VMRegState::CLEAN;
|
||||
}
|
||||
~EagerVMRegAnchor() {
|
||||
tl_regState = m_old;
|
||||
|
||||
@@ -163,7 +163,7 @@ TCA fcallHelper(ActRec* ar) {
|
||||
have to tell the unwinder that.
|
||||
*/
|
||||
DECLARE_FRAME_POINTER(framePtr);
|
||||
tl_regState = REGSTATE_CLEAN;
|
||||
tl_regState = VMRegState::CLEAN;
|
||||
framePtr->m_savedRip = ar->m_savedRip;
|
||||
throw;
|
||||
}
|
||||
@@ -198,7 +198,7 @@ asm (
|
||||
*/
|
||||
TCA funcBodyHelper(ActRec* fp) {
|
||||
setupAfterProlog(fp);
|
||||
tl_regState = REGSTATE_CLEAN;
|
||||
tl_regState = VMRegState::CLEAN;
|
||||
Func* func = const_cast<Func*>(fp->m_func);
|
||||
|
||||
TCA tca = tx64->getCallArrayProlog(func);
|
||||
@@ -208,7 +208,7 @@ TCA funcBodyHelper(ActRec* fp) {
|
||||
} else {
|
||||
tca = Translator::Get()->getResumeHelper();
|
||||
}
|
||||
tl_regState = REGSTATE_DIRTY;
|
||||
tl_regState = VMRegState::DIRTY;
|
||||
return tca;
|
||||
}
|
||||
|
||||
@@ -222,10 +222,10 @@ void TranslatorX64::fCallArrayHelper(const Offset pcOff, const Offset pcNext) {
|
||||
ec->m_pc = curUnit()->at(pcOff);
|
||||
PC pc = curUnit()->at(pcNext);
|
||||
|
||||
tl_regState = REGSTATE_CLEAN;
|
||||
tl_regState = VMRegState::CLEAN;
|
||||
bool runFunc = ec->doFCallArray(pc);
|
||||
sp = ec->m_stack.top();
|
||||
tl_regState = REGSTATE_DIRTY;
|
||||
tl_regState = VMRegState::DIRTY;
|
||||
if (!runFunc) return;
|
||||
|
||||
ec->m_fp->m_savedRip = framePtr->m_savedRip;
|
||||
|
||||
@@ -136,7 +136,7 @@ TranslatorX64* volatile nextTx64;
|
||||
__thread TranslatorX64* tx64;
|
||||
|
||||
// Register dirtiness: thread-private.
|
||||
__thread VMRegState tl_regState = REGSTATE_CLEAN;
|
||||
__thread VMRegState tl_regState = VMRegState::CLEAN;
|
||||
|
||||
static StaticString s___call(LITSTR_INIT("__call"));
|
||||
static StaticString s___callStatic(LITSTR_INIT("__callStatic"));
|
||||
@@ -857,18 +857,18 @@ bool isSmashable(Address frontier, int nBytes, int offset /* = 0 */) {
|
||||
*/
|
||||
void prepareForTestAndSmash(Asm& a, int testBytes, TestAndSmashFlags flags) {
|
||||
switch (flags) {
|
||||
case kAlignJcc:
|
||||
case TestAndSmashFlags::kAlignJcc:
|
||||
prepareForSmash(a, testBytes + kJmpccLen, testBytes);
|
||||
assert(isSmashable(a.code.frontier + testBytes, kJmpccLen));
|
||||
break;
|
||||
case kAlignJccImmediate:
|
||||
case TestAndSmashFlags::kAlignJccImmediate:
|
||||
prepareForSmash(a,
|
||||
testBytes + kJmpccLen,
|
||||
testBytes + kJmpccLen - kJmpImmBytes);
|
||||
assert(isSmashable(a.code.frontier + testBytes, kJmpccLen,
|
||||
kJmpccLen - kJmpImmBytes));
|
||||
break;
|
||||
case kAlignJccAndJmp:
|
||||
case TestAndSmashFlags::kAlignJccAndJmp:
|
||||
// Ensure that the entire jcc, and the entire jmp are smashable
|
||||
// (but we dont need them both to be in the same cache line)
|
||||
prepareForSmash(a, testBytes + kJmpccLen, testBytes);
|
||||
@@ -1042,14 +1042,14 @@ TranslatorX64::shuffleArgsForMagicCall(ActRec* ar) {
|
||||
* Geronimo!
|
||||
*/
|
||||
static void sync_regstate_to_caller(ActRec* preLive) {
|
||||
assert(tl_regState == REGSTATE_DIRTY);
|
||||
assert(tl_regState == VMRegState::DIRTY);
|
||||
VMExecutionContext* ec = g_vmContext;
|
||||
ec->m_stack.top() = (TypedValue*)preLive - preLive->numArgs();
|
||||
ActRec* fp = preLive == ec->m_firstAR ?
|
||||
ec->m_nestedVMs.back().m_savedState.fp : (ActRec*)preLive->m_savedRbp;
|
||||
ec->m_fp = fp;
|
||||
ec->m_pc = fp->m_func->unit()->at(fp->m_func->base() + preLive->m_soff);
|
||||
tl_regState = REGSTATE_CLEAN;
|
||||
tl_regState = VMRegState::CLEAN;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1083,7 +1083,7 @@ TranslatorX64::trimExtraArgs(ActRec* ar) {
|
||||
|
||||
// Only go back to dirty in a non-exception case. (Same reason as
|
||||
// above.)
|
||||
tl_regState = REGSTATE_DIRTY;
|
||||
tl_regState = VMRegState::DIRTY;
|
||||
}
|
||||
|
||||
TCA
|
||||
@@ -1332,8 +1332,8 @@ TranslatorX64::emitPopRetIntoActRec(Asm& a) {
|
||||
}
|
||||
|
||||
static void interp_set_regs(ActRec* ar, Cell* sp, Offset pcOff) {
|
||||
assert(tl_regState == REGSTATE_DIRTY);
|
||||
tl_regState = REGSTATE_CLEAN;
|
||||
assert(tl_regState == VMRegState::DIRTY);
|
||||
tl_regState = VMRegState::CLEAN;
|
||||
vmfp() = (Cell*)ar;
|
||||
vmsp() = sp;
|
||||
vmpc() = curUnit()->at(pcOff);
|
||||
@@ -1365,7 +1365,7 @@ TranslatorX64::funcPrologue(Func* func, int nPassed, ActRec* ar) {
|
||||
interp_set_regs(ar, (Cell*)ar - func->numSlotsInFrame(), entry);
|
||||
SrcKey funcBody(func, entry);
|
||||
TCA tca = getTranslation(TranslArgs(funcBody, false));
|
||||
tl_regState = REGSTATE_DIRTY;
|
||||
tl_regState = VMRegState::DIRTY;
|
||||
if (tca) {
|
||||
// racy, but ok...
|
||||
func->setPrologue(paramIndex, tca);
|
||||
@@ -1828,7 +1828,7 @@ TranslatorX64::emitCondJmp(SrcKey skTaken, SrcKey skNotTaken,
|
||||
|
||||
// reserve space for a smashable jnz/jmp pair; both initially point
|
||||
// to our stub.
|
||||
prepareForTestAndSmash(a, 0, kAlignJccAndJmp);
|
||||
prepareForTestAndSmash(a, 0, TestAndSmashFlags::kAlignJccAndJmp);
|
||||
TCA old = a.code.frontier;
|
||||
TCA stub = astubs.code.frontier;
|
||||
|
||||
@@ -1965,7 +1965,7 @@ TranslatorX64::bindJmpccSecond(TCA toSmash, const Offset off,
|
||||
const Func* f = curFunc();
|
||||
SrcKey dest(f, off);
|
||||
TCA branch = getTranslation(TranslArgs(dest, true).src(toSmash));
|
||||
LeaseHolder writer(s_writeLease, NO_ACQUIRE);
|
||||
LeaseHolder writer(s_writeLease, LeaseAcquire::NO_ACQUIRE);
|
||||
if (branch && writer.acquire()) {
|
||||
smashed = true;
|
||||
SrcRec* destRec = getSrcRec(dest);
|
||||
@@ -2280,7 +2280,7 @@ TranslatorX64::enterTC(TCA start, void* data) {
|
||||
|
||||
TRACE(1, "enterTC: %p fp%p(%s) sp%p enter {\n", start,
|
||||
vmfp(), func->name()->data(), vmsp());
|
||||
tl_regState = REGSTATE_DIRTY;
|
||||
tl_regState = VMRegState::DIRTY;
|
||||
|
||||
// We have to force C++ to spill anything that might be in a callee-saved
|
||||
// register (aside from rbp). enterTCHelper does not save them.
|
||||
@@ -2290,7 +2290,7 @@ TranslatorX64::enterTC(TCA start, void* data) {
|
||||
CALLEE_SAVED_BARRIER();
|
||||
assert(g_vmContext->m_stack.isValidAddress((uintptr_t)vmsp()));
|
||||
|
||||
tl_regState = REGSTATE_CLEAN; // Careful: pc isn't sync'ed yet.
|
||||
tl_regState = VMRegState::CLEAN; // Careful: pc isn't sync'ed yet.
|
||||
TRACE(1, "enterTC: %p fp%p sp%p } return\n", start,
|
||||
vmfp(), vmsp());
|
||||
|
||||
@@ -2361,7 +2361,7 @@ bool TranslatorX64::handleServiceRequest(TReqInfo& info,
|
||||
TRACE(2, "enterTC: bindCall immutably %s -> %p\n",
|
||||
func->fullName()->data(), dest);
|
||||
}
|
||||
LeaseHolder writer(s_writeLease, NO_ACQUIRE);
|
||||
LeaseHolder writer(s_writeLease, LeaseAcquire::NO_ACQUIRE);
|
||||
if (dest && writer.acquire()) {
|
||||
TRACE(2, "enterTC: bindCall smash %p -> %p\n", toSmash, dest);
|
||||
smashCall(tx64->getAsmFor(toSmash), toSmash, dest);
|
||||
@@ -2754,7 +2754,7 @@ interpOne##opcode(ActRec* ar, Cell* sp, Offset pcOff) { \
|
||||
* is actually still correct, and we don't have information in the
|
||||
* fixup map for interpOne calls anyway.
|
||||
*/ \
|
||||
tl_regState = REGSTATE_DIRTY; \
|
||||
tl_regState = VMRegState::DIRTY; \
|
||||
return ec; \
|
||||
}
|
||||
|
||||
@@ -2837,9 +2837,9 @@ TCA TranslatorX64::getTranslatedCaller() const {
|
||||
|
||||
void
|
||||
TranslatorX64::syncWork() {
|
||||
assert(tl_regState == REGSTATE_DIRTY);
|
||||
assert(tl_regState == VMRegState::DIRTY);
|
||||
fixup(g_vmContext);
|
||||
tl_regState = REGSTATE_CLEAN;
|
||||
tl_regState = VMRegState::CLEAN;
|
||||
Stats::inc(Stats::TC_Sync);
|
||||
}
|
||||
|
||||
@@ -2971,17 +2971,17 @@ TranslatorX64::getNativeTrampoline(TCA helperAddr) {
|
||||
}
|
||||
|
||||
static void defClsHelper(PreClass *preClass) {
|
||||
assert(tl_regState == REGSTATE_DIRTY);
|
||||
tl_regState = REGSTATE_CLEAN;
|
||||
assert(tl_regState == VMRegState::DIRTY);
|
||||
tl_regState = VMRegState::CLEAN;
|
||||
Unit::defClass(preClass);
|
||||
|
||||
/*
|
||||
* m_defClsHelper sync'd the registers for us already. This means
|
||||
* if an exception propagates we want to leave things as
|
||||
* REGSTATE_CLEAN, since we're still in sync. Only set it to dirty
|
||||
* VMRegState::CLEAN, since we're still in sync. Only set it to dirty
|
||||
* if we are actually returning to run in the TC again.
|
||||
*/
|
||||
tl_regState = REGSTATE_DIRTY;
|
||||
tl_regState = VMRegState::DIRTY;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -3729,7 +3729,7 @@ TCA TranslatorX64::getCatchTrace(CTCA ip) const {
|
||||
void
|
||||
TranslatorX64::requestInit() {
|
||||
TRACE(1, "in requestInit(%" PRId64 ")\n", g_vmContext->m_currentThreadIdx);
|
||||
tl_regState = REGSTATE_CLEAN;
|
||||
tl_regState = VMRegState::CLEAN;
|
||||
PendQ::drain();
|
||||
requestResetHighLevelTranslator();
|
||||
Treadmill::startRequest(g_vmContext->m_currentThreadIdx);
|
||||
|
||||
@@ -113,7 +113,7 @@ constexpr int kTestImmRegLen = 5; // only for rax -- special encoding
|
||||
constexpr size_t kX64CacheLineSize = 64;
|
||||
constexpr size_t kX64CacheLineMask = kX64CacheLineSize - 1;
|
||||
|
||||
enum TestAndSmashFlags {
|
||||
enum class TestAndSmashFlags {
|
||||
kAlignJccImmediate,
|
||||
kAlignJcc,
|
||||
kAlignJccAndJmp
|
||||
|
||||
@@ -2481,13 +2481,12 @@ static bool isPop(const NormalizedInstruction* instr) {
|
||||
|
||||
NormalizedInstruction::OutputUse
|
||||
NormalizedInstruction::getOutputUsage(const DynLocation* output) const {
|
||||
for (NormalizedInstruction* succ = next;
|
||||
succ; succ = succ->next) {
|
||||
for (NormalizedInstruction* succ = next; succ; succ = succ->next) {
|
||||
if (succ->noOp) continue;
|
||||
for (size_t i = 0; i < succ->inputs.size(); ++i) {
|
||||
if (succ->inputs[i] == output) {
|
||||
if (succ->inputWasInferred(i)) {
|
||||
return OutputInferred;
|
||||
return OutputUse::Inferred;
|
||||
}
|
||||
if (Translator::Get()->dontGuardAnyInputs(succ->op())) {
|
||||
/* the consumer doesnt care about its inputs
|
||||
@@ -2496,22 +2495,22 @@ NormalizedInstruction::getOutputUsage(const DynLocation* output) const {
|
||||
*/
|
||||
if (!outputDependsOnInput(succ->op()) ||
|
||||
!(succ->outStack && !succ->outStack->rtt.isVagueValue() &&
|
||||
succ->getOutputUsage(succ->outStack) != OutputUsed) ||
|
||||
succ->getOutputUsage(succ->outStack) != OutputUse::Used) ||
|
||||
!(succ->outLocal && !succ->outLocal->rtt.isVagueValue() &&
|
||||
succ->getOutputUsage(succ->outLocal)) != OutputUsed) {
|
||||
return OutputDoesntCare;
|
||||
succ->getOutputUsage(succ->outLocal) != OutputUse::Used)) {
|
||||
return OutputUse::DoesntCare;
|
||||
}
|
||||
}
|
||||
return OutputUsed;
|
||||
return OutputUse::Used;
|
||||
}
|
||||
}
|
||||
}
|
||||
return OutputUnused;
|
||||
return OutputUse::Unused;
|
||||
}
|
||||
|
||||
bool NormalizedInstruction::isOutputUsed(const DynLocation* output) const {
|
||||
return (output && !output->rtt.isVagueValue() &&
|
||||
getOutputUsage(output) == OutputUsed);
|
||||
getOutputUsage(output) == OutputUse::Used);
|
||||
}
|
||||
|
||||
bool NormalizedInstruction::isAnyOutputUsed() const
|
||||
@@ -3276,7 +3275,7 @@ std::unique_ptr<Tracelet> Translator::analyze(SrcKey sk,
|
||||
NormalizedInstruction* ni = t.newNormalizedInstruction();
|
||||
ni->source = sk;
|
||||
ni->stackOffset = stackFrameOffset;
|
||||
ni->funcd = (t.m_arState.getCurrentState() == ActRecState::KNOWN) ?
|
||||
ni->funcd = (t.m_arState.getCurrentState() == ActRecState::State::KNOWN) ?
|
||||
t.m_arState.getCurrentFunc() : nullptr;
|
||||
ni->m_unit = unit;
|
||||
ni->preppedByRef = false;
|
||||
@@ -4056,7 +4055,7 @@ void
|
||||
ActRecState::pushFuncD(const Func* func) {
|
||||
TRACE(2, "ActRecState: pushStatic func %p(%s)\n", func, func->name()->data());
|
||||
Record r;
|
||||
r.m_state = KNOWN;
|
||||
r.m_state = State::KNOWN;
|
||||
r.m_topFunc = func;
|
||||
r.m_entryArDelta = InvalidEntryArDelta;
|
||||
m_arStack.push_back(r);
|
||||
@@ -4066,7 +4065,7 @@ void
|
||||
ActRecState::pushDynFunc() {
|
||||
TRACE(2, "ActRecState: pushDynFunc\n");
|
||||
Record r;
|
||||
r.m_state = UNKNOWABLE;
|
||||
r.m_state = State::UNKNOWABLE;
|
||||
r.m_topFunc = nullptr;
|
||||
r.m_entryArDelta = InvalidEntryArDelta;
|
||||
m_arStack.push_back(r);
|
||||
@@ -4098,20 +4097,20 @@ ActRecState::getReffiness(int argNum, int entryArDelta, RefDeps* outRefDeps) {
|
||||
// guards.
|
||||
const ActRec* ar = arFromSpOffset((ActRec*)vmsp(), entryArDelta);
|
||||
Record r;
|
||||
r.m_state = GUESSABLE;
|
||||
r.m_state = State::GUESSABLE;
|
||||
r.m_entryArDelta = entryArDelta;
|
||||
r.m_topFunc = ar->m_func;
|
||||
m_arStack.push_back(r);
|
||||
}
|
||||
Record& r = m_arStack.back();
|
||||
if (r.m_state == UNKNOWABLE) {
|
||||
if (r.m_state == State::UNKNOWABLE) {
|
||||
TRACE(2, "ActRecState: unknowable, throwing in the towel\n");
|
||||
throwUnknownInput();
|
||||
not_reached();
|
||||
}
|
||||
assert(r.m_topFunc);
|
||||
bool retval = r.m_topFunc->byRef(argNum);
|
||||
if (r.m_state == GUESSABLE) {
|
||||
if (r.m_state == State::GUESSABLE) {
|
||||
assert(r.m_entryArDelta != InvalidEntryArDelta);
|
||||
TRACE(2, "ActRecState: guessing arg%d -> %d\n", argNum, retval);
|
||||
outRefDeps->addDep(r.m_entryArDelta, argNum, retval);
|
||||
@@ -4127,7 +4126,7 @@ ActRecState::getCurrentFunc() {
|
||||
|
||||
ActRecState::State
|
||||
ActRecState::getCurrentState() {
|
||||
if (m_arStack.empty()) return GUESSABLE;
|
||||
if (m_arStack.empty()) return State::GUESSABLE;
|
||||
return m_arStack.back().m_state;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,13 +65,12 @@ extern TranslatorX64* volatile nextTx64;
|
||||
extern __thread TranslatorX64* tx64;
|
||||
|
||||
/*
|
||||
* REGSTATE_DIRTY when the live register state is spread across the
|
||||
* stack and m_fixup, REGSTATE_CLEAN when it has been sync'ed into
|
||||
* g_context.
|
||||
* DIRTY when the live register state is spread across the stack and m_fixup,
|
||||
* CLEAN when it has been sync'ed into g_context.
|
||||
*/
|
||||
enum VMRegState {
|
||||
REGSTATE_CLEAN,
|
||||
REGSTATE_DIRTY
|
||||
enum class VMRegState {
|
||||
CLEAN,
|
||||
DIRTY
|
||||
};
|
||||
extern __thread VMRegState tl_regState;
|
||||
|
||||
@@ -321,11 +320,11 @@ class NormalizedInstruction {
|
||||
return i < 32 && ((checkedInputs >> i) & 1);
|
||||
}
|
||||
|
||||
enum OutputUse {
|
||||
OutputUsed,
|
||||
OutputUnused,
|
||||
OutputInferred,
|
||||
OutputDoesntCare
|
||||
enum class OutputUse {
|
||||
Used,
|
||||
Unused,
|
||||
Inferred,
|
||||
DoesntCare
|
||||
};
|
||||
OutputUse getOutputUsage(const DynLocation* output) const;
|
||||
bool isOutputUsed(const DynLocation* output) const;
|
||||
@@ -470,7 +469,7 @@ struct ActRecState {
|
||||
// instructions that need to do so.
|
||||
static const int InvalidEntryArDelta = INT_MAX;
|
||||
|
||||
enum State {
|
||||
enum class State {
|
||||
GUESSABLE, KNOWN, UNKNOWABLE
|
||||
};
|
||||
|
||||
@@ -1058,12 +1057,12 @@ public:
|
||||
static bool liveFrameIsPseudoMain();
|
||||
|
||||
inline void sync() {
|
||||
if (tl_regState == REGSTATE_CLEAN) return;
|
||||
if (tl_regState == VMRegState::CLEAN) return;
|
||||
syncWork();
|
||||
}
|
||||
|
||||
inline bool stateIsDirty() {
|
||||
return tl_regState == REGSTATE_DIRTY;
|
||||
return tl_regState == VMRegState::DIRTY;
|
||||
}
|
||||
|
||||
inline bool isTransDBEnabled() const {
|
||||
@@ -1115,10 +1114,10 @@ public:
|
||||
|
||||
int getStackDelta(const NormalizedInstruction& ni);
|
||||
|
||||
enum ControlFlowInfo {
|
||||
ControlFlowNone,
|
||||
ControlFlowChangesPC,
|
||||
ControlFlowBreaksBB
|
||||
enum class ControlFlowInfo {
|
||||
None,
|
||||
ChangesPC,
|
||||
BreaksBB
|
||||
};
|
||||
|
||||
static inline ControlFlowInfo
|
||||
@@ -1153,7 +1152,7 @@ opcodeControlFlowInfo(const Opcode instr) {
|
||||
case OpEval:
|
||||
case OpNativeImpl:
|
||||
case OpContHandle:
|
||||
return ControlFlowBreaksBB;
|
||||
return ControlFlowInfo::BreaksBB;
|
||||
case OpFCall:
|
||||
case OpFCallArray:
|
||||
case OpContEnter:
|
||||
@@ -1162,9 +1161,9 @@ opcodeControlFlowInfo(const Opcode instr) {
|
||||
case OpReq:
|
||||
case OpReqOnce:
|
||||
case OpReqDoc:
|
||||
return ControlFlowChangesPC;
|
||||
return ControlFlowInfo::ChangesPC;
|
||||
default:
|
||||
return ControlFlowNone;
|
||||
return ControlFlowInfo::None;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1176,7 +1175,7 @@ opcodeControlFlowInfo(const Opcode instr) {
|
||||
*/
|
||||
static inline bool
|
||||
opcodeChangesPC(const Opcode instr) {
|
||||
return opcodeControlFlowInfo(instr) >= ControlFlowChangesPC;
|
||||
return opcodeControlFlowInfo(instr) >= ControlFlowInfo::ChangesPC;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1188,7 +1187,7 @@ opcodeChangesPC(const Opcode instr) {
|
||||
*/
|
||||
static inline bool
|
||||
opcodeBreaksBB(const Opcode instr) {
|
||||
return opcodeControlFlowInfo(instr) == ControlFlowBreaksBB;
|
||||
return opcodeControlFlowInfo(instr) == ControlFlowInfo::BreaksBB;
|
||||
}
|
||||
|
||||
bool outputDependsOnInput(const Opcode instr);
|
||||
|
||||
@@ -53,7 +53,7 @@ void append_vec(std::vector<char>& v,
|
||||
}
|
||||
|
||||
void sync_regstate(_Unwind_Context* context) {
|
||||
assert(tl_regState == REGSTATE_DIRTY);
|
||||
assert(tl_regState == VMRegState::DIRTY);
|
||||
|
||||
uintptr_t frameRbp = _Unwind_GetGR(context, Debug::RBP);
|
||||
uintptr_t frameRip = _Unwind_GetGR(context, Debug::RIP);
|
||||
@@ -73,7 +73,7 @@ void sync_regstate(_Unwind_Context* context) {
|
||||
|
||||
Stats::inc(Stats::TC_SyncUnwind);
|
||||
tx64->fixupWork(g_vmContext, &fakeAr);
|
||||
tl_regState = REGSTATE_CLEAN;
|
||||
tl_regState = VMRegState::CLEAN;
|
||||
}
|
||||
|
||||
bool install_catch_trace(_Unwind_Context* ctx, _Unwind_Exception* exn,
|
||||
@@ -134,7 +134,7 @@ tc_unwind_personality(int version,
|
||||
assert(status == 0);
|
||||
FTRACE(1, "unwind {} exn {}: regState: {} ip: {} type: {}. ",
|
||||
unwindType, exceptionObj,
|
||||
tl_regState == REGSTATE_DIRTY ? "dirty" : "clean",
|
||||
tl_regState == VMRegState::DIRTY ? "dirty" : "clean",
|
||||
(TCA)_Unwind_GetIP(context), exnType);
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ tc_unwind_personality(int version,
|
||||
* which is an exit traces from hhir with a few special instructions.
|
||||
*/
|
||||
else if (actions & _UA_CLEANUP_PHASE) {
|
||||
if (tl_regState == REGSTATE_DIRTY) {
|
||||
if (tl_regState == VMRegState::DIRTY) {
|
||||
sync_regstate(context);
|
||||
}
|
||||
if (install_catch_trace(context, exceptionObj, ism)) {
|
||||
|
||||
@@ -869,7 +869,7 @@ SSATmp* HhbcTranslator::VectorTranslator::checkInitProp(
|
||||
[&] { // Taken: Property is Uninit. Raise a warning and return
|
||||
// a pointer to InitNull, either in the object or
|
||||
// init_null_variant.
|
||||
m_tb.hint(Block::Unlikely);
|
||||
m_tb.hint(Block::Hint::Unlikely);
|
||||
if (doWarn && wantPropSpecializedWarnings()) {
|
||||
gen(RaiseUndefProp, m_ht.getCatchTrace(), baseAsObj, key);
|
||||
}
|
||||
@@ -931,7 +931,7 @@ void HhbcTranslator::VectorTranslator::emitPropSpecialized(const MInstrAttr mia,
|
||||
doDefine);
|
||||
},
|
||||
[&] { // Taken: Base is Null. Raise warnings/errors and return InitNull.
|
||||
m_tb.hint(Block::Unlikely);
|
||||
m_tb.hint(Block::Hint::Unlikely);
|
||||
if (doWarn) {
|
||||
gen(WarnNonObjProp);
|
||||
}
|
||||
|
||||
@@ -121,8 +121,8 @@ void Lease::drop(int64_t hintExpireDelay) {
|
||||
LeaseHolderBase::LeaseHolderBase(Lease& l, LeaseAcquire acquire,
|
||||
bool blocking)
|
||||
: m_lease(l), m_haveLock(false), m_acquired(false) {
|
||||
assert(IMPLIES(blocking, acquire == ACQUIRE));
|
||||
if (!m_lease.amOwner() && acquire == ACQUIRE) {
|
||||
assert(IMPLIES(blocking, acquire == LeaseAcquire::ACQUIRE));
|
||||
if (!m_lease.amOwner() && acquire == LeaseAcquire::ACQUIRE) {
|
||||
m_acquired = m_lease.acquire(blocking);
|
||||
}
|
||||
m_haveLock = m_lease.amOwner();
|
||||
|
||||
@@ -71,7 +71,7 @@ private:
|
||||
void gremlinUnlockImpl();
|
||||
};
|
||||
|
||||
enum LeaseAcquire {
|
||||
enum class LeaseAcquire {
|
||||
ACQUIRE,
|
||||
NO_ACQUIRE,
|
||||
};
|
||||
@@ -91,12 +91,12 @@ struct LeaseHolderBase {
|
||||
bool m_acquired;
|
||||
};
|
||||
struct LeaseHolder : public LeaseHolderBase {
|
||||
explicit LeaseHolder(Lease& l, LeaseAcquire acquire = ACQUIRE)
|
||||
explicit LeaseHolder(Lease& l, LeaseAcquire acquire = LeaseAcquire::ACQUIRE)
|
||||
: LeaseHolderBase(l, acquire, false) {}
|
||||
};
|
||||
struct BlockingLeaseHolder : public LeaseHolderBase {
|
||||
explicit BlockingLeaseHolder(Lease& l)
|
||||
: LeaseHolderBase(l, ACQUIRE, true) {}
|
||||
: LeaseHolderBase(l, LeaseAcquire::ACQUIRE, true) {}
|
||||
};
|
||||
|
||||
}} // HPHP::Transl
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário