diff --git a/ecmascript/base/config.h b/ecmascript/base/config.h index 70a03edc..4e0ce14c 100644 --- a/ecmascript/base/config.h +++ b/ecmascript/base/config.h @@ -23,7 +23,7 @@ namespace panda::ecmascript { #define ECMASCRIPT_ENABLE_DEBUG_MODE 0 #define ECMASCRIPT_ENABLE_ARK_CONTAINER 1 #define ECMASCRIPT_ENABLE_TS_AOT_PRINT 0 -#define ECMASCRIPT_COMPILE_INTERPRETER_ASM 0 +#define ECMASCRIPT_COMPILE_ASM_INTERPRETER 0 #define ECMASCRIPT_ENABLE_ASM_INTERPRETER_LOG 0 #define ECMASCRIPT_ENABLE_RUNTIME_STAT 0 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) diff --git a/ecmascript/compiler/interpreter_stub-inl.h b/ecmascript/compiler/interpreter_stub-inl.h index 62dddea4..63a9eee2 100644 --- a/ecmascript/compiler/interpreter_stub-inl.h +++ b/ecmascript/compiler/interpreter_stub-inl.h @@ -173,7 +173,7 @@ GateRef InterpreterStub::ReadInst16_5(GateRef pc) GateRef InterpreterStub::GetFrame(GateRef CurrentSp) { - return IntPtrSub(CurrentSp, GetIntPtrConstant(InterpretedFrame::GetSize(GetEnvironment()->IsArch32Bit()))); + return IntPtrSub(CurrentSp, GetIntPtrConstant(AsmInterpretedFrame::GetSize(GetEnvironment()->IsArch32Bit()))); } GateRef InterpreterStub::GetPcFromFrame(GateRef frame) @@ -184,25 +184,25 @@ GateRef InterpreterStub::GetPcFromFrame(GateRef frame) GateRef InterpreterStub::GetFunctionFromFrame(GateRef frame) { return Load(VariableType::JS_POINTER(), frame, - GetIntPtrConstant(InterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit()))); + GetIntPtrConstant(AsmInterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit()))); } GateRef InterpreterStub::GetCallSizeFromFrame(GateRef frame) { return Load(VariableType::POINTER(), frame, - GetIntPtrConstant(InterpretedFrame::GetCallSizeOffset(GetEnvironment()->IsArch32Bit()))); + GetIntPtrConstant(AsmInterpretedFrame::GetCallSizeOffset(GetEnvironment()->IsArch32Bit()))); } GateRef InterpreterStub::GetAccFromFrame(GateRef frame) { return Load(VariableType::JS_ANY(), frame, - GetIntPtrConstant(InterpretedFrame::GetAccOffset(GetEnvironment()->IsArch32Bit()))); + GetIntPtrConstant(AsmInterpretedFrame::GetAccOffset(GetEnvironment()->IsArch32Bit()))); } GateRef InterpreterStub::GetEnvFromFrame(GateRef frame) { return Load(VariableType::JS_POINTER(), frame, - GetIntPtrConstant(InterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit()))); + GetIntPtrConstant(AsmInterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit()))); } GateRef InterpreterStub::GetEnvFromFunction(GateRef function) @@ -234,12 +234,6 @@ GateRef InterpreterStub::GetResumeModeFromGeneratorObject(GateRef obj) GetInt32Constant((1LU << JSGeneratorObject::ResumeModeBits::SIZE) - 1)); } -void InterpreterStub::SetEnvToFrame(GateRef glue, GateRef frame, GateRef value) -{ - Store(VariableType::INT64(), glue, frame, - GetIntPtrConstant(InterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit())), value); -} - void InterpreterStub::SetPcToFrame(GateRef glue, GateRef frame, GateRef value) { Store(VariableType::INT64(), glue, frame, GetIntPtrConstant(0), value); @@ -247,20 +241,26 @@ void InterpreterStub::SetPcToFrame(GateRef glue, GateRef frame, GateRef value) void InterpreterStub::SetCallSizeToFrame(GateRef glue, GateRef frame, GateRef value) { - Store(VariableType::INT64(), glue, frame, - GetIntPtrConstant(InterpretedFrame::GetCallSizeOffset(GetEnvironment()->IsArch32Bit())), value); + Store(VariableType::POINTER(), glue, frame, + GetIntPtrConstant(AsmInterpretedFrame::GetCallSizeOffset(GetEnvironment()->IsArch32Bit())), value); } void InterpreterStub::SetAccToFrame(GateRef glue, GateRef frame, GateRef value) { Store(VariableType::INT64(), glue, frame, - GetIntPtrConstant(InterpretedFrame::GetAccOffset(GetEnvironment()->IsArch32Bit())), value); + GetIntPtrConstant(AsmInterpretedFrame::GetAccOffset(GetEnvironment()->IsArch32Bit())), value); +} + +void InterpreterStub::SetEnvToFrame(GateRef glue, GateRef frame, GateRef value) +{ + Store(VariableType::INT64(), glue, frame, + GetIntPtrConstant(AsmInterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit())), value); } void InterpreterStub::SetFunctionToFrame(GateRef glue, GateRef frame, GateRef value) { Store(VariableType::INT64(), glue, frame, - GetIntPtrConstant(InterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit())), value); + GetIntPtrConstant(AsmInterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit())), value); } void InterpreterStub::SetConstantPoolToFunction(GateRef glue, GateRef function, GateRef value) diff --git a/ecmascript/compiler/interpreter_stub.cpp b/ecmascript/compiler/interpreter_stub.cpp index 14361132..b3187926 100644 --- a/ecmascript/compiler/interpreter_stub.cpp +++ b/ecmascript/compiler/interpreter_stub.cpp @@ -20,7 +20,7 @@ #include "ecmascript/compiler/variable_type.h" #include "ecmascript/global_env_constants.h" #include "ecmascript/ic/profile_type_info.h" -#include "ecmascript/interpreter/interpreter.h" +#include "ecmascript/interpreter/interpreter_assembly.h" #include "ecmascript/js_array.h" #include "ecmascript/js_function.h" #include "ecmascript/js_generator_object.h" @@ -87,7 +87,7 @@ void name##Stub::GenerateCircuitImpl(GateRef glue, GateRef pc, GateRef sp, { \ varProfileTypeInfo = CallRuntimeTrampoline(glue, \ GetInt64Constant(RTSTUB_ID(UpdateHotnessCounter)), {}); \ - varHotnessCounter = GetInt32Constant(EcmaInterpreter::METHOD_HOTNESS_THRESHOLD); \ + varHotnessCounter = GetInt32Constant(InterpreterAssembly::METHOD_HOTNESS_THRESHOLD); \ Jump(&dispatch); \ } \ Bind(&dispatch); @@ -4254,7 +4254,7 @@ DECLARE_ASM_HANDLER(HandleReturnDyn) Bind(&tryContinue); varSp = Load(VariableType::POINTER(), frame, - GetIntPtrConstant(InterpretedFrame::GetBaseOffset(env->IsArch32Bit()))); + GetIntPtrConstant(AsmInterpretedFrame::GetBaseOffset(env->IsArch32Bit()))); GateRef prevState = GetFrame(*varSp); varPc = GetPcFromFrame(prevState); Branch(IntPtrEqual(*varPc, GetIntPtrConstant(0)), &pcEqualNullptr, &pcNotEqualNullptr); @@ -4314,7 +4314,7 @@ DECLARE_ASM_HANDLER(HandleReturnUndefinedPref) Bind(&tryContinue); varSp = Load(VariableType::POINTER(), frame, - GetIntPtrConstant(InterpretedFrame::GetBaseOffset(env->IsArch32Bit()))); + GetIntPtrConstant(AsmInterpretedFrame::GetBaseOffset(env->IsArch32Bit()))); GateRef prevState = GetFrame(*varSp); varPc = GetPcFromFrame(prevState); varAcc = GetUndefinedConstant(); @@ -4389,7 +4389,7 @@ DECLARE_ASM_HANDLER(HandleSuspendGeneratorPrefV8V8) Bind(&tryContinue); varSp = Load(VariableType::POINTER(), frame, - GetIntPtrConstant(InterpretedFrame::GetBaseOffset(env->IsArch32Bit()))); + GetIntPtrConstant(AsmInterpretedFrame::GetBaseOffset(env->IsArch32Bit()))); GateRef prevState = GetFrame(*varSp); varPc = GetPcFromFrame(prevState); Branch(IntPtrEqual(*varPc, GetIntPtrConstant(0)), &pcEqualNullptr, &pcNotEqualNullptr); @@ -5009,7 +5009,7 @@ DECLARE_ASM_HANDLER(HandleSub2DynPrefV8) Branch(IsCallable(func), &funcIsCallable, &funcNotCallable); \ Bind(&funcNotCallable); \ { \ - CallRuntimeTrampoline(glue, GetInt64Constant(RTSTUB_ID(SetNotCallableException)), {}); \ + CallRuntimeTrampoline(glue, GetInt64Constant(RTSTUB_ID(SetNotCallableException)), {}); \ DISPATCH_LAST(); \ } \ Bind(&funcIsCallable); \ @@ -5035,7 +5035,7 @@ DECLARE_ASM_HANDLER(HandleSub2DynPrefV8) 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())))) + PointerSub(sp, GetIntPtrConstant(AsmInterpretedFrame::GetSize(env->IsArch32Bit())))) #define CALL_PUSH_UNDEFINED(n) \ i = GetInt32Constant(0); \ @@ -5137,12 +5137,12 @@ DECLARE_ASM_HANDLER(HandleSub2DynPrefV8) &stackOverflow, &stackNotOverflow); \ Bind(&stackOverflow); \ { \ - CallRuntimeTrampoline(glue, GetInt64Constant(RTSTUB_ID(SetStackOverflowException)), {}); \ + CallRuntimeTrampoline(glue, GetInt64Constant(RTSTUB_ID(SetStackOverflowException)), {}); \ DISPATCH_LAST(); \ } \ Bind(&stackNotOverflow); \ GateRef state = GetFrame(*newSp); \ - GateRef prevOffset = GetIntPtrConstant(InterpretedFrame::GetBaseOffset(env->IsArch32Bit())); \ + GateRef prevOffset = GetIntPtrConstant(AsmInterpretedFrame::GetBaseOffset(env->IsArch32Bit())); \ Store(VariableType::POINTER(), glue, state, prevOffset, sp); \ GateRef frameTypeOffset = IntPtrAdd(prevOffset, GetIntPtrSize()); \ Store(VariableType::INT64(), glue, state, frameTypeOffset, \ @@ -5151,7 +5151,7 @@ DECLARE_ASM_HANDLER(HandleSub2DynPrefV8) SetFunctionToFrame(glue, state, func); \ SetCurrentSpFrame(glue, *newSp); \ GateRef numArgs = Int32Add(GetInt32Constant(NUM_MANDATORY_JSFUNC_ARGS), actualNumArgs); \ - GateRef retValue = CallRuntimeTrampoline(glue, GetInt64Constant(RTSTUB_ID(CallNative)), \ + GateRef retValue = CallRuntimeTrampoline(glue, GetInt64Constant(RTSTUB_ID(CallNative)), \ {IntBuildTaggedTypeWithNoGC(numArgs), *newSp, method}); \ SetCurrentSpFrame(glue, sp); \ DEFVARIABLE(varAcc, VariableType::JS_ANY(), retValue); \ @@ -5163,7 +5163,7 @@ DECLARE_ASM_HANDLER(HandleSub2DynPrefV8) Branch(IsClassConstructor(func), &funcIsClassConstructor, &funcNotClassConstructor); \ Bind(&funcIsClassConstructor); \ { \ - CallRuntimeTrampoline(glue, GetInt64Constant(RTSTUB_ID(SetCallConstructorException)), {}); \ + CallRuntimeTrampoline(glue, GetInt64Constant(RTSTUB_ID(SetCallConstructorException)), {}); \ DISPATCH_LAST(); \ } \ Bind(&funcNotClassConstructor); \ @@ -5243,14 +5243,14 @@ DECLARE_ASM_HANDLER(HandleSub2DynPrefV8) &stackOverflow, &stackNotOverflow); \ Bind(&stackOverflow); \ { \ - CallRuntimeTrampoline(glue, GetInt64Constant(RTSTUB_ID(SetStackOverflowException)), {}); \ + CallRuntimeTrampoline(glue, GetInt64Constant(RTSTUB_ID(SetStackOverflowException)), {}); \ DISPATCH_LAST(); \ } \ Bind(&stackNotOverflow); \ SetCallSizeToFrame(glue, GetFrame(sp), \ GetIntPtrConstant(BytecodeInstruction::Size(BytecodeInstruction::Format::format))); \ GateRef state = GetFrame(*newSp); \ - GateRef prevOffset = GetIntPtrConstant(InterpretedFrame::GetBaseOffset(env->IsArch32Bit())); \ + GateRef prevOffset = GetIntPtrConstant(AsmInterpretedFrame::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)); \ @@ -5283,18 +5283,18 @@ DECLARE_ASM_HANDLER(HandleSub2DynPrefV8) 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); \ - } \ +#define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8() \ + Label push0(env); \ + Label skip0(env); \ + Branch(Int32GreaterThanOrEqual(declaredNumArgs, \ + GetInt32Constant(InterpreterAssembly::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() \ @@ -5303,19 +5303,19 @@ DECLARE_ASM_HANDLER(HandleSub2DynPrefV8) 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); \ +#define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8_V8() \ + Label push1(env); \ + Label skip1(env); \ + Branch(Int32GreaterThanOrEqual(declaredNumArgs, \ + GetInt32Constant(InterpreterAssembly::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() \ @@ -5324,19 +5324,19 @@ DECLARE_ASM_HANDLER(HandleSub2DynPrefV8) 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); \ +#define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8_V8_V8() \ + Label push2(env); \ + Label skip2(env); \ + Branch(Int32GreaterThanOrEqual(declaredNumArgs, \ + GetInt32Constant(InterpreterAssembly::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() \ @@ -5395,7 +5395,7 @@ DECLARE_ASM_HANDLER(HandleCallArg0DynPrefV8) { auto env = GetEnvironment(); - GateRef actualNumArgs = GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARG0); + GateRef actualNumArgs = GetInt32Constant(InterpreterAssembly::ActualNumArgsOfCall::CALLARG0); GateRef funcReg = ReadInst8_1(pc); CALL_INITIALIZE(); GateRef callThis = FalseConstant(); @@ -5406,7 +5406,7 @@ DECLARE_ASM_HANDLER(HandleCallArg1DynPrefV8V8) { auto env = GetEnvironment(); - GateRef actualNumArgs = GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARG1); + GateRef actualNumArgs = GetInt32Constant(InterpreterAssembly::ActualNumArgsOfCall::CALLARG1); GateRef funcReg = ReadInst8_1(pc); GateRef a0 = ReadInst8_2(pc); CALL_INITIALIZE(); @@ -5418,7 +5418,7 @@ DECLARE_ASM_HANDLER(HandleCallArgs2DynPrefV8V8V8) { auto env = GetEnvironment(); - GateRef actualNumArgs = GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARGS2); + GateRef actualNumArgs = GetInt32Constant(InterpreterAssembly::ActualNumArgsOfCall::CALLARGS2); GateRef funcReg = ReadInst8_1(pc); GateRef a0 = ReadInst8_2(pc); GateRef a1 = ReadInst8_3(pc); @@ -5431,7 +5431,7 @@ DECLARE_ASM_HANDLER(HandleCallArgs3DynPrefV8V8V8V8) { auto env = GetEnvironment(); - GateRef actualNumArgs = GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARGS3); + GateRef actualNumArgs = GetInt32Constant(InterpreterAssembly::ActualNumArgsOfCall::CALLARGS3); GateRef funcReg = ReadInst8_1(pc); GateRef a0 = ReadInst8_2(pc); GateRef a1 = ReadInst8_3(pc); diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index ff1b7e1b..a95a32aa 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -138,6 +138,7 @@ EcmaVM::EcmaVM(JSRuntimeOptions options) } snapshotFileName_ = options_.GetSnapshotFile(); frameworkAbcFileName_ = options_.GetFrameworkAbcFile(); + options_.ParseAsmInterOption(); auto runtime = Runtime::GetCurrent(); notificationManager_ = chunk_.New(runtime->GetInternalAllocator()); @@ -161,7 +162,6 @@ bool EcmaVM::Initialize() LOG_ECMA(FATAL) << "alloc factory_ failed"; UNREACHABLE(); } - options_.ParseAsmInterOption(); [[maybe_unused]] EcmaHandleScope scope(thread_); if (!snapshotDeserializeEnable_ || !VerifyFilePath(snapshotFileName_)) { LOG_ECMA(DEBUG) << "EcmaVM::Initialize run builtins"; diff --git a/ecmascript/frames.h b/ecmascript/frames.h index e62e161b..4346dd2e 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -319,12 +319,10 @@ public: }; STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrameBase), InterpretedFrameBase::SizeArch32, InterpretedFrameBase::SizeArch64); -// align with 8 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) struct InterpretedFrame : public base::AlignedStruct(Index::NumOfMembers) == NumOfTypes); inline JSTaggedType* GetPrevFrameFp() @@ -356,54 +352,8 @@ struct InterpretedFrame : public base::AlignedStruct(sp) - 1; } - static uint32_t GetSpOffset(bool isArch32) - { - return GetOffset(Index::SpIndex)>(isArch32); - } - - static uint32_t GetCallSizeOffset(bool isArch32) - { - return GetOffset(Index::CallSizeIndex)>(isArch32); - } - - static uint32_t GetConstpoolOffset(bool isArch32) - { - return GetOffset(Index::ConstPoolIndex)>(isArch32); - } - - static uint32_t GetFunctionOffset(bool isArch32) - { - return GetOffset(Index::FunctionIndex)>(isArch32); - } - - static uint32_t GetProfileTypeInfoOffset(bool isArch32) - { - return GetOffset(Index::ProFileTypeInfoIndex)>(isArch32); - } - - static uint32_t GetAccOffset(bool isArch32) - { - return GetOffset(Index::AccIndex)>(isArch32); - } - - static uint32_t GetEnvOffset(bool isArch32) - { - return GetOffset(Index::EnvIndex)>(isArch32); - } - - static uint32_t GetBaseOffset(bool isArch32) - { - return GetOffset(Index::BaseIndex)>(isArch32); - } - - static constexpr uint32_t GetSize(bool isArch32) - { - return isArch32 ? InterpretedFrame::SizeArch32 : InterpretedFrame::SizeArch64; - } - alignas(EAS) const uint8_t *pc {nullptr}; alignas(EAS) JSTaggedType *sp {nullptr}; - alignas(EAS) size_t callSize {0}; alignas(EAS) JSTaggedValue constpool {JSTaggedValue::Hole()}; alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; alignas(EAS) JSTaggedValue profileTypeInfo {JSTaggedValue::Hole()}; @@ -411,10 +361,77 @@ struct InterpretedFrame : public base::AlignedStruct { + enum class Index : size_t { + PcIndex = 0, + CallSizeIndex, + FunctionIndex, + AccIndex, + EnvIndex, + BaseIndex, + NumOfMembers + }; + static_assert(static_cast(Index::NumOfMembers) == NumOfTypes); + + inline JSTaggedType* GetPrevFrameFp() + { + return base.prev; + } + + static AsmInterpretedFrame* GetFrameFromSp(JSTaggedType *sp) + { + return reinterpret_cast(sp) - 1; + } + + static size_t GetCallSizeOffset(bool isArch32) + { + return GetOffset(Index::CallSizeIndex)>(isArch32); + } + + static size_t GetFunctionOffset(bool isArch32) + { + return GetOffset(Index::FunctionIndex)>(isArch32); + } + + static size_t GetAccOffset(bool isArch32) + { + return GetOffset(Index::AccIndex)>(isArch32); + } + + static size_t GetEnvOffset(bool isArch32) + { + return GetOffset(Index::EnvIndex)>(isArch32); + } + + static size_t GetBaseOffset(bool isArch32) + { + return GetOffset(Index::BaseIndex)>(isArch32); + } + + static constexpr size_t GetSize(bool isArch32) + { + return isArch32 ? AsmInterpretedFrame::SizeArch32 : AsmInterpretedFrame::SizeArch64; + } + + alignas(EAS) const uint8_t *pc {nullptr}; + alignas(EAS) size_t callSize {0}; + alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; + alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()}; + alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; + alignas(EAS) InterpretedFrameBase base; +}; +STATIC_ASSERT_EQ_ARCH(sizeof(AsmInterpretedFrame), AsmInterpretedFrame::SizeArch32, AsmInterpretedFrame::SizeArch64); +static_assert(sizeof(AsmInterpretedFrame) % sizeof(uint64_t) == 0u); // the size should be the multiple of 8 bytes struct OptimizedLeaveFrame { FrameType type; diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index 1ae07ce2..2e2cc282 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -70,7 +70,11 @@ void InterpretedFrameHandler::PrevFrame() { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER + AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(sp_); +#else InterpretedFrame *frame = InterpretedFrame::GetFrameFromSp(sp_); +#endif sp_ = frame->base.prev; } @@ -84,7 +88,11 @@ InterpretedFrameHandler InterpretedFrameHandler::GetPrevFrame() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER + AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(sp_); +#else InterpretedFrame *frame = InterpretedFrame::GetFrameFromSp(sp_); +#endif return InterpretedFrameHandler(frame->base.prev); } @@ -106,7 +114,11 @@ JSTaggedValue InterpretedFrameHandler::GetAcc() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER + AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(sp_); +#else InterpretedFrame *frame = InterpretedFrame::GetFrameFromSp(sp_); +#endif return frame->acc; } @@ -114,7 +126,11 @@ uint32_t InterpretedFrameHandler::GetSize() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER + AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(sp_); +#else InterpretedFrame *frame = InterpretedFrame::GetFrameFromSp(sp_); +#endif JSTaggedType *prevSp = frame->base.prev; ASSERT(prevSp != nullptr); auto size = (prevSp - sp_) - FRAME_STATE_SIZE; @@ -125,7 +141,11 @@ uint32_t InterpretedFrameHandler::GetBytecodeOffset() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER + AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(sp_); +#else InterpretedFrame *frame = InterpretedFrame::GetFrameFromSp(sp_); +#endif JSMethod *method = ECMAObject::Cast(frame->function.GetTaggedObject())->GetCallTarget(); auto offset = frame->pc - method->GetBytecodeArray(); return static_cast(offset); @@ -135,7 +155,11 @@ JSMethod *InterpretedFrameHandler::GetMethod() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER + AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(sp_); +#else InterpretedFrame *frame = InterpretedFrame::GetFrameFromSp(sp_); +#endif return ECMAObject::Cast(frame->function.GetTaggedObject())->GetCallTarget(); } @@ -143,7 +167,11 @@ JSTaggedValue InterpretedFrameHandler::GetFunction() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER + AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(sp_); +#else InterpretedFrame *frame = InterpretedFrame::GetFrameFromSp(sp_); +#endif return frame->function; } @@ -151,7 +179,11 @@ const uint8_t *InterpretedFrameHandler::GetPc() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER + AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(sp_); +#else InterpretedFrame *frame = InterpretedFrame::GetFrameFromSp(sp_); +#endif return frame->pc; } @@ -165,15 +197,30 @@ ConstantPool *InterpretedFrameHandler::GetConstpool() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER + AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(sp_); + JSTaggedValue function = frame->function; + if (function.IsJSFunction()) { + JSTaggedValue constpool = JSFunction::Cast(function.GetTaggedObject())->GetConstantPool(); + return ConstantPool::Cast(constpool.GetTaggedObject()); + } else { + return nullptr; + } +#else InterpretedFrame *frame = InterpretedFrame::GetFrameFromSp(sp_); return ConstantPool::Cast(frame->constpool.GetTaggedObject()); +#endif } JSTaggedValue InterpretedFrameHandler::GetEnv() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER + AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(sp_); +#else InterpretedFrame *frame = InterpretedFrame::GetFrameFromSp(sp_); +#endif return frame->env; } @@ -182,8 +229,23 @@ void InterpretedFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisi JSTaggedType *current = sp_; if (current != nullptr) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER + AsmInterpretedFrame *frame = reinterpret_cast(current) - 1; + if (frame->function != JSTaggedValue::Hole()) { + uintptr_t start = ToUintPtr(current); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + AsmInterpretedFrame *prev_frame = reinterpret_cast(frame->base.prev) - 1; + uintptr_t end = ToUintPtr(prev_frame); + v1(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end)); + v0(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function))); + if (frame->pc != nullptr) { + // interpreter frame + v0(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->acc))); + v0(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->env))); + } + } +#else InterpretedFrame *frame = reinterpret_cast(current) - 1; - if (frame->sp != nullptr) { uintptr_t start = ToUintPtr(current); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -199,6 +261,7 @@ void InterpretedFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisi v0(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->profileTypeInfo))); } } +#endif } } @@ -321,7 +384,11 @@ void FrameIterator::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) c while (current) { FrameType type = FrameHandler(current).GetFrameType(); if (type == FrameType::INTERPRETER_FRAME || type == FrameType::INTERPRETER_FAST_NEW_FRAME) { +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER + AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(current); +#else InterpretedFrame *frame = InterpretedFrame::GetFrameFromSp(current); +#endif InterpretedFrameHandler(current).Iterate(v0, v1); current = frame->GetPrevFrameFp(); } else if (type == FrameType::OPTIMIZED_FRAME) { diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index 57803dfa..b00a5d2c 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -45,9 +45,15 @@ public: bool IsBreakFrame() const { ASSERT(HasFrame()); +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + AsmInterpretedFrame *state = AsmInterpretedFrame::GetFrameFromSp(sp_); + return state->function == JSTaggedValue::Hole(); +#else // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) InterpretedFrame *state = InterpretedFrame::GetFrameFromSp(sp_); return state->sp == nullptr; +#endif } void PrevFrame(); diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index 03402ae1..d2d6f76c 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -439,6 +439,12 @@ JSTaggedValue EcmaInterpreter::Execute(JSThread *thread, const JSHandleGetEcmaVM()->GetJSOptions().GetAsmInterParsedOption(); + if (asmInterOpt.enableAsm) { + return InterpreterAssembly::Execute(thread, params); + } +#endif JSMethod *method = params.callTarget->GetCallTarget(); if (method->IsNativeWithCallField()) { return EcmaInterpreter::ExecuteNative(thread, params); @@ -544,12 +550,7 @@ JSTaggedValue EcmaInterpreter::Execute(JSThread *thread, const CallParams& param << std::hex << reinterpret_cast(pc); thread->GetEcmaVM()->GetNotificationManager()->MethodEntryEvent(thread, method); - AsmInterParsedOption asmInterOpt = thread->GetEcmaVM()->GetJSOptions().GetAsmInterParsedOption(); - if (asmInterOpt.enableAsm) { - InterpreterAssembly::RunInternal(thread, ConstantPool::Cast(constpool.GetTaggedObject()), pc, newSp); - } else { - EcmaInterpreter::RunInternal(thread, ConstantPool::Cast(constpool.GetTaggedObject()), pc, newSp); - } + EcmaInterpreter::RunInternal(thread, ConstantPool::Cast(constpool.GetTaggedObject()), pc, newSp); thread->GetEcmaVM()->GetNotificationManager()->MethodExitEvent(thread, method); // NOLINTNEXTLINE(readability-identifier-naming) @@ -565,6 +566,12 @@ JSTaggedValue EcmaInterpreter::Execute(JSThread *thread, const CallParams& param JSTaggedValue EcmaInterpreter::GeneratorReEnterInterpreter(JSThread *thread, JSHandle context) { [[maybe_unused]] EcmaHandleScope handleScope(thread); +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER + AsmInterParsedOption asmInterOpt = thread->GetEcmaVM()->GetJSOptions().GetAsmInterParsedOption(); + if (asmInterOpt.enableAsm) { + return InterpreterAssembly::GeneratorReEnterInterpreter(thread, context); + } +#endif JSHandle func = JSHandle::Cast(JSHandle(thread, context->GetMethod())); JSMethod *method = func->GetCallTarget(); @@ -617,12 +624,7 @@ JSTaggedValue EcmaInterpreter::GeneratorReEnterInterpreter(JSThread *thread, JSH thread->SetCurrentSPFrame(newSp); thread->GetEcmaVM()->GetNotificationManager()->MethodEntryEvent(thread, method); - AsmInterParsedOption asmInterOpt = thread->GetEcmaVM()->GetJSOptions().GetAsmInterParsedOption(); - if (asmInterOpt.enableAsm) { - InterpreterAssembly::RunInternal(thread, ConstantPool::Cast(constpool.GetTaggedObject()), resumePc, newSp); - } else { - EcmaInterpreter::RunInternal(thread, ConstantPool::Cast(constpool.GetTaggedObject()), resumePc, newSp); - } + EcmaInterpreter::RunInternal(thread, ConstantPool::Cast(constpool.GetTaggedObject()), resumePc, newSp); thread->GetEcmaVM()->GetNotificationManager()->MethodExitEvent(thread, method); JSTaggedValue res = state->acc; @@ -634,6 +636,12 @@ JSTaggedValue EcmaInterpreter::GeneratorReEnterInterpreter(JSThread *thread, JSH void EcmaInterpreter::ChangeGenContext(JSThread *thread, JSHandle context) { [[maybe_unused]] EcmaHandleScope handleScope(thread); +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER + AsmInterParsedOption asmInterOpt = thread->GetEcmaVM()->GetJSOptions().GetAsmInterParsedOption(); + if (asmInterOpt.enableAsm) { + return InterpreterAssembly::ChangeGenContext(thread, context); + } +#endif JSHandle func = JSHandle::Cast(JSHandle(thread, context->GetMethod())); JSMethod *method = func->GetCallTarget(); @@ -687,6 +695,12 @@ void EcmaInterpreter::ChangeGenContext(JSThread *thread, JSHandleGetEcmaVM()->GetJSOptions().GetAsmInterParsedOption(); + if (asmInterOpt.enableAsm) { + return InterpreterAssembly::ResumeContext(thread); + } +#endif JSTaggedType *sp = const_cast(thread->GetCurrentSPFrame()); InterpretedFrame *state = GET_FRAME(sp); thread->SetCurrentSPFrame(state->base.prev); @@ -3742,6 +3756,12 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool void EcmaInterpreter::InitStackFrame(JSThread *thread) { +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER + AsmInterParsedOption asmInterOpt = thread->GetEcmaVM()->GetJSOptions().GetAsmInterParsedOption(); + if (asmInterOpt.enableAsm) { + return InterpreterAssembly::InitStackFrame(thread); + } +#endif uint64_t *prevSp = const_cast(thread->GetCurrentSPFrame()); InterpretedFrame *state = GET_FRAME(prevSp); state->pc = nullptr; @@ -4072,6 +4092,45 @@ std::string GetEcmaOpcodeStr(EcmaOpcode opcode) } return "bytecode-" + std::to_string(opcode); } +#undef LOG_INST +#undef HANDLE_OPCODE +#undef ADVANCE_PC +#undef GOTO_NEXT +#undef DISPATCH +#undef DISPATCH_OFFSET +#undef GET_FRAME +#undef SAVE_PC +#undef SAVE_ACC +#undef RESTORE_ACC +#undef INTERPRETER_GOTO_EXCEPTION_HANDLER +#undef INTERPRETER_HANDLE_RETURN +#undef CHECK_SWITCH_TO_DEBUGGER_TABLE +#undef REAL_GOTO_DISPATCH_OPCODE +#undef REAL_GOTO_EXCEPTION_HANDLER +#undef INTERPRETER_RETURN_IF_ABRUPT +#undef NOTIFY_DEBUGGER_EVENT +#undef CALL_INITIALIZE +#undef CALL_PUSH_UNDEFINED +#undef CALL_PUSH_ARGS_0 +#undef CALL_PUSH_ARGS_1 +#undef CALL_PUSH_ARGS_2 +#undef CALL_PUSH_ARGS_3 +#undef CALL_PUSH_ARGS_I +#undef CALL_PUSH_ARGS_I_THIS +#undef CALL_PUSH_ARGS_0_NO_EXTRA +#undef CALL_PUSH_ARGS_1_NO_EXTRA +#undef CALL_PUSH_ARGS_2_NO_EXTRA +#undef CALL_PUSH_ARGS_3_NO_EXTRA +#undef CALL_PUSH_ARGS_I_NO_EXTRA +#undef CALL_PUSH_ARGS_I_THIS_NO_EXTRA +#undef CALL_PUSH_ARGS +#undef UPDATE_HOTNESS_COUNTER_NON_ACC +#undef UPDATE_HOTNESS_COUNTER +#undef GET_VREG +#undef GET_VREG_VALUE +#undef SET_VREG +#undef GET_ACC +#undef SET_ACC #if defined(__clang__) #pragma clang diagnostic pop #elif defined(__GNUC__) diff --git a/ecmascript/interpreter/interpreter.h b/ecmascript/interpreter/interpreter.h index 5af98762..6b01d037 100644 --- a/ecmascript/interpreter/interpreter.h +++ b/ecmascript/interpreter/interpreter.h @@ -28,7 +28,11 @@ class ECMAObject; class GeneratorContext; // NOLINTNEXTLINE(bugprone-sizeof-expression) +#if ECMASCRIPT_COMPILE_ASM_INTERPRETER +static const uint32_t FRAME_STATE_SIZE = sizeof(AsmInterpretedFrame) / sizeof(uint64_t); +#else static const uint32_t FRAME_STATE_SIZE = sizeof(InterpretedFrame) / sizeof(uint64_t); +#endif static constexpr uint32_t RESERVED_CALL_ARGCOUNT = 3; static constexpr uint32_t RESERVED_INDEX_CALL_TARGET = 0; diff --git a/ecmascript/interpreter/interpreter_assembly.cpp b/ecmascript/interpreter/interpreter_assembly.cpp index 0ab053e0..af217bda 100644 --- a/ecmascript/interpreter/interpreter_assembly.cpp +++ b/ecmascript/interpreter/interpreter_assembly.cpp @@ -63,7 +63,7 @@ using panda::ecmascript::kungfu::CommonStubCSigns; ADVANCE_PC(offset) \ SAVE_PC(); \ SAVE_ACC(); \ - InterpretedFrame *frame = GET_FRAME(sp); \ + AsmInterpretedFrame *frame = GET_ASM_FRAME(sp); \ auto currentMethod = ECMAObject::Cast(frame->function.GetTaggedObject())->GetCallTarget(); \ currentMethod->SetHotnessCounter(static_cast(hotnessCounter)); \ return; \ @@ -72,14 +72,14 @@ using panda::ecmascript::kungfu::CommonStubCSigns; #define DISPATCH(format) DISPATCH_OFFSET(BytecodeInstruction::Size(format)) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define GET_FRAME(CurrentSp) \ - (reinterpret_cast(CurrentSp) - 1) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) +#define GET_ASM_FRAME(CurrentSp) \ + (reinterpret_cast(CurrentSp) - 1) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define SAVE_PC() (GET_FRAME(sp)->pc = pc) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) +#define SAVE_PC() (GET_ASM_FRAME(sp)->pc = pc) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define SAVE_ACC() (GET_FRAME(sp)->acc = acc) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) +#define SAVE_ACC() (GET_ASM_FRAME(sp)->acc = acc) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define RESTORE_ACC() (acc = GET_FRAME(sp)->acc) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) +#define RESTORE_ACC() (acc = GET_ASM_FRAME(sp)->acc) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define INTERPRETER_GOTO_EXCEPTION_HANDLER() \ @@ -337,11 +337,10 @@ using panda::ecmascript::kungfu::CommonStubCSigns; } \ EcmaRuntimeCallInfo ecmaRuntimeCallInfo(thread, actualNumArgs + NUM_MANDATORY_JSFUNC_ARGS, \ reinterpret_cast(newSp)); \ - InterpretedFrame *state = GET_FRAME(newSp); \ + AsmInterpretedFrame *state = GET_ASM_FRAME(newSp); \ state->base.prev = sp; \ state->base.type = FrameType::INTERPRETER_FRAME; \ state->pc = nullptr; \ - state->sp = newSp; \ state->function = funcValue; \ thread->SetCurrentSPFrame(newSp); \ LOG(DEBUG, INTERPRETER) << "Entry: Runtime Call."; \ @@ -387,22 +386,18 @@ using panda::ecmascript::kungfu::CommonStubCSigns; int32_t numVregs = static_cast(JSMethod::NumVregsBits::Decode(callField)); \ /* push vregs */ \ CALL_PUSH_UNDEFINED(numVregs); \ - SAVE_PC(); \ if (UNLIKELY(thread->DoStackOverflowCheck(newSp))) { \ INTERPRETER_GOTO_EXCEPTION_HANDLER(); \ } \ - GET_FRAME(sp)->callSize = GetJumpSizeAfterCall(pc); \ - InterpretedFrame *state = GET_FRAME(newSp); \ + SAVE_PC(); \ + GET_ASM_FRAME(sp)->callSize = GetJumpSizeAfterCall(pc); \ + AsmInterpretedFrame *state = GET_ASM_FRAME(newSp); \ state->base.prev = sp; \ state->base.type = FrameType::INTERPRETER_FRAME; \ - state->pc = pc = JSMethod::Cast(method)->GetBytecodeArray(); \ - state->sp = sp = newSp; \ + pc = JSMethod::Cast(method)->GetBytecodeArray(); /* will be stored in DISPATCH_OFFSET */ \ + sp = newSp; /* for DISPATCH_OFFSET */ \ state->function = funcValue; \ - state->acc = JSTaggedValue::Hole(); \ - state->constpool = JSFunction::Cast(funcObject)->GetConstantPool(); \ - constpool = state->constpool; \ - state->profileTypeInfo = JSFunction::Cast(funcObject)->GetProfileTypeInfo(); \ - profileTypeInfo = state->profileTypeInfo; \ + acc = JSTaggedValue::Hole(); /* will be stored in DISPATCH_OFFSET */ \ JSTaggedValue env = JSFunction::Cast(funcObject)->GetLexicalEnv(); \ state->env = env; \ hotnessCounter = static_cast(method->GetHotnessCounter()); \ @@ -418,7 +413,7 @@ using panda::ecmascript::kungfu::CommonStubCSigns; void InterpreterAssembly::RunInternal(JSThread *thread, ConstantPool *constpool, const uint8_t *pc, JSTaggedType *sp) { JSTaggedValue acc = JSTaggedValue::Hole(); - InterpretedFrame *state = GET_FRAME(sp); + AsmInterpretedFrame *state = GET_ASM_FRAME(sp); auto method = ECMAObject::Cast(state->function.GetTaggedObject())->GetCallTarget(); auto hotnessCounter = static_cast(method->GetHotnessCounter()); auto profileTypeInfo = JSFunction::Cast(state->function.GetTaggedObject())->GetProfileTypeInfo(); @@ -428,6 +423,292 @@ void InterpreterAssembly::RunInternal(JSThread *thread, ConstantPool *constpool, asmEntry(thread->GetGlueAddr(), pc, sp, JSTaggedValue(constpool), profileTypeInfo, acc, hotnessCounter); } +void InterpreterAssembly::InitStackFrame(JSThread *thread) +{ + uint64_t *prevSp = const_cast(thread->GetCurrentSPFrame()); + AsmInterpretedFrame *state = GET_ASM_FRAME(prevSp); + state->pc = nullptr; + state->function = JSTaggedValue::Hole(); + state->acc = JSTaggedValue::Hole(); + state->base.type = FrameType::INTERPRETER_FRAME; + state->base.prev = nullptr; +} + +JSTaggedValue InterpreterAssembly::ExecuteNative(JSThread *thread, const CallParams& params) +{ + JSTaggedType *sp = const_cast(thread->GetCurrentSPFrame()); + + JSMethod *method = params.callTarget->GetCallTarget(); + ASSERT(method->GetNumVregsWithCallField() == 0); + uint32_t numActualArgs = params.argc + RESERVED_CALL_ARGCOUNT; + // Tags and values of thread, new_tgt and argv_length are put into frames too for native frames + // NOLINTNEXTLINE(hicpp-signed-bitwise) + size_t frameSize = FRAME_STATE_SIZE + numActualArgs; + JSTaggedType *newSp = sp - frameSize; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + if (thread->DoStackOverflowCheck(newSp) || thread->HasPendingException()) { + return JSTaggedValue::Undefined(); + } + + EcmaRuntimeCallInfo ecmaRuntimeCallInfo(thread, numActualArgs, reinterpret_cast(newSp)); + newSp[RESERVED_INDEX_CALL_TARGET] = reinterpret_cast(params.callTarget); + newSp[RESERVED_INDEX_NEW_TARGET] = params.newTarget; + newSp[RESERVED_INDEX_THIS] = params.thisArg; + for (size_t i = 0; i < params.argc; i++) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + newSp[i + RESERVED_CALL_ARGCOUNT] = params.argv[i]; + } + + AsmInterpretedFrame *state = GET_ASM_FRAME(newSp); + state->base.prev = sp; + state->base.type = FrameType::INTERPRETER_FRAME; + state->pc = nullptr; + state->function = JSTaggedValue(params.callTarget); + thread->SetCurrentSPFrame(newSp); +#if ECMASCRIPT_ENABLE_ACTIVE_CPUPROFILER + CpuProfiler::IsNeedAndGetStack(thread); +#endif + thread->CheckSafepoint(); + LOG(DEBUG, INTERPRETER) << "Entry: Runtime Call."; + JSTaggedValue tagged = + reinterpret_cast(const_cast(method->GetNativePointer()))(&ecmaRuntimeCallInfo); + LOG(DEBUG, INTERPRETER) << "Exit: Runtime Call."; + thread->SetCurrentSPFrame(sp); +#if ECMASCRIPT_ENABLE_ACTIVE_CPUPROFILER + CpuProfiler::IsNeedAndGetStack(thread); +#endif + return tagged; +} + +JSTaggedValue InterpreterAssembly::Execute(JSThread *thread, const CallParams& params) +{ + JSMethod *method = params.callTarget->GetCallTarget(); + if (method->IsNativeWithCallField()) { + return InterpreterAssembly::ExecuteNative(thread, params); + } + JSTaggedType *sp = const_cast(thread->GetCurrentSPFrame()); + JSTaggedType *newSp = sp - FRAME_STATE_SIZE; + // push break state + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + if (thread->DoStackOverflowCheck(newSp) || thread->HasPendingException()) { + return JSTaggedValue::Undefined(); + } + AsmInterpretedFrame *breakState = GET_ASM_FRAME(newSp); + auto leaveFrame = const_cast(thread->GetLastLeaveFrame()); + if (leaveFrame != nullptr) { + [[maybe_unused]] OptimizedLeaveFrame *frame = OptimizedLeaveFrame::GetFrameFromSp(leaveFrame); + frame->callsiteFp = reinterpret_cast(sp); + breakState->base.prev = leaveFrame; + } else { + breakState->base.prev = sp; + } + breakState->pc = nullptr; + breakState->function = JSTaggedValue::Hole(); + breakState->base.type = FrameType::INTERPRETER_FRAME; + JSTaggedType *prevSp = newSp; + + int32_t actualNumArgs = static_cast(params.argc); + int32_t declaredNumArgs = static_cast(method->GetNumArgsWithCallField()); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + newSp -= FRAME_STATE_SIZE; + // push args + if (actualNumArgs == declaredNumArgs) { + // fast path, just push all args directly + for (int i = actualNumArgs - 1; i >= 0; i--) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + *(--newSp) = params.argv[i]; + } + } else { + // slow path + if (!method->HaveExtraWithCallField()) { + // push length = declaredNumArgs, may push undefined + CALL_PUSH_UNDEFINED(declaredNumArgs - actualNumArgs); + for (int i = std::min(actualNumArgs, declaredNumArgs) - 1; i >= 0; i--) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + *(--newSp) = params.argv[i]; + } + } else { + // push actualNumArgs in the end, then all args, may push undefined + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + *(--newSp) = JSTaggedValue(actualNumArgs).GetRawData(); + CALL_PUSH_UNDEFINED(declaredNumArgs - actualNumArgs); + for (int i = actualNumArgs - 1; i >= 0; i--) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + *(--newSp) = params.argv[i]; + } + } + } + uint64_t callField = method->GetCallField(); + if ((callField & CALL_TYPE_MASK) != 0) { + // not normal call type, setting func/newTarget/this cannot be skipped + if (method->HaveThisWithCallField()) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + *(--newSp) = params.thisArg; // push this + } + if (method->HaveNewTargetWithCallField()) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + *(--newSp) = params.newTarget; // push new target + } + if (method->HaveFuncWithCallField()) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + *(--newSp) = reinterpret_cast(params.callTarget); // push func + } + } + int32_t numVregs = static_cast(method->GetNumVregsWithCallField()); + // push vregs + CALL_PUSH_UNDEFINED(numVregs); + if (UNLIKELY(thread->DoStackOverflowCheck(newSp))) { + return JSTaggedValue::Undefined(); + } + + const uint8_t *pc = method->GetBytecodeArray(); + AsmInterpretedFrame *state = GET_ASM_FRAME(newSp); + state->pc = pc; + state->function = JSTaggedValue(params.callTarget); + state->acc = JSTaggedValue::Hole(); + JSHandle callTargetHandle(thread, params.callTarget); + JSHandle thisFunc = JSHandle::Cast(callTargetHandle); + JSTaggedValue constpool = thisFunc->GetConstantPool(); + state->base.prev = prevSp; + state->base.type = FrameType::INTERPRETER_FRAME; + + JSTaggedValue env = thisFunc->GetLexicalEnv(); + state->env = env; + thread->SetCurrentSPFrame(newSp); +#if ECMASCRIPT_ENABLE_ACTIVE_CPUPROFILER + CpuProfiler::IsNeedAndGetStack(thread); +#endif + thread->CheckSafepoint(); + LOG(DEBUG, INTERPRETER) << "break Entry: Runtime Call " << std::hex << reinterpret_cast(newSp) << " " + << std::hex << reinterpret_cast(pc); + + thread->GetEcmaVM()->GetNotificationManager()->MethodEntryEvent(thread, method); + InterpreterAssembly::RunInternal(thread, ConstantPool::Cast(constpool.GetTaggedObject()), pc, newSp); + thread->GetEcmaVM()->GetNotificationManager()->MethodExitEvent(thread, method); + + // NOLINTNEXTLINE(readability-identifier-naming) + const JSTaggedValue resAcc = state->acc; + // pop frame + thread->SetCurrentSPFrame(sp); +#if ECMASCRIPT_ENABLE_ACTIVE_CPUPROFILER + CpuProfiler::IsNeedAndGetStack(thread); +#endif + return resAcc; +} + +JSTaggedValue InterpreterAssembly::GeneratorReEnterInterpreter(JSThread *thread, JSHandle context) +{ + JSHandle func = JSHandle::Cast(JSHandle(thread, context->GetMethod())); + JSMethod *method = func->GetCallTarget(); + + JSTaggedType *currentSp = const_cast(thread->GetCurrentSPFrame()); + + // push break frame + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + JSTaggedType *breakSp = currentSp - FRAME_STATE_SIZE; + if (thread->DoStackOverflowCheck(breakSp) || thread->HasPendingException()) { + return JSTaggedValue::Exception(); + } + AsmInterpretedFrame *breakState = GET_ASM_FRAME(breakSp); + breakState->pc = nullptr; + breakState->function = JSTaggedValue::Hole(); + breakState->base.prev = currentSp; + breakState->base.type = FrameType::INTERPRETER_FRAME; + + // create new frame and resume sp and pc + uint32_t nregs = context->GetNRegs(); + size_t newFrameSize = FRAME_STATE_SIZE + nregs; + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic + JSTaggedType *newSp = breakSp - newFrameSize; + if (thread->DoStackOverflowCheck(newSp) || thread->HasPendingException()) { + return JSTaggedValue::Exception(); + } + JSHandle regsArray(thread, context->GetRegsArray()); + for (size_t i = 0; i < nregs; i++) { + newSp[i] = regsArray->Get(i).GetRawData(); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + } + JSTaggedValue constpool = func->GetConstantPool(); + uint32_t pcOffset = context->GetBCOffset(); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + const uint8_t *resumePc = method->GetBytecodeArray() + pcOffset + + BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8); + + AsmInterpretedFrame *state = GET_ASM_FRAME(newSp); + state->pc = resumePc; + state->function = func.GetTaggedValue(); + state->acc = context->GetAcc(); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + state->base.prev = breakSp; + state->base.type = FrameType::INTERPRETER_FRAME; + JSTaggedValue env = context->GetLexicalEnv(); + state->env = env; + // execute interpreter + thread->SetCurrentSPFrame(newSp); + + thread->GetEcmaVM()->GetNotificationManager()->MethodEntryEvent(thread, method); + InterpreterAssembly::RunInternal(thread, ConstantPool::Cast(constpool.GetTaggedObject()), resumePc, newSp); + thread->GetEcmaVM()->GetNotificationManager()->MethodExitEvent(thread, method); + + JSTaggedValue res = state->acc; + // pop frame + thread->SetCurrentSPFrame(currentSp); + return res; +} + +void InterpreterAssembly::ChangeGenContext(JSThread *thread, JSHandle context) +{ + JSHandle func = JSHandle::Cast(JSHandle(thread, context->GetMethod())); + JSMethod *method = func->GetCallTarget(); + + JSTaggedType *currentSp = const_cast(thread->GetCurrentSPFrame()); + + // push break frame + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + JSTaggedType *breakSp = currentSp - FRAME_STATE_SIZE; + if (thread->DoStackOverflowCheck(breakSp) || thread->HasPendingException()) { + return; + } + AsmInterpretedFrame *breakState = GET_ASM_FRAME(breakSp); + breakState->pc = nullptr; + breakState->function = JSTaggedValue::Hole(); + breakState->base.prev = currentSp; + breakState->base.type = FrameType::INTERPRETER_FRAME; + + // create new frame and resume sp and pc + uint32_t nregs = context->GetNRegs(); + size_t newFrameSize = FRAME_STATE_SIZE + nregs; + + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic + JSTaggedType *newSp = breakSp - newFrameSize; + if (thread->DoStackOverflowCheck(newSp) || thread->HasPendingException()) { + return; + } + JSHandle regsArray(thread, context->GetRegsArray()); + for (size_t i = 0; i < nregs; i++) { + newSp[i] = regsArray->Get(i).GetRawData(); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + } + uint32_t pcOffset = context->GetBCOffset(); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + const uint8_t *pc = method->GetBytecodeArray() + pcOffset; + + AsmInterpretedFrame *state = GET_ASM_FRAME(newSp); + state->pc = pc; + state->function = func.GetTaggedValue(); + state->acc = context->GetAcc(); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + state->base.prev = breakSp; + state->base.type = FrameType::INTERPRETER_FRAME; + state->env = context->GetLexicalEnv(); + + thread->SetCurrentSPFrame(newSp); +} + +void InterpreterAssembly::ResumeContext(JSThread *thread) +{ + JSTaggedType *sp = const_cast(thread->GetCurrentSPFrame()); + AsmInterpretedFrame *state = GET_ASM_FRAME(sp); + thread->SetCurrentSPFrame(state->base.prev); +} + void InterpreterAssembly::HandleMovV4V4( JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo, JSTaggedValue acc, int32_t hotnessCounter) @@ -746,8 +1027,8 @@ void InterpreterAssembly::HandleReturnDyn( JSTaggedValue acc, int32_t hotnessCounter) { LOG_INST() << "returnla "; - InterpretedFrame *state = GET_FRAME(sp); - LOG(DEBUG, INTERPRETER) << "Exit: Runtime Call " << std::hex << reinterpret_cast(state->sp) << " " + AsmInterpretedFrame *state = GET_ASM_FRAME(sp); + LOG(DEBUG, INTERPRETER) << "Exit: Runtime Call " << std::hex << reinterpret_cast(sp) << " " << std::hex << reinterpret_cast(state->pc); JSMethod *method = ECMAObject::Cast(state->function.GetTaggedObject())->GetCallTarget(); [[maybe_unused]] auto fistPC = method->GetInstructions(); @@ -755,7 +1036,7 @@ void InterpreterAssembly::HandleReturnDyn( method->SetHotnessCounter(static_cast(hotnessCounter)); sp = state->base.prev; ASSERT(sp != nullptr); - InterpretedFrame *prevState = GET_FRAME(sp); + AsmInterpretedFrame *prevState = GET_ASM_FRAME(sp); pc = prevState->pc; // break frame @@ -766,13 +1047,12 @@ void InterpreterAssembly::HandleReturnDyn( } thread->SetCurrentSPFrame(sp); - constpool = prevState->constpool; - profileTypeInfo = prevState->profileTypeInfo; - method = ECMAObject::Cast(prevState->function.GetTaggedObject())->GetCallTarget(); + JSFunction* prevFunc = JSFunction::Cast(prevState->function.GetTaggedObject()); + method = prevFunc->GetMethod(); hotnessCounter = static_cast(method->GetHotnessCounter()); - size_t jumpSize = GetJumpSizeAfterCall(pc); - DISPATCH_OFFSET(jumpSize); + ASSERT(prevState->callSize == GetJumpSizeAfterCall(pc)); + DISPATCH_OFFSET(prevState->callSize); } void InterpreterAssembly::HandleReturnUndefinedPref( @@ -780,7 +1060,7 @@ void InterpreterAssembly::HandleReturnUndefinedPref( JSTaggedValue acc, int32_t hotnessCounter) { LOG_INST() << "return.undefined"; - InterpretedFrame *state = GET_FRAME(sp); + AsmInterpretedFrame *state = GET_ASM_FRAME(sp); LOG(DEBUG, INTERPRETER) << "Exit: Runtime Call " << std::hex << reinterpret_cast(sp) << " " << std::hex << reinterpret_cast(state->pc); JSMethod *method = ECMAObject::Cast(state->function.GetTaggedObject())->GetCallTarget(); @@ -789,7 +1069,7 @@ void InterpreterAssembly::HandleReturnUndefinedPref( method->SetHotnessCounter(static_cast(hotnessCounter)); sp = state->base.prev; ASSERT(sp != nullptr); - InterpretedFrame *prevState = GET_FRAME(sp); + AsmInterpretedFrame *prevState = GET_ASM_FRAME(sp); pc = prevState->pc; // break frame @@ -800,14 +1080,13 @@ void InterpreterAssembly::HandleReturnUndefinedPref( } thread->SetCurrentSPFrame(sp); - constpool = prevState->constpool; - profileTypeInfo = prevState->profileTypeInfo; - method = ECMAObject::Cast(prevState->function.GetTaggedObject())->GetCallTarget(); + JSFunction* prevFunc = JSFunction::Cast(prevState->function.GetTaggedObject()); + method = prevFunc->GetMethod(); hotnessCounter = static_cast(method->GetHotnessCounter()); acc = JSTaggedValue::Undefined(); - size_t jumpSize = GetJumpSizeAfterCall(pc); - DISPATCH_OFFSET(jumpSize); + ASSERT(prevState->callSize == GetJumpSizeAfterCall(pc)); + DISPATCH_OFFSET(prevState->callSize); } void InterpreterAssembly::HandleLdNanPref( @@ -904,7 +1183,7 @@ void InterpreterAssembly::HandleLdLexEnvDynPref( JSTaggedValue acc, int32_t hotnessCounter) { LOG_INST() << "intrinsics::ldlexenvDyn "; - InterpretedFrame *state = GET_FRAME(sp); + AsmInterpretedFrame *state = GET_ASM_FRAME(sp); JSTaggedValue currentLexenv = state->env; SET_ACC(currentLexenv); DISPATCH(BytecodeInstruction::Format::PREF_NONE); @@ -1807,7 +2086,7 @@ void InterpreterAssembly::HandleDefineFuncDynPrefId16Imm16V8( JSTaggedValue envHandle = GET_VREG_VALUE(v0); result->SetLexicalEnv(thread, envHandle); - JSFunction *currentFunc = JSFunction::Cast((GET_FRAME(sp)->function).GetTaggedObject()); + JSFunction *currentFunc = JSFunction::Cast((GET_ASM_FRAME(sp)->function).GetTaggedObject()); result->SetModule(thread, currentFunc->GetModule()); SET_ACC(JSTaggedValue(result)) @@ -1844,7 +2123,7 @@ void InterpreterAssembly::HandleDefineNCFuncDynPrefId16Imm16V8( result->SetLexicalEnv(thread, env); result->SetHomeObject(thread, homeObject); - JSFunction *currentFunc = JSFunction::Cast((GET_FRAME(sp)->function).GetTaggedObject()); + JSFunction *currentFunc = JSFunction::Cast((GET_ASM_FRAME(sp)->function).GetTaggedObject()); result->SetModule(thread, currentFunc->GetModule()); SET_ACC(JSTaggedValue(result)); @@ -1878,7 +2157,7 @@ void InterpreterAssembly::HandleDefineMethodPrefId16Imm16V8( JSTaggedValue taggedCurEnv = GET_VREG_VALUE(v0); result->SetLexicalEnv(thread, taggedCurEnv); - JSFunction *currentFunc = JSFunction::Cast((GET_FRAME(sp)->function).GetTaggedObject()); + JSFunction *currentFunc = JSFunction::Cast((GET_ASM_FRAME(sp)->function).GetTaggedObject()); result->SetModule(thread, currentFunc->GetModule()); SET_ACC(JSTaggedValue(result)); @@ -2011,7 +2290,7 @@ void InterpreterAssembly::HandleLdLexVarDynPrefImm16Imm16( LOG_INST() << "intrinsics::ldlexvardyn" << " level:" << level << " slot:" << slot; - InterpretedFrame *state = GET_FRAME(sp); + AsmInterpretedFrame *state = GET_ASM_FRAME(sp); JSTaggedValue currentLexenv = state->env; JSTaggedValue env(currentLexenv); for (int i = 0; i < level; i++) { @@ -2032,7 +2311,7 @@ void InterpreterAssembly::HandleLdLexVarDynPrefImm8Imm8( LOG_INST() << "intrinsics::ldlexvardyn" << " level:" << level << " slot:" << slot; - InterpretedFrame *state = GET_FRAME(sp); + AsmInterpretedFrame *state = GET_ASM_FRAME(sp); JSTaggedValue currentLexenv = state->env; JSTaggedValue env(currentLexenv); for (int i = 0; i < level; i++) { @@ -2053,7 +2332,7 @@ void InterpreterAssembly::HandleLdLexVarDynPrefImm4Imm4( LOG_INST() << "intrinsics::ldlexvardyn" << " level:" << level << " slot:" << slot; - InterpretedFrame *state = GET_FRAME(sp); + AsmInterpretedFrame *state = GET_ASM_FRAME(sp); JSTaggedValue currentLexenv = state->env; JSTaggedValue env(currentLexenv); for (int i = 0; i < level; i++) { @@ -2076,7 +2355,7 @@ void InterpreterAssembly::HandleStLexVarDynPrefImm16Imm16V8( << " level:" << level << " slot:" << slot << " v" << v0; JSTaggedValue value = GET_VREG_VALUE(v0); - InterpretedFrame *state = GET_FRAME(sp); + AsmInterpretedFrame *state = GET_ASM_FRAME(sp); JSTaggedValue env = state->env; for (int i = 0; i < level; i++) { JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv(); @@ -2099,7 +2378,7 @@ void InterpreterAssembly::HandleStLexVarDynPrefImm8Imm8V8( << " level:" << level << " slot:" << slot << " v" << v0; JSTaggedValue value = GET_VREG_VALUE(v0); - InterpretedFrame *state = GET_FRAME(sp); + AsmInterpretedFrame *state = GET_ASM_FRAME(sp); JSTaggedValue env = state->env; for (int i = 0; i < level; i++) { JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv(); @@ -2122,7 +2401,7 @@ void InterpreterAssembly::HandleStLexVarDynPrefImm4Imm4V8( << " level:" << level << " slot:" << slot << " v" << v0; JSTaggedValue value = GET_VREG_VALUE(v0); - InterpretedFrame *state = GET_FRAME(sp); + AsmInterpretedFrame *state = GET_ASM_FRAME(sp); JSTaggedValue env = state->env; for (int i = 0; i < level; i++) { JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv(); @@ -2149,7 +2428,7 @@ void InterpreterAssembly::HandleNewLexEnvDynPrefImm16( INTERPRETER_RETURN_IF_ABRUPT(res); } SET_ACC(res); - GET_FRAME(sp)->env = res; + GET_ASM_FRAME(sp)->env = res; DISPATCH(BytecodeInstruction::Format::PREF_IMM16); } @@ -2157,10 +2436,10 @@ void InterpreterAssembly::HandlePopLexEnvDynPref( JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo, JSTaggedValue acc, int32_t hotnessCounter) { - InterpretedFrame *state = GET_FRAME(sp); + AsmInterpretedFrame *state = GET_ASM_FRAME(sp); JSTaggedValue currentLexenv = state->env; JSTaggedValue parentLexenv = LexicalEnv::Cast(currentLexenv.GetTaggedObject())->GetParentEnv(); - GET_FRAME(sp)->env = parentLexenv; + GET_ASM_FRAME(sp)->env = parentLexenv; DISPATCH(BytecodeInstruction::Format::PREF_NONE); } @@ -2197,7 +2476,7 @@ void InterpreterAssembly::HandleSuspendGeneratorPrefV8V8( INTERPRETER_RETURN_IF_ABRUPT(res); SET_ACC(res); - InterpretedFrame *state = GET_FRAME(sp); + AsmInterpretedFrame *state = GET_ASM_FRAME(sp); JSMethod *method = ECMAObject::Cast(state->function.GetTaggedObject())->GetCallTarget(); [[maybe_unused]] auto fistPC = method->GetInstructions(); UPDATE_HOTNESS_COUNTER(-(pc - fistPC)); @@ -2205,7 +2484,7 @@ void InterpreterAssembly::HandleSuspendGeneratorPrefV8V8( << std::hex << reinterpret_cast(state->pc); sp = state->base.prev; ASSERT(sp != nullptr); - InterpretedFrame *prevState = GET_FRAME(sp); + AsmInterpretedFrame *prevState = GET_ASM_FRAME(sp); pc = prevState->pc; // break frame @@ -2215,10 +2494,9 @@ void InterpreterAssembly::HandleSuspendGeneratorPrefV8V8( return; } thread->SetCurrentSPFrame(sp); - constpool = prevState->constpool; - size_t jumpSize = GetJumpSizeAfterCall(pc); - DISPATCH_OFFSET(jumpSize); + ASSERT(prevState->callSize == GetJumpSizeAfterCall(pc)); + DISPATCH_OFFSET(prevState->callSize); } void InterpreterAssembly::HandleAsyncFunctionAwaitUncaughtPrefV8V8( @@ -2652,7 +2930,7 @@ void InterpreterAssembly::HandleDefineGeneratorFuncPrefId16Imm16V8( JSTaggedValue env = GET_VREG_VALUE(v0); result->SetLexicalEnv(thread, env); - JSFunction *currentFunc = JSFunction::Cast((GET_FRAME(sp)->function).GetTaggedObject()); + JSFunction *currentFunc = JSFunction::Cast((GET_ASM_FRAME(sp)->function).GetTaggedObject()); result->SetModule(thread, currentFunc->GetModule()); SET_ACC(JSTaggedValue(result)) DISPATCH(BytecodeInstruction::Format::PREF_ID16_IMM16_V8); @@ -2683,7 +2961,7 @@ void InterpreterAssembly::HandleDefineAsyncFuncPrefId16Imm16V8( JSTaggedValue env = GET_VREG_VALUE(v0); result->SetLexicalEnv(thread, env); - JSFunction *currentFunc = JSFunction::Cast((GET_FRAME(sp)->function).GetTaggedObject()); + JSFunction *currentFunc = JSFunction::Cast((GET_ASM_FRAME(sp)->function).GetTaggedObject()); result->SetModule(thread, currentFunc->GetModule()); SET_ACC(JSTaggedValue(result)) DISPATCH(BytecodeInstruction::Format::PREF_ID16_IMM16_V8); @@ -3495,7 +3773,7 @@ void InterpreterAssembly::HandleDefineClassWithBufferPrefId16Imm16Imm16V8V8( lexenv = GET_VREG_VALUE(v0); // slow runtime may gc cls->SetLexicalEnv(thread, lexenv); - JSFunction *currentFunc = JSFunction::Cast((GET_FRAME(sp)->function).GetTaggedObject()); + JSFunction *currentFunc = JSFunction::Cast((GET_ASM_FRAME(sp)->function).GetTaggedObject()); cls->SetModule(thread, currentFunc->GetModule()); SlowRuntimeStub::SetClassConstructorLength(thread, res, JSTaggedValue(length)); @@ -3527,7 +3805,7 @@ void InterpreterAssembly::HandleNewLexEnvWithNameDynPrefImm16Imm16( INTERPRETER_RETURN_IF_ABRUPT(res); SET_ACC(res); - GET_FRAME(sp)->env = res; + GET_ASM_FRAME(sp)->env = res; DISPATCH(BytecodeInstruction::Format::PREF_IMM16_IMM16); } @@ -3709,7 +3987,7 @@ void InterpreterAssembly::HandleOverflow( LOG(FATAL, INTERPRETER) << "opcode overflow"; } -inline uint32_t InterpreterAssembly::FindCatchBlock(JSMethod *caller, uint32_t pc) +uint32_t InterpreterAssembly::FindCatchBlock(JSMethod *caller, uint32_t pc) { auto *pandaFile = caller->GetPandaFile(); panda_file::MethodDataAccessor mda(*pandaFile, caller->GetFileId()); @@ -3746,17 +4024,17 @@ inline void InterpreterAssembly::InterpreterFrameCopyArgs( } } -inline JSTaggedValue InterpreterAssembly::GetThisFunction(JSTaggedType *sp) +JSTaggedValue InterpreterAssembly::GetThisFunction(JSTaggedType *sp) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - InterpretedFrame *state = reinterpret_cast(sp) - 1; + AsmInterpretedFrame *state = reinterpret_cast(sp) - 1; return JSTaggedValue(state->function); } -inline JSTaggedValue InterpreterAssembly::GetNewTarget(JSTaggedType *sp) +JSTaggedValue InterpreterAssembly::GetNewTarget(JSTaggedType *sp) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - InterpretedFrame *state = reinterpret_cast(sp) - 1; + AsmInterpretedFrame *state = reinterpret_cast(sp) - 1; JSMethod *method = JSFunction::Cast(state->function.GetTaggedObject())->GetMethod(); uint64_t callField = method->GetCallField(); ASSERT(JSMethod::HaveNewTargetBit::Decode(callField)); @@ -3765,10 +4043,10 @@ inline JSTaggedValue InterpreterAssembly::GetNewTarget(JSTaggedType *sp) return JSTaggedValue(sp[numVregs + haveFunc]); } -inline uint32_t InterpreterAssembly::GetNumArgs(JSTaggedType *sp, uint32_t restIdx, uint32_t &startIdx) +uint32_t InterpreterAssembly::GetNumArgs(JSTaggedType *sp, uint32_t restIdx, uint32_t &startIdx) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - InterpretedFrame *state = reinterpret_cast(sp) - 1; + AsmInterpretedFrame *state = reinterpret_cast(sp) - 1; JSMethod *method = JSFunction::Cast(state->function.GetTaggedObject())->GetMethod(); uint64_t callField = method->GetCallField(); ASSERT(JSMethod::HaveExtraBit::Decode(callField)); @@ -3822,18 +4100,50 @@ inline size_t InterpreterAssembly::GetJumpSizeAfterCall(const uint8_t *prevPc) inline JSTaggedValue InterpreterAssembly::UpdateHotnessCounter(JSThread* thread, TaggedType *sp) { - InterpretedFrame *state = GET_FRAME(sp); + AsmInterpretedFrame *state = GET_ASM_FRAME(sp); 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; + JSFunction* function = JSFunction::Cast(state->function.GetTaggedObject()); + JSTaggedValue profileTypeInfo = function->GetProfileTypeInfo(); + if (profileTypeInfo == JSTaggedValue::Undefined()) { + auto method = function->GetMethod(); + auto res = SlowRuntimeStub::NotifyInlineCache(thread, function, method); + function->SetProfileTypeInfo(res); return res; } - return state->profileTypeInfo; + return profileTypeInfo; } +#undef LOG_INST +#undef ADVANCE_PC +#undef GOTO_NEXT +#undef DISPATCH_OFFSET +#undef GET_ASM_FRAME +#undef SAVE_PC +#undef SAVE_ACC +#undef RESTORE_ACC +#undef INTERPRETER_GOTO_EXCEPTION_HANDLER +#undef UPDATE_HOTNESS_COUNTER +#undef GET_VREG +#undef GET_VREG_VALUE +#undef SET_VREG +#undef GET_ACC +#undef SET_ACC +#undef CALL_INITIALIZE +#undef CALL_PUSH_UNDEFINED +#undef CALL_PUSH_ARGS_0 +#undef CALL_PUSH_ARGS_1 +#undef CALL_PUSH_ARGS_2 +#undef CALL_PUSH_ARGS_3 +#undef CALL_PUSH_ARGS_I +#undef CALL_PUSH_ARGS_I_THIS +#undef CALL_PUSH_ARGS_0_NO_EXTRA +#undef CALL_PUSH_ARGS_1_NO_EXTRA +#undef CALL_PUSH_ARGS_2_NO_EXTRA +#undef CALL_PUSH_ARGS_3_NO_EXTRA +#undef CALL_PUSH_ARGS_I_NO_EXTRA +#undef CALL_PUSH_ARGS_I_THIS_NO_EXTRA +#undef CALL_PUSH_ARGS +#undef SET_VREGS_AND_FRAME_NATIVE +#undef SET_VREGS_AND_FRAME_NOT_NATIVE #if defined(__clang__) #pragma clang diagnostic pop #elif defined(__GNUC__) diff --git a/ecmascript/interpreter/interpreter_assembly.h b/ecmascript/interpreter/interpreter_assembly.h index 8a24b1f9..571735f2 100644 --- a/ecmascript/interpreter/interpreter_assembly.h +++ b/ecmascript/interpreter/interpreter_assembly.h @@ -32,20 +32,28 @@ using AsmDispatchEntryPoint = class ConstantPool; class ECMAObject; class GeneratorContext; +struct CallParams; class InterpreterAssembly { public: + static const uint32_t METHOD_HOTNESS_THRESHOLD = 512; enum ActualNumArgsOfCall : uint8_t { CALLARG0 = 0, CALLARG1, CALLARGS2, CALLARGS3 }; static void RunInternal(JSThread *thread, ConstantPool *constpool, const uint8_t *pc, JSTaggedType *sp); - static inline uint32_t FindCatchBlock(JSMethod *caller, uint32_t pc); + static void InitStackFrame(JSThread *thread); + static JSTaggedValue Execute(JSThread *thread, const CallParams& params); + static JSTaggedValue ExecuteNative(JSThread *thread, const CallParams& params); + static JSTaggedValue GeneratorReEnterInterpreter(JSThread *thread, JSHandle context); + static void ChangeGenContext(JSThread *thread, JSHandle context); + static void ResumeContext(JSThread *thread); + static uint32_t FindCatchBlock(JSMethod *caller, uint32_t pc); static inline size_t GetJumpSizeAfterCall(const uint8_t *prevPc); static inline JSTaggedValue UpdateHotnessCounter(JSThread* thread, TaggedType *sp); static inline void InterpreterFrameCopyArgs(JSTaggedType *newSp, uint32_t numVregs, uint32_t numActualArgs, uint32_t numDeclaredArgs, bool haveExtraArgs = true); - static inline JSTaggedValue GetThisFunction(JSTaggedType *sp); - static inline JSTaggedValue GetNewTarget(JSTaggedType *sp); - static inline uint32_t GetNumArgs(JSTaggedType *sp, uint32_t restIdx, uint32_t &startIdx); + static JSTaggedValue GetThisFunction(JSTaggedType *sp); + static JSTaggedValue GetNewTarget(JSTaggedType *sp); + static uint32_t GetNumArgs(JSTaggedType *sp, uint32_t restIdx, uint32_t &startIdx); static void HandleOverflow(JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo, diff --git a/ecmascript/js_method.h b/ecmascript/js_method.h index c5c3c388..2ab9711d 100644 --- a/ecmascript/js_method.h +++ b/ecmascript/js_method.h @@ -36,7 +36,8 @@ static constexpr size_t STORAGE_PTR_NUM = 3; V(SHORTY, CODEID, sizeof(uint32_t), sizeof(uint32_t)) \ V(PROFILINGDATA, SHORTY, 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(JSPANDAFILE, CALLFIELD, sizeof(uint64_t), sizeof(uint64_t)) \ + V(BYTECODEARRAY, JSPANDAFILE, sizeof(uint32_t), sizeof(uint64_t)) \ V(BYTECODEARRAYSIZE, BYTECODEARRAY, sizeof(uint32_t), sizeof(uint64_t)) \ V(SLOTSIZE, BYTECODEARRAYSIZE, sizeof(uint32_t), sizeof(uint32_t)) \ diff --git a/ecmascript/stubs/runtime_stubs.cpp b/ecmascript/stubs/runtime_stubs.cpp index 0159c243..8d8b2522 100644 --- a/ecmascript/stubs/runtime_stubs.cpp +++ b/ecmascript/stubs/runtime_stubs.cpp @@ -75,6 +75,9 @@ JSTaggedType RuntimeStubs::name(uintptr_t argGlue, uint32_t argc, uintptr_t argv ASSERT((index) < argc); \ type name = reinterpret_cast(*(reinterpret_cast(argv) + (index))) +#define GET_ASM_FRAME(CurrentSp) \ + (reinterpret_cast(CurrentSp) - 1) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + DEF_RUNTIME_STUBS(AddElementInternal) { RUNTIME_STUBS_HEADER(AddElementInternal); @@ -556,7 +559,7 @@ DEF_RUNTIME_STUBS(SuperCallSpread) CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, func, 0); CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, array, 1); auto sp = const_cast(thread->GetCurrentSPFrame()); - JSTaggedValue function = EcmaInterpreter::GetNewTarget(sp); + JSTaggedValue function = InterpreterAssembly::GetNewTarget(sp); return RuntimeSuperCallSpread(thread, func, JSHandle(thread, function), array).GetRawData(); } @@ -683,7 +686,7 @@ DEF_RUNTIME_STUBS(LdSuperByValue) CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, obj, 0); CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, key, 1); auto sp = const_cast(thread->GetCurrentSPFrame()); - JSTaggedValue thisFunc = EcmaInterpreter::GetThisFunction(sp); + JSTaggedValue thisFunc = InterpreterAssembly::GetThisFunction(sp); return RuntimeLdSuperByValue(thread, obj, key, thisFunc).GetRawData(); } @@ -694,7 +697,7 @@ DEF_RUNTIME_STUBS(StSuperByValue) CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, key, 1); CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, value, 2); auto sp = const_cast(thread->GetCurrentSPFrame()); - JSTaggedValue thisFunc = EcmaInterpreter::GetThisFunction(sp); + JSTaggedValue thisFunc = InterpreterAssembly::GetThisFunction(sp); return RuntimeStSuperByValue(thread, obj, key, value, thisFunc).GetRawData(); } @@ -842,7 +845,7 @@ DEF_RUNTIME_STUBS(SetClassConstructorLength) DEF_RUNTIME_STUBS(UpdateHotnessCounter) { RUNTIME_STUBS_HEADER(UpdateHotnessCounter); - InterpretedFrame *state = GET_FRAME(const_cast(thread->GetCurrentSPFrame())); + AsmInterpretedFrame *state = GET_ASM_FRAME(const_cast(thread->GetCurrentSPFrame())); thread->CheckSafepoint(); auto thisFunc = JSFunction::Cast(state->function.GetTaggedObject()); if (thisFunc->GetProfileTypeInfo() == JSTaggedValue::Undefined()) { @@ -945,7 +948,7 @@ DEF_RUNTIME_STUBS(UpFrame) return JSTaggedValue(static_cast(0)).GetRawData(); } auto method = frameHandler.GetMethod(); - pcOffset = EcmaInterpreter::FindCatchBlock(method, frameHandler.GetBytecodeOffset()); + pcOffset = InterpreterAssembly::FindCatchBlock(method, frameHandler.GetBytecodeOffset()); if (pcOffset != panda_file::INVALID_OFFSET) { thread->SetCurrentSPFrame(frameHandler.GetSp()); uintptr_t pc = reinterpret_cast(method->GetBytecodeArray() + pcOffset); @@ -1266,7 +1269,7 @@ DEF_RUNTIME_STUBS(CallArg0Dyn) { RUNTIME_STUBS_HEADER(CallArg0Dyn); CONVERT_ARG_TAGGED_CHECKED(func, 0); - uint32_t actualNumArgs = EcmaInterpreter::ActualNumArgsOfCall::CALLARG0; + uint32_t actualNumArgs = InterpreterAssembly::ActualNumArgsOfCall::CALLARG0; bool callThis = false; std::vector actualArgs; return RuntimeNativeCall(thread, func, callThis, actualNumArgs, actualArgs); @@ -1277,7 +1280,7 @@ DEF_RUNTIME_STUBS(CallArg1Dyn) RUNTIME_STUBS_HEADER(CallArg1Dyn); CONVERT_ARG_TAGGED_CHECKED(func, 0); CONVERT_ARG_TAGGED_TYPE_CHECKED(arg0, 1); - uint32_t actualNumArgs = EcmaInterpreter::ActualNumArgsOfCall::CALLARG1; + uint32_t actualNumArgs = InterpreterAssembly::ActualNumArgsOfCall::CALLARG1; bool callThis = false; std::vector actualArgs; actualArgs.emplace_back(arg0); @@ -1290,7 +1293,7 @@ DEF_RUNTIME_STUBS(CallArgs2Dyn) CONVERT_ARG_TAGGED_CHECKED(func, 0); CONVERT_ARG_TAGGED_TYPE_CHECKED(arg0, 1); CONVERT_ARG_TAGGED_TYPE_CHECKED(arg1, 2); - uint32_t actualNumArgs = EcmaInterpreter::ActualNumArgsOfCall::CALLARGS2; + uint32_t actualNumArgs = InterpreterAssembly::ActualNumArgsOfCall::CALLARGS2; bool callThis = false; std::vector actualArgs; actualArgs.emplace_back(arg0); @@ -1305,7 +1308,7 @@ DEF_RUNTIME_STUBS(CallArgs3Dyn) CONVERT_ARG_TAGGED_TYPE_CHECKED(arg0, 1); CONVERT_ARG_TAGGED_TYPE_CHECKED(arg1, 2); CONVERT_ARG_TAGGED_TYPE_CHECKED(arg2, 3); - uint32_t actualNumArgs = EcmaInterpreter::ActualNumArgsOfCall::CALLARGS3; + uint32_t actualNumArgs = InterpreterAssembly::ActualNumArgsOfCall::CALLARGS3; bool callThis = false; std::vector actualArgs; actualArgs.emplace_back(arg0); @@ -1351,12 +1354,12 @@ DEF_RUNTIME_STUBS(JumpToCInterpreter) CONVERT_ARG_TAGGED_CHECKED(hotnessCounter, 3); auto sp = const_cast(thread->GetCurrentSPFrame()); - const uint8_t* currentPc = reinterpret_cast(GET_FRAME(sp)->pc); + const uint8_t* currentPc = reinterpret_cast(GET_ASM_FRAME(sp)->pc); uint8_t opcode = currentPc[0]; asmDispatchTable[opcode](thread, currentPc, sp, constpool, profileTypeInfo, acc, hotnessCounter.GetInt()); sp = const_cast(thread->GetCurrentSPFrame()); - InterpretedFrame *frame = GET_FRAME(sp); + AsmInterpretedFrame *frame = GET_ASM_FRAME(sp); uintptr_t framePc = reinterpret_cast(frame->pc); return JSTaggedValue(static_cast(framePc)).GetRawData(); } @@ -1392,7 +1395,7 @@ DEF_RUNTIME_STUBS(GetUnmapedArgs) RUNTIME_STUBS_HEADER(GetUnmapedArgs); auto sp = const_cast(thread->GetCurrentSPFrame()); uint32_t startIdx = 0; - uint32_t actualNumArgs = EcmaInterpreter::GetNumArgs(sp, 0, startIdx); + uint32_t actualNumArgs = InterpreterAssembly::GetNumArgs(sp, 0, startIdx); return RuntimeGetUnmapedArgs(thread, sp, actualNumArgs, startIdx).GetRawData(); } @@ -1402,7 +1405,7 @@ DEF_RUNTIME_STUBS(CopyRestArgs) CONVERT_ARG_TAGGED_CHECKED(restIdx, 0); auto sp = const_cast(thread->GetCurrentSPFrame()); uint32_t startIdx = 0; - uint32_t restNumArgs = EcmaInterpreter::GetNumArgs(sp, restIdx.GetInt(), startIdx); + uint32_t restNumArgs = InterpreterAssembly::GetNumArgs(sp, restIdx.GetInt(), startIdx); return RuntimeCopyRestArgs(thread, sp, restNumArgs, startIdx).GetRawData(); } @@ -1543,7 +1546,7 @@ DEF_RUNTIME_STUBS(SuperCall) CONVERT_ARG_TAGGED_CHECKED(firstVRegIdx, 1); CONVERT_ARG_TAGGED_CHECKED(length, 2); auto sp = const_cast(thread->GetCurrentSPFrame()); - JSTaggedValue newTarget = EcmaInterpreter::GetNewTarget(sp); + JSTaggedValue newTarget = InterpreterAssembly::GetNewTarget(sp); return RuntimeSuperCall(thread, func, JSHandle(thread, newTarget), static_cast(firstVRegIdx.GetInt()), static_cast(length.GetInt())).GetRawData();