From 9d7acb0fe3cfbcc882110447835828941da9dd83 Mon Sep 17 00:00:00 2001 From: bsimmers Date: Tue, 11 Mar 2014 15:31:56 -0700 Subject: [PATCH] Move RawMemSlot to ExtraData This simplifies things quite a bit since we don't have to stuff an enum value in and out of a constant int source. I also deduped some of the codegen logic between StRaw/StContArRaw LdRaw/LdContArRaw. Reviewed By: @edwinsmith Differential Revision: D1215180 --- hphp/runtime/base/string-data.h | 2 +- hphp/runtime/ext/ext_continuation.h | 5 +- hphp/runtime/vm/func.h | 4 +- hphp/runtime/vm/jit/code-gen-arm.cpp | 56 ++----- hphp/runtime/vm/jit/code-gen-arm.h | 1 + hphp/runtime/vm/jit/code-gen-x64.cpp | 249 +++++++++++++----------------- hphp/runtime/vm/jit/code-gen-x64.h | 2 + hphp/runtime/vm/jit/extra-data.cpp | 27 ++++ hphp/runtime/vm/jit/extra-data.h | 36 +++++ hphp/runtime/vm/jit/hhbc-translator.cpp | 30 ++-- hphp/runtime/vm/jit/ir.cpp | 2 + hphp/runtime/vm/jit/ir.h | 79 +--------- hphp/runtime/vm/jit/minstr-translator.cpp | 24 +-- hphp/runtime/vm/jit/native-calls.cpp | 4 +- hphp/runtime/vm/jit/reg-alloc.cpp | 2 - hphp/runtime/vm/jit/translator-runtime.h | 1 - hphp/runtime/vm/jit/type.cpp | 19 +-- 17 files changed, 233 insertions(+), 310 deletions(-) diff --git a/hphp/runtime/base/string-data.h b/hphp/runtime/base/string-data.h index 129eb9fdacb..bbfb644ffbf 100644 --- a/hphp/runtime/base/string-data.h +++ b/hphp/runtime/base/string-data.h @@ -166,7 +166,7 @@ struct StringData { /* * Offset accessor for the JIT compiler. */ - static std::ptrdiff_t sizeOffset() { return offsetof(StringData, m_len); } + static constexpr ptrdiff_t sizeOff() { return offsetof(StringData, m_len); } /* * Shared StringData's have a sweep list running through them for diff --git a/hphp/runtime/ext/ext_continuation.h b/hphp/runtime/ext/ext_continuation.h index 60b6b2cf5b6..0fd84cf7a52 100644 --- a/hphp/runtime/ext/ext_continuation.h +++ b/hphp/runtime/ext/ext_continuation.h @@ -35,7 +35,7 @@ FORWARD_DECLARE_CLASS(Continuation); struct c_Continuation : ExtObjectDataFlags { DECLARE_CLASS_NO_ALLOCATION(Continuation) - static constexpr uint startedOffset() { + static constexpr ptrdiff_t startedOff() { return offsetof(c_Continuation, o_subclassData); } bool started() const { return o_subclassData.u8[0]; } @@ -45,9 +45,10 @@ struct c_Continuation : ExtObjectDataFlags { Running = 1, Done = 2 }; - static constexpr uint stateOffset() { + static constexpr ptrdiff_t stateOff() { return offsetof(c_Continuation, o_subclassData) + 1; } + bool done() const { return o_subclassData.u8[1] & ContState::Done; } void setDone() { o_subclassData.u8[1] = ContState::Done; } diff --git a/hphp/runtime/vm/func.h b/hphp/runtime/vm/func.h index 1740bf767bd..093ce215cc6 100644 --- a/hphp/runtime/vm/func.h +++ b/hphp/runtime/vm/func.h @@ -462,7 +462,9 @@ struct Func { } public: // Offset accessors for the translator. -#define X(f) static ptrdiff_t f##Off() { return offsetof(Func, m_##f); } +#define X(f) static constexpr ptrdiff_t f##Off() { \ + return offsetof(Func, m_##f); \ + } X(attrs); X(unit); X(cls); diff --git a/hphp/runtime/vm/jit/code-gen-arm.cpp b/hphp/runtime/vm/jit/code-gen-arm.cpp index e444aedb7f4..37cc2eb87d4 100644 --- a/hphp/runtime/vm/jit/code-gen-arm.cpp +++ b/hphp/runtime/vm/jit/code-gen-arm.cpp @@ -19,6 +19,7 @@ #include "folly/Optional.h" +#include "hphp/runtime/ext/ext_continuation.h" #include "hphp/runtime/vm/jit/abi-arm.h" #include "hphp/runtime/vm/jit/arg-group.h" #include "hphp/runtime/vm/jit/code-gen-helpers-arm.h" @@ -1708,56 +1709,25 @@ void CodeGenerator::cgLdStack(IRInstruction* inst) { emitLoad(inst->dst()->type(), dstLoc(0), srcReg, offset); } -void CodeGenerator::cgLdRaw(IRInstruction* inst) { - auto* addr = inst->src(0); - auto* offset = inst->src(1); +void CodeGenerator::emitLdRaw(IRInstruction* inst, size_t extraOff) { auto destReg = x2a(dstLoc(0).reg()); - auto addrReg = x2a(srcLoc(0).reg()); - auto offsetLoc = srcLoc(1); + auto offset = inst->extra()->info().offset; + auto src = x2a(srcLoc(0).reg())[offset + extraOff]; - if (addr->isConst()) { - not_implemented(); + switch (inst->extra()->info().size) { + case sz::byte: m_as. Ldrb (destReg.W(), src); break; + case sz::dword: m_as. Ldr (destReg.W(), src); break; + case sz::qword: m_as. Ldr (destReg, src); break; + default: not_implemented(); } +} - if (offset->isConst()) { - auto kind = offset->intVal(); - auto& slot = RawMemSlot::Get(RawMemSlot::Kind(kind)); - auto ldSize = slot.size(); - auto offs = slot.offset(); - - switch (ldSize) { - case sz::qword: - m_as. Ldr (destReg, addrReg[offs]); - break; - case sz::dword: - m_as. Ldr (destReg.W(), addrReg[offs]); - break; - case sz::byte: - // Ldrb zero-extends - m_as. Ldrb (destReg.W(), addrReg[offs]); - break; - default: not_reached(); - } - } else { - auto offsetReg = x2a(offsetLoc.reg()); - assert(inst->dst()->type().nativeSize() == sz::qword); - m_as. Ldr (destReg, addrReg[offsetReg]); - } +void CodeGenerator::cgLdRaw(IRInstruction* inst) { + emitLdRaw(inst, 0); } void CodeGenerator::cgLdContArRaw(IRInstruction* inst) { - auto destReg = x2a(dstLoc(0).reg()); - auto contArReg = x2a(srcLoc(0).reg()); - auto kind = inst->src(1)->intVal(); - auto const& slot = RawMemSlot::Get(RawMemSlot::Kind(kind)); - - auto off = slot.offset() - c_Continuation::getArOffset(); - switch (slot.size()) { - case sz::byte: m_as. Ldrb (destReg.W(), contArReg[off]); break; - case sz::dword: m_as. Ldr (destReg.W(), contArReg[off]); break; - case sz::qword: m_as. Ldr (destReg, contArReg[off]); break; - default: not_implemented(); - } + emitLdRaw(inst, -c_Continuation::getArOffset()); } void CodeGenerator::cgLdARFuncPtr(IRInstruction* inst) { diff --git a/hphp/runtime/vm/jit/code-gen-arm.h b/hphp/runtime/vm/jit/code-gen-arm.h index 27703169021..d44a49d7e0f 100644 --- a/hphp/runtime/vm/jit/code-gen-arm.h +++ b/hphp/runtime/vm/jit/code-gen-arm.h @@ -103,6 +103,7 @@ struct CodeGenerator { ptrdiff_t offset, SSATmp* src, PhysLoc srcLoc, bool genStoreType = true); + void emitLdRaw(IRInstruction* inst, size_t extraOff); Address cgInst(IRInstruction* inst); diff --git a/hphp/runtime/vm/jit/code-gen-x64.cpp b/hphp/runtime/vm/jit/code-gen-x64.cpp index d3ee6e5cb0d..0b8e856fee5 100644 --- a/hphp/runtime/vm/jit/code-gen-x64.cpp +++ b/hphp/runtime/vm/jit/code-gen-x64.cpp @@ -747,9 +747,65 @@ static int64_t shuffleArgs(Asm& a, ArgGroup& args, CppCall& call) { } } - auto const howTo = doRegMoves(moves, rCgGP); + // Store any arguments past the initial 6 to the stack. This has to happen + // before the shuffles below in case the shuffles would clobber any of the + // srcRegs here. + for (int i = args.numStackArgs() - 1; i >= 0; --i) { + auto& arg = args.stk(i); + auto srcReg = arg.srcReg(); + assert(arg.dstReg() == InvalidReg); + switch (arg.kind()) { + case ArgDesc::Kind::Reg: + if (arg.isZeroExtend()) { + a. movzbl(rbyte(srcReg), r32(rCgGP)); + a. push(rCgGP); + } else { + if (srcReg.isSIMD()) { + emitMovRegReg(a, srcReg, rCgGP); + a.push(rCgGP); + } else { + a.push(srcReg); + } + } + break; + + case ArgDesc::Kind::TypeReg: + static_assert(kTypeWordOffset == 0 || kTypeWordOffset == 1, + "kTypeWordOffset value not supported"); + assert(srcReg.isGP()); + // x86 stacks grow down, so push higher offset items first + if (kTypeWordOffset == 0) { + a. pushl(eax); // 4 bytes of garbage overlapping m_aux + a. pushl(r32(srcReg)); + } else { + // 4 bytes of garbage: + a. pushl(eax); + // get the type in the right place in rCgGP before pushing it + a. movb (rbyte(srcReg), rbyte(rCgGP)); + a. shll (CHAR_BIT, r32(rCgGP)); + a. pushl(r32(rCgGP)); + } + break; + + case ArgDesc::Kind::Imm: + a. emitImmReg(arg.imm(), rCgGP); + a. push(rCgGP); + break; + + case ArgDesc::Kind::Addr: + not_implemented(); + + case ArgDesc::Kind::None: + a. push(rax); + if (RuntimeOption::EvalHHIRGenerateAsserts) { + a. storeq(0xbadbadbadbadbad, *rsp); + } + break; + } + } // Execute the plan + auto const howTo = doRegMoves(moves, rCgGP); for (auto& how : howTo) { if (how.m_kind == MoveInfo::Kind::Move) { if (how.m_reg2 == rCgGP) { @@ -813,60 +869,6 @@ static int64_t shuffleArgs(Asm& a, ArgGroup& args, CppCall& call) { } } - // Store any remaining arguments to the stack - for (int i = args.numStackArgs() - 1; i >= 0; --i) { - auto& arg = args.stk(i); - auto srcReg = arg.srcReg(); - assert(arg.dstReg() == InvalidReg); - switch (arg.kind()) { - case ArgDesc::Kind::Reg: - if (arg.isZeroExtend()) { - a. movzbl(rbyte(srcReg), r32(rCgGP)); - a. push(rCgGP); - } else { - if (srcReg.isSIMD()) { - emitMovRegReg(a, srcReg, rCgGP); - a.push(rCgGP); - } else { - a.push(srcReg); - } - } - break; - - case ArgDesc::Kind::TypeReg: - static_assert(kTypeWordOffset == 0 || kTypeWordOffset == 1, - "kTypeWordOffset value not supported"); - assert(srcReg.isGP()); - // x86 stacks grow down, so push higher offset items first - if (kTypeWordOffset == 0) { - a. pushl(eax); // 4 bytes of garbage overlapping m_aux - a. pushl(r32(srcReg)); - } else { - // 4 bytes of garbage: - a. pushl(eax); - // get the type in the right place in rCgGP before pushing it - a. movb (rbyte(srcReg), rbyte(rCgGP)); - a. shll (CHAR_BIT, r32(rCgGP)); - a. pushl(r32(rCgGP)); - } - break; - - case ArgDesc::Kind::Imm: - a. emitImmReg(arg.imm(), rCgGP); - a. push(rCgGP); - break; - - case ArgDesc::Kind::Addr: - not_implemented(); - - case ArgDesc::Kind::None: - a. push(rax); - if (RuntimeOption::EvalHHIRGenerateAsserts) { - a. storeq(0xbadbadbadbadbad, *rsp); - } - break; - } - } return args.numStackArgs() * sizeof(int64_t); } @@ -3905,58 +3907,6 @@ void CodeGenerator::cgLdARFuncPtr(IRInstruction* inst) { m_as.loadq(baseReg[offset->intVal() + AROFF(m_func)], dstReg); } -void CodeGenerator::cgLdRaw(IRInstruction* inst) { - PhysReg destReg = dstLoc(0).reg(); - Reg64 addrReg = srcLoc(0).reg(); - int64_t kind = inst->src(1)->intVal(); - - RawMemSlot& slot = RawMemSlot::Get(RawMemSlot::Kind(kind)); - int ldSize = slot.size(); - int64_t off = slot.offset(); - if (ldSize == sz::qword) { - m_as.loadq (addrReg[off], destReg); - } else if (ldSize == sz::dword) { - m_as.loadl (addrReg[off], r32(destReg)); - } else { - assert(ldSize == sz::byte); - m_as.loadzbl (addrReg[off], r32(destReg)); - } -} - -void CodeGenerator::cgStRaw(IRInstruction* inst) { - auto baseReg = srcLoc(0).reg(); - int64_t kind = inst->src(1)->intVal(); - SSATmp* value = inst->src(2); - - RawMemSlot& slot = RawMemSlot::Get(RawMemSlot::Kind(kind)); - assert(value->type() <= slot.type()); - int stSize = slot.size(); - int64_t off = slot.offset(); - auto dest = baseReg[off]; - - auto valueReg = srcLoc(2).reg(); - if (valueReg == InvalidReg) { - auto val = value->rawVal(); - if (stSize == sz::qword) { - m_as.storeq(val, dest); - } else if (stSize == sz::dword) { - m_as.storel(val, dest); - } else { - assert(stSize == sz::byte); - m_as.storeb(val, dest); - } - } else { - if (stSize == sz::qword) { - m_as.storeq(r64(valueReg), dest); - } else if (stSize == sz::dword) { - m_as.storel(r32(valueReg), dest); - } else { - assert(stSize == sz::byte); - m_as.storeb(rbyte(valueReg), dest); - } - } -} - void CodeGenerator::cgLdStaticLocCached(IRInstruction* inst) { auto const extra = inst->extra(); auto const link = RDS::bindStaticLocal(extra->func, extra->name); @@ -4200,9 +4150,9 @@ void CodeGenerator::cgStringIsset(IRInstruction* inst) { auto idxReg = srcLoc(1).reg(); auto dstReg = dstLoc(0).reg(); if (idxReg == InvalidReg) { - m_as.cmpl(inst->src(1)->intVal(), strReg[StringData::sizeOffset()]); + m_as.cmpl(inst->src(1)->intVal(), strReg[StringData::sizeOff()]); } else { - m_as.cmpl(r32(idxReg), strReg[StringData::sizeOffset()]); + m_as.cmpl(r32(idxReg), strReg[StringData::sizeOff()]); } m_as.setnbe(rbyte(dstReg)); } @@ -5532,8 +5482,8 @@ void CodeGenerator::cgContEnter(IRInstruction* inst) { void CodeGenerator::cgContPreNext(IRInstruction* inst) { auto contReg = srcLoc(0).reg(); - const Offset startedOffset = c_Continuation::startedOffset(); - const Offset stateOffset = c_Continuation::stateOffset(); + const Offset startedOffset = c_Continuation::startedOff(); + const Offset stateOffset = c_Continuation::stateOff(); // Check done and running at the same time m_as.testb(0x3, contReg[stateOffset]); emitFwdJcc(CC_NZ, inst->taken()); @@ -5545,7 +5495,7 @@ void CodeGenerator::cgContPreNext(IRInstruction* inst) { void CodeGenerator::cgContStartedCheck(IRInstruction* inst) { auto contReg = srcLoc(0).reg(); - auto startedOffset = c_Continuation::startedOffset(); + auto startedOffset = c_Continuation::startedOff(); m_as.testb(0x1, contReg[startedOffset]); emitFwdJcc(CC_Z, inst->taken()); @@ -5555,7 +5505,7 @@ void CodeGenerator::cgContSetRunning(IRInstruction* inst) { auto contReg = srcLoc(0).reg(); bool running = inst->src(1)->boolVal(); - const Offset stateOffset = c_Continuation::stateOffset(); + const Offset stateOffset = c_Continuation::stateOff(); if (running) { m_as.storeb(0x1, contReg[stateOffset]); } else { @@ -5567,7 +5517,7 @@ void CodeGenerator::cgContValid(IRInstruction* inst) { auto contReg = srcLoc(0).reg(); auto destReg = dstLoc(0).reg(); - m_as.loadzbl(contReg[c_Continuation::stateOffset()], r32(destReg)); + m_as.loadzbl(contReg[c_Continuation::stateOff()], r32(destReg)); m_as.shrl(0x1, r32(destReg)); m_as.xorb(0x1, rbyte(destReg)); } @@ -5607,48 +5557,59 @@ void CodeGenerator::cgLdContActRec(IRInstruction* inst) { m_as.lea (base[offset], dest) ; } -void CodeGenerator::cgLdContArRaw(IRInstruction* inst) { - auto destReg = dstLoc(0).reg(); - auto contArReg = srcLoc(0).reg(); - int64_t kind = inst->src(1)->intVal(); - RawMemSlot& slot = RawMemSlot::Get(RawMemSlot::Kind(kind)); - - int64_t off = slot.offset() - c_Continuation::getArOffset(); - switch (slot.size()) { - case sz::byte: m_as.loadzbl(contArReg[off], r32(destReg)); break; - case sz::dword: m_as.loadl(contArReg[off], r32(destReg)); break; - case sz::qword: m_as.loadq(contArReg[off], destReg); break; +void CodeGenerator::emitLdRaw(IRInstruction* inst, size_t extraOff) { + auto destReg = dstLoc(0).reg(); + auto offset = inst->extra()->info().offset; + auto src = srcLoc(0).reg()[offset + extraOff]; + + switch (inst->extra()->info().size) { + case sz::byte: m_as.loadzbl(src, r32(destReg)); break; + case sz::dword: m_as.loadl(src, r32(destReg)); break; + case sz::qword: m_as.loadq(src, destReg); break; default: not_implemented(); } } -void CodeGenerator::cgStContArRaw(IRInstruction* inst) { - auto contArReg = srcLoc(0).reg(); - int64_t kind = inst->src(1)->intVal(); - SSATmp* value = inst->src(2); - auto valueReg = srcLoc(2).reg(); - RawMemSlot& slot = RawMemSlot::Get(RawMemSlot::Kind(kind)); - - assert(value->type() <= slot.type()); - int64_t off = slot.offset() - c_Continuation::getArOffset(); - - if (value->isConst()) { - switch (slot.size()) { - case sz::byte: m_as.storeb(value->rawVal(), contArReg[off]); break; - case sz::dword: m_as.storel(value->rawVal(), contArReg[off]); break; - case sz::qword: m_as.storeq(value->rawVal(), contArReg[off]); break; +void CodeGenerator::cgLdRaw(IRInstruction* inst) { + emitLdRaw(inst, 0); +} + +void CodeGenerator::cgLdContArRaw(IRInstruction* inst) { + emitLdRaw(inst, -c_Continuation::getArOffset()); +} + +void CodeGenerator::emitStRaw(IRInstruction* inst, size_t extraOff) { + auto offset = inst->extra()->info().offset; + auto dest = srcLoc(0).reg()[offset + extraOff]; + auto size = inst->extra()->info().size; + + auto const valueReg = srcLoc(1).reg(); + if (valueReg == InvalidReg) { + auto const val = inst->src(0)->rawVal(); + switch (size) { + case sz::byte: m_as.storeb(val, dest); break; + case sz::dword: m_as.storel(val, dest); break; + case sz::qword: m_as.storeq(val, dest); break; default: not_implemented(); } } else { - switch (slot.size()) { - case sz::byte: m_as.storeb(rbyte(valueReg), contArReg[off]); break; - case sz::dword: m_as.storel(r32(valueReg), contArReg[off]); break; - case sz::qword: m_as.storeq(r64(valueReg), contArReg[off]); break; + switch (size) { + case sz::byte: m_as.storeb(rbyte(valueReg), dest); break; + case sz::dword: m_as.storel(r32(valueReg), dest); break; + case sz::qword: m_as.storeq(r64(valueReg), dest); break; default: not_implemented(); } } } +void CodeGenerator::cgStRaw(IRInstruction* inst) { + emitStRaw(inst, 0); +} + +void CodeGenerator::cgStContArRaw(IRInstruction* inst) { + emitStRaw(inst, -c_Continuation::getArOffset()); +} + void CodeGenerator::cgLdContArValue(IRInstruction* inst) { auto contArReg = srcLoc(0).reg(); const int64_t valueOff = CONTOFF(m_value); diff --git a/hphp/runtime/vm/jit/code-gen-x64.h b/hphp/runtime/vm/jit/code-gen-x64.h index 482b3376ac1..6ba56ca5121 100644 --- a/hphp/runtime/vm/jit/code-gen-x64.h +++ b/hphp/runtime/vm/jit/code-gen-x64.h @@ -315,6 +315,8 @@ private: void emitAdjustSp(PhysReg spReg, PhysReg dstReg, int64_t adjustment); void emitConvBoolOrIntToDbl(IRInstruction* inst); void cgLdClsMethodCacheCommon(IRInstruction* inst, Offset offset); + void emitLdRaw(IRInstruction* inst, size_t extraOff); + void emitStRaw(IRInstruction* inst, size_t extraOff); /* * Generate an if-block that branches around some unlikely code, handling diff --git a/hphp/runtime/vm/jit/extra-data.cpp b/hphp/runtime/vm/jit/extra-data.cpp index d8a14b86401..9d576f4d11d 100644 --- a/hphp/runtime/vm/jit/extra-data.cpp +++ b/hphp/runtime/vm/jit/extra-data.cpp @@ -15,6 +15,8 @@ */ #include "hphp/runtime/vm/jit/extra-data.h" + +#include "hphp/runtime/ext/ext_continuation.h" #include "hphp/runtime/vm/jit/ssa-tmp.h" #include "hphp/util/text-util.h" @@ -37,6 +39,31 @@ std::string NewStructData::show() const { return os.str(); } +const RawMemData::Info& RawMemData::info() const { + static const Info infos[] = { + {CONTOFF(m_label), sz::dword, JIT::Type::Int}, + {CONTOFF(m_index), sz::qword, JIT::Type::Int}, + {c_Continuation::stateOff(), sz::byte, JIT::Type::Int}, + {CONTOFF(m_entry), sz::qword, JIT::Type::TCA}, + {StringData::sizeOff(), sz::dword, JIT::Type::Int}, + {Func::numParamsOff(), sz::dword, JIT::Type::Int}, + }; + static_assert(sizeof infos / sizeof infos[0] == kNumTypes, + "Incorrect size of infos array"); + + always_assert(type < kNumTypes); + return infos[type]; +} + +std::string RawMemData::show() const { + switch (type) { +# define RAW_TYPE(name) case name: return #name; + RAW_MEM_DATA_TYPES +# undef RAW_TYPE + } + not_reached(); +} + ////////////////////////////////////////////////////////////////////// namespace { diff --git a/hphp/runtime/vm/jit/extra-data.h b/hphp/runtime/vm/jit/extra-data.h index 47d25805685..b8da6430584 100644 --- a/hphp/runtime/vm/jit/extra-data.h +++ b/hphp/runtime/vm/jit/extra-data.h @@ -726,6 +726,38 @@ struct NewStructData : IRExtraData { std::string show() const; }; +struct RawMemData : IRExtraData { +# define RAW_MEM_DATA_TYPES \ + RAW_TYPE(ContLabel) \ + RAW_TYPE(ContIndex) \ + RAW_TYPE(ContState) \ + RAW_TYPE(ContEntry) \ + RAW_TYPE(StrLen) \ + RAW_TYPE(FuncNumParams) \ + + enum Type : uint8_t { +# define RAW_TYPE(name) name, + RAW_MEM_DATA_TYPES +# undef RAW_TYPE + }; +# define RAW_TYPE(name) +1 + static constexpr size_t kNumTypes = RAW_MEM_DATA_TYPES; +# undef RAW_TYPE + + struct Info { + const int64_t offset; + const int size; + const JIT::Type type; + }; + + explicit RawMemData(Type t) : type(t) {} + + Type type; + + const Info& info() const; + std::string show() const; +}; + ////////////////////////////////////////////////////////////////////// #define X(op, data) \ @@ -856,6 +888,10 @@ X(RBTrace, RBTraceData); X(Shuffle, ShuffleData); X(ThingExists, ClassKindData); X(NewStructArray, NewStructData); +X(LdRaw, RawMemData); +X(StRaw, RawMemData); +X(LdContArRaw, RawMemData); +X(StContArRaw, RawMemData); #undef X diff --git a/hphp/runtime/vm/jit/hhbc-translator.cpp b/hphp/runtime/vm/jit/hhbc-translator.cpp index 783f64fbe5d..0342d4e6782 100644 --- a/hphp/runtime/vm/jit/hhbc-translator.cpp +++ b/hphp/runtime/vm/jit/hhbc-translator.cpp @@ -1530,9 +1530,7 @@ void HhbcTranslator::emitContEnter(int32_t returnBcOffset) { SSATmp* cont = gen(LdThis, m_irb->fp()); SSATmp* contAR = gen(LdContActRec, Type::FramePtr, cont); - SSATmp* funcBody = gen( - LdRaw, Type::TCA, cont, cns(RawMemSlot::ContEntry) - ); + SSATmp* funcBody = gen(LdRaw, RawMemData{RawMemData::ContEntry}, cont); // The top of the stack will be consumed by the callee, so discard // it without decreffing. @@ -1559,7 +1557,7 @@ void HhbcTranslator::emitContReturnControl() { } void HhbcTranslator::emitUnpackCont() { - push(gen(LdContArRaw, Type::Int, m_irb->fp(), cns(RawMemSlot::ContLabel))); + push(gen(LdContArRaw, RawMemData{RawMemData::ContLabel}, m_irb->fp())); } void HhbcTranslator::emitContSuspendImpl(int64_t labelId) { @@ -1569,7 +1567,8 @@ void HhbcTranslator::emitContSuspendImpl(int64_t labelId) { gen(DecRef, oldValue); // set m_label = labelId; - gen(StContArRaw, m_irb->fp(), cns(RawMemSlot::ContLabel), cns(labelId)); + gen(StContArRaw, RawMemData{RawMemData::ContLabel}, m_irb->fp(), + cns(labelId)); } void HhbcTranslator::emitContSuspend(int64_t labelId) { @@ -1578,10 +1577,10 @@ void HhbcTranslator::emitContSuspend(int64_t labelId) { // take a fast path if this generator has no yield k => v; if (curFunc()->isPairGenerator()) { // this needs optimization - auto const idx = gen(LdContArRaw, Type::Int, - m_irb->fp(), cns(RawMemSlot::ContIndex)); + auto const idx = + gen(LdContArRaw, RawMemData{RawMemData::ContIndex}, m_irb->fp()); auto const newIdx = gen(AddInt, idx, cns(1)); - gen(StContArRaw, m_irb->fp(), cns(RawMemSlot::ContIndex), newIdx); + gen(StContArRaw, RawMemData{RawMemData::ContIndex}, m_irb->fp(), newIdx); auto const oldKey = gen(LdContArKey, Type::Cell, m_irb->fp()); gen(StContArKey, m_irb->fp(), newIdx); @@ -1614,7 +1613,7 @@ void HhbcTranslator::emitContSuspendK(int64_t labelId) { void HhbcTranslator::emitContRetC() { // set state to done - gen(StContArRaw, m_irb->fp(), cns(RawMemSlot::ContState), + gen(StContArRaw, RawMemData{RawMemData::ContState}, m_irb->fp(), cns(c_Continuation::Done)); // set m_value = popC(); @@ -1638,9 +1637,9 @@ void HhbcTranslator::emitContCheck(bool checkStarted) { void HhbcTranslator::emitContRaise() { assert(curClass()); SSATmp* cont = gen(LdThis, m_irb->fp()); - SSATmp* label = gen(LdRaw, Type::Int, cont, cns(RawMemSlot::ContLabel)); + SSATmp* label = gen(LdRaw, RawMemData{RawMemData::ContLabel}, cont); label = gen(SubInt, label, cns(1)); - gen(StRaw, cont, cns(RawMemSlot::ContLabel), label); + gen(StRaw, RawMemData{RawMemData::ContLabel}, cont, label); } void HhbcTranslator::emitContValid() { @@ -1793,7 +1792,7 @@ void HhbcTranslator::emitStrlen() { // static string; fold its strlen operation push(cns(input->strVal()->size())); } else { - push(gen(LdRaw, Type::Int, input, cns(RawMemSlot::StrLen))); + push(gen(LdRaw, RawMemData{RawMemData::StrLen}, input)); gen(DecRef, input); } } else if (inType <= Type::Null) { @@ -3632,15 +3631,14 @@ void HhbcTranslator::guardRefs(int64_t entryArDelta, if (mask64 == 0) { continue; } - uint64_t vals64 = packBitVec(vals, i); if (i == 0) { nParams = cns(64); } else if (i == 64) { - nParams = gen( - LdRaw, Type::Int, funcPtr, cns(RawMemSlot::FuncNumParams) - ); + nParams = gen(LdRaw, RawMemData{RawMemData::FuncNumParams}, funcPtr); } + + uint64_t vals64 = packBitVec(vals, i); gen( GuardRefs, funcPtr, diff --git a/hphp/runtime/vm/jit/ir.cpp b/hphp/runtime/vm/jit/ir.cpp index 01fe5881b9b..a7fc34c41d0 100644 --- a/hphp/runtime/vm/jit/ir.cpp +++ b/hphp/runtime/vm/jit/ir.cpp @@ -78,6 +78,7 @@ namespace { #define DPtrToParam HasDest #define DBuiltin HasDest #define DSubtract(n,t) HasDest +#define DLdRaw HasDest struct { const char* name; @@ -123,6 +124,7 @@ struct { #undef DPtrToParam #undef DBuiltin #undef DSubtract +#undef DLdRaw } // namespace diff --git a/hphp/runtime/vm/jit/ir.h b/hphp/runtime/vm/jit/ir.h index db9641d717e..f906c3a262f 100644 --- a/hphp/runtime/vm/jit/ir.h +++ b/hphp/runtime/vm/jit/ir.h @@ -40,7 +40,6 @@ #include "hphp/util/asm-x64.h" #include "hphp/util/trace.h" #include "hphp/runtime/base/smart-containers.h" -#include "hphp/runtime/ext/ext_continuation.h" #include "hphp/runtime/vm/jit/phys-reg.h" #include "hphp/runtime/vm/jit/abi-x64.h" #include "hphp/runtime/vm/jit/types.h" @@ -155,6 +154,7 @@ class FailedCodeGen : public std::runtime_error { * DBuiltin single dst for CallBuiltin. This can return complex data * types such as (Type::Str | Type::Null) * DSubtract(N,t) single dest has type of src N with t removed + * DLdRaw single dst has type determined by RawMemData * * srcinfo: * @@ -499,7 +499,7 @@ O(NewPackedArray, D(Arr), C(Int) S(StkPtr), E|N|PRc|CRc) \ O(NewStructArray, D(Arr), S(StkPtr), E|N|PRc|CRc) \ O(NewCol, D(Obj), C(Int) C(Int), N|PRc) \ O(Clone, D(Obj), S(Obj), N|E|PRc|Er) \ -O(LdRaw, DParam, SUnk, NF) \ +O(LdRaw, DLdRaw, S(Str,Obj,Func), NF) \ O(FreeActRec, D(FramePtr), S(FramePtr), NF) \ /* name dstinfo srcinfo flags */ \ O(Call, D(StkPtr), SUnk, E|CRc) \ @@ -517,7 +517,7 @@ O(StProp, ND, S(Obj) C(Int) S(Gen), E|CRc) \ O(StLoc, ND, S(FramePtr) S(Gen), E|CRc) \ O(StLocNT, ND, S(FramePtr) S(Gen), E|CRc) \ O(StRef, DBox(1), S(BoxedCell) S(Cell), E|CRc|P) \ -O(StRaw, ND, SUnk, E) \ +O(StRaw, ND, S(Obj) S(Int), E) \ O(StElem, ND, S(PtrToCell) \ S(Int) \ S(Cell), E|CRc) \ @@ -618,8 +618,8 @@ O(ContValid, D(Bool), S(Obj), E) \ O(ContArIncKey, ND, S(FramePtr), E) \ O(ContArUpdateIdx, ND, S(FramePtr) S(Int), E) \ O(LdContActRec, DParam, S(Obj), C) \ -O(LdContArRaw, DParam, S(FramePtr) C(Int), NF) \ -O(StContArRaw, ND, S(FramePtr) C(Int) S(Gen), E) \ +O(LdContArRaw, DLdRaw, S(FramePtr), NF) \ +O(StContArRaw, ND, S(FramePtr) S(Int), E) \ O(LdContArValue, DParam, S(FramePtr), PRc) \ O(StContArValue, ND, S(FramePtr) S(Cell), E|CRc) \ O(LdContArKey, DParam, S(FramePtr), PRc) \ @@ -695,12 +695,14 @@ O(UnsetProp, ND, C(TCA) \ S(Obj,PtrToGen) \ S(Cell), E|N|Er) \ O_STK(SetOpProp, D(Cell), C(TCA) \ + C(Cls) \ S(Obj,PtrToGen) \ S(Cell) \ S(Cell) \ S(PtrToCell) \ C(Int), MProp|E|N|PRc|Er) \ O_STK(IncDecProp, D(Cell), C(TCA) \ + C(Cls) \ S(Obj,PtrToGen) \ S(Cell) \ S(PtrToCell) \ @@ -962,73 +964,6 @@ bool hasEdges(Opcode opc); bool opcodeHasFlags(Opcode opc, uint64_t flags); Opcode getStackModifyingOpcode(Opcode opc); -class RawMemSlot { - public: - - enum Kind { - ContLabel, ContIndex, ContState, - StrLen, FuncNumParams, ContEntry, MisCtx, MaxKind - }; - - static RawMemSlot& Get(Kind k) { - switch (k) { - case ContLabel: return GetContLabel(); - case ContIndex: return GetContIndex(); - case ContState: return GetContState(); - case StrLen: return GetStrLen(); - case FuncNumParams: return GetFuncNumParams(); - case ContEntry: return GetContEntry(); - case MisCtx: return GetMisCtx(); - default: not_reached(); - } - } - - int64_t offset() const { return m_offset; } - int32_t size() const { return m_size; } - Type type() const { return m_type; } - bool allowExtra() const { return m_allowExtra; } - - private: - RawMemSlot(int64_t offset, int32_t size, Type type, bool allowExtra = false) - : m_offset(offset), m_size(size), m_type(type), m_allowExtra(allowExtra) { } - - static RawMemSlot& GetContLabel() { - static RawMemSlot m(CONTOFF(m_label), sz::dword, Type::Int); - return m; - } - static RawMemSlot& GetContIndex() { - static RawMemSlot m(CONTOFF(m_index), sz::qword, Type::Int); - return m; - } - static RawMemSlot& GetContState() { - static RawMemSlot m(c_Continuation::stateOffset(), - sz::byte, Type::Int); - return m; - } - static RawMemSlot& GetStrLen() { - static RawMemSlot m(StringData::sizeOffset(), sz::dword, Type::Int); - return m; - } - static RawMemSlot& GetFuncNumParams() { - static RawMemSlot m(Func::numParamsOff(), sz::dword, Type::Int); - return m; - } - static RawMemSlot& GetContEntry() { - static RawMemSlot m(CONTOFF(m_entry), sz::qword, Type::TCA); - return m; - } - static RawMemSlot& GetMisCtx() { - static RawMemSlot m(MISOFF(ctx), sz::qword, Type::Cls); - return m; - } - - int64_t m_offset; - int32_t m_size; - Type m_type; - bool m_allowExtra; // Used as a flag to ensure that extra offets are - // only used with RawMemSlots that support it -}; - bool isRefCounted(SSATmp* opnd); using folly::Range; diff --git a/hphp/runtime/vm/jit/minstr-translator.cpp b/hphp/runtime/vm/jit/minstr-translator.cpp index d449bf00ba2..ced5331e46d 100644 --- a/hphp/runtime/vm/jit/minstr-translator.cpp +++ b/hphp/runtime/vm/jit/minstr-translator.cpp @@ -1495,10 +1495,11 @@ void HhbcTranslator::MInstrTranslator::emitSetProp() { #undef HELPER_TABLE template -static inline TypedValue setOpPropImpl(TypedValue* base, TypedValue keyVal, +static inline TypedValue setOpPropImpl(Class* ctx, TypedValue* base, + TypedValue keyVal, Cell val, MInstrState* mis, SetOpOp op) { TypedValue* result = HPHP::SetOpProp( - mis->tvScratch, mis->tvRef, mis->ctx, op, base, &keyVal, &val); + mis->tvScratch, mis->tvRef, ctx, op, base, &keyVal, &val); Cell ret; cellDup(*tvToCell(result), ret); @@ -1511,9 +1512,9 @@ static inline TypedValue setOpPropImpl(TypedValue* base, TypedValue keyVal, m(setOpPropCO, true) #define SETOP(nm, ...) \ -TypedValue nm(TypedValue* base, TypedValue key, \ +TypedValue nm(Class* ctx, TypedValue* base, TypedValue key, \ Cell val, MInstrState* mis, SetOpOp op) { \ - return setOpPropImpl<__VA_ARGS__>(base, key, val, mis, op); \ + return setOpPropImpl<__VA_ARGS__>(ctx, base, key, val, mis, op); \ } namespace MInstrHelpers { HELPER_TABLE(SETOP) @@ -1527,19 +1528,19 @@ void HhbcTranslator::MInstrTranslator::emitSetOpProp() { typedef TypedValue (*OpFunc)(TypedValue*, TypedValue, Cell, MInstrState*, SetOpOp); BUILD_OPTAB(m_base->isA(Type::Obj)); - m_irb.gen(StRaw, m_misBase, cns(RawMemSlot::MisCtx), CTX()); m_result = genStk(SetOpProp, makeCatch(), cns((TCA)opFunc), - m_base, key, value, genMisPtr(), cns(op)); + CTX(), m_base, key, value, genMisPtr(), cns(op)); } #undef HELPER_TABLE template -static inline TypedValue incDecPropImpl(TypedValue* base, TypedValue keyVal, +static inline TypedValue incDecPropImpl(Class* ctx, TypedValue* base, + TypedValue keyVal, MInstrState* mis, IncDecOp op) { TypedValue result; result.m_type = KindOfUninit; HPHP::IncDecProp( - mis->tvScratch, mis->tvRef, mis->ctx, op, base, &keyVal, result); + mis->tvScratch, mis->tvRef, ctx, op, base, &keyVal, result); assert(result.m_type != KindOfRef); return result; } @@ -1551,9 +1552,9 @@ static inline TypedValue incDecPropImpl(TypedValue* base, TypedValue keyVal, m(incDecPropCO, true) #define INCDEC(nm, ...) \ -TypedValue nm(TypedValue* base, TypedValue key, \ +TypedValue nm(Class* ctx, TypedValue* base, TypedValue key, \ MInstrState* mis, IncDecOp op) { \ - return incDecPropImpl<__VA_ARGS__>(base, key, mis, op); \ + return incDecPropImpl<__VA_ARGS__>(ctx, base, key, mis, op); \ } namespace MInstrHelpers { HELPER_TABLE(INCDEC) @@ -1566,9 +1567,8 @@ void HhbcTranslator::MInstrTranslator::emitIncDecProp() { typedef TypedValue (*OpFunc)(TypedValue*, TypedValue, MInstrState*, IncDecOp); BUILD_OPTAB(m_base->isA(Type::Obj)); - m_irb.gen(StRaw, m_misBase, cns(RawMemSlot::MisCtx), CTX()); m_result = genStk(IncDecProp, makeCatch(), cns((TCA)opFunc), - m_base, key, genMisPtr(), cns(op)); + CTX(), m_base, key, genMisPtr(), cns(op)); } #undef HELPER_TABLE diff --git a/hphp/runtime/vm/jit/native-calls.cpp b/hphp/runtime/vm/jit/native-calls.cpp index fa34185fd6c..82797c3d2f6 100644 --- a/hphp/runtime/vm/jit/native-calls.cpp +++ b/hphp/runtime/vm/jit/native-calls.cpp @@ -283,9 +283,9 @@ static CallMap s_callMap { {UnsetProp, fssa(0), DNone, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}}}, {SetOpProp, fssa(0), DTV, SSync, - {{SSA, 1}, {TV, 2}, {TV, 3}, {SSA, 4}, {SSA, 5}}}, + {{SSA, 1}, {SSA, 2}, {TV, 3}, {TV, 4}, {SSA, 5}, {SSA, 6}}}, {IncDecProp, fssa(0), DTV, SSync, - {{SSA, 1}, {TV, 2}, {SSA, 3}, {SSA, 4}}}, + {{SSA, 1}, {SSA, 2}, {TV, 3}, {SSA, 4}, {SSA, 5}}}, {EmptyProp, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}}}, {IssetProp, fssa(0), DSSA, SSync, diff --git a/hphp/runtime/vm/jit/reg-alloc.cpp b/hphp/runtime/vm/jit/reg-alloc.cpp index af49c18d8f9..c0a05614068 100644 --- a/hphp/runtime/vm/jit/reg-alloc.cpp +++ b/hphp/runtime/vm/jit/reg-alloc.cpp @@ -147,8 +147,6 @@ bool mustUseConst(const IRInstruction& inst, int i) { case LdAddr: return check(i == 1); // offset case Call: return check(i == 1); // returnBcOffset case CallBuiltin: return check(i == 0); // f - case LdRaw: return check(i == 1); // offset - case StRaw: return check(i == 1); // offset default: break; } return check(g_const_table.mustBeConst(int(inst.op()), i)); diff --git a/hphp/runtime/vm/jit/translator-runtime.h b/hphp/runtime/vm/jit/translator-runtime.h index 1bd44d658c0..4d47341f400 100644 --- a/hphp/runtime/vm/jit/translator-runtime.h +++ b/hphp/runtime/vm/jit/translator-runtime.h @@ -55,7 +55,6 @@ struct MInstrState { TypedValue tvRef2; TypedValue tvResult; TypedValue tvVal; - Class* ctx; } __attribute__((aligned(16))); static_assert(offsetof(MInstrState, tvScratch) % 16 == 0, "MInstrState members require 16-byte alignment for SSE"); diff --git a/hphp/runtime/vm/jit/type.cpp b/hphp/runtime/vm/jit/type.cpp index 695a9023414..0fc6d074759 100644 --- a/hphp/runtime/vm/jit/type.cpp +++ b/hphp/runtime/vm/jit/type.cpp @@ -737,6 +737,7 @@ Type outputType(const IRInstruction* inst, int dstId) { #define ND assert(0 && "outputType requires HasDest or NaryDest"); #define DBuiltin return builtinReturn(inst); #define DSubtract(n, t) return inst->src(n)->type() - t; +#define DLdRaw return inst->extra()->info().type; #define O(name, dstinfo, srcinfo, flags) case name: dstinfo not_reached(); @@ -762,6 +763,7 @@ Type outputType(const IRInstruction* inst, int dstId) { #undef ND #undef DBuiltin #undef DSubtract +#undef DLdRaw } @@ -894,19 +896,6 @@ void assertOperandTypes(const IRInstruction* inst) { } }; - auto checkCustom = [&] { - switch (inst->op()) { - case LdRaw: - case StRaw: { - auto s1 = inst->src(1); // field kind - check(s1->isConst() && s1->isA(Type::Int), Type::Int, nullptr); - break; - } - default: - break; - } - }; - #define IRT(name, ...) UNUSED static const Type name = Type::name; IR_TYPES #undef IRT @@ -923,7 +912,7 @@ void assertOperandTypes(const IRInstruction* inst) { "constant " #type); \ ++curSrc; #define CStr C(StaticStr) -#define SUnk return checkCustom(); +#define SUnk return; #define SSpills checkSpills(); #define ND #define DMulti @@ -946,6 +935,7 @@ void assertOperandTypes(const IRInstruction* inst) { #define DLdRef requireTypeParam(); #define DAllocObj #define DThis +#define DLdRaw #define O(opcode, dstinfo, srcinfo, flags) \ case opcode: dstinfo srcinfo countCheck(); return; @@ -979,6 +969,7 @@ void assertOperandTypes(const IRInstruction* inst) { #undef DAllocObj #undef DLdRef #undef DThis +#undef DLdRaw } -- 2.11.4.GIT