mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
Add Call Stub
Change several structures for call stub. Related issue: #I4XK12 Signed-off-by: lichenshuai <lichenshuai@huawei.com> Change-Id: Ie7389ff96c619451304a3f0d352b271310c4b73e
This commit is contained in:
parent
aa42d76018
commit
e6b8f48f69
@ -197,6 +197,11 @@ GateRef InterpreterStub::GetEnvFromFrame(GateRef frame)
|
||||
GetIntPtrConstant(InterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit())));
|
||||
}
|
||||
|
||||
GateRef InterpreterStub::GetEnvFromFunction(GateRef function)
|
||||
{
|
||||
return Load(VariableType::JS_POINTER(), function, GetIntPtrConstant(JSFunction::LEXICAL_ENV_OFFSET));
|
||||
}
|
||||
|
||||
GateRef InterpreterStub::GetProfileTypeInfoFromFunction(GateRef function)
|
||||
{
|
||||
return Load(VariableType::JS_POINTER(), function, GetIntPtrConstant(JSFunction::PROFILE_TYPE_INFO_OFFSET));
|
||||
|
@ -74,8 +74,8 @@ void name##Stub::GenerateCircuitImpl(GateRef glue, GateRef pc, GateRef sp,
|
||||
#define DISPATCH_LAST() \
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, acc, hotnessCounter) \
|
||||
|
||||
#define DISPATCH_LAST() \
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, acc, hotnessCounter) \
|
||||
#define DISPATCH_LAST_WITH_ACC() \
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter) \
|
||||
|
||||
#define UPDATE_HOTNESS(_sp) \
|
||||
varHotnessCounter = Int32Add(offset, *varHotnessCounter); \
|
||||
@ -83,7 +83,7 @@ void name##Stub::GenerateCircuitImpl(GateRef glue, GateRef pc, GateRef sp,
|
||||
Bind(&slowPath); \
|
||||
{ \
|
||||
varProfileTypeInfo = CallRuntimeTrampoline(glue, \
|
||||
GetInt64Constant(RUNTIME_CALL_ID(UpdateHotnessCounter)), {}); \
|
||||
GetInt64Constant(RUNTIME_CALL_ID(UpdateHotnessCounter)), {}); \
|
||||
varHotnessCounter = GetInt32Constant(EcmaInterpreter::METHOD_HOTNESS_THRESHOLD); \
|
||||
Jump(&dispatch); \
|
||||
} \
|
||||
@ -869,7 +869,7 @@ DECLARE_ASM_HANDLER(HandleGetPropIteratorPref)
|
||||
Branch(TaggedIsException(res), &isException, ¬Exception);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(¬Exception);
|
||||
varAcc = res;
|
||||
@ -887,7 +887,7 @@ DECLARE_ASM_HANDLER(HandleAsyncFunctionEnterPref)
|
||||
Branch(TaggedIsException(res), &isException, ¬Exception);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(¬Exception);
|
||||
varAcc = res;
|
||||
@ -941,7 +941,7 @@ DECLARE_ASM_HANDLER(HandleGetIteratorPref)
|
||||
Branch(TaggedIsException(res), &isException, ¬Exception);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(¬Exception);
|
||||
varAcc = res;
|
||||
@ -2781,7 +2781,7 @@ DECLARE_ASM_HANDLER(HandleLdSuperByNamePrefId32V8)
|
||||
Branch(TaggedIsException(result), &isException, &dispatch);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(&dispatch);
|
||||
varAcc = result;
|
||||
@ -2953,7 +2953,7 @@ DECLARE_ASM_HANDLER(HandleStConstToGlobalRecordPrefId32)
|
||||
Branch(TaggedIsException(result), &isException, ¬Exception);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(¬Exception);
|
||||
DISPATCH_WITH_ACC(PREF_ID32);
|
||||
@ -2974,7 +2974,7 @@ DECLARE_ASM_HANDLER(HandleStLetToGlobalRecordPrefId32)
|
||||
Branch(TaggedIsException(result), &isException, ¬Exception);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(¬Exception);
|
||||
DISPATCH_WITH_ACC(PREF_ID32);
|
||||
@ -2995,7 +2995,7 @@ DECLARE_ASM_HANDLER(HandleStClassToGlobalRecordPrefId32)
|
||||
Branch(TaggedIsException(result), &isException, ¬Exception);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(¬Exception);
|
||||
DISPATCH_WITH_ACC(PREF_ID32);
|
||||
@ -3052,7 +3052,7 @@ DECLARE_ASM_HANDLER(HandleNegDynPrefV8)
|
||||
Branch(TaggedIsException(result), &isException, ¬Exception);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(¬Exception);
|
||||
varAcc = result;
|
||||
@ -3104,7 +3104,7 @@ DECLARE_ASM_HANDLER(HandleNotDynPrefV8)
|
||||
Branch(TaggedIsException(result), &isException, ¬Exception);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(¬Exception);
|
||||
varAcc = result;
|
||||
@ -3193,7 +3193,7 @@ DECLARE_ASM_HANDLER(HandleAnd2DynPrefV8)
|
||||
Branch(TaggedIsException(taggedNumber), &isException, ¬Exception);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(¬Exception);
|
||||
{
|
||||
@ -3286,7 +3286,7 @@ DECLARE_ASM_HANDLER(HandleOr2DynPrefV8)
|
||||
Branch(TaggedIsException(taggedNumber), &isException, ¬Exception);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(¬Exception);
|
||||
{
|
||||
@ -3379,7 +3379,7 @@ DECLARE_ASM_HANDLER(HandleXOr2DynPrefV8)
|
||||
Branch(TaggedIsException(taggedNumber), &isException, ¬Exception);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(¬Exception);
|
||||
{
|
||||
@ -3472,7 +3472,7 @@ DECLARE_ASM_HANDLER(HandleAshr2DynPrefV8)
|
||||
Branch(TaggedIsException(taggedNumber), &isException, ¬Exception);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(¬Exception);
|
||||
{
|
||||
@ -3566,7 +3566,7 @@ DECLARE_ASM_HANDLER(HandleShr2DynPrefV8)
|
||||
Branch(TaggedIsException(taggedNumber), &isException, ¬Exception);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(¬Exception);
|
||||
{
|
||||
@ -3659,7 +3659,7 @@ DECLARE_ASM_HANDLER(HandleShl2DynPrefV8)
|
||||
Branch(TaggedIsException(taggedNumber), &IsException, &NotException);
|
||||
Bind(&IsException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(&NotException);
|
||||
{
|
||||
@ -3717,7 +3717,7 @@ DECLARE_ASM_HANDLER(HandleDefineClassWithBufferPrefId16Imm16Imm16V8V8)
|
||||
Branch(TaggedIsException(*res), &isException, &isNotException);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(&isNotException);
|
||||
GateRef newLexicalEnv = GetVregValue(sp, ZExtInt8ToPtr(v0)); // slow runtime may gc
|
||||
@ -3807,7 +3807,7 @@ DECLARE_ASM_HANDLER(HandleLdObjByNamePrefId32V8)
|
||||
Branch(TaggedIsException(result), &isException, &noException);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(&noException);
|
||||
varAcc = result;
|
||||
@ -4598,7 +4598,7 @@ DECLARE_ASM_HANDLER(HandleTryLdGlobalByNamePrefId32)
|
||||
Branch(TaggedIsException(*icResult), &isException, &isNotException);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(&isNotException);
|
||||
varAcc = *icResult;
|
||||
@ -4630,7 +4630,7 @@ DECLARE_ASM_HANDLER(HandleTryLdGlobalByNamePrefId32)
|
||||
Branch(TaggedIsException(slowResult), &isException, &isNotException);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(&isNotException);
|
||||
varAcc = slowResult;
|
||||
@ -4791,7 +4791,7 @@ DECLARE_ASM_HANDLER(HandleLdGlobalVarPrefId32)
|
||||
Branch(TaggedIsException(*result), &isException, &dispatch);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
}
|
||||
Bind(&dispatch);
|
||||
@ -4973,7 +4973,7 @@ DECLARE_ASM_HANDLER(HandleToNumberPrefV8)
|
||||
Branch(TaggedIsException(res), &isException, ¬Exception);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(¬Exception);
|
||||
{
|
||||
@ -5078,7 +5078,7 @@ DECLARE_ASM_HANDLER(HandleAdd2DynPrefV8)
|
||||
Branch(TaggedIsException(taggedNumber), &isException, ¬Exception);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(¬Exception);
|
||||
{
|
||||
@ -5188,7 +5188,7 @@ DECLARE_ASM_HANDLER(HandleSub2DynPrefV8)
|
||||
Branch(TaggedIsException(taggedNumber), &isException, ¬Exception);
|
||||
Bind(&isException);
|
||||
{
|
||||
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
|
||||
DISPATCH_LAST_WITH_ACC();
|
||||
}
|
||||
Bind(¬Exception);
|
||||
{
|
||||
@ -5200,9 +5200,475 @@ DECLARE_ASM_HANDLER(HandleSub2DynPrefV8)
|
||||
Bind(&accDispatch);
|
||||
DISPATCH_WITH_ACC(PREF_V8);
|
||||
}
|
||||
|
||||
#define CALL_INITIALIZE() \
|
||||
SetPcToFrame(glue, GetFrame(sp), pc); \
|
||||
GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); \
|
||||
Label funcIsHeapObject(env); \
|
||||
Label funcIsCallable(env); \
|
||||
Label funcNotCallable(env); \
|
||||
Branch(TaggedIsHeapObject(func), &funcIsHeapObject, &funcNotCallable); \
|
||||
Bind(&funcIsHeapObject); \
|
||||
Branch(IsCallable(func), &funcIsCallable, &funcNotCallable); \
|
||||
Bind(&funcNotCallable); \
|
||||
{ \
|
||||
CallRuntimeTrampoline(glue, GetInt64Constant(RUNTIME_CALL_ID(SetNotCallableException)), {}); \
|
||||
DISPATCH_LAST(); \
|
||||
} \
|
||||
Bind(&funcIsCallable); \
|
||||
DEFVARIABLE(methodOffset, VariableType::INT32(), GetInt32Constant(0)); \
|
||||
/* method = func->GetCallTarget() */ \
|
||||
/* ASSERT(JSTaggedValue(func).IsJSFunctionBase() || JSTaggedValue(func).IsJSProxy()) */ \
|
||||
Label funcIsJSFunctionBase(env); \
|
||||
Label funcIsJSProxy(env); \
|
||||
Label getMethod(env); \
|
||||
Branch(IsJSFunctionBase(func), &funcIsJSFunctionBase, &funcIsJSProxy); \
|
||||
Bind(&funcIsJSFunctionBase); \
|
||||
{ \
|
||||
methodOffset = GetInt32Constant(JSFunctionBase::METHOD_OFFSET); \
|
||||
Jump(&getMethod); \
|
||||
} \
|
||||
Bind(&funcIsJSProxy); \
|
||||
{ \
|
||||
methodOffset = GetInt32Constant(JSProxy::METHOD_OFFSET); \
|
||||
Jump(&getMethod); \
|
||||
} \
|
||||
Bind(&getMethod); \
|
||||
GateRef method = Load(VariableType::POINTER(), func, ChangeInt32ToIntPtr(*methodOffset)); \
|
||||
GateRef callFieldOffset = GetIntPtrConstant(JSMethod::GetCallFieldOffset(env->IsArch32Bit())); \
|
||||
GateRef callField = Load(VariableType::INT64(), method, callFieldOffset); \
|
||||
DEFVARIABLE(newSp, VariableType::POINTER(), \
|
||||
PointerSub(sp, GetIntPtrConstant(InterpretedFrame::GetSize(env->IsArch32Bit()))))
|
||||
|
||||
#define CALL_PUSH_UNDEFINED(n) \
|
||||
i = GetInt32Constant(0); \
|
||||
Label pushUndefined(env); \
|
||||
Label pushUndefinedAgain(env); \
|
||||
Label pushUndefinedEnd(env); \
|
||||
Branch(Int32LessThan(*i, n), &pushUndefined, &pushUndefinedEnd); \
|
||||
LoopBegin(&pushUndefined); \
|
||||
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), \
|
||||
GetInt64Constant(JSTaggedValue::VALUE_UNDEFINED)); \
|
||||
i = Int32Add(*i, GetInt32Constant(1)); \
|
||||
Branch(Int32LessThan(*i, n), &pushUndefinedAgain, &pushUndefinedEnd); \
|
||||
Bind(&pushUndefinedAgain); \
|
||||
LoopEnd(&pushUndefined); \
|
||||
Bind(&pushUndefinedEnd)
|
||||
|
||||
#define CALL_PUSH_ARGS(format) \
|
||||
DEFVARIABLE(i, VariableType::INT32(), GetInt32Constant(0)); \
|
||||
GateRef isNativeMask = GetInt64Constant(static_cast<uint64_t>(1) << JSMethod::IsNativeBit::START_BIT); \
|
||||
Label methodIsNative(env); \
|
||||
Label methodNotNative(env); \
|
||||
Branch(Int64NotEqual(Int64And(callField, isNativeMask), GetInt64Constant(0)), &methodIsNative, &methodNotNative); \
|
||||
Bind(&methodIsNative); \
|
||||
{ \
|
||||
CALL_PUSH_ARGS_##format(); \
|
||||
SET_VREGS_AND_FRAME_NATIVE(format); \
|
||||
} \
|
||||
Bind(&methodNotNative); \
|
||||
GateRef numArgsOffset = GetInt64Constant(JSMethod::NumArgsBits::START_BIT); \
|
||||
GateRef numArgsMask = GetInt64Constant((static_cast<uint64_t>(1) << JSMethod::NumArgsBits::SIZE) - 1); \
|
||||
GateRef declaredNumArgs = ChangeInt64ToInt32(Int64And(UInt64LSR(callField, numArgsOffset), numArgsMask)); \
|
||||
Label fastPath(env); \
|
||||
Label slowPath(env); \
|
||||
Label setVregsAndFrameNotNative(env); \
|
||||
Branch(Int32Equal(actualNumArgs, declaredNumArgs), &fastPath, &slowPath); \
|
||||
Bind(&fastPath); \
|
||||
{ \
|
||||
CALL_PUSH_ARGS_##format(); \
|
||||
Jump(&setVregsAndFrameNotNative); \
|
||||
} \
|
||||
Bind(&slowPath); \
|
||||
GateRef haveExtraMask = GetInt64Constant(static_cast<uint64_t>(1) << JSMethod::HaveExtraBit::START_BIT); \
|
||||
Label methodNoExtra(env); \
|
||||
Label methodHaveExtra(env); \
|
||||
Branch(Int64NotEqual(Int64And(callField, haveExtraMask), GetInt64Constant(0)), &methodHaveExtra, &methodNoExtra); \
|
||||
Bind(&methodNoExtra); \
|
||||
{ \
|
||||
GateRef undefinedNumArgs = Int32Sub(declaredNumArgs, actualNumArgs); \
|
||||
CALL_PUSH_UNDEFINED(undefinedNumArgs); \
|
||||
CALL_PUSH_ARGS_NO_EXTRA_##format(); \
|
||||
Jump(&setVregsAndFrameNotNative); \
|
||||
} \
|
||||
Bind(&methodHaveExtra); \
|
||||
{ \
|
||||
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), IntBuildTaggedTypeWithNoGC(actualNumArgs)); \
|
||||
GateRef undefinedNumArgs = Int32Sub(declaredNumArgs, actualNumArgs); \
|
||||
CALL_PUSH_UNDEFINED(undefinedNumArgs); \
|
||||
CALL_PUSH_ARGS_##format(); \
|
||||
Jump(&setVregsAndFrameNotNative); \
|
||||
} \
|
||||
Bind(&setVregsAndFrameNotNative); \
|
||||
SET_VREGS_AND_FRAME_NOT_NATIVE(format)
|
||||
|
||||
#define SET_VREGS_AND_FRAME_NATIVE(format) \
|
||||
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
|
||||
Label pushThis(env); \
|
||||
Label pushThisUndefined(env); \
|
||||
Label pushNewTarget(env); \
|
||||
Branch(callThis, &pushThis, &pushThisUndefined); \
|
||||
Bind(&pushThis); \
|
||||
{ \
|
||||
GateRef thisValue = GetVregValue(sp, IntPtrAdd(ZExtInt8ToPtr(funcReg), GetIntPtrConstant(1))); \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), thisValue); \
|
||||
Jump(&pushNewTarget); \
|
||||
} \
|
||||
Bind(&pushThisUndefined); \
|
||||
{ \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), \
|
||||
GetInt64Constant(JSTaggedValue::VALUE_UNDEFINED)); \
|
||||
Jump(&pushNewTarget); \
|
||||
} \
|
||||
Bind(&pushNewTarget); \
|
||||
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), \
|
||||
GetInt64Constant(JSTaggedValue::VALUE_UNDEFINED)); \
|
||||
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), func); \
|
||||
/* ASSERT(JSMethod::NumVregsBits::Decode(callField) == 0) */ \
|
||||
/* thread->DoStackOverflowCheck(newSp) */ \
|
||||
GateRef frameBaseOffset = GetIntPtrConstant(JSThread::GlueData::GetFrameBaseOffset(env->IsArch32Bit())); \
|
||||
GateRef frameBase = Load(VariableType::POINTER(), glue, frameBaseOffset); \
|
||||
Label stackOverflow(env); \
|
||||
Label stackNotOverflow(env); \
|
||||
Branch(UInt64LessThanOrEqual(*newSp, IntPtrAdd(frameBase, \
|
||||
/* 2: double size in case */ \
|
||||
GetIntPtrConstant(JSThread::RESERVE_STACK_SIZE * sizeof(JSTaggedType) * 2))), \
|
||||
&stackOverflow, &stackNotOverflow); \
|
||||
Bind(&stackOverflow); \
|
||||
{ \
|
||||
CallRuntimeTrampoline(glue, GetInt64Constant(RUNTIME_CALL_ID(SetStackOverflowException)), {}); \
|
||||
DISPATCH_LAST(); \
|
||||
} \
|
||||
Bind(&stackNotOverflow); \
|
||||
GateRef state = GetFrame(*newSp); \
|
||||
GateRef prevOffset = GetIntPtrConstant(InterpretedFrame::GetBaseOffset(env->IsArch32Bit())); \
|
||||
Store(VariableType::POINTER(), glue, state, prevOffset, sp); \
|
||||
GateRef frameTypeOffset = IntPtrAdd(prevOffset, GetIntPtrSize()); \
|
||||
Store(VariableType::INT64(), glue, state, frameTypeOffset, \
|
||||
GetInt64Constant(static_cast<uint64_t>(FrameType::INTERPRETER_FRAME))); \
|
||||
SetPcToFrame(glue, state, GetIntPtrConstant(0)); \
|
||||
SetFunctionToFrame(glue, state, func); \
|
||||
SetCurrentSpFrame(glue, *newSp); \
|
||||
GateRef numArgs = Int32Add(GetInt32Constant(NUM_MANDATORY_JSFUNC_ARGS), actualNumArgs); \
|
||||
GateRef retValue = CallRuntimeTrampoline(glue, GetInt64Constant(RUNTIME_CALL_ID(CallNative)), \
|
||||
{IntBuildTaggedTypeWithNoGC(numArgs), *newSp, method}); \
|
||||
SetCurrentSpFrame(glue, sp); \
|
||||
DEFVARIABLE(varAcc, VariableType::JS_ANY(), retValue); \
|
||||
DISPATCH_WITH_ACC(format)
|
||||
|
||||
#define SET_VREGS_AND_FRAME_NOT_NATIVE(format) \
|
||||
Label funcIsClassConstructor(env); \
|
||||
Label funcNotClassConstructor(env); \
|
||||
Branch(IsClassConstructor(func), &funcIsClassConstructor, &funcNotClassConstructor); \
|
||||
Bind(&funcIsClassConstructor); \
|
||||
{ \
|
||||
CallRuntimeTrampoline(glue, GetInt64Constant(RUNTIME_CALL_ID(SetCallConstructorException)), {}); \
|
||||
DISPATCH_LAST(); \
|
||||
} \
|
||||
Bind(&funcNotClassConstructor); \
|
||||
Label notNormalCallType(env); \
|
||||
Label isNormalCallType(env); \
|
||||
Branch(Int64Equal(Int64And(callField, GetInt64Constant(CALL_TYPE_MASK)), GetInt64Constant(0)), \
|
||||
&isNormalCallType, ¬NormalCallType); \
|
||||
Bind(¬NormalCallType); \
|
||||
{ \
|
||||
GateRef haveThisMask = GetInt64Constant(static_cast<uint64_t>(1) << JSMethod::HaveThisBit::START_BIT); \
|
||||
Label methodHaveThis(env); \
|
||||
Label methodNoThis(env); \
|
||||
Branch(Int64NotEqual(Int64And(callField, haveThisMask), GetInt64Constant(0)), \
|
||||
&methodHaveThis, &methodNoThis); \
|
||||
Bind(&methodHaveThis); \
|
||||
{ \
|
||||
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
|
||||
Label pushThis(env); \
|
||||
Label pushThisUndefined(env); \
|
||||
Branch(callThis, &pushThis, &pushThisUndefined); \
|
||||
Bind(&pushThis); \
|
||||
{ \
|
||||
GateRef thisValue = GetVregValue(sp, IntPtrAdd(ZExtInt8ToPtr(funcReg), GetIntPtrConstant(1))); \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), thisValue); \
|
||||
Jump(&methodNoThis); \
|
||||
} \
|
||||
Bind(&pushThisUndefined); \
|
||||
{ \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), \
|
||||
GetInt64Constant(JSTaggedValue::VALUE_UNDEFINED)); \
|
||||
Jump(&methodNoThis); \
|
||||
} \
|
||||
} \
|
||||
Bind(&methodNoThis); \
|
||||
GateRef haveNewTargetMask = GetInt64Constant(static_cast<uint64_t>(1) << \
|
||||
JSMethod::HaveNewTargetBit::START_BIT); \
|
||||
Label methodHaveNewTarget(env); \
|
||||
Label methodNoNewTarget(env); \
|
||||
Branch(Int64NotEqual(Int64And(callField, haveNewTargetMask), GetInt64Constant(0)), \
|
||||
&methodHaveNewTarget, &methodNoNewTarget); \
|
||||
Bind(&methodHaveNewTarget); \
|
||||
{ \
|
||||
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), \
|
||||
GetInt64Constant(JSTaggedValue::VALUE_UNDEFINED)); \
|
||||
Jump(&methodNoNewTarget); \
|
||||
} \
|
||||
Bind(&methodNoNewTarget); \
|
||||
GateRef haveFuncMask = GetInt64Constant(static_cast<uint64_t>(1) << JSMethod::HaveFuncBit::START_BIT); \
|
||||
Label methodHaveFunc(env); \
|
||||
Label methodNoFunc(env); \
|
||||
Branch(Int64NotEqual(Int64And(callField, haveFuncMask), GetInt64Constant(0)), \
|
||||
&methodHaveFunc, &methodNoFunc); \
|
||||
Bind(&methodHaveFunc); \
|
||||
{ \
|
||||
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), func); \
|
||||
Jump(&methodNoFunc); \
|
||||
} \
|
||||
Bind(&methodNoFunc); \
|
||||
Jump(&isNormalCallType); \
|
||||
} \
|
||||
Bind(&isNormalCallType); \
|
||||
{ \
|
||||
GateRef numVregsOffset = GetInt64Constant(JSMethod::NumVregsBits::START_BIT); \
|
||||
GateRef numVregsMask = GetInt64Constant((static_cast<uint64_t>(1) << JSMethod::NumVregsBits::SIZE) - 1); \
|
||||
GateRef numVregs = ChangeInt64ToInt32(Int64And(UInt64LSR(callField, numVregsOffset), numVregsMask)); \
|
||||
CALL_PUSH_UNDEFINED(numVregs); \
|
||||
/* thread->DoStackOverflowCheck(newSp) */ \
|
||||
GateRef frameBaseOffset = GetIntPtrConstant(JSThread::GlueData::GetFrameBaseOffset(env->IsArch32Bit())); \
|
||||
GateRef frameBase = Load(VariableType::POINTER(), glue, frameBaseOffset); \
|
||||
Label stackOverflow(env); \
|
||||
Label stackNotOverflow(env); \
|
||||
Branch(UInt64LessThanOrEqual(*newSp, IntPtrAdd(frameBase, \
|
||||
/* 2: double size in case */ \
|
||||
GetIntPtrConstant(JSThread::RESERVE_STACK_SIZE * sizeof(JSTaggedType) * 2))), \
|
||||
&stackOverflow, &stackNotOverflow); \
|
||||
Bind(&stackOverflow); \
|
||||
{ \
|
||||
CallRuntimeTrampoline(glue, GetInt64Constant(RUNTIME_CALL_ID(SetStackOverflowException)), {}); \
|
||||
DISPATCH_LAST(); \
|
||||
} \
|
||||
Bind(&stackNotOverflow); \
|
||||
SetPcToFrame(glue, GetFrame(sp), \
|
||||
IntPtrAdd(pc, GetIntPtrConstant(BytecodeInstruction::Size(BytecodeInstruction::Format::format)))); \
|
||||
GateRef state = GetFrame(*newSp); \
|
||||
GateRef prevOffset = GetIntPtrConstant(InterpretedFrame::GetBaseOffset(env->IsArch32Bit())); \
|
||||
Store(VariableType::POINTER(), glue, state, prevOffset, sp); \
|
||||
GateRef frameTypeOffset = IntPtrAdd(prevOffset, GetIntPtrConstant( \
|
||||
env->IsArch32Bit() ? InterpretedFrameBase::TYPE_OFFSET_32 : InterpretedFrameBase::TYPE_OFFSET_64)); \
|
||||
Store(VariableType::INT64(), glue, state, frameTypeOffset, \
|
||||
GetInt64Constant(static_cast<uint64_t>(FrameType::INTERPRETER_FRAME))); \
|
||||
GateRef bytecodeArrayOffset = GetIntPtrConstant(JSMethod::GetBytecodeArrayOffset(env->IsArch32Bit())); \
|
||||
GateRef bytecodeArray = Load(VariableType::POINTER(), method, bytecodeArrayOffset); \
|
||||
SetPcToFrame(glue, state, bytecodeArray); \
|
||||
SetFunctionToFrame(glue, state, func); \
|
||||
SetAccToFrame(glue, state, GetHoleConstant(VariableType::JS_ANY())); \
|
||||
GateRef newEnv = GetEnvFromFunction(func); \
|
||||
SetEnvToFrame(glue, state, newEnv); \
|
||||
SetCurrentSpFrame(glue, *newSp); \
|
||||
GateRef newConstpool = GetConstpoolFromFunction(func); \
|
||||
GateRef newProfileTypeInfo = GetProfileTypeInfoFromFunction(func); \
|
||||
GateRef newHotnessCounter = Load(VariableType::INT32(), method, \
|
||||
GetIntPtrConstant(JSMethod::HOTNESS_COUNTER_OFFSET)); \
|
||||
Dispatch(glue, bytecodeArray, *newSp, newConstpool, newProfileTypeInfo, \
|
||||
GetHoleConstant(VariableType::JS_ANY()), newHotnessCounter, GetIntPtrConstant(0)); \
|
||||
}
|
||||
|
||||
#define CALL_PUSH_ARGS_PREF_V8() \
|
||||
static_cast<void>(0) // do nothing when 0 arg
|
||||
|
||||
#define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8() \
|
||||
static_cast<void>(0) // do nothing when 0 arg
|
||||
|
||||
#define CALL_PUSH_ARGS_PREF_V8_V8() \
|
||||
GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0)); \
|
||||
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), a0Value)
|
||||
|
||||
#define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8() \
|
||||
Label push0(env); \
|
||||
Label skip0(env); \
|
||||
Branch(Int32GreaterThanOrEqual(declaredNumArgs, \
|
||||
GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARG1)), &push0, &skip0); \
|
||||
Bind(&push0); \
|
||||
{ \
|
||||
GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0)); \
|
||||
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), a0Value); \
|
||||
Jump(&skip0); \
|
||||
} \
|
||||
Bind(&skip0)
|
||||
|
||||
#define CALL_PUSH_ARGS_PREF_V8_V8_V8() \
|
||||
GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1)); \
|
||||
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), a1Value); \
|
||||
CALL_PUSH_ARGS_PREF_V8_V8()
|
||||
|
||||
#define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8_V8() \
|
||||
Label push1(env); \
|
||||
Label skip1(env); \
|
||||
Branch(Int32GreaterThanOrEqual(declaredNumArgs, \
|
||||
GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARGS2)), &push1, &skip1); \
|
||||
Bind(&push1); \
|
||||
{ \
|
||||
GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1)); \
|
||||
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), a1Value); \
|
||||
Jump(&skip1); \
|
||||
} \
|
||||
Bind(&skip1); \
|
||||
CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8()
|
||||
|
||||
#define CALL_PUSH_ARGS_PREF_V8_V8_V8_V8() \
|
||||
GateRef a2Value = GetVregValue(sp, ZExtInt8ToPtr(a2)); \
|
||||
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), a2Value); \
|
||||
CALL_PUSH_ARGS_PREF_V8_V8_V8()
|
||||
|
||||
#define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8_V8_V8() \
|
||||
Label push2(env); \
|
||||
Label skip2(env); \
|
||||
Branch(Int32GreaterThanOrEqual(declaredNumArgs, \
|
||||
GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARGS3)), &push2, &skip2); \
|
||||
Bind(&push2); \
|
||||
{ \
|
||||
GateRef a2Value = GetVregValue(sp, ZExtInt8ToPtr(a2)); \
|
||||
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), a2Value); \
|
||||
Jump(&skip2); \
|
||||
} \
|
||||
Bind(&skip2); \
|
||||
CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8_V8()
|
||||
|
||||
#define CALL_PUSH_ARGS_PREF_IMM16_V8() \
|
||||
i = actualNumArgs; \
|
||||
CALL_PUSH_ARGS_I()
|
||||
|
||||
#define CALL_PUSH_ARGS_NO_EXTRA_PREF_IMM16_V8() \
|
||||
/* i = std::min(actualNumArgs, declaredNumArgs) */ \
|
||||
i = actualNumArgs; \
|
||||
Label declaredNumArgsSmaller(env); \
|
||||
Label callPushArgsI(env); \
|
||||
Branch(Int32LessThan(*i, declaredNumArgs), &callPushArgsI, &declaredNumArgsSmaller); \
|
||||
Bind(&declaredNumArgsSmaller); \
|
||||
i = declaredNumArgs; \
|
||||
Jump(&callPushArgsI); \
|
||||
Bind(&callPushArgsI); \
|
||||
CALL_PUSH_ARGS_I()
|
||||
|
||||
#define CALL_PUSH_ARGS_I() \
|
||||
Label pushWithThis(env); \
|
||||
Label pushWithoutThis(env); \
|
||||
Label pushArgsEnd(env); \
|
||||
Branch(callThis, &pushWithThis, &pushWithoutThis); \
|
||||
Bind(&pushWithThis); \
|
||||
{ \
|
||||
i = Int32Add(*i, GetInt32Constant(1)); /* 1: skip this */ \
|
||||
Label pushArgs(env); \
|
||||
Label pushArgsAgain(env); \
|
||||
Branch(Int32GreaterThan(*i, GetInt32Constant(1)), &pushArgs, &pushArgsEnd); \
|
||||
LoopBegin(&pushArgs); \
|
||||
GateRef aValue = GetVregValue(sp, IntPtrAdd(ZExtInt8ToPtr(funcReg), ChangeInt32ToIntPtr(*i))); \
|
||||
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), aValue); \
|
||||
i = Int32Sub(*i, GetInt32Constant(1)); \
|
||||
Branch(Int32GreaterThan(*i, GetInt32Constant(1)), &pushArgsAgain, &pushArgsEnd); \
|
||||
Bind(&pushArgsAgain); \
|
||||
LoopEnd(&pushArgs); \
|
||||
} \
|
||||
Bind(&pushWithoutThis); \
|
||||
{ \
|
||||
Label pushArgs(env); \
|
||||
Label pushArgsAgain(env); \
|
||||
Branch(Int32GreaterThan(*i, GetInt32Constant(0)), &pushArgs, &pushArgsEnd); \
|
||||
LoopBegin(&pushArgs); \
|
||||
GateRef aValue = GetVregValue(sp, IntPtrAdd(ZExtInt8ToPtr(funcReg), ChangeInt32ToIntPtr(*i))); \
|
||||
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
|
||||
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), aValue); \
|
||||
i = Int32Sub(*i, GetInt32Constant(1)); \
|
||||
Branch(Int32GreaterThan(*i, GetInt32Constant(0)), &pushArgsAgain, &pushArgsEnd); \
|
||||
Bind(&pushArgsAgain); \
|
||||
LoopEnd(&pushArgs); \
|
||||
} \
|
||||
Bind(&pushArgsEnd)
|
||||
|
||||
DECLARE_ASM_HANDLER(HandleCallArg0DynPrefV8)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
|
||||
GateRef actualNumArgs = GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARG0);
|
||||
GateRef funcReg = ReadInst8_1(pc);
|
||||
CALL_INITIALIZE();
|
||||
GateRef callThis = FalseConstant();
|
||||
CALL_PUSH_ARGS(PREF_V8);
|
||||
}
|
||||
|
||||
DECLARE_ASM_HANDLER(HandleCallArg1DynPrefV8V8)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
|
||||
GateRef actualNumArgs = GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARG1);
|
||||
GateRef funcReg = ReadInst8_1(pc);
|
||||
GateRef a0 = ReadInst8_2(pc);
|
||||
CALL_INITIALIZE();
|
||||
GateRef callThis = FalseConstant();
|
||||
CALL_PUSH_ARGS(PREF_V8_V8);
|
||||
}
|
||||
|
||||
DECLARE_ASM_HANDLER(HandleCallArgs2DynPrefV8V8V8)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
|
||||
GateRef actualNumArgs = GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARGS2);
|
||||
GateRef funcReg = ReadInst8_1(pc);
|
||||
GateRef a0 = ReadInst8_2(pc);
|
||||
GateRef a1 = ReadInst8_3(pc);
|
||||
CALL_INITIALIZE();
|
||||
GateRef callThis = FalseConstant();
|
||||
CALL_PUSH_ARGS(PREF_V8_V8_V8);
|
||||
}
|
||||
|
||||
DECLARE_ASM_HANDLER(HandleCallArgs3DynPrefV8V8V8V8)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
|
||||
GateRef actualNumArgs = GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARGS3);
|
||||
GateRef funcReg = ReadInst8_1(pc);
|
||||
GateRef a0 = ReadInst8_2(pc);
|
||||
GateRef a1 = ReadInst8_3(pc);
|
||||
GateRef a2 = ReadInst8_4(pc);
|
||||
CALL_INITIALIZE();
|
||||
GateRef callThis = FalseConstant();
|
||||
CALL_PUSH_ARGS(PREF_V8_V8_V8_V8);
|
||||
}
|
||||
|
||||
DECLARE_ASM_HANDLER(HandleCallIRangeDynPrefImm16V8)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
|
||||
GateRef actualNumArgs = ZExtInt16ToInt32(ReadInst16_1(pc));
|
||||
GateRef funcReg = ReadInst8_3(pc);
|
||||
CALL_INITIALIZE();
|
||||
GateRef callThis = FalseConstant();
|
||||
CALL_PUSH_ARGS(PREF_IMM16_V8);
|
||||
}
|
||||
|
||||
DECLARE_ASM_HANDLER(HandleCallIThisRangeDynPrefImm16V8)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
|
||||
GateRef actualNumArgs = Int32Sub(ZExtInt16ToInt32(ReadInst16_1(pc)), GetInt32Constant(1)); // 1: exclude this
|
||||
GateRef funcReg = ReadInst8_3(pc);
|
||||
CALL_INITIALIZE();
|
||||
GateRef callThis = TrueConstant();
|
||||
CALL_PUSH_ARGS(PREF_IMM16_V8);
|
||||
}
|
||||
#endif
|
||||
#undef DECLARE_ASM_HANDLER
|
||||
#undef DISPATCH
|
||||
#undef DISPATCH_WITH_ACC
|
||||
#undef DISPATCH_LAST
|
||||
#undef DISPATCH_LAST_WITH_ACC
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -64,6 +64,7 @@ public:
|
||||
inline GateRef GetFunctionFromFrame(GateRef frame);
|
||||
inline GateRef GetAccFromFrame(GateRef frame);
|
||||
inline GateRef GetEnvFromFrame(GateRef frame);
|
||||
inline GateRef GetEnvFromFunction(GateRef frame);
|
||||
inline GateRef GetConstpoolFromFunction(GateRef function);
|
||||
inline GateRef GetProfileTypeInfoFromFunction(GateRef function);
|
||||
|
||||
|
@ -24,12 +24,15 @@ namespace panda::ecmascript::kungfu {
|
||||
#define IGNORE_STUB(...)
|
||||
|
||||
#define INTERPRETER_STUB_LIST(V) \
|
||||
ASM_INTERPRETER_STUB_LIST(IGNORE_STUB, V)
|
||||
ASM_INTERPRETER_STUB_LIST(IGNORE_STUB, V, V)
|
||||
|
||||
#define INTERPRETER_IGNORE_STUB_LIST(V) \
|
||||
ASM_INTERPRETER_STUB_LIST(IGNORE_STUB, IGNORE_STUB, V)
|
||||
|
||||
#define ASM_INTERPRETER_ID_LIST(V) \
|
||||
ASM_INTERPRETER_STUB_LIST(V, V)
|
||||
ASM_INTERPRETER_STUB_LIST(V, V, V)
|
||||
|
||||
#define ASM_INTERPRETER_STUB_LIST(V, T) \
|
||||
#define ASM_INTERPRETER_STUB_LIST(V, T, I) \
|
||||
T(HandleLdNanPref, 7) \
|
||||
T(HandleLdInfinityPref, 7) \
|
||||
T(HandleLdGlobalThisPref, 7) \
|
||||
@ -89,7 +92,7 @@ namespace panda::ecmascript::kungfu {
|
||||
T(HandleThrowConstAssignmentPrefV8, 7) \
|
||||
T(HandleGetTemplateObjectPrefV8, 7) \
|
||||
T(HandleGetNextPropNamePrefV8, 7) \
|
||||
V(HandleCallArg0DynPrefV8, 7) \
|
||||
I(HandleCallArg0DynPrefV8, 7) \
|
||||
T(HandleThrowIfNotObjectPrefV8, 7) \
|
||||
T(HandleIterNextPrefV8, 7) \
|
||||
T(HandleCloseIteratorPrefV8, 7) \
|
||||
@ -101,7 +104,7 @@ namespace panda::ecmascript::kungfu {
|
||||
T(HandleSuspendGeneratorPrefV8V8, 7) \
|
||||
T(HandleAsyncFunctionAwaitUncaughtPrefV8V8, 7) \
|
||||
T(HandleThrowUndefinedIfHolePrefV8V8, 7) \
|
||||
V(HandleCallArg1DynPrefV8V8, 7) \
|
||||
I(HandleCallArg1DynPrefV8V8, 7) \
|
||||
T(HandleCopyDataPropertiesPrefV8V8, 7) \
|
||||
T(HandleStArraySpreadPrefV8V8, 7) \
|
||||
T(HandleGetIteratorNextPrefV8V8, 7) \
|
||||
@ -117,12 +120,12 @@ namespace panda::ecmascript::kungfu {
|
||||
T(HandleCallSpreadDynPrefV8V8V8, 7) \
|
||||
T(HandleAsyncFunctionResolvePrefV8V8V8, 7) \
|
||||
T(HandleAsyncFunctionRejectPrefV8V8V8, 7) \
|
||||
V(HandleCallArgs2DynPrefV8V8V8, 7) \
|
||||
V(HandleCallArgs3DynPrefV8V8V8V8, 7) \
|
||||
I(HandleCallArgs2DynPrefV8V8V8, 7) \
|
||||
I(HandleCallArgs3DynPrefV8V8V8V8, 7) \
|
||||
T(HandleDefineGetterSetterByValuePrefV8V8V8V8, 7) \
|
||||
T(HandleNewObjDynRangePrefImm16V8, 7) \
|
||||
V(HandleCallIRangeDynPrefImm16V8, 7) \
|
||||
V(HandleCallIThisRangeDynPrefImm16V8, 7) \
|
||||
I(HandleCallIRangeDynPrefImm16V8, 7) \
|
||||
I(HandleCallIThisRangeDynPrefImm16V8, 7) \
|
||||
T(HandleSuperCallPrefImm16V8, 7) \
|
||||
T(HandleCreateObjectWithExcludedKeysPrefImm16V8V8, 7) \
|
||||
T(HandleDefineFuncDynPrefId16Imm16V8, 7) \
|
||||
|
@ -126,8 +126,11 @@ void LLVMIRBuilder::AssignHandleMap()
|
||||
{OpCode::SLT, &LLVMIRBuilder::HandleCmp},
|
||||
{OpCode::ULT, &LLVMIRBuilder::HandleCmp},
|
||||
{OpCode::SLE, &LLVMIRBuilder::HandleCmp},
|
||||
{OpCode::ULE, &LLVMIRBuilder::HandleCmp},
|
||||
{OpCode::SGT, &LLVMIRBuilder::HandleCmp},
|
||||
{OpCode::UGT, &LLVMIRBuilder::HandleCmp},
|
||||
{OpCode::SGE, &LLVMIRBuilder::HandleCmp},
|
||||
{OpCode::UGE, &LLVMIRBuilder::HandleCmp},
|
||||
{OpCode::NE, &LLVMIRBuilder::HandleCmp},
|
||||
{OpCode::EQ, &LLVMIRBuilder::HandleCmp},
|
||||
{OpCode::LOAD, &LLVMIRBuilder::HandleLoad},
|
||||
@ -1264,7 +1267,8 @@ void LLVMIRBuilder::VisitSub(GateRef gate, GateRef e1, GateRef e2)
|
||||
COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value);
|
||||
LLVMValueRef result = nullptr;
|
||||
auto machineType = circuit_->LoadGatePtrConst(gate)->GetMachineType();
|
||||
if (machineType == MachineType::I16 || machineType == MachineType::I32 || machineType == MachineType::I64) {
|
||||
if (machineType == MachineType::I16 || machineType == MachineType::I32 ||
|
||||
machineType == MachineType::I64 || machineType == MachineType::ARCH) {
|
||||
result = LLVMBuildSub(builder_, e1Value, e2Value, "");
|
||||
} else if (machineType == MachineType::F64) {
|
||||
result = LLVMBuildFSub(builder_, e1Value, e2Value, "");
|
||||
@ -1384,16 +1388,31 @@ void LLVMIRBuilder::VisitCmp(GateRef gate, GateRef e1, GateRef e2)
|
||||
realOpcode = LLVMRealOLE;
|
||||
break;
|
||||
}
|
||||
case OpCode::ULE: {
|
||||
intOpcode = LLVMIntULE;
|
||||
realOpcode = LLVMRealOLE;
|
||||
break;
|
||||
}
|
||||
case OpCode::SGT: {
|
||||
intOpcode = LLVMIntSGT;
|
||||
realOpcode = LLVMRealOGT;
|
||||
break;
|
||||
}
|
||||
case OpCode::UGT: {
|
||||
intOpcode = LLVMIntUGT;
|
||||
realOpcode = LLVMRealOGT;
|
||||
break;
|
||||
}
|
||||
case OpCode::SGE: {
|
||||
intOpcode = LLVMIntSGE;
|
||||
realOpcode = LLVMRealOGE;
|
||||
break;
|
||||
}
|
||||
case OpCode::UGE: {
|
||||
intOpcode = LLVMIntUGE;
|
||||
realOpcode = LLVMRealOGE;
|
||||
break;
|
||||
}
|
||||
case OpCode::NE: {
|
||||
intOpcode = LLVMIntNE;
|
||||
realOpcode = LLVMRealONE;
|
||||
|
@ -477,6 +477,11 @@ GateRef Stub::IntPtrSub(GateRef x, GateRef y)
|
||||
return Int64Sub(x, y);
|
||||
}
|
||||
|
||||
GateRef Stub::PointerSub(GateRef x, GateRef y)
|
||||
{
|
||||
return env_.GetCircuitBuilder().NewArithmeticGate(OpCode(OpCode::SUB), MachineType::ARCH, x, y);
|
||||
}
|
||||
|
||||
GateRef Stub::Int16Sub(GateRef x, GateRef y)
|
||||
{
|
||||
return env_.GetCircuitBuilder().NewArithmeticGate(OpCode(OpCode::SUB), MachineType::I16, x, y);
|
||||
|
@ -452,6 +452,7 @@ public:
|
||||
inline GateRef DoubleAdd(GateRef x, GateRef y);
|
||||
inline GateRef IntPtrAdd(GateRef x, GateRef y);
|
||||
inline GateRef IntPtrSub(GateRef x, GateRef y);
|
||||
inline GateRef PointerSub(GateRef x, GateRef y);
|
||||
inline GateRef IntPtrEqual(GateRef x, GateRef y);
|
||||
inline GateRef Int16Sub(GateRef x, GateRef y);
|
||||
inline GateRef Int32Sub(GateRef x, GateRef y);
|
||||
|
@ -312,8 +312,10 @@ public:
|
||||
~InterpretedFrameBase() = default;
|
||||
JSTaggedType *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc
|
||||
FrameType type;
|
||||
static constexpr size_t SizeArch32 = sizeof(JSTaggedType *) + sizeof(FrameType);
|
||||
static constexpr size_t SizeArch64 = sizeof(JSTaggedType *) + sizeof(FrameType);
|
||||
static constexpr size_t TYPE_OFFSET_32 = sizeof(uint32_t);
|
||||
static constexpr size_t TYPE_OFFSET_64 = sizeof(uint64_t);
|
||||
static constexpr size_t SizeArch32 = TYPE_OFFSET_32 + sizeof(FrameType);
|
||||
static constexpr size_t SizeArch64 = TYPE_OFFSET_64 + sizeof(FrameType);
|
||||
};
|
||||
STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrameBase), InterpretedFrameBase::SizeArch32, InterpretedFrameBase::SizeArch64);
|
||||
|
||||
|
@ -3792,7 +3792,7 @@ uint32_t EcmaInterpreter::GetNumArgs(JSTaggedType *sp, uint32_t restIdx, uint32_
|
||||
uint32_t numArgs = method->GetNumArgsWithCallField();
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
JSTaggedType *lastFrame = state->base.prev - FRAME_STATE_SIZE;
|
||||
if (lastFrame - sp > numVregs + copyArgs + numArgs) {
|
||||
if (static_cast<uint32_t>(lastFrame - sp) > numVregs + copyArgs + numArgs) {
|
||||
// In this case, actualNumArgs is in the end
|
||||
// If not, then actualNumArgs == declaredNumArgs, therefore do nothing
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
|
@ -35,10 +35,10 @@ static constexpr size_t STORAGE_PTR_NUM = 3;
|
||||
V(CODEID, FILEID, sizeof(uint32_t), sizeof(uint32_t)) \
|
||||
V(SHORTY, CODEID, sizeof(uint32_t), sizeof(uint32_t)) \
|
||||
V(PROFILINGDATA, SHORTY, sizeof(uint32_t), sizeof(uint64_t)) \
|
||||
V(BYTECODEARRAY, PROFILINGDATA, sizeof(uint32_t), sizeof(uint64_t)) \
|
||||
V(CALLFIELD, PROFILINGDATA, sizeof(uint32_t), sizeof(uint64_t)) \
|
||||
V(BYTECODEARRAY, CALLFIELD, sizeof(uint64_t), sizeof(uint64_t)) \
|
||||
V(BYTECODEARRAYSIZE, BYTECODEARRAY, sizeof(uint32_t), sizeof(uint64_t)) \
|
||||
V(SLOTSIZE, BYTECODEARRAYSIZE, sizeof(uint32_t), sizeof(uint32_t)) \
|
||||
V(CALLFIELD, SLOTSIZE, sizeof(uint8_t), sizeof(uint8_t)) \
|
||||
|
||||
static constexpr uint32_t JS_METHOD_STOR32_OFFSET_32 = 0U;
|
||||
static constexpr uint32_t JS_METHOD_STOR32_OFFSET_64 = 0U;
|
||||
@ -131,6 +131,14 @@ public:
|
||||
return callField_;
|
||||
}
|
||||
|
||||
static constexpr uint32_t GetCallFieldOffset(bool isArm32)
|
||||
{
|
||||
if (isArm32) {
|
||||
return JS_METHOD_CALLFIELD_OFFSET_32;
|
||||
}
|
||||
return JS_METHOD_CALLFIELD_OFFSET_64;
|
||||
}
|
||||
|
||||
void SetNativeBit(bool isNative)
|
||||
{
|
||||
callField_ = IsNativeBit::Update(callField_, isNative);
|
||||
@ -180,10 +188,10 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t callField_ {0};
|
||||
const uint8_t *bytecodeArray_ {nullptr};
|
||||
uint32_t bytecodeArraySize_ {0};
|
||||
uint8_t slotSize_ {0};
|
||||
uint64_t callField_ {0};
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
|
@ -31,9 +31,9 @@ JSThread *JSThread::Create(Runtime *runtime, PandaVM *vm)
|
||||
jsThread->nativeAreaAllocator_ = EcmaVM::Cast(vm)->GetNativeAreaAllocator();
|
||||
jsThread->heapRegionAllocator_ = EcmaVM::Cast(vm)->GetHeapRegionAllocator();
|
||||
// algin with 16
|
||||
jsThread->frameBase_ = static_cast<JSTaggedType *>(
|
||||
jsThread->glueData_.frameBase_ = static_cast<JSTaggedType *>(
|
||||
EcmaVM::Cast(vm)->GetNativeAreaAllocator()->Allocate(sizeof(JSTaggedType) * MAX_STACK_SIZE));
|
||||
jsThread->glueData_.currentFrame_ = jsThread->frameBase_ + MAX_STACK_SIZE;
|
||||
jsThread->glueData_.currentFrame_ = jsThread->glueData_.frameBase_ + MAX_STACK_SIZE;
|
||||
JSThread::SetCurrent(jsThread);
|
||||
EcmaInterpreter::InitStackFrame(jsThread);
|
||||
return jsThread;
|
||||
@ -62,8 +62,8 @@ JSThread::~JSThread()
|
||||
handleScopeStorageNext_ = handleScopeStorageEnd_ = nullptr;
|
||||
EcmaVM::Cast(GetVM())->GetChunk()->Delete(globalStorage_);
|
||||
|
||||
GetNativeAreaAllocator()->Free(frameBase_, sizeof(JSTaggedType) * MAX_STACK_SIZE);
|
||||
frameBase_ = nullptr;
|
||||
GetNativeAreaAllocator()->Free(glueData_.frameBase_, sizeof(JSTaggedType) * MAX_STACK_SIZE);
|
||||
glueData_.frameBase_ = nullptr;
|
||||
nativeAreaAllocator_ = nullptr;
|
||||
heapRegionAllocator_ = nullptr;
|
||||
if (internalCallParams_ != nullptr) {
|
||||
@ -158,7 +158,7 @@ void JSThread::IterateWeakEcmaGlobalStorage(const WeakRootVisitor &visitor)
|
||||
bool JSThread::DoStackOverflowCheck(const JSTaggedType *sp)
|
||||
{
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
if (UNLIKELY(sp <= frameBase_ + RESERVE_STACK_SIZE)) {
|
||||
if (UNLIKELY(sp <= glueData_.frameBase_ + RESERVE_STACK_SIZE)) {
|
||||
ObjectFactory *factory = GetEcmaVM()->GetFactory();
|
||||
JSHandle<JSObject> error = factory->GetJSError(base::ErrorType::RANGE_ERROR, "Stack overflow!");
|
||||
if (LIKELY(!HasPendingException())) {
|
||||
@ -247,7 +247,12 @@ void JSThread::LoadStubModule(const char *moduleFile)
|
||||
glueData_.bcHandlers_.Set(kungfu::InterpreterStubId::name##Id, \
|
||||
stubModule.GetStubEntry(kungfu::StubId::STUB_##name));
|
||||
INTERPRETER_STUB_LIST(DEF_STUB)
|
||||
#define UNDEF_STUB(name, counter) \
|
||||
glueData_.bcHandlers_.Set(kungfu::InterpreterStubId::name##Id, \
|
||||
stubModule.GetStubEntry(kungfu::StubId::STUB_SingleStepDebugging));
|
||||
INTERPRETER_IGNORE_STUB_LIST(UNDEF_STUB)
|
||||
#undef DEF_STUB
|
||||
#undef UNDEF_STUB
|
||||
#endif
|
||||
|
||||
#ifdef NDEBUG
|
||||
|
@ -96,6 +96,7 @@ STATIC_ASSERT_EQ_ARCH(sizeof(StubEntries), StubEntries::SizeArch32, StubEntries:
|
||||
class JSThread : public ManagedThread {
|
||||
public:
|
||||
static constexpr int CONCURRENT_MARKING_BITFIELD_NUM = 2;
|
||||
static constexpr uint32_t RESERVE_STACK_SIZE = 128;
|
||||
using MarkStatusBits = BitField<MarkStatus, 0, CONCURRENT_MARKING_BITFIELD_NUM>;
|
||||
|
||||
static JSThread *Cast(ManagedThread *thread)
|
||||
@ -356,6 +357,7 @@ public:
|
||||
RTInterfaces,
|
||||
StubEntries,
|
||||
base::AlignedUint64,
|
||||
base::AlignedPointer,
|
||||
GlobalEnvConstants> {
|
||||
enum class Index : size_t {
|
||||
ExceptionIndex = 0,
|
||||
@ -366,6 +368,7 @@ public:
|
||||
RTInterfacesIndex,
|
||||
StubEntriesIndex,
|
||||
StateBitFieldIndex,
|
||||
FrameBaseIndex,
|
||||
GlobalConstIndex,
|
||||
NumOfMembers
|
||||
};
|
||||
@ -416,6 +419,11 @@ public:
|
||||
return GetOffset<static_cast<size_t>(Index::StubEntriesIndex)>(isArch32);
|
||||
}
|
||||
|
||||
static size_t GetFrameBaseOffset(bool isArch32)
|
||||
{
|
||||
return GetOffset<static_cast<size_t>(Index::FrameBaseIndex)>(isArch32);
|
||||
}
|
||||
|
||||
alignas(EAS) JSTaggedValue exception_ {JSTaggedValue::Hole()};
|
||||
alignas(EAS) JSTaggedValue globalObject_ {JSTaggedValue::Hole()};
|
||||
alignas(EAS) JSTaggedType *currentFrame_ {nullptr};
|
||||
@ -424,6 +432,7 @@ public:
|
||||
alignas(EAS) RTInterfaces rtInterfaces_;
|
||||
alignas(EAS) StubEntries stubEntries_;
|
||||
alignas(EAS) volatile uint64_t threadStateBitField_ {0ULL};
|
||||
alignas(EAS) JSTaggedType *frameBase_ {nullptr};
|
||||
alignas(EAS) GlobalEnvConstants globalConst_;
|
||||
};
|
||||
static_assert(MEMBER_OFFSET(GlueData, rtInterfaces_) == ASM_GLUE_RUNTIME_FUNCTIONS_OFFSET);
|
||||
@ -438,7 +447,6 @@ private:
|
||||
void DumpStack() DUMP_API_ATTR;
|
||||
|
||||
static constexpr uint32_t MAX_STACK_SIZE = 128 * 1024;
|
||||
static constexpr uint32_t RESERVE_STACK_SIZE = 128;
|
||||
static const uint32_t NODE_BLOCK_SIZE_LOG2 = 10;
|
||||
static const uint32_t NODE_BLOCK_SIZE = 1U << NODE_BLOCK_SIZE_LOG2;
|
||||
static constexpr int32_t MIN_HANDLE_STORAGE_SIZE = 2;
|
||||
@ -462,7 +470,6 @@ private:
|
||||
bool gcState_ {false};
|
||||
VmThreadControl *vmThreadControl_ {nullptr};
|
||||
|
||||
JSTaggedType *frameBase_ {nullptr};
|
||||
bool stableArrayElementsGuardians_ {true};
|
||||
InternalCallParams *internalCallParams_ {nullptr};
|
||||
GlueData glueData_;
|
||||
|
@ -26,7 +26,8 @@ static std::array<std::string, MessageString::MAX_MESSAGE_COUNT> g_messageString
|
||||
#undef DEF_COMMON_MESSAGE
|
||||
#define DEF_ASM_INTERPRETER_STUB_MESSAGE(name, count) #name,
|
||||
INTERPRETER_STUB_HELPER_LIST(DEF_ASM_INTERPRETER_STUB_MESSAGE)
|
||||
ASM_INTERPRETER_STUB_LIST(DEF_ASM_INTERPRETER_STUB_MESSAGE, DEF_ASM_INTERPRETER_STUB_MESSAGE)
|
||||
ASM_INTERPRETER_STUB_LIST(DEF_ASM_INTERPRETER_STUB_MESSAGE, DEF_ASM_INTERPRETER_STUB_MESSAGE,
|
||||
DEF_ASM_INTERPRETER_STUB_MESSAGE)
|
||||
#undef DEF_ASM_INTERPRETER_STUB_MESSAGE
|
||||
};
|
||||
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
#define DEF_MESSAGE_ID(name, string) Message_##name,
|
||||
COMMON_MESSAGE_STRING_LIST(DEF_MESSAGE_ID)
|
||||
INTERPRETER_STUB_HELPER_LIST(DEF_MESSAGE_ID)
|
||||
ASM_INTERPRETER_STUB_LIST(DEF_MESSAGE_ID, DEF_MESSAGE_ID)
|
||||
ASM_INTERPRETER_STUB_LIST(DEF_MESSAGE_ID, DEF_MESSAGE_ID, DEF_MESSAGE_ID)
|
||||
#undef DEF_MESSAGE_ID
|
||||
MAX_MESSAGE_COUNT
|
||||
};
|
||||
|
@ -157,6 +157,10 @@ namespace panda::ecmascript {
|
||||
V(DefineGeneratorFunc, 2) \
|
||||
V(DefineAsyncFunc, 2) \
|
||||
V(DefineMethod, 3) \
|
||||
V(SetNotCallableException, 0) \
|
||||
V(SetCallConstructorException, 0) \
|
||||
V(SetStackOverflowException, 0) \
|
||||
V(CallNative, 3) \
|
||||
V(CallSpreadDyn, 4) \
|
||||
V(DefineGetterSetterByValue, 6) \
|
||||
V(SuperCall, 5)
|
||||
|
@ -884,14 +884,13 @@ DEF_RUNTIME_TRAMPOLINES(UpdateHotnessCounter)
|
||||
RUNTIME_TRAMPOLINES_HEADER(UpdateHotnessCounter);
|
||||
InterpretedFrame *state = GET_FRAME(const_cast<JSTaggedType *>(thread->GetCurrentSPFrame()));
|
||||
thread->CheckSafepoint();
|
||||
if (state->profileTypeInfo == JSTaggedValue::Undefined()) {
|
||||
auto thisFunc = state->function;
|
||||
auto method = ECMAObject::Cast(thisFunc.GetTaggedObject())->GetCallTarget();
|
||||
auto res = SlowRuntimeStub::NotifyInlineCache(
|
||||
thread, JSFunction::Cast(thisFunc.GetHeapObject()), method);
|
||||
state->profileTypeInfo = res;
|
||||
auto thisFunc = JSFunction::Cast(state->function.GetTaggedObject());
|
||||
if (thisFunc->GetProfileTypeInfo() == JSTaggedValue::Undefined()) {
|
||||
auto method = thisFunc->GetCallTarget();
|
||||
auto res = SlowRuntimeStub::NotifyInlineCache(thread, thisFunc, method);
|
||||
return res.GetRawData();
|
||||
}
|
||||
return state->profileTypeInfo.GetRawData();
|
||||
return thisFunc->GetProfileTypeInfo().GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_TRAMPOLINES(LoadICByName)
|
||||
@ -1523,6 +1522,52 @@ DEF_RUNTIME_TRAMPOLINES(SuperCall)
|
||||
static_cast<uint16_t>(length.GetInt())).GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_TRAMPOLINES(SetNotCallableException)
|
||||
{
|
||||
RUNTIME_TRAMPOLINES_HEADER(SetNotCallableException);
|
||||
EcmaVM *ecmaVm = thread->GetEcmaVM();
|
||||
ObjectFactory *factory = ecmaVm->GetFactory();
|
||||
JSHandle<JSObject> error = factory->GetJSError(ErrorType::TYPE_ERROR, "is not callable");
|
||||
thread->SetException(error.GetTaggedValue());
|
||||
return JSTaggedValue::Hole().GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_TRAMPOLINES(SetCallConstructorException)
|
||||
{
|
||||
RUNTIME_TRAMPOLINES_HEADER(SetCallConstructorException);
|
||||
EcmaVM *ecmaVm = thread->GetEcmaVM();
|
||||
ObjectFactory *factory = ecmaVm->GetFactory();
|
||||
JSHandle<JSObject> error = factory->GetJSError(ErrorType::TYPE_ERROR,
|
||||
"class constructor cannot called without 'new'");
|
||||
thread->SetException(error.GetTaggedValue());
|
||||
return JSTaggedValue::Hole().GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_TRAMPOLINES(SetStackOverflowException)
|
||||
{
|
||||
RUNTIME_TRAMPOLINES_HEADER(SetStackOverflowException);
|
||||
EcmaVM *ecmaVm = thread->GetEcmaVM();
|
||||
ObjectFactory *factory = ecmaVm->GetFactory();
|
||||
JSHandle<JSObject> error = factory->GetJSError(base::ErrorType::RANGE_ERROR, "Stack overflow!");
|
||||
if (LIKELY(!thread->HasPendingException())) {
|
||||
thread->SetException(error.GetTaggedValue());
|
||||
}
|
||||
return JSTaggedValue::Hole().GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_TRAMPOLINES(CallNative)
|
||||
{
|
||||
RUNTIME_TRAMPOLINES_HEADER(CallNative);
|
||||
CONVERT_ARG_TAGGED_CHECKED(numArgs, 0);
|
||||
CONVERT_ARG_PTR_CHECKED(JSTaggedValue *, sp, 1);
|
||||
CONVERT_ARG_PTR_CHECKED(JSMethod *, method, 2);
|
||||
|
||||
EcmaRuntimeCallInfo ecmaRuntimeCallInfo(thread, numArgs.GetInt(), sp);
|
||||
JSTaggedValue retValue = reinterpret_cast<EcmaEntrypoint>(
|
||||
const_cast<void *>(method->GetNativePointer()))(&ecmaRuntimeCallInfo);
|
||||
return retValue.GetRawData();
|
||||
}
|
||||
|
||||
int32_t RuntimeTrampolines::DoubleToInt(double x)
|
||||
{
|
||||
return base::NumberHelper::DoubleToInt(x, base::INT32_BITS);
|
||||
|
Loading…
Reference in New Issue
Block a user