/* * "switch" statement */ void doswitch (void ) { INTPTR_T ws[7]; INTPTR_T *ptr; ws[WSSYM] = (INTPTR_T)locptr; ws[WSSP] = stkp; ws[WSTYP] = WSSWITCH; ws[WSCASEP] = swstp; ws[WSTAB] = getlabel (); ws[WSDEF] = ws[WSEXIT] = getlabel (); addwhile (ws); immed (T_LABEL, ws[WSTAB]); gpush (); needbrack ("("); expression (YES); needbrack (")"); stkp = stkp + INTSIZE; /* '?case' will adjust the stack */ gjcase (); statement (NO); ptr = readswitch (); jump (ptr[WSEXIT]); dumpsw (ptr); gnlabel (ptr[WSEXIT]); locptr = (char*)ptr[WSSYM]; stkp = modstk (ptr[WSSP]); swstp = ptr[WSCASEP]; delwhile (); }
void cgKillClsRef(IRLS& env, const IRInstruction* inst) { if (!debug) return; auto& v = vmain(env); auto const fp = srcLoc(env, inst, 0).reg(); auto const off = frame_clsref_offset( funcFromFp(inst->src(0)), inst->extra<ClsRefSlotData>()->slot ); LowPtr<Class> trash; memset(&trash, kTrashClsRef, sizeof(trash)); Immed64 immed(trash.get()); if (sizeof(trash) == 4) { v << storeli{immed.l(), fp[off]}; } else if (sizeof(trash) == 8) { if (immed.fits(sz::dword)) { v << storeqi{immed.l(), fp[off]}; } else { v << store{v.cns(immed.q()), fp[off]}; } } else { not_implemented(); } }
inline void Assembler::ldub( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldub_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
inline void Assembler::ldxfsr( Register s1, int simm13a) { v9_only(); emit_data( op(ldst_op) | rd(G1) | op3(ldfsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d, RelocationHolder const& rspec) { emit_data( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); }
inline void Assembler::jmpl( Register s1, int simm13a, Register d, RelocationHolder const& rspec ) { insert_nop_after_cbcond(); cti(); emit_data( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); has_delay_slot(); }
inline void Assembler::flush( Register s1, int simm13a) { emit_data( op(arith_op) | op3(flush_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
inline void Assembler::cbcond(Condition c, CC cc, Register s1, int simm5, Label& L) { cti(); no_cbcond_before(); emit_data(op(branch_op) | cond_cbcond(c) | op2(bpr_op2) | branchcc(cc) | wdisp10(intptr_t(target(L)), intptr_t(pc())) | rs1(s1) | immed(true) | simm(simm5, 5)); }
inline void Assembler::swap( Register s1, int simm13a, Register d) { v9_dep(); emit_data( op(ldst_op) | rd(d) | op3(swap_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
inline void Assembler::std( Register d, Register s1, int simm13a) { v9_dep(); assert(d->is_even(), "not even"); emit_data( op(ldst_op) | rd(d) | op3(std_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
inline void Assembler::stx( Register d, Register s1, int simm13a) { v9_only(); emit_data( op(ldst_op) | rd(d) | op3(stx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
inline void Assembler::stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a) { emit_data( op(ldst_op) | fd(d, w) | alt_op3(stf_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
inline void Assembler::rett( Register s1, int simm13a, relocInfo::relocType rt) { cti(); emit_data( op(arith_op) | op3(rett_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rt); has_delay_slot(); }
namespace HPHP { namespace JIT { namespace NativeCalls { namespace { constexpr SyncOptions SNone = SyncOptions::kNoSyncPoint; constexpr SyncOptions SSync = SyncOptions::kSyncPoint; constexpr SyncOptions SSyncAdj1 = SyncOptions::kSyncPointAdjustOne; constexpr DestType DSSA = DestType::SSA; constexpr DestType DSSA2 = DestType::SSA2; constexpr DestType DTV = DestType::TV; constexpr DestType DNone = DestType::None; template<class EDType, class MemberType> Arg extra(MemberType EDType::*ptr) { auto fun = [ptr] (const IRInstruction* inst) { auto const extra = inst->extra<EDType>(); return Type::cns(extra->*ptr).rawVal(); }; return Arg(fun); } Arg immed(intptr_t imm) { return Arg(ArgType::Imm, imm); } FuncPtr fssa(uint64_t i) { return FuncPtr { FuncType::SSA, i }; } template<class Ret, class T, class... Args> FuncPtr method(Ret (T::*fp)(Args...) const) { return FuncPtr(reinterpret_cast<TCA>(getMethodPtr(fp))); } template<class Ret, class T, class... Args> FuncPtr method(Ret (T::*fp)(Args...)) { return FuncPtr(reinterpret_cast<TCA>(getMethodPtr(fp))); } auto constexpr SSA = ArgType::SSA; auto constexpr TV = ArgType::TV; auto constexpr MemberKeyS = ArgType::MemberKeyS; auto constexpr MemberKeyIS = ArgType::MemberKeyIS; using IFaceSupportFn = bool (*)(const StringData*); } ////////////////////////////////////////////////////////////////////// /* * The table passed to s_callMap's constructor describes helpers calls * used by translated code. Each row consists of the following values: * * Opcode * The opcode that uses the call * * Func * A value describing the function to call: * <function pointer> - Raw function pointer * method(<pointer to member>) - Dispatch to a C++ member function---the * function must be non-virtual. * fssa(idx) - Use a const TCA from inst->src(idx) * * Dest * DSSA - The helper returns a single-register value * DSSA2 - The helper returns a two-register value * DTV - The helper returns a TypedValue in two registers * DNone - The helper does not return a value * * SyncPoint * SNone - The helper does not need a sync point * SSync - The helper needs a normal sync point * SSyncAdj1 - The helper needs a sync point that skips top of stack on unwind * * Args * A list of tuples describing the arguments to pass to the helper * {SSA, idx} - Pass the value in inst->src(idx) * {TV, idx} - Pass the value in inst->src(idx) as a * TypedValue, in two registers * {MemberKeyS, idx} - Like TV, but Str values are passed as a raw * StringData*, in a single register * {MemberKeyIS, idx} - Like MemberKeyS, including Int * extra(&EDStruct::member) - extract an immediate from extra data * immed(int64_t) - constant immediate */ static CallMap s_callMap { /* Opcode, Func, Dest, SyncPoint, Args */ {TypeProfileFunc, profileOneArgument, DNone, SNone, {{TV,0}, extra(&TypeProfileData::param), {SSA, 1}}}, {ConvBoolToArr, convCellToArrHelper, DSSA, SNone, {{TV, 0}}}, {ConvDblToArr, convCellToArrHelper, DSSA, SNone, {{TV, 0}}}, {ConvIntToArr, convCellToArrHelper, DSSA, SNone, {{TV, 0}}}, {ConvObjToArr, convCellToArrHelper, DSSA, SNone, {{TV, 0}}}, {ConvStrToArr, convCellToArrHelper, DSSA, SNone, {{TV, 0}}}, {ConvCellToArr, convCellToArrHelper, DSSA, SNone, {{TV, 0}}}, {ConvStrToBool, method(&StringData::toBoolean), DSSA, SNone, {{SSA, 0}}}, {ConvCellToBool, cellToBool, DSSA, SNone, {{TV, 0}}}, {ConvArrToDbl, convArrToDblHelper, DSSA, SNone, {{SSA, 0}}}, {ConvObjToDbl, convCellToDblHelper, DSSA, SSync, {{TV, 0}}}, {ConvStrToDbl, convStrToDblHelper, DSSA, SSync, {{SSA, 0}}}, {ConvCellToDbl, convCellToDblHelper, DSSA, SSync, {{TV, 0}}}, {ConvArrToInt, convArrToIntHelper, DSSA, SNone, {{SSA, 0}}}, {ConvObjToInt, cellToInt, DSSA, SSync, {{TV, 0}}}, {ConvStrToInt, method(&StringData::toInt64), DSSA, SNone, {{SSA, 0}, immed(10)}}, {ConvCellToInt, cellToInt, DSSA, SSync, {{TV, 0}}}, {ConvCellToObj, convCellToObjHelper, DSSA, SSync, {{TV, 0}}}, {ConvDblToStr, convDblToStrHelper, DSSA, SNone, {{SSA, 0}}}, {ConvIntToStr, convIntToStrHelper, DSSA, SNone, {{SSA, 0}}}, {ConvObjToStr, convObjToStrHelper, DSSA, SSync, {{SSA, 0}}}, {ConvResToStr, convResToStrHelper, DSSA, SSync, {{SSA, 0}}}, {ConvCellToStr, convCellToStrHelper, DSSA, SSync, {{TV, 0}}}, {ConcatStrStr, concat_ss, DSSA, SNone, {{SSA, 0}, {SSA, 1}}}, {ConcatStrInt, concat_si, DSSA, SNone, {{SSA, 0}, {SSA, 1}}}, {ConcatIntStr, concat_is, DSSA, SNone, {{SSA, 0}, {SSA, 1}}}, {AddElemStrKey, addElemStringKeyHelper, DSSA, SNone, {{SSA, 0}, {SSA, 1}, {TV, 2}}}, {AddElemIntKey, addElemIntKeyHelper, DSSA, SNone, {{SSA, 0}, {SSA, 1}, {TV, 2}}}, {AddNewElem, &HphpArray::AddNewElemC, DSSA, SNone, {{SSA, 0}, {TV, 1}}}, {ArrayAdd, arrayAdd, DSSA, SNone, {{SSA, 0}, {SSA, 1}}}, {Box, boxValue, DSSA, SNone, {{TV, 0}}}, {NewArray, HphpArray::MakeReserve, DSSA, SNone, {{SSA, 0}}}, {Clone, method(&ObjectData::clone), DSSA, SSync, {{SSA, 0}}}, {NewPackedArray, HphpArray::MakePacked, DSSA, SNone, {{SSA, 0}, {SSA, 1}}}, {NewCol, newColHelper, DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {ColAddNewElemC, colAddNewElemCHelper, DSSA, SSync, {{SSA, 0}, {TV, 1}}}, {ColAddElemC, colAddElemCHelper, DSSA, SSync, {{SSA, 0}, {TV, 1}, {TV, 2}}}, {AllocObj, newInstance, DSSA, SSync, {{SSA, 0}}}, {CustomInstanceInit, method(&ObjectData::callCustomInstanceInit), DSSA, SSync, {{SSA, 0}}}, {LdClsCtor, loadClassCtor, DSSA, SSync, {{SSA, 0}}}, {LookupClsRDSHandle, lookupClsRDSHandle, DSSA, SNone, {{SSA, 0}}}, {LookupClsMethod, lookupClsMethodHelper, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}}}, {LdArrFuncCtx, loadArrayFunctionContext, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {LdArrFPushCuf, fpushCufHelperArray, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {LdStrFPushCuf, fpushCufHelperString, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {PrintStr, print_string, DNone, SNone, {{SSA, 0}}}, {PrintInt, print_int, DNone, SNone, {{SSA, 0}}}, {PrintBool, print_boolean, DNone, SNone, {{SSA, 0}}}, {VerifyParamCls, VerifyParamTypeSlow, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}}}, {VerifyParamCallable, VerifyParamTypeCallable, DNone, SSync, {{TV, 0}, {SSA, 1}}}, {VerifyParamFail, VerifyParamTypeFail, DNone, SSync, {{SSA, 0}}}, {VerifyRetCls, VerifyRetTypeSlow, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}, {TV, 3}}}, {VerifyRetCallable, VerifyRetTypeCallable, DNone, SSync, {{TV, 0}}}, {VerifyRetFail, VerifyRetTypeFail, DNone, SSync, {{TV, 0}}}, {RaiseUninitLoc, raiseUndefVariable, DNone, SSync, {{SSA, 0}}}, {RaiseWarning, raiseWarning, DNone, SSync, {{SSA, 0}}}, {RaiseNotice, raiseNotice, DNone, SSync, {{SSA, 0}}}, {RaiseArrayIndexNotice, raiseArrayIndexNotice, DNone, SSync, {{SSA, 0}}}, {WarnNonObjProp, raisePropertyOnNonObject, DNone, SSync, {}}, {ThrowNonObjProp, throw_null_object_prop, DNone, SSync, {}}, {RaiseUndefProp, raiseUndefProp, DNone, SSync, {{SSA, 0}, {SSA, 1}}}, {RaiseError, raise_error_sd, DNone, SSync, {{SSA, 0}}}, {IncStatGrouped, Stats::incStatGrouped, DNone, SNone, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {ClosureStaticLocInit, closureStaticLocInit, DSSA, SNone, {{SSA, 0}, {SSA, 1}, {TV, 2}}}, {ArrayIdx, fssa(0), DTV, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}}}, {GenericIdx, genericIdx, DTV, SSync, {{TV, 0}, {TV, 1}, {TV, 2}}}, {LdGblAddrDef, ldGblAddrDefHelper, DSSA, SNone, {{SSA, 0}}}, /* Switch helpers */ {LdSwitchDblIndex, switchDoubleHelper, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {LdSwitchStrIndex, switchStringHelper, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {LdSwitchObjIndex, switchObjHelper, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, /* Continuation support helpers */ {CreateContFunc, &c_Continuation::CreateFunc, DSSA, SNone, { extra(&CreateContData::func), {SSA, 0} }}, {CreateContMeth, &c_Continuation::CreateMeth, DSSA, SNone, { extra(&CreateContData::func), {SSA, 0}, {SSA, 1} }}, /* Async function support helpers */ {CreateAFWHFunc, &c_AsyncFunctionWaitHandle::CreateFunc, DSSA, SSync, { extra(&CreateContData::func), {SSA, 0}, {SSA, 1} }}, {CreateAFWHMeth, &c_AsyncFunctionWaitHandle::CreateMeth, DSSA, SSync, { extra(&CreateContData::func), {SSA, 0}, {SSA, 1}, {SSA, 2} }}, {CreateSRWH, &c_StaticResultWaitHandle::CreateFromVM, DSSA, SNone, { {TV, 0} }}, /* MInstrTranslator helpers */ {BaseG, fssa(0), DSSA, SSync, {{TV, 1}, {SSA, 2}}}, {PropX, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}, {SSA, 4}}}, {PropDX, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}, {SSA, 4}}}, {CGetProp, fssa(0), DTV, SSync, {{SSA, 1}, {SSA, 2}, {MemberKeyS, 3}, {SSA, 4}}}, {VGetProp, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}, {MemberKeyS, 3}, {SSA, 4}}}, {BindProp, fssa(0), DNone, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}, {SSA, 4}, {SSA, 5}}}, {SetProp, fssa(0), DNone, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}, {TV, 4}}}, {UnsetProp, fssa(0), DNone, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}}}, {SetOpProp, fssa(0), DTV, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}, {TV, 4}, {SSA, 5}, {SSA, 6}}}, {IncDecProp, fssa(0), DTV, SSync, {{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, {{SSA, 1}, {SSA, 2}, {TV, 3}}}, {ElemX, fssa(0), DSSA, SSync, {{SSA, 1}, {MemberKeyIS, 2}, {SSA, 3}}}, {ElemArray, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}}}, {ElemDX, fssa(0), DSSA, SSync, {{SSA, 1}, {MemberKeyIS, 2}, {SSA, 3}}}, {ElemUX, fssa(0), DSSA, SSync, {{SSA, 1}, {MemberKeyIS, 2}, {SSA, 3}}}, {ArrayGet, fssa(0), DTV, SSync, {{SSA, 1}, {SSA, 2}}}, {StringGet, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}}}, {MapGet, fssa(0), DTV, SSync, {{SSA, 1}, {SSA, 2}}}, {CGetElem, fssa(0), DTV, SSync, {{SSA, 1}, {MemberKeyIS, 2}, {SSA, 3}}}, {VGetElem, fssa(0), DSSA, SSync, {{SSA, 1}, {MemberKeyIS, 2}, {SSA, 3}}}, {BindElem, fssa(0), DNone, SSync, {{SSA, 1}, {TV, 2}, {SSA, 3}, {SSA, 4}}}, {SetWithRefElem, fssa(0), DNone, SSync, {{SSA, 1}, {TV, 2}, {SSA, 3}, {SSA, 4}}}, {ArraySet, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}}}, {MapSet, fssa(0), DNone, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}}}, {ArraySetRef, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}, {SSA, 4}}}, {SetElem, fssa(0), DSSA, SSync, {{SSA, 1}, {MemberKeyIS, 2}, {TV, 3}}}, {UnsetElem, fssa(0), DNone, SSync, {{SSA, 1}, {MemberKeyIS, 2}}}, {SetOpElem, setOpElem, DTV, SSync, {{SSA, 0}, {TV, 1}, {TV, 2}, {SSA, 3}, {SSA, 4}}}, {IncDecElem, incDecElem, DTV, SSync, {{SSA, 0}, {TV, 1}, {SSA, 2}, {SSA, 3}}}, {SetNewElem, setNewElem, DNone, SSync, {{SSA, 0}, {TV, 1}}}, {SetNewElemArray, setNewElemArray, DNone, SSync, {{SSA, 0}, {TV, 1}}}, {SetWithRefNewElem, fssa(0), DNone, SSync, {{SSA, 1}, {SSA, 2}, {SSA, 3}}}, {BindNewElem, bindNewElemIR, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {ArrayIsset, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}}}, {VectorIsset, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}}}, {PairIsset, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}}}, {MapIsset, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}}}, {IssetElem, fssa(0), DSSA, SSync, {{SSA, 1}, {MemberKeyIS, 2}, {SSA, 3}}}, {EmptyElem, fssa(0), DSSA, SSync, {{SSA, 1}, {MemberKeyIS, 2}, {SSA, 3}}}, /* instanceof checks */ {InstanceOf, method(&Class::classof), DSSA, SNone, {{SSA, 0}, {SSA, 1}}}, {InstanceOfIface, method(&Class::ifaceofDirect), DSSA, SNone, {{SSA, 0}, {SSA, 1}}}, {InterfaceSupportsArr, IFaceSupportFn{interface_supports_array}, DSSA, SNone, {{SSA, 0}}}, {InterfaceSupportsStr, IFaceSupportFn{interface_supports_string}, DSSA, SNone, {{SSA, 0}}}, {InterfaceSupportsInt, IFaceSupportFn{interface_supports_int}, DSSA, SNone, {{SSA, 0}}}, {InterfaceSupportsDbl, IFaceSupportFn{interface_supports_double}, DSSA, SNone, {{SSA, 0}}}, /* debug assert helpers */ {DbgAssertPtr, assertTv, DNone, SNone, {{SSA, 0}}}, /* surprise flag support */ {SurpriseHook, &EventHook::CheckSurprise, DNone, SSync, {}}, {FunctionExitSurpriseHook, &EventHook::onFunctionExit, DNone, SSync, {{SSA, 0}}}, }; ArgGroup CallInfo::toArgGroup(const RegAllocInfo& regs, const IRInstruction* inst) const { ArgGroup argGroup{inst, regs[inst]}; for (auto const& arg : args) { switch (arg.type) { case ArgType::SSA: argGroup.ssa(arg.ival); break; case ArgType::TV: argGroup.typedValue(arg.ival); break; case ArgType::MemberKeyS: argGroup.memberKeyS(arg.ival); break; case ArgType::MemberKeyIS: argGroup.memberKeyIS(arg.ival); break; case ArgType::ExtraImm: argGroup.imm(arg.extraFunc(inst)); break; case ArgType::Imm: argGroup.imm(arg.ival); break; } } return argGroup; } CallMap::CallMap(CallInfoList infos) { for (auto const& info : infos) { m_map[info.op] = info; // Check for opcodes that have a version which modifies the stack, // and add an entry to the table for that one. if (opcodeHasFlags(info.op, HasStackVersion)) { Opcode stkOp = getStackModifyingOpcode(info.op); assert(opcodeHasFlags(stkOp, ModifiesStack)); auto& slot = m_map[stkOp]; slot = info; slot.op = stkOp; } } } bool CallMap::hasInfo(Opcode op) { return s_callMap.m_map.count(op) != 0; } const CallInfo& CallMap::info(Opcode op) { auto it = s_callMap.m_map.find(op); assert(it != s_callMap.m_map.end()); return it->second; } } } }
namespace HPHP { namespace jit { namespace NativeCalls { namespace { constexpr SyncOptions SNone = SyncOptions::kNoSyncPoint; constexpr SyncOptions SSync = SyncOptions::kSyncPoint; 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] (const IRInstruction* inst) { auto const extra = inst->extra<EDType>(); return Type::cns(extra->*ptr).rawVal(); }; return Arg(fun); } Arg immed(intptr_t imm) { return Arg(ArgType::Imm, imm); } FuncPtr fssa(uint64_t i) { return FuncPtr { FuncType::SSA, i }; } auto constexpr SSA = ArgType::SSA; auto constexpr TV = ArgType::TV; auto constexpr MemberKeyS = ArgType::MemberKeyS; auto constexpr MemberKeyIS = ArgType::MemberKeyIS; using IFaceSupportFn = bool (*)(const StringData*); } ////////////////////////////////////////////////////////////////////// /* * The table passed to s_callMap's constructor describes helpers calls * used by translated code. Each row consists of the following values: * * Opcode * The opcode that uses the call * * Func * A value describing the function to call: * <function pointer> - Raw function pointer * <pointer to member> - Dispatch to a C++ member function---the * function must be non-virtual. * fssa(idx) - Use a const TCA from inst->src(idx) * * Dest * DSSA - The helper returns a single-register value * DTV - The helper returns a TypedValue in two registers * DNone - The helper does not return a value * * SyncPoint * SNone - The helper does not need a sync point * SSync - The helper needs a normal sync point * SSyncAdj1 - The helper needs a sync point that skips top of stack on unwind * * Args * A list of tuples describing the arguments to pass to the helper * {SSA, idx} - Pass the value in inst->src(idx) * {TV, idx} - Pass the value in inst->src(idx) as a * TypedValue, in two registers * {MemberKeyS, idx} - Like TV, but Str values are passed as a raw * StringData*, in a single register * {MemberKeyIS, idx} - Like MemberKeyS, including Int * extra(&EDStruct::member) - extract an immediate from extra data * immed(int64_t) - constant immediate */ static CallMap s_callMap { /* Opcode, Func, Dest, SyncPoint, Args */ {TypeProfileFunc, profileOneArgument, DNone, SNone, {{TV,0}, extra(&TypeProfileData::param), {SSA, 1}}}, {ConvBoolToArr, convCellToArrHelper, DSSA, SNone, {{TV, 0}}}, {ConvDblToArr, convCellToArrHelper, DSSA, SNone, {{TV, 0}}}, {ConvIntToArr, convCellToArrHelper, DSSA, SNone, {{TV, 0}}}, {ConvObjToArr, convCellToArrHelper, DSSA, SSync, {{TV, 0}}}, {ConvStrToArr, convCellToArrHelper, DSSA, SNone, {{TV, 0}}}, {ConvCellToArr, convCellToArrHelper, DSSA, SSync, {{TV, 0}}}, {ConvStrToBool, &StringData::toBoolean, DSSA, SNone, {{SSA, 0}}}, {ConvCellToBool, cellToBool, DSSA, SNone, {{TV, 0}}}, {ConvArrToDbl, convArrToDblHelper, DSSA, SNone, {{SSA, 0}}}, {ConvObjToDbl, convCellToDblHelper, DSSA, SSync, {{TV, 0}}}, {ConvStrToDbl, convStrToDblHelper, DSSA, SSync, {{SSA, 0}}}, {ConvCellToDbl, convCellToDblHelper, DSSA, SSync, {{TV, 0}}}, {ConvArrToInt, convArrToIntHelper, DSSA, SNone, {{SSA, 0}}}, {ConvObjToInt, cellToInt, DSSA, SSync, {{TV, 0}}}, {ConvStrToInt, &StringData::toInt64, DSSA, SNone, {{SSA, 0}, immed(10)}}, {ConvCellToInt, cellToInt, DSSA, SSync, {{TV, 0}}}, {ConvCellToObj, convCellToObjHelper, DSSA, SSync, {{TV, 0}}}, {ConvDblToStr, convDblToStrHelper, DSSA, SNone, {{SSA, 0}}}, {ConvIntToStr, convIntToStrHelper, DSSA, SNone, {{SSA, 0}}}, {ConvObjToStr, convObjToStrHelper, DSSA, SSync, {{SSA, 0}}}, {ConvResToStr, convResToStrHelper, DSSA, SSync, {{SSA, 0}}}, {ConvCellToStr, convCellToStrHelper, DSSA, SSync, {{TV, 0}}}, {CoerceStrToInt, coerceStrToIntHelper, DSSA, SSync, {{SSA, 0}, extra(&CoerceData::argNum), extra(&CoerceData::callee)}}, {CoerceStrToDbl, coerceStrToDblHelper, DSSA, SSync, {{SSA, 0}, extra(&CoerceData::argNum), extra(&CoerceData::callee)}}, {CoerceCellToInt, coerceCellToIntHelper, DSSA, SSync, {{TV, 0}, extra(&CoerceData::argNum), extra(&CoerceData::callee)}}, {CoerceCellToDbl, coerceCellToDblHelper, DSSA, SSync, {{TV, 0}, extra(&CoerceData::argNum), extra(&CoerceData::callee)}}, {CoerceCellToBool, coerceCellToBoolHelper, DSSA, SSync, {{TV, 0}, extra(&CoerceData::argNum), extra(&CoerceData::callee)}}, {ConcatStrStr, concat_ss, DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {ConcatStrInt, concat_si, DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {ConcatIntStr, concat_is, DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {ConcatStr3, concat_s3, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {ConcatStr4, concat_s4, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}}}, {AddElemStrKey, addElemStringKeyHelper, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {TV, 2}}}, {AddElemIntKey, addElemIntKeyHelper, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {TV, 2}}}, {AddNewElem, addNewElemHelper, DSSA, SSync, {{SSA, 0}, {TV, 1}}}, {ArrayAdd, arrayAdd, DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {Box, boxValue, DSSA, SNone, {{TV, 0}}}, {Clone, &ObjectData::clone, DSSA, SSync, {{SSA, 0}}}, {NewArray, MixedArray::MakeReserve, DSSA, SNone, {{SSA, 0}}}, {NewMixedArray, MixedArray::MakeReserveMixed, DSSA, SNone, {{SSA, 0}}}, {NewVArray, MixedArray::MakeReserveVArray, DSSA, SNone, {{SSA, 0}}}, {NewMIArray, MixedArray::MakeReserveIntMap, DSSA, SNone, {{SSA, 0}}}, {NewMSArray, MixedArray::MakeReserveStrMap, DSSA, SNone, {{SSA, 0}}}, {NewLikeArray, MixedArray::MakeReserveLike, DSSA, SNone, {{SSA, 0}, {SSA, 1}}}, {NewPackedArray, MixedArray::MakePacked, DSSA, SNone, {{extra(&PackedArrayData::size)}, {SSA, 1}}}, {AllocPackedArray, MixedArray::MakePackedUninitialized, DSSA, SNone, {{extra(&PackedArrayData::size)}}}, {NewCol, newColHelper, DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {ColAddNewElemC, colAddNewElemCHelper, DSSA, SSync, {{SSA, 0}, {TV, 1}}}, {ColAddElemC, colAddElemCHelper, DSSA, SSync, {{SSA, 0}, {TV, 1}, {TV, 2}}}, {AllocObj, newInstance, DSSA, SSync, {{SSA, 0}}}, {CustomInstanceInit, &ObjectData::callCustomInstanceInit, DSSA, SSync, {{SSA, 0}}}, {InitProps, &Class::initProps, DNone, SSync, {{extra(&ClassData::cls)}}}, {InitSProps, &Class::initSProps, DNone, SSync, {{extra(&ClassData::cls)}}}, {RegisterLiveObj, registerLiveObj, DNone, SNone, {{SSA, 0}}}, {LdClsCtor, loadClassCtor, DSSA, SSync, {{SSA, 0}}}, {LookupClsRDSHandle, lookupClsRDSHandle, DSSA, SNone, {{SSA, 0}}}, {LookupClsMethod, lookupClsMethodHelper, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}}}, {LdArrFuncCtx, loadArrayFunctionContext, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {LdArrFPushCuf, fpushCufHelperArray, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {LdStrFPushCuf, fpushCufHelperString, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {PrintStr, print_string, DNone, SSync, {{SSA, 0}}}, {PrintInt, print_int, DNone, SSync, {{SSA, 0}}}, {PrintBool, print_boolean, DNone, SSync, {{SSA, 0}}}, {VerifyParamCls, VerifyParamTypeSlow, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}}}, {VerifyParamCallable, VerifyParamTypeCallable, DNone, SSync, {{TV, 0}, {SSA, 1}}}, {VerifyParamFail, VerifyParamTypeFail, DNone, SSync, {{SSA, 0}}}, {VerifyRetCls, VerifyRetTypeSlow, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}, {TV, 3}}}, {VerifyRetCallable, VerifyRetTypeCallable, DNone, SSync, {{TV, 0}}}, {VerifyRetFail, VerifyRetTypeFail, DNone, SSync, {{TV, 0}}}, {RaiseUninitLoc, raiseUndefVariable, DNone, SSync, {{SSA, 0}}}, {RaiseWarning, raiseWarning, DNone, SSync, {{SSA, 0}}}, {RaiseNotice, raiseNotice, DNone, SSync, {{SSA, 0}}}, {RaiseArrayIndexNotice, raiseArrayIndexNotice, DNone, SSync, {{SSA, 0}}}, {WarnNonObjProp, raisePropertyOnNonObject, DNone, SSync, {}}, {ThrowNonObjProp, throw_null_object_prop, DNone, SSync, {}}, {RaiseUndefProp, raiseUndefProp, DNone, SSync, {{SSA, 0}, {SSA, 1}}}, {RaiseError, raise_error_sd, DNone, SSync, {{SSA, 0}}}, {IncStatGrouped, Stats::incStatGrouped, DNone, SNone, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {ClosureStaticLocInit, closureStaticLocInit, DSSA, SNone, {{SSA, 0}, {SSA, 1}, {TV, 2}}}, {ArrayIdx, fssa(0), DTV, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}}}, {GenericIdx, genericIdx, DTV, SSync, {{TV, 0}, {TV, 1}, {TV, 2}}}, /* Static prop helpers */ {LdClsPropAddrOrNull, getSPropOrNull, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {LdClsPropAddrOrRaise, getSPropOrRaise, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, /* Global helpers */ {LdGblAddrDef, ldGblAddrDefHelper, DSSA, SNone, {{SSA, 0}}}, /* Switch helpers */ {LdSwitchDblIndex, switchDoubleHelper, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {LdSwitchStrIndex, switchStringHelper, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {LdSwitchObjIndex, switchObjHelper, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, /* Generator support helpers */ {CreateCont, &c_Generator::Create<false>, DSSA, SNone, {{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}}}, /* Async function support helpers */ {CreateAFWH, &c_AsyncFunctionWaitHandle::Create, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}, {SSA, 4}}}, {CreateSSWH, &c_StaticWaitHandle::CreateSucceededVM, DSSA, SNone, {{TV, 0}}}, {AFWHPrepareChild, &c_AsyncFunctionWaitHandle::PrepareChild, DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {ABCUnblock, &AsioBlockableChain::Unblock, DSSA, SNone, {{SSA, 0}}}, /* MInstrTranslator helpers */ {BaseG, fssa(0), DSSA, SSync, {{TV, 1}}}, {PropX, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}, {SSA, 4}}}, {PropDX, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}, {SSA, 4}}}, {CGetProp, fssa(0), DTV, SSync, {{SSA, 1}, {SSA, 2}, {MemberKeyS, 3}, {SSA, 4}}}, {VGetProp, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}, {MemberKeyS, 3}, {SSA, 4}}}, {BindProp, fssa(0), DNone, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}, {SSA, 4}, {SSA, 5}}}, {SetProp, fssa(0), DNone, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}, {TV, 4}}}, {UnsetProp, fssa(0), DNone, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}}}, {SetOpProp, fssa(0), DTV, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}, {TV, 4}, {SSA, 5}, {SSA, 6}}}, {IncDecProp, fssa(0), DTV, SSync, {{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, {{SSA, 1}, {SSA, 2}, {TV, 3}}}, {ElemX, fssa(0), DSSA, SSync, {{SSA, 1}, {MemberKeyIS, 2}, {SSA, 3}}}, {ElemArray, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}}}, {ElemDX, fssa(0), DSSA, SSync, {{SSA, 1}, {MemberKeyIS, 2}, {SSA, 3}}}, {ElemUX, fssa(0), DSSA, SSync, {{SSA, 1}, {MemberKeyIS, 2}, {SSA, 3}}}, {ArrayGet, fssa(0), DTV, SSync, {{SSA, 1}, {SSA, 2}}}, {StringGet, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}}}, {MapGet, fssa(0), DTV, SSync, {{SSA, 1}, {SSA, 2}}}, {CGetElem, fssa(0), DTV, SSync, {{SSA, 1}, {MemberKeyIS, 2}, {SSA, 3}}}, {VGetElem, fssa(0), DSSA, SSync, {{SSA, 1}, {MemberKeyIS, 2}, {SSA, 3}}}, {BindElem, fssa(0), DNone, SSync, {{SSA, 1}, {TV, 2}, {SSA, 3}, {SSA, 4}}}, {SetWithRefElem, fssa(0), DNone, SSync, {{SSA, 1}, {TV, 2}, {SSA, 3}, {SSA, 4}}}, {ArraySet, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}}}, {MapSet, fssa(0), DNone, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}}}, {ArraySetRef, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}, {TV, 3}, {SSA, 4}}}, {SetElem, fssa(0), DSSA, SSync, {{SSA, 1}, {MemberKeyIS, 2}, {TV, 3}}}, {UnsetElem, fssa(0), DNone, SSync, {{SSA, 1}, {MemberKeyIS, 2}}}, {SetOpElem, setOpElem, DTV, SSync, {{SSA, 0}, {TV, 1}, {TV, 2}, {SSA, 3}, {SSA, 4}}}, {IncDecElem, incDecElem, DTV, SSync, {{SSA, 0}, {TV, 1}, {SSA, 2}, {SSA, 3}}}, {SetNewElem, setNewElem, DNone, SSync, {{SSA, 0}, {TV, 1}}}, {SetNewElemArray, setNewElemArray, DNone, SSync, {{SSA, 0}, {TV, 1}}}, {SetWithRefNewElem, fssa(0), DNone, SSync, {{SSA, 1}, {SSA, 2}, {SSA, 3}}}, {BindNewElem, bindNewElemIR, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {ArrayIsset, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}}}, {VectorIsset, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}}}, {PairIsset, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}}}, {MapIsset, fssa(0), DSSA, SSync, {{SSA, 1}, {SSA, 2}}}, {IssetElem, fssa(0), DSSA, SSync, {{SSA, 1}, {MemberKeyIS, 2}, {SSA, 3}}}, {EmptyElem, fssa(0), DSSA, SSync, {{SSA, 1}, {MemberKeyIS, 2}, {SSA, 3}}}, /* instanceof checks */ {InstanceOf, &Class::classof, DSSA, SNone, {{SSA, 0}, {SSA, 1}}}, {InstanceOfIface, &Class::ifaceofDirect, DSSA, SNone, {{SSA, 0}, {SSA, 1}}}, {InterfaceSupportsArr, IFaceSupportFn{interface_supports_array}, DSSA, SNone, {{SSA, 0}}}, {InterfaceSupportsStr, IFaceSupportFn{interface_supports_string}, DSSA, SNone, {{SSA, 0}}}, {InterfaceSupportsInt, IFaceSupportFn{interface_supports_int}, DSSA, SNone, {{SSA, 0}}}, {InterfaceSupportsDbl, IFaceSupportFn{interface_supports_double}, DSSA, SNone, {{SSA, 0}}}, {OODeclExists, &Unit::classExists, DSSA, SSync, {{SSA, 0}, {SSA, 1}, extra(&ClassKindData::kind)}}, /* debug assert helpers */ {DbgAssertPtr, assertTv, DNone, SNone, {{SSA, 0}}}, /* surprise flag support */ {SurpriseHook, &EventHook::CheckSurprise, DNone, SSync, {}}, {FunctionSuspendHook, &EventHook::onFunctionSuspend, DNone, SSync, {{SSA, 0}, {SSA, 1}}}, {FunctionReturnHook, &EventHook::onFunctionReturnJit, DNone, SSync, {{SSA, 0}, {TV, 1}}}, /* silence operator support */ {ZeroErrorLevel, &zero_error_level, DSSA, SNone, {}}, {RestoreErrorLevel, &restore_error_level, DNone, SNone, {{SSA, 0}}}, // count($mixed) {Count, &countHelper, DSSA, SSync, {{TV, 0}}}, // count($array) {CountArray, &ArrayData::size, DSSA, SNone, {{SSA, 0}}}, }; CallMap::CallMap(CallInfoList infos) { for (auto const& info : infos) { m_map[info.op] = info; // Check for opcodes that have a version which modifies the stack, // and add an entry to the table for that one. if (opcodeHasFlags(info.op, HasStackVersion)) { Opcode stkOp = getStackModifyingOpcode(info.op); assert(opcodeHasFlags(stkOp, ModifiesStack)); auto& slot = m_map[stkOp]; slot = info; slot.op = stkOp; } } } bool CallMap::hasInfo(Opcode op) { return s_callMap.m_map.count(op) != 0; } const CallInfo& CallMap::info(Opcode op) { auto it = s_callMap.m_map.find(op); assert(it != s_callMap.m_map.end()); return it->second; } } // NativeCalls
namespace NativeCalls { /////////////////////////////////////////////////////////////////////////////// namespace { constexpr irlower::SyncOptions SNone = irlower::SyncOptions::None; constexpr irlower::SyncOptions SSync = irlower::SyncOptions::Sync; 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] (const IRInstruction* inst) { auto const extra = inst->extra<EDType>(); return Type::cns(extra->*ptr).rawVal(); }; return Arg(fun); } Arg immed(intptr_t imm) { return Arg(ArgType::Imm, imm); } auto constexpr SSA = ArgType::SSA; auto constexpr TV = ArgType::TV; using IFaceSupportFn = bool (*)(const StringData*); using StrCmpFn = bool (*)(const StringData*, const StringData*); using ObjCmpFn = bool (*)(const ObjectData*, const ObjectData*); using ArrCmpFn = bool (*)(const ArrayData*, const ArrayData*); using ResCmpFn = bool (*)(const ResourceHdr*, const ResourceHdr*); using StrIntCmpFn = bool (*)(const StringData*, int64_t); using StrCmpFnInt = int64_t (*)(const StringData*, const StringData*); using ObjCmpFnInt = int64_t (*)(const ObjectData*, const ObjectData*); using ArrCmpFnInt = int64_t (*)(const ArrayData*, const ArrayData*); using ResCmpFnInt = int64_t (*)(const ResourceHdr*, const ResourceHdr*); using StrIntCmpFnInt = int64_t (*)(const StringData*, int64_t); } ////////////////////////////////////////////////////////////////////// /* * The table passed to s_callMap's constructor describes helpers calls * used by translated code. Each row consists of the following values: * * Opcode * The opcode that uses the call * * Func * A value describing the function to call: * <function pointer> - Raw function pointer * <pointer to member> - Dispatch to a C++ member function---the * function must be non-virtual. * * Dest * DSSA - The helper returns a single-register value * DTV - The helper returns a TypedValue in two registers * DNone - The helper does not return a value * * SyncPoint * SNone - The helper does not need a sync point * SSync - The helper needs a normal sync point * SSyncAdj1 - The helper needs a sync point that skips top of stack on unwind * * Args * A list of tuples describing the arguments to pass to the helper * {SSA, idx} - Pass the value in inst->src(idx) * {TV, idx} - Pass the value in inst->src(idx) as a * TypedValue, in two registers * extra(&EDStruct::member) - extract an immediate from extra data * immed(int64_t) - constant immediate */ static CallMap s_callMap { /* Opcode, Func, Dest, SyncPoint, Args */ {ConvBoolToArr, convCellToArrHelper, DSSA, SNone, {{TV, 0}}}, {ConvDblToArr, convCellToArrHelper, DSSA, SNone, {{TV, 0}}}, {ConvIntToArr, convCellToArrHelper, DSSA, SNone, {{TV, 0}}}, {ConvObjToArr, convCellToArrHelper, DSSA, SSync, {{TV, 0}}}, {ConvStrToArr, convCellToArrHelper, DSSA, SNone, {{TV, 0}}}, {ConvCellToArr, convCellToArrHelper, DSSA, SSync, {{TV, 0}}}, {ConvStrToBool, &StringData::toBoolean, DSSA, SNone, {{SSA, 0}}}, {ConvCellToBool, cellToBool, DSSA, SNone, {{TV, 0}}}, {ConvArrToDbl, convArrToDblHelper, DSSA, SNone, {{SSA, 0}}}, {ConvObjToDbl, convObjToDblHelper, DSSA, SSync, {{SSA, 0}}}, {ConvStrToDbl, convStrToDblHelper, DSSA, SSync, {{SSA, 0}}}, {ConvResToDbl, convResToDblHelper, DSSA, SNone, {{SSA, 0}}}, {ConvCellToDbl, convCellToDblHelper, DSSA, SSync, {{TV, 0}}}, {ConvArrToInt, convArrToIntHelper, DSSA, SNone, {{SSA, 0}}}, {ConvObjToInt, &ObjectData::toInt64, DSSA, SSync, {{SSA, 0}}}, {ConvStrToInt, &StringData::toInt64, DSSA, SNone, {{SSA, 0}, immed(10)}}, {ConvResToInt, &ResourceHdr::getId, DSSA, SNone, {{SSA, 0}}}, {ConvCellToInt, cellToInt, DSSA, SSync, {{TV, 0}}}, {ConvCellToObj, convCellToObjHelper, DSSA, SSync, {{TV, 0}}}, {ConvDblToStr, convDblToStrHelper, DSSA, SNone, {{SSA, 0}}}, {ConvIntToStr, convIntToStrHelper, DSSA, SNone, {{SSA, 0}}}, {ConvObjToStr, convObjToStrHelper, DSSA, SSync, {{SSA, 0}}}, {ConvResToStr, convResToStrHelper, DSSA, SSync, {{SSA, 0}}}, {ConvCellToStr, convCellToStrHelper, DSSA, SSync, {{TV, 0}}}, {CoerceStrToInt, coerceStrToIntHelper, DSSA, SSync, {{SSA, 0}, extra(&FuncArgData::argNum), extra(&FuncArgData::func)}}, {CoerceStrToDbl, coerceStrToDblHelper, DSSA, SSync, {{SSA, 0}, extra(&FuncArgData::argNum), extra(&FuncArgData::func)}}, {CoerceCellToInt, coerceCellToIntHelper, DSSA, SSync, {{TV, 0}, extra(&FuncArgData::argNum), extra(&FuncArgData::func)}}, {CoerceCellToDbl, coerceCellToDblHelper, DSSA, SSync, {{TV, 0}, extra(&FuncArgData::argNum), extra(&FuncArgData::func)}}, {CoerceCellToBool, coerceCellToBoolHelper, DSSA, SSync, {{TV, 0}, extra(&FuncArgData::argNum), extra(&FuncArgData::func)}}, {ConcatStrStr, concat_ss, DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {ConcatStrInt, concat_si, DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {ConcatIntStr, concat_is, DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {ConcatStr3, concat_s3, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {ConcatStr4, concat_s4, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}}}, {AddElemStrKey, addElemStringKeyHelper, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {TV, 2}}}, {AddElemIntKey, addElemIntKeyHelper, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {TV, 2}}}, {AddNewElem, addNewElemHelper, DSSA, SSync, {{SSA, 0}, {TV, 1}}}, {ArrayAdd, arrayAdd, DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {Box, boxValue, DSSA, SNone, {{TV, 0}}}, {Clone, &ObjectData::clone, DSSA, SSync, {{SSA, 0}}}, {NewArray, MixedArray::MakeReserve, DSSA, SNone, {{SSA, 0}}}, {NewMixedArray, MixedArray::MakeReserveMixed, DSSA, SNone, {{SSA, 0}}}, {NewLikeArray, MixedArray::MakeReserveLike, DSSA, SNone, {{SSA, 0}, {SSA, 1}}}, {AllocPackedArray, MixedArray::MakePackedUninitialized, DSSA, SNone, {{extra(&PackedArrayData::size)}}}, {ColAddNewElemC, colAddNewElemCHelper, DSSA, SSync, {{SSA, 0}, {TV, 1}}}, {MapAddElemC, colAddElemCHelper, DSSA, SSync, {{SSA, 0}, {TV, 1}, {TV, 2}}}, {AllocObj, newInstance, DSSA, SSync, {{SSA, 0}}}, {InitProps, &Class::initProps, DNone, SSync, {{extra(&ClassData::cls)}}}, {InitSProps, &Class::initSProps, DNone, SSync, {{extra(&ClassData::cls)}}}, {RegisterLiveObj, registerLiveObj, DNone, SNone, {{SSA, 0}}}, {LdClsCtor, loadClassCtor, DSSA, SSync, {{SSA, 0}}}, {LookupClsRDSHandle, lookupClsRDSHandle, DSSA, SNone, {{SSA, 0}}}, {PrintStr, print_string, DNone, SSync, {{SSA, 0}}}, {PrintInt, print_int, DNone, SSync, {{SSA, 0}}}, {PrintBool, print_boolean, DNone, SSync, {{SSA, 0}}}, {VerifyParamCls, VerifyParamTypeSlow, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}}}, {VerifyParamCallable, VerifyParamTypeCallable, DNone, SSync, {{TV, 0}, {SSA, 1}}}, {VerifyParamFail, VerifyParamTypeFail, DNone, SSync, {{SSA, 0}}}, {VerifyRetCls, VerifyRetTypeSlow, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}, {TV, 3}}}, {VerifyRetCallable, VerifyRetTypeCallable, DNone, SSync, {{TV, 0}}}, {VerifyRetFail, VerifyRetTypeFail, DNone, SSync, {{TV, 0}}}, {RaiseUninitLoc, raiseUndefVariable, DNone, SSync, {{SSA, 0}}}, {RaiseError, raise_error_sd, DNone, SSync, {{SSA, 0}}}, {RaiseWarning, raiseWarning, DNone, SSync, {{SSA, 0}}}, {RaiseNotice, raiseNotice, DNone, SSync, {{SSA, 0}}}, {RaiseArrayIndexNotice, raiseArrayIndexNotice, DNone, SSync, {{SSA, 0}}}, {RaiseArrayKeyNotice, raiseArrayKeyNotice, DNone, SSync, {{SSA, 0}}}, {RaiseUndefProp, raiseUndefProp, DNone, SSync, {{SSA, 0}, {SSA, 1}}}, {RaiseMissingArg, raiseMissingArgument, DNone, SSync, {extra(&FuncArgData::func), extra(&FuncArgData::argNum)}}, {IncStatGrouped, Stats::incStatGrouped, DNone, SNone, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {ClosureStaticLocInit, closureStaticLocInit, DSSA, SNone, {{SSA, 0}, {SSA, 1}, {TV, 2}}}, {GenericIdx, genericIdx, DTV, SSync, {{TV, 0}, {TV, 1}, {TV, 2}}}, {MapIdx, mapIdx, DTV, SSync, {{SSA, 0}, {SSA, 1}, {TV, 2}}}, {ThrowInvalidOperation, throw_invalid_operation_exception, DNone, SSync, {{SSA, 0}}}, {HasToString, &ObjectData::hasToString, DSSA, SSync, {{SSA, 0}}}, /* Type specialized comparison operators */ {GtStr, static_cast<StrCmpFn>(more), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {GteStr, static_cast<StrCmpFn>(moreEqual), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {LtStr, static_cast<StrCmpFn>(less), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {LteStr, static_cast<StrCmpFn>(lessEqual), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {EqStr, static_cast<StrCmpFn>(equal), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {NeqStr, static_cast<StrCmpFn>(nequal), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {SameStr, static_cast<StrCmpFn>(same), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {NSameStr, static_cast<StrCmpFn>(nsame), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {CmpStr, static_cast<StrCmpFnInt>(compare), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {GtStrInt, static_cast<StrIntCmpFn>(more), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {GteStrInt, static_cast<StrIntCmpFn>(moreEqual), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {LtStrInt, static_cast<StrIntCmpFn>(less), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {LteStrInt, static_cast<StrIntCmpFn>(lessEqual), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {EqStrInt, static_cast<StrIntCmpFn>(equal), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {NeqStrInt, static_cast<StrIntCmpFn>(nequal), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {CmpStrInt, static_cast<StrIntCmpFnInt>(compare), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {GtObj, static_cast<ObjCmpFn>(more), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {GteObj, static_cast<ObjCmpFn>(moreEqual), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {LtObj, static_cast<ObjCmpFn>(less), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {LteObj, static_cast<ObjCmpFn>(lessEqual), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {EqObj, static_cast<ObjCmpFn>(equal), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {NeqObj, static_cast<ObjCmpFn>(nequal), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {CmpObj, static_cast<ObjCmpFnInt>(compare), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {GtArr, static_cast<ArrCmpFn>(more), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {GteArr, static_cast<ArrCmpFn>(moreEqual), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {LtArr, static_cast<ArrCmpFn>(less), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {LteArr, static_cast<ArrCmpFn>(lessEqual), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {EqArr, static_cast<ArrCmpFn>(equal), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {NeqArr, static_cast<ArrCmpFn>(nequal), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {SameArr, static_cast<ArrCmpFn>(same), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {NSameArr, static_cast<ArrCmpFn>(nsame), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {CmpArr, static_cast<ArrCmpFnInt>(compare), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {GtRes, static_cast<ResCmpFn>(more), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {GteRes, static_cast<ResCmpFn>(moreEqual), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {LtRes, static_cast<ResCmpFn>(less), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {LteRes, static_cast<ResCmpFn>(lessEqual), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {CmpRes, static_cast<ResCmpFnInt>(compare), DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, /* Static prop helpers */ {LdClsPropAddrOrNull, getSPropOrNull, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {LdClsPropAddrOrRaise, getSPropOrRaise, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, /* Global helpers */ {LdGblAddrDef, ldGblAddrDefHelper, DSSA, SNone, {{SSA, 0}}}, /* Switch helpers */ {LdSwitchDblIndex, switchDoubleHelper, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {LdSwitchStrIndex, switchStringHelper, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {LdSwitchObjIndex, switchObjHelper, DSSA, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, /* Generator support helpers */ {CreateCont, &Generator::Create<false>, DSSA, SNone, {{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}}}, /* Async function support helpers */ {CreateAFWH, &c_AsyncFunctionWaitHandle::Create<true>, DSSA, SNone, {{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}, {SSA, 4}}}, {CreateAFWHNoVV, &c_AsyncFunctionWaitHandle::Create<false>, DSSA, SNone, {{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}, {SSA, 4}}}, {CreateSSWH, &c_StaticWaitHandle::CreateSucceeded, DSSA, SNone, {{TV, 0}}}, {AFWHPrepareChild, &c_AsyncFunctionWaitHandle::PrepareChild, DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {ABCUnblock, &AsioBlockableChain::Unblock, DSSA, SNone, {{SSA, 0}}}, /* MInstrTranslator helpers */ {SetOpElem, setOpElem, DTV, SSync, {{SSA, 0}, {TV, 1}, {TV, 2}, {SSA, 3}, extra(&SetOpData::op)}}, {IncDecElem, incDecElem, DTV, SSync, {{SSA, 0}, {TV, 1}, {SSA, 2}, extra(&IncDecData::op)}}, {SetNewElem, setNewElem, DNone, SSync, {{SSA, 0}, {TV, 1}}}, {SetNewElemArray, setNewElemArray, DNone, SSync, {{SSA, 0}, {TV, 1}}}, {BindNewElem, bindNewElemIR, DNone, SSync, {{SSA, 0}, {SSA, 1}, {SSA, 2}}}, {StringGet, MInstrHelpers::stringGetI, DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {PairIsset, MInstrHelpers::pairIsset, DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {VectorIsset, MInstrHelpers::vectorIsset, DSSA, SSync, {{SSA, 0}, {SSA, 1}}}, {BindElem, MInstrHelpers::bindElemC, DNone, SSync, {{SSA, 0}, {TV, 1}, {SSA, 2}, {SSA, 3}}}, {SetWithRefElem, MInstrHelpers::setWithRefElemC, DNone, SSync, {{SSA, 0}, {TV, 1}, {TV, 2}, {SSA, 3}}}, {SetWithRefNewElem, MInstrHelpers::setWithRefNewElem, DNone, SSync, {{SSA, 0}, {TV, 1}, {SSA, 2}}}, {ThrowOutOfBounds, throwOOB, DNone, SSync, {{SSA, 0}}}, /* instanceof checks */ {InstanceOf, &Class::classof, DSSA, SNone, {{SSA, 0}, {SSA, 1}}}, {InstanceOfIface, &Class::ifaceofDirect, DSSA, SNone, {{SSA, 0}, {SSA, 1}}}, {InterfaceSupportsArr, IFaceSupportFn{interface_supports_array}, DSSA, SNone, {{SSA, 0}}}, {InterfaceSupportsStr, IFaceSupportFn{interface_supports_string}, DSSA, SNone, {{SSA, 0}}}, {InterfaceSupportsInt, IFaceSupportFn{interface_supports_int}, DSSA, SNone, {{SSA, 0}}}, {InterfaceSupportsDbl, IFaceSupportFn{interface_supports_double}, DSSA, SNone, {{SSA, 0}}}, {OODeclExists, &Unit::classExists, DSSA, SSync, {{SSA, 0}, {SSA, 1}, extra(&ClassKindData::kind)}}, /* debug assert helpers */ {DbgAssertPtr, assertTv, DNone, SNone, {{SSA, 0}}}, /* surprise flag support */ {SuspendHookE, &EventHook::onFunctionSuspendE, DNone, SSync, {{SSA, 0}, {SSA, 1}}}, {SuspendHookR, &EventHook::onFunctionSuspendR, DNone, SSync, {{SSA, 0}, {SSA, 1}}}, {ReturnHook, &EventHook::onFunctionReturn, DNone, SSync, {{SSA, 0}, {TV, 1}}}, /* silence operator support */ {ZeroErrorLevel, &zero_error_level, DSSA, SNone, {}}, {RestoreErrorLevel, &restore_error_level, DNone, SNone, {{SSA, 0}}}, // count($mixed) {Count, &countHelper, DSSA, SSync, {{TV, 0}}}, {GetMemoKey, getMemoKeyHelper, DTV, SSync, {{TV, 0}}}, }; CallMap::CallMap(CallInfoList infos) { for (auto const& info : infos) { m_map[info.op] = info; } } bool CallMap::hasInfo(Opcode op) { return s_callMap.m_map.count(op) != 0; } const CallInfo& CallMap::info(Opcode op) { auto it = s_callMap.m_map.find(op); assertx(it != s_callMap.m_map.end()); return it->second; } /////////////////////////////////////////////////////////////////////////////// } // NativeCalls
inline void Assembler::add(Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }