Allow using ExtraData-supplied immediates in native-calls.cpp

Ports CreateCont* opcodes to use extra data for their
compile-time constants as a test case.
Esse commit está contido em:
Jordan DeLong
2013-07-18 13:44:08 -07:00
commit de Sara Golemon
commit e28e3f205e
9 arquivos alterados com 132 adições e 64 exclusões
+5 -11
Ver Arquivo
@@ -1518,20 +1518,14 @@ D:Obj = CreateCl S0:ConstCls S1:ConstInt S2:FramePtr S3:StkPtr
object. Saves the $this and Func* from ActRec S2 into the object,
and returns the object.
D:Obj = CreateContFunc S0:ConstFunc S1:ConstFunc
D:Obj = CreateContFunc<origFunc,generatorFunc>
Create a continuation object from function. Arguments:
Create a continuation object for a generator function.
S0 - the "original" function
S1 - the generator function
D:Obj = CreateContMeth<origFunc,generatorFunc> S0:Ctx
D:Obj = CreateContMeth S0:ConstFunc S1:ConstFunc S2:Ctx
Create a continuation object from method. Arguments:
S0 - the "original" method
S1 - the generator function
S2 - the m_this/m_cls field of the current frame pointer
Create a continuation object for a generator method. S0 is the
m_this/m_cls field of the current frame pointer.
ContEnter S0:FramePtr S1:TCA S2:ConstInt S3:FramePtr
+5 -2
Ver Arquivo
@@ -340,7 +340,7 @@ Address CodeGenerator::cgInst(IRInstruction* inst) {
void CodeGenerator::cg##opcode(IRInstruction*) {}
#define CALL_OPCODE(opcode) \
void CodeGenerator::cg##opcode(IRInstruction* i) { cgCallNative(i); }
void CodeGenerator::cg##opcode(IRInstruction* i) { cgCallNative(m_as, i); }
#define CALL_STK_OPCODE(opcode) \
CALL_OPCODE(opcode) \
@@ -1046,6 +1046,9 @@ void CodeGenerator::cgCallNative(Asm& a, IRInstruction* inst) {
case VecKeyIS:
argGroup.vectorKeyIS(src);
break;
case ExtraImm:
argGroup.imm(arg.extraFunc(inst));
break;
}
}
@@ -5768,7 +5771,7 @@ void CodeGenerator::cgVerifyParamCls(IRInstruction* inst) {
// The native call for this instruction is the slow path that does
// proper subtype checking. The comparison above is just to
// short-circuit the overhead when the Classes are an exact match.
ifThen(m_as, CC_NE, [&]{ cgCallNative(inst); });
ifThen(m_as, CC_NE, [&]{ cgCallNative(m_as, inst); });
}
static void emitTraceCall(CodeGenerator::Asm& as,
-3
Ver Arquivo
@@ -140,9 +140,6 @@ private:
#undef O
// helper functions for code generation
void cgCallNative(IRInstruction* inst) {
cgCallNative(m_as, inst);
}
void cgCallNative(Asm& a, IRInstruction* inst);
void doStackArgs(Asm&, ArgGroup&);
void cgCallHelper(Asm&,
+22 -27
Ver Arquivo
@@ -154,30 +154,8 @@ struct FPushCufData : IRExtraData {
struct ConstData : IRExtraData {
template<class T>
explicit ConstData(T data)
: m_dataBits(0)
{
static_assert(sizeof(T) <= sizeof m_dataBits,
"Constant data was larger than supported");
static_assert(std::is_pod<T>::value,
"Constant data wasn't a pod?");
const auto toCopy = promoteIfNeeded(data);
std::memcpy(&m_dataBits, &toCopy, sizeof(toCopy));
}
template<typename T>
struct needsPromotion {
static constexpr bool value = std::is_integral<T>::value ||
std::is_same<T,bool>::value ||
std::is_enum<T>::value;
};
template<class T>
typename std::enable_if<needsPromotion<T>::value, int64_t>::type
promoteIfNeeded(T t) { return t; }
template<class T>
typename std::enable_if<!needsPromotion<T>::value, T>::type
promoteIfNeeded(T t) { return t; }
: m_dataBits(constToBits(data))
{}
template<class T>
T as() const {
@@ -324,9 +302,6 @@ struct CheckDefinedClsData : IRExtraData {
* Offset and stack deltas for InterpOne.
*/
struct InterpOneData : IRExtraData {
InterpOneData(Offset o, int64_t pop, int64_t push, Op op)
: bcOff(o), cellsPopped(pop), cellsPushed(push), opcode(op) {}
// Offset of the instruction to interpret, in the Unit indicated by
// the current Marker.
Offset bcOff;
@@ -341,6 +316,24 @@ struct InterpOneData : IRExtraData {
Op opcode;
};
/*
* Information for creating continuation objects.
* CreateCont{Func,Meth}.
*/
struct CreateContData : IRExtraData {
CreateContData(const Func* origFunc, const Func* genFunc)
: origFunc(origFunc)
, genFunc(genFunc)
{}
std::string show() const {
return folly::to<std::string>(origFunc->fullName()->data(), "()");
}
const Func* origFunc;
const Func* genFunc;
};
//////////////////////////////////////////////////////////////////////
#define X(op, data) \
@@ -405,6 +398,8 @@ X(SideExitGuardLoc, SideExitGuardData);
X(SideExitGuardStk, SideExitGuardData);
X(CheckDefinedClsEq, CheckDefinedClsData);
X(InterpOne, InterpOneData);
X(CreateContFunc, CreateContData);
X(CreateContMeth, CreateContData);
#undef X
+10 -7
Ver Arquivo
@@ -1152,14 +1152,12 @@ void HhbcTranslator::emitCreateCont(Id funNameStrId) {
auto const cont = origFunc->isMethod()
? gen(
CreateContMeth,
cns(origFunc),
cns(genFunc),
CreateContData { origFunc, genFunc },
gen(LdCtx, m_tb->fp(), cns(curFunc()))
)
: gen(
CreateContFunc,
cns(origFunc),
cns(genFunc)
CreateContData { origFunc, genFunc }
);
ContParamMap params;
@@ -3805,9 +3803,14 @@ void HhbcTranslator::emitInterpOne(Type outType, int popped) {
void HhbcTranslator::emitInterpOne(Type outType, int popped, int pushed) {
auto sp = spillStack();
Unit *u = curFunc()->unit();
gen(InterpOne, outType, InterpOneData(bcOff(), popped, pushed,
u->getOpcode(bcOff())),
m_tb->fp(), sp);
InterpOneData idata;
idata.bcOff = bcOff();
idata.cellsPopped = popped;
idata.cellsPushed = pushed;
idata.opcode = u->getOpcode(bcOff());
gen(InterpOne, outType, idata, m_tb->fp(), sp);
assert(m_stackDeficit == 0);
}
+42 -2
Ver Arquivo
@@ -475,8 +475,8 @@ O(InterpOneCF, ND, S(FramePtr) S(StkPtr) \
C(Int), T|E|N|Mem|Refs|Er) \
O(Spill, DofS(0), SUnk, Mem) \
O(Reload, DofS(0), SUnk, Mem) \
O(CreateContFunc, D(Obj), C(Func) C(Func), E|N|PRc) \
O(CreateContMeth, D(Obj), C(Func) C(Func) S(Ctx), E|N|PRc) \
O(CreateContFunc, D(Obj), NA, E|N|PRc) \
O(CreateContMeth, D(Obj), S(Ctx), E|N|PRc) \
O(ContEnter, ND, S(FramePtr) \
S(TCA) C(Int) S(FramePtr), E|Mem) \
O(ContPreNext, ND, S(Obj), E|Mem) \
@@ -840,6 +840,46 @@ inline Type typeForConst(const ArrayData* ad) {
return Type::Arr;
}
/*
* constToBits(T)
*
* Returns a constant value as a 8-byte word (in the shape it would
* need to be to go into a register). Takes care to ensure that
* various types are safely copied.
*/
namespace constToBits_detail {
template<class T>
struct needs_promotion
: std::integral_constant<
bool,
std::is_integral<T>::value ||
std::is_same<T,bool>::value ||
std::is_enum<T>::value
>
{};
template<class T>
typename std::enable_if<needs_promotion<T>::value,uint64_t>::type
promoteIfNeeded(T t) { return t; }
template<class T>
typename std::enable_if<!needs_promotion<T>::value,T>::type
promoteIfNeeded(T t) { return t; }
}
template<class T>
uintptr_t constToBits(T input) {
uintptr_t ret;
static_assert(sizeof(T) <= sizeof ret,
"Constant data was larger than supported");
static_assert(std::is_pod<T>::value,
"Constant data wasn't a pod?");
const auto toCopy = constToBits_detail::promoteIfNeeded(input);
std::memcpy(&ret, &toCopy, sizeof toCopy);
return ret;
}
bool cmpOpTypesMayReenter(Opcode, Type t0, Type t1);
class RawMemSlot {
+2
Ver Arquivo
@@ -780,6 +780,8 @@ void LinearScan::computePreColoringHint() {
m_preColoringHint.add(inst->src(arg.srcIdx), 0, reg++);
m_preColoringHint.add(inst->src(arg.srcIdx), 1, reg++);
break;
case ExtraImm:
break;
}
}
return;
+29 -10
Ver Arquivo
@@ -27,13 +27,28 @@ namespace HPHP { namespace JIT { namespace NativeCalls {
using namespace HPHP::Transl;
using namespace HPHP::Transl::TargetCache;
const SyncOptions SNone = SyncOptions::kNoSyncPoint;
const SyncOptions SSync = SyncOptions::kSyncPoint;
const SyncOptions SSyncAdj1 = SyncOptions::kSyncPointAdjustOne;
namespace {
const DestType DSSA = DestType::SSA;
const DestType DTV = DestType::TV;
const DestType DNone = DestType::None;
constexpr SyncOptions SNone = SyncOptions::kNoSyncPoint;
constexpr SyncOptions SSync = SyncOptions::kSyncPoint;
constexpr SyncOptions SSyncAdj1 = SyncOptions::kSyncPointAdjustOne;
constexpr DestType DSSA = DestType::SSA;
constexpr DestType DTV = DestType::TV;
constexpr DestType DNone = DestType::None;
template<class EDType, class MemberType>
Arg extra(MemberType EDType::*ptr) {
auto fun = [ptr] (IRInstruction* inst) {
auto const extra = inst->extra<EDType>();
return constToBits(extra->*ptr);
};
return Arg(fun);
}
}
//////////////////////////////////////////////////////////////////////
/*
* The table passed to s_callMap's constructor describes helpers calls
@@ -65,8 +80,9 @@ const DestType DNone = DestType::None;
* {VecKeyS, idx} - Like TV, but Str values are passed as a raw
* StringData*, in a single register
* {VecKeyIS, idx} - Like VecKeyS, including Int
* extra(&EDStruct::member) -- extract an immediate from extra data
*/
static CallMap s_callMap({
static CallMap s_callMap {
/* Opcode, Func, Dest, SyncPoint, Args */
{ConvBoolToArr, (TCA)convCellToArrHelper, DSSA, SNone,
{{TV, 0}}},
@@ -175,9 +191,12 @@ static CallMap s_callMap({
/* Continuation support helpers */
{CreateContFunc, (TCA)&VMExecutionContext::createContFunc, DSSA, SNone,
{{SSA, 0}, {SSA, 1}}},
{ extra(&CreateContData::origFunc),
extra(&CreateContData::genFunc) }},
{CreateContMeth, (TCA)&VMExecutionContext::createContMeth, DSSA, SNone,
{{SSA, 0}, {SSA, 1}, {SSA, 2}}},
{ extra(&CreateContData::origFunc),
extra(&CreateContData::genFunc),
{SSA, 0} }},
/* VectorTranslator helpers */
{BaseG, {FSSA, 0}, DSSA, SSync, {{TV, 1}, {SSA, 2}}},
@@ -267,7 +286,7 @@ static CallMap s_callMap({
/* debug assert helpers */
{DbgAssertPtr, (TCA)assertTv, DNone, SNone, {{SSA, 0}}},
});
};
CallMap::CallMap(CallInfoList infos) {
for (auto const& info : infos) {
+17 -2
Ver Arquivo
@@ -18,6 +18,7 @@
#define incl_HPHP_VM_TRANSL_HOPT_NATIVECALLS_H_
#include <initializer_list>
#include <functional>
#include <vector>
#include "hphp/runtime/vm/jit/types.h"
@@ -51,19 +52,33 @@ enum ArgType : unsigned {
TV,
VecKeyS,
VecKeyIS,
ExtraImm,
};
// Function that extracts the bits for an immediate value from extra
// data.
typedef std::function<uintptr_t (IRInstruction*)> ExtraDataBits;
struct Arg {
Arg(ArgType type, unsigned srcIdx) : type(type), srcIdx(srcIdx) {}
explicit Arg(ExtraDataBits&& func)
: type(ExtraImm)
, srcIdx(-1u)
, extraFunc(std::move(func))
{}
ArgType type;
unsigned srcIdx;
ExtraDataBits extraFunc;
};
typedef std::vector<Arg> ArgVec;
struct CallInfo {
Opcode op;
FuncPtr func;
DestType dest;
SyncOptions sync;
ArgVec args;
std::vector<Arg> args;
};
typedef std::initializer_list<CallInfo> CallInfoList;