hphp/runtime/vm/jit/native-calls.cpp (407 lines of code) (raw):
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/runtime/vm/jit/native-calls.h"
#include <folly/ClockGettimeWrappers.h>
#include "hphp/runtime/base/comparisons.h"
#include "hphp/runtime/base/exceptions.h"
#include "hphp/runtime/base/rds.h"
#include "hphp/runtime/base/stats.h"
#include "hphp/runtime/base/timestamp.h"
#include "hphp/runtime/base/tv-conversions.h"
#include "hphp/runtime/base/vanilla-vec.h"
#include "hphp/runtime/vm/class-meth-data-ref.h"
#include "hphp/runtime/vm/property-profile.h"
#include "hphp/runtime/vm/reified-generics.h"
#include "hphp/runtime/vm/runtime.h"
#include "hphp/runtime/vm/unit-util.h"
#include "hphp/runtime/vm/jit/arg-group.h"
#include "hphp/runtime/vm/jit/func-order.h"
#include "hphp/runtime/vm/jit/ir-opcode.h"
#include "hphp/runtime/vm/jit/irlower.h"
#include "hphp/runtime/vm/jit/translator-runtime.h"
#include "hphp/runtime/ext/array/ext_array.h"
#include "hphp/runtime/ext/asio/asio-blockable.h"
#include "hphp/runtime/ext/asio/ext_async-function-wait-handle.h"
#include "hphp/runtime/ext/asio/ext_static-wait-handle.h"
#include "hphp/runtime/ext/collections/ext_collections-pair.h"
#include "hphp/runtime/ext/collections/ext_collections-vector.h"
#include "hphp/runtime/ext/collections/ext_collections.h"
#include "hphp/runtime/ext/functioncredential/ext_functioncredential.h"
#include "hphp/runtime/ext/std/ext_std_errorfunc.h"
#include "hphp/util/abi-cxx.h"
#include "hphp/util/assertions.h"
namespace HPHP::jit {
///////////////////////////////////////////////////////////////////////////////
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 ResCmpFn = bool (*)(const ResourceHdr*, const ResourceHdr*);
using StrCmpFnInt = int64_t (*)(const StringData*, const StringData*);
using ObjCmpFnInt = int64_t (*)(const ObjectData*, const ObjectData*);
using ResCmpFnInt = int64_t (*)(const ResourceHdr*, const ResourceHdr*);
}
//////////////////////////////////////////////////////////////////////
/*
* 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
* 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 */
{ConvArrLikeToVec, convArrLikeToVecHelper, DSSA, SSync,
{{SSA, 0}}},
{ConvObjToVec, convObjToVecHelper, DSSA, SSync,
{{SSA, 0}}},
{ConvArrLikeToDict, convArrLikeToDictHelper, DSSA, SSync,
{{SSA, 0}}},
{ConvObjToDict, convObjToDictHelper, DSSA, SSync,
{{SSA, 0}}},
{ConvArrLikeToKeyset, convArrLikeToKeysetHelper, DSSA, SSync,
{{SSA, 0}}},
{ConvObjToKeyset, convObjToKeysetHelper, DSSA, SSync,
{{SSA, 0}}},
{ConvTVToBool, tvToBool, DSSA, SSync,
{{TV, 0}}},
{ConvObjToDbl, convObjToDblHelper, DSSA, SSync,
{{SSA, 0}}},
{ConvStrToDbl, convStrToDblHelper, DSSA, SNone,
{{SSA, 0}}},
{ConvResToDbl, convResToDblHelper, DSSA, SNone,
{{SSA, 0}}},
{ConvTVToDbl, convTVToDblHelper, DSSA, SSync,
{{TV, 0}}},
{ConvObjToInt, &ObjectData::toInt64, DSSA, SSync, {{SSA, 0}}},
{ConvStrToInt, &StringData::toInt64, DSSA, SNone,
{{SSA, 0}, immed(10)}},
{ConvResToInt, &ResourceHdr::getId, DSSA, SNone,
{{SSA, 0}}},
{ConvTVToInt, tvToInt, DSSA, SSync, {{TV, 0}}},
{ConvDblToStr, convDblToStrHelper, DSSA, SNone,
{{SSA, 0}}},
{ConvIntToStr, convIntToStrHelper, DSSA, SNone,
{{SSA, 0}}},
{ConvObjToStr, convObjToStrHelper, DSSA, SSync,
{{SSA, 0}}},
{ConvTVToStr, static_cast<StringData* (*)(
TypedValue,
const ConvNoticeLevel,
const StringData*)>(tvCastToStringData), DSSA, SSync,
{{TV, 0}, extra(&ConvNoticeData::level),
extra(&ConvNoticeData::reasonIntVal)}},
{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}}},
{Clone, &ObjectData::clone, DSSA, SSync, {{SSA, 0}}},
{NewRFunc, RFuncData::newInstance, DSSA, SNone,
{{SSA, 0}, {SSA, 1}}},
{NewRClsMeth, RClsMethData::create, DSSA, SNone,
{{SSA, 0}, {SSA, 1}, {SSA, 2}}},
{NewPair, collections::allocPair, DSSA, SNone,
{{TV, 0}, {TV, 1}}},
{FuncCred, &FunctionCredential::newInstance, DSSA, SNone,
{{SSA, 0}}},
{AllocObj, ObjectData::newInstance<true>, DSSA, SSync,
{{SSA, 0}}},
{AllocObjReified, ObjectData::newInstanceReified<true>, DSSA, SSync,
{{SSA, 0}, {SSA, 1}}},
{InitProps, &Class::initProps, DNone, SSync,
{{extra(&ClassData::cls)}}},
{InitSProps, &Class::initSProps, DNone, SSync,
{{extra(&ClassData::cls)}}},
{DebugBacktrace, debug_backtrace_jit, DSSA, SSync, {{SSA, 0}}},
{InitThrowableFileAndLine,
throwable_init_file_and_line_from_builtin,
DNone, debug ? SSync : SNone, {{SSA, 0}}},
{LdClsCtor, loadClassCtor, DSSA, SSync,
{{SSA, 0}, {SSA, 1}}},
{LookupClsMethod, lookupClsMethodHelper, DSSA, SSync,
{{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}}},
{LookupClsCns, lookupClsCns, DTV, SSync, {{SSA, 0}, {SSA, 1}}},
{LookupClsCtxCns, lookupClsCtxCns, DSSA, SSync, {{SSA, 0}, {SSA, 1}}},
{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, 2},
extra(&FuncParamWithTCData::func),
extra(&FuncParamWithTCData::paramId),
extra(&FuncParamWithTCData::tcAsInt)}},
{VerifyParamCallable, VerifyParamTypeCallable, DNone, SSync,
{{TV, 0},
extra(&FuncParamData::func),
extra(&FuncParamData::paramId)}},
{VerifyRetCls, VerifyRetTypeSlow, DNone, SSync,
{{SSA, 0}, {SSA, 2},
extra(&FuncParamWithTCData::func),
extra(&FuncParamWithTCData::paramId),
extra(&FuncParamWithTCData::tcAsInt)}},
{VerifyRetCallable, VerifyRetTypeCallable, DNone, SSync,
{{TV, 0},
extra(&FuncParamData::func),
extra(&FuncParamData::paramId)}},
{ThrowUninitLoc, throwUndefVariable, DNone, SSync, {{SSA, 0}}},
{RaiseError, raise_error_sd, DNone, SSync, {{SSA, 0}}},
{RaiseWarning, raiseWarning, DNone, SSync, {{SSA, 0}}},
{RaiseNotice, raiseNotice, DNone, SSync, {{SSA, 0}}},
{ThrowCannotModifyReadonlyCollection,
throw_cannot_modify_readonly_collection, DNone, SSync,
{}},
{ThrowMustBeEnclosedInReadonly,
throwMustBeEnclosedInReadonlyException, DNone, SSync,
{extra(&ClassData::cls), {SSA, 0}}},
{ThrowMustBeReadonlyException,
throwMustBeReadonlyException, DNone, SSync,
{extra(&ClassData::cls), {SSA, 0}}},
{ThrowMustBeMutableException,
throwMustBeMutableException, DNone, SSync,
{extra(&ClassData::cls), {SSA, 0}}},
{ThrowMustBeValueTypeException,
throwMustBeValueTypeException, DNone, SSync,
{extra(&ClassData::cls), {SSA, 0}}},
{ThrowLocalMustBeValueTypeException,
throwOrWarnLocalMustBeValueTypeException, DNone, SSync,
{{SSA, 0}}},
{ThrowArrayKeyException,
throwArrayKeyException, DNone, SSync,
{{SSA, 0}, {SSA, 1}}},
{ThrowUndefPropException,
throwUndefPropException, DNone, SSync,
{{SSA, 0}, {SSA, 1}}},
{RaiseTooManyArg, raiseTooManyArgumentsPrologue, DNone, SSync,
{extra(&FuncData::func), {SSA, 0}}},
{RaiseCoeffectsFunParamTypeViolation, raiseCoeffectsFunParamTypeViolation,
DNone, SSync, {{TV, 0}, extra(&ParamData::paramId)}},
{RaiseCoeffectsFunParamCoeffectRulesViolation,
raiseCoeffectsFunParamCoeffectRulesViolation,
DNone, SSync, {{SSA, 0}}},
{ThrowInvalidOperation, throw_invalid_operation_exception,
DNone, SSync, {{SSA, 0}}},
{ThrowCallReifiedFunctionWithoutGenerics,
throw_call_reified_func_without_generics,
DNone, SSync, {{SSA, 0}}},
{ThrowDivisionByZeroException, throw_division_by_zero_exception,
DNone, SSync, {}},
{ThrowHasThisNeedStatic, throw_has_this_need_static,
DNone, SSync, {{SSA, 0}}},
{ThrowMissingArg, throwMissingArgument, DNone, SSync,
{extra(&FuncArgData::func),
extra(&FuncArgData::argNum)}},
{ThrowMissingThis, throw_missing_this,
DNone, SSync, {{SSA, 0}}},
{ThrowParameterWrongType, throw_parameter_wrong_type, DNone, SSync,
{{TV, 0},
extra(&FuncArgTypeData::func),
extra(&FuncArgTypeData::argNum),
extra(&FuncArgTypeData::type)}},
{CheckInOutMismatch, checkInOutMismatch, DNone, SSync,
{{SSA, 0},
extra(&BoolVecArgsData::numArgs),
extra(&BoolVecArgsData::args)}},
{ThrowInOutMismatch, throwParamInOutMismatch, DNone, SSync,
{{SSA, 0},
extra(&ParamData::paramId)}},
{CheckReadonlyMismatch, checkReadonlyMismatch, DNone, SSync,
{{SSA, 0},
extra(&BoolVecArgsData::numArgs),
extra(&BoolVecArgsData::args)}},
{ThrowReadonlyMismatch, throwReadonlyMismatch, DNone, SSync,
{{SSA, 0},
extra(&ParamData::paramId)}},
{HasToString, &ObjectData::hasToString, DSSA, SNone,
{{SSA, 0}}},
/* Type specialized comparison operators */
{GtStr, static_cast<StrCmpFn>(more), DSSA, SNone,
{{SSA, 0}, {SSA, 1}}},
{GteStr, static_cast<StrCmpFn>(moreEqual), DSSA, SNone,
{{SSA, 0}, {SSA, 1}}},
{LtStr, static_cast<StrCmpFn>(less), DSSA, SNone,
{{SSA, 0}, {SSA, 1}}},
{LteStr, static_cast<StrCmpFn>(lessEqual), DSSA, SNone,
{{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, SNone,
{{SSA, 0}, {SSA, 1}}},
{NSameStr, static_cast<StrCmpFn>(nsame), DSSA, SNone,
{{SSA, 0}, {SSA, 1}}},
{CmpStr, static_cast<StrCmpFnInt>(compare), DSSA, SNone,
{{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}}},
{GtArrLike, ArrayData::Gt, DSSA, SSync,
{{SSA, 0}, {SSA, 1}}},
{GteArrLike, ArrayData::Gte, DSSA, SSync,
{{SSA, 0}, {SSA, 1}}},
{LtArrLike, ArrayData::Lt, DSSA, SSync,
{{SSA, 0}, {SSA, 1}}},
{LteArrLike, ArrayData::Lte, DSSA, SSync,
{{SSA, 0}, {SSA, 1}}},
{EqArrLike, ArrayData::Equal, DSSA, SSync,
{{SSA, 0}, {SSA, 1}}},
{NeqArrLike, ArrayData::NotEqual, DSSA, SSync,
{{SSA, 0}, {SSA, 1}}},
{SameArrLike, ArrayData::Same, DSSA, SSync,
{{SSA, 0}, {SSA, 1}}},
{NSameArrLike, ArrayData::NotSame, DSSA, SSync,
{{SSA, 0}, {SSA, 1}}},
{CmpArrLike, ArrayData::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,
{{extra(&ReadonlyData::op)}, {SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}, {SSA, 4}}},
{LdClsPropAddrOrRaise,
getSPropOrRaise, DSSA, SSync,
{{extra(&ReadonlyData::op)}, {SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}, {SSA, 4}}},
{ProfileProp, &PropertyProfile::incCount, DNone, SNone,
{{SSA, 0}, {SSA, 1}}},
{IncCallCounter, FuncOrder::incCount, DNone, SNone, {{extra(&FuncData::func)}, {SSA, 0}}},
/* Global helpers */
{LdGblAddrDef, ldGblAddrDefHelper, DSSA, SSync,
{{SSA, 0}}},
/* Generator support helpers */
{CreateGen, &Generator::Create, DSSA, SNone,
{{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}}},
/* Async generator support helpers */
{CreateAGen, &AsyncGenerator::Create, DSSA, SNone,
{{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}}},
/* Async function support helpers */
{CreateAFWH, &c_AsyncFunctionWaitHandle::Create, DSSA, SNone,
{{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}, {SSA, 4}}},
{CreateAGWH, &c_AsyncGeneratorWaitHandle::Create, DSSA, SNone,
{{SSA, 0}, {SSA, 1}, {SSA, 2}, {SSA, 3}}},
{AFWHPrepareChild, &c_AsyncFunctionWaitHandle::PrepareChild, DSSA, SSync,
{{SSA, 0}, {SSA, 1}}},
/* SetNewElem helpers */
{SetNewElemDict, setNewElemDict, DSSA, SSync, {{SSA, 0}, {TV, 1}}},
{SetNewElemVec, setNewElemVec, DSSA, SSync, {{SSA, 0}, {TV, 1}}},
{SetNewElem, setNewElem, DSSA, SSync, {{SSA, 0}, {TV, 1}}},
/* AddNewElem helpers */
{AddNewElemKeyset, addNewElemKeyset, DSSA, SSync, {{SSA, 0}, {TV, 1}}},
{AddNewElemVec, addNewElemVec, DSSA, SNone, {{SSA, 0}, {TV, 1}}},
/* MInstrTranslator helpers */
{StringGet, MInstrHelpers::stringGetI, DSSA, SSync, {{SSA, 0}, {SSA, 1}}},
{PairIsset, MInstrHelpers::pairIsset, DSSA, SNone, {{SSA, 0}, {SSA, 1}}},
{VectorIsset, MInstrHelpers::vectorIsset, DSSA, SNone,
{{SSA, 0}, {SSA, 1}}},
{ThrowOutOfBounds, throwOOBException, DNone, SSync, {{TV, 0}, {TV, 1}}},
{ThrowInvalidArrayKey, invalidArrayKeyHelper, DNone, SSync,
{{SSA, 0}, {TV, 1}}},
/* instanceof checks */
{ProfileInstanceCheck, &InstanceBits::profile, DNone, SNone, {{SSA, 0}}},
{InstanceOfIface, &Class::ifaceofDirect, DSSA,
SNone, {{SSA, 0}, {SSA, 1}}},
{InterfaceSupportsArrLike, IFaceSupportFn{interface_supports_arrlike},
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, &Class::exists, DSSA, SSync,
{{SSA, 0}, {SSA, 1}, extra(&ClassKindData::kind)}},
/* is/as expressions */
{IsTypeStruct, isTypeStructHelper, DSSA, SSync,
{{SSA, 0}, {TV, 1}, {extra(&RDSHandleData::handle)}}},
{ThrowAsTypeStructException, throwAsTypeStructExceptionHelper, DNone, SSync,
{{SSA, 0}, {TV, 1}}},
/* surprise flag support */
{SuspendHookAwaitEF, &EventHook::onFunctionSuspendAwaitEFJit, DNone,
SSync, {{SSA, 0}, {SSA, 1}}},
{SuspendHookAwaitEG, &EventHook::onFunctionSuspendAwaitEGJit, DNone,
SSync, {{SSA, 0}}},
{SuspendHookAwaitR, &EventHook::onFunctionSuspendAwaitRJit, DNone,
SSync, {{SSA, 0}, {SSA, 1}}},
{SuspendHookCreateCont, &EventHook::onFunctionSuspendCreateContJit, DNone,
SSync, {{SSA, 0}, {SSA, 1}}},
{SuspendHookYield, &EventHook::onFunctionSuspendYieldJit, DNone,
SSync, {{SSA, 0}}},
{ReturnHook, &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}}},
/* microtime(true) */
{GetTime, TimeStamp::CurrentSecond, DSSA, SNone, {}},
/* clock_gettime_ns($clk_id) */
{GetTimeNs, folly::chrono::clock_gettime_ns, DSSA, SNone, {{SSA, 0}}},
/* ClsMethDataRef */
{CheckClsMethFunc, checkClsMethFuncHelper, DNone, SSync, {{SSA, 0}}},
/* reified generics operations */
{CheckClsReifiedGenericMismatch, checkClassReifiedGenericMismatch,
DNone, SSync,
{{extra(&ClassData::cls)}, {SSA, 0}}},
{CheckFunReifiedGenericMismatch, checkFunReifiedGenericMismatch,
DNone, SSync,
{{SSA, 0}, {SSA, 1}}},
{VerifyReifiedLocalType, VerifyReifiedLocalTypeImpl, DNone, SSync,
{{TV, 0}, {SSA, 1}, {SSA, 2},
extra(&FuncParamData::func),
extra(&FuncParamData::paramId)}},
{VerifyReifiedReturnType, VerifyReifiedReturnTypeImpl, DNone, SSync,
{{TV, 0}, {SSA, 1}, {SSA, 2},
extra(&FuncData::func)}},
{RecordReifiedGenericsAndGetTSList, recordReifiedGenericsAndGetTSList,
DSSA, SSync, {{SSA, 0}}},
{RaiseErrorOnInvalidIsAsExpressionType,
errorOnIsAsExpressionInvalidTypesHelper, DSSA, SSync, {{SSA, 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
///////////////////////////////////////////////////////////////////////////////
using namespace NativeCalls;
ArgGroup toArgGroup(const CallInfo& info,
const StateVector<SSATmp,Vloc>& locs,
const IRInstruction* inst) {
ArgGroup argGroup{inst, locs};
for (auto const& arg : info.args) {
switch (arg.type) {
case ArgType::SSA:
argGroup.ssa(arg.ival);
break;
case ArgType::TV:
argGroup.typedValue(arg.ival);
break;
case ArgType::ExtraImm:
argGroup.imm(arg.extraFunc(inst));
break;
case ArgType::Imm:
argGroup.imm(arg.ival);
break;
}
}
return argGroup;
}
///////////////////////////////////////////////////////////////////////////////
}