From 690ca22d2a09a8eb0d61d4de9ca6c68ea31ae402 Mon Sep 17 00:00:00 2001 From: xujie Date: Wed, 29 Jun 2022 17:09:09 +0800 Subject: [PATCH] Support Lexenv In TSAOT 1. Support lexical env when running tsaot 2. fix getunmappedargs and copyrestargs bugs Issue: https://gitee.com/openharmony/ark_js_runtime/issues/I5C1P2 Signed-off-by: xujie Change-Id: Ia78ea4d89654d6924c0dee6f491cdf1e4fe718ee --- .../compiler/bytecode_circuit_builder.cpp | 14 +- .../compiler/bytecode_circuit_builder.h | 1 + ecmascript/compiler/call_signature.cpp | 5 +- ecmascript/compiler/circuit_builder.cpp | 5 + ecmascript/compiler/circuit_builder.h | 1 + ecmascript/compiler/common_stubs.cpp | 3 +- ecmascript/compiler/llvm_ir_builder.cpp | 25 ++- ecmascript/compiler/llvm_ir_builder.h | 1 + ecmascript/compiler/slowpath_lowering.cpp | 135 ++++++--------- ecmascript/compiler/slowpath_lowering.h | 12 +- ecmascript/compiler/stub.cpp | 13 +- ecmascript/compiler/test_stubs.cpp | 161 ++++++++++-------- ecmascript/compiler/test_stubs.h | 40 ++--- ecmascript/compiler/test_stubs_signature.cpp | 50 +++--- ecmascript/compiler/tests/stub_tests.cpp | 14 +- .../trampoline/aarch64/assembler_stubs.cpp | 52 +++--- .../trampoline/aarch64/assembler_stubs.h | 8 +- .../trampoline/x64/assembler_stubs_x64.cpp | 84 +++++---- .../trampoline/x64/assembler_stubs_x64.h | 5 + ecmascript/ecma_vm.cpp | 8 +- ecmascript/frames.cpp | 56 +++++- ecmascript/frames.h | 124 ++++++++++---- ecmascript/interpreter/frame_handler.cpp | 16 +- ecmascript/stubs/runtime_stubs-inl.h | 110 ++++++++++-- ecmascript/stubs/runtime_stubs.cpp | 59 ++++++- ecmascript/stubs/runtime_stubs.h | 18 +- test/aottest/BUILD.gn | 3 + 27 files changed, 668 insertions(+), 355 deletions(-) diff --git a/ecmascript/compiler/bytecode_circuit_builder.cpp b/ecmascript/compiler/bytecode_circuit_builder.cpp index 0326fe5f..3a62bfb2 100644 --- a/ecmascript/compiler/bytecode_circuit_builder.cpp +++ b/ecmascript/compiler/bytecode_circuit_builder.cpp @@ -1843,13 +1843,18 @@ void BytecodeCircuitBuilder::BuildCircuitArgs() const size_t numArgs = method_->GetNumArgs(); const size_t actualNumArgs = GetActualNumArgs(numArgs); actualArgs_.resize(actualNumArgs); + auto argRoot = Circuit::GetCircuitRoot(OpCode(OpCode::ARG_LIST)); auto glueGate = circuit_.NewGate(OpCode(OpCode::ARG), MachineType::I64, 0, - {Circuit::GetCircuitRoot(OpCode(OpCode::ARG_LIST))}, - GateType::NJSValue()); + {argRoot}, GateType::NJSValue()); actualArgs_.at(0) = glueGate; commonArgs_.at(0) = glueGate; - auto argRoot = Circuit::GetCircuitRoot(OpCode(OpCode::ARG_LIST)); + + auto envGate = circuit_.NewGate(OpCode(OpCode::ARG), MachineType::I64, CommonArgIdx::LEXENV, + {argRoot}, GateType::TaggedValue()); + actualArgs_.at(CommonArgIdx::LEXENV) = envGate; + commonArgs_.at(CommonArgIdx::LEXENV) = envGate; + auto actualArgc = circuit_.NewGate(OpCode(OpCode::ARG), MachineType::I32, CommonArgIdx::ACTUAL_ARGC, {argRoot}, GateType::NJSValue()); actualArgs_.at(CommonArgIdx::ACTUAL_ARGC) = actualArgc; @@ -1863,8 +1868,7 @@ void BytecodeCircuitBuilder::BuildCircuitArgs() for (size_t argIdx = CommonArgIdx::NUM_OF_ARGS; argIdx < actualNumArgs; argIdx++) { actualArgs_.at(argIdx) = circuit_.NewGate(OpCode(OpCode::ARG), MachineType::I64, argIdx, - {Circuit::GetCircuitRoot(OpCode(OpCode::ARG_LIST))}, - GateType::TaggedValue()); + {argRoot}, GateType::TaggedValue()); } } diff --git a/ecmascript/compiler/bytecode_circuit_builder.h b/ecmascript/compiler/bytecode_circuit_builder.h index 86adfc85..48cccf80 100644 --- a/ecmascript/compiler/bytecode_circuit_builder.h +++ b/ecmascript/compiler/bytecode_circuit_builder.h @@ -376,6 +376,7 @@ enum BytecodeOffset { enum CommonArgIdx : uint8_t { GLUE = 0, + LEXENV, ACTUAL_ARGC, FUNC, NEW_TARGET, diff --git a/ecmascript/compiler/call_signature.cpp b/ecmascript/compiler/call_signature.cpp index a113d33b..aaf9e3f4 100644 --- a/ecmascript/compiler/call_signature.cpp +++ b/ecmascript/compiler/call_signature.cpp @@ -550,11 +550,12 @@ DEF_CALL_SIGNATURE(OptimizedCallOptimized) DEF_CALL_SIGNATURE(JSCall) { // 5 : 5 input parameters - CallSignature jSCall("JSCall", 0, 5, + CallSignature jSCall("JSCall", 0, 6, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY()); *callSign = jSCall; - std::array params = { // 5 : 5 input parameters + std::array params = { // 6 : 6 input parameters VariableType::NATIVE_POINTER(), // glue + VariableType::JS_ANY(), // lexenv VariableType::INT32(), // actual argC VariableType::JS_ANY(), // call target VariableType::JS_ANY(), // new target diff --git a/ecmascript/compiler/circuit_builder.cpp b/ecmascript/compiler/circuit_builder.cpp index f0e476c9..94996588 100644 --- a/ecmascript/compiler/circuit_builder.cpp +++ b/ecmascript/compiler/circuit_builder.cpp @@ -469,6 +469,11 @@ void CircuitBuilder::SetLexicalEnvToFunction(GateRef glue, GateRef function, Gat Store(VariableType::JS_ANY(), glue, function, offset, value); } +GateRef CircuitBuilder::GetLexicalEnv(GateRef function) +{ + return Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::LEXICAL_ENV_OFFSET)); +} + void CircuitBuilder::SetModuleToFunction(GateRef glue, GateRef function, GateRef value) { GateRef offset = IntPtr(JSFunction::ECMA_MODULE_OFFSET); diff --git a/ecmascript/compiler/circuit_builder.h b/ecmascript/compiler/circuit_builder.h index 177e1d0c..94a2bc30 100644 --- a/ecmascript/compiler/circuit_builder.h +++ b/ecmascript/compiler/circuit_builder.h @@ -355,6 +355,7 @@ public: void SetResolvedToFunction(GateRef glue, GateRef function, GateRef value); void SetConstPoolToFunction(GateRef glue, GateRef function, GateRef value); void SetLexicalEnvToFunction(GateRef glue, GateRef function, GateRef value); + GateRef GetLexicalEnv(GateRef function); void SetModuleToFunction(GateRef glue, GateRef function, GateRef value); void SetPropertyInlinedProps(GateRef glue, GateRef obj, GateRef hClass, GateRef value, GateRef attrOffset, VariableType type); diff --git a/ecmascript/compiler/common_stubs.cpp b/ecmascript/compiler/common_stubs.cpp index 314f285a..5bc85928 100644 --- a/ecmascript/compiler/common_stubs.cpp +++ b/ecmascript/compiler/common_stubs.cpp @@ -488,8 +488,9 @@ void JsProxyCallInternalStub::GenerateCircuit(const CompilationConfig *cfg) GateRef arrHandle = CallRuntime(glue, RTSTUB_ID(CreateArrayFromList), argc, argv); GateRef thisArg = Load(VariableType::JS_POINTER(), argv, IntPtr(2*sizeof(JSTaggedValue))); GateRef numArgs = Int32(6); + GateRef lexEnv = Load(VariableType::JS_POINTER(), method, IntPtr(JSFunction::LEXICAL_ENV_OFFSET)); result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), - {glue, numArgs, method, Undefined(), handler, target, thisArg, arrHandle}); + {glue, lexEnv, numArgs, method, Undefined(), handler, target, thisArg, arrHandle}); Jump(&exit); } } diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index cdc5d96f..0208399f 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -1072,12 +1072,29 @@ void LLVMIRBuilder::VisitParameter(GateRef gate) ASSERT(LLVMTypeOf(value) == ConvertLLVMTypeFromGate(gate)); gate2LValue_[gate] = value; // NOTE: caller put args, otherwise crash - if (value == nullptr) { - COMPILER_OPTIONAL_LOG(FATAL) << "generate LLVM IR for para: " << argth << "fail"; - return; + ASSERT(value != nullptr); + + // add env slot for optimized jsfunction frame + auto frameType = circuit_->GetFrameType(); + if (frameType == panda::ecmascript::FrameType::OPTIMIZED_JS_FUNCTION_FRAME) { + if (argth == CommonArgIdx::LEXENV) { + SaveLexicalEnvOnFrame(value); + } } } +void LLVMIRBuilder::SaveLexicalEnvOnFrame(LLVMValueRef value) +{ + LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false); + LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder_, llvmFpAddr, slotType_, "cast_int_t"); + LLVMValueRef frameEnvSlotAddr = LLVMBuildSub(builder_, frameAddr, LLVMConstInt(slotType_, + static_cast(ReservedSlots::OPTIMIZED_JS_FUNCTION_RESERVED_SLOT) * slotSize_, false), ""); + LLVMValueRef envAddr = LLVMBuildIntToPtr(builder_, frameEnvSlotAddr, + LLVMPointerType(slotType_, 0), "env.Addr"); + LLVMValueRef envValue = LLVMBuildPtrToInt(builder_, value, slotType_, "cast_to_i64"); + LLVMBuildStore(builder_, envValue, envAddr); +} + void LLVMIRBuilder::HandleBranch(GateRef gate) { std::vector ins = circuit_->GetInVector(gate); @@ -1942,6 +1959,8 @@ LLVMValueRef LLVMModule::AddFunc(const panda::ecmascript::JSMethod *method) auto paramCount = method->GetNumArgs() + CommonArgIdx::NUM_OF_ARGS; VariableType glueParamType(MachineType::I64, GateType::NJSValue()); paramTys.push_back(ConvertLLVMTypeFromVariableType(glueParamType)); + VariableType lexEnv(MachineType::I64, GateType::TaggedValue()); + paramTys.push_back(ConvertLLVMTypeFromVariableType(lexEnv)); VariableType actualArgc(MachineType::I32, GateType::NJSValue()); paramTys.push_back(ConvertLLVMTypeFromVariableType(actualArgc)); for (uint32_t i = CommonArgIdx::FUNC; i < CommonArgIdx::NUM_OF_ARGS; i++) { diff --git a/ecmascript/compiler/llvm_ir_builder.h b/ecmascript/compiler/llvm_ir_builder.h index 527e3841..9677e104 100644 --- a/ecmascript/compiler/llvm_ir_builder.h +++ b/ecmascript/compiler/llvm_ir_builder.h @@ -305,6 +305,7 @@ private: bool NeedBCOffset(OpCode op); void ComputeArgCountAndBCOffset(size_t &actualNumArgs, LLVMValueRef &bcOffset, const std::vector &inList, OpCode op); + void SaveLexicalEnvOnFrame(LLVMValueRef value); const CompilationConfig *compCfg_ {nullptr}; const std::vector> *scheduledGates_ {nullptr}; const Circuit *circuit_ {nullptr}; diff --git a/ecmascript/compiler/slowpath_lowering.cpp b/ecmascript/compiler/slowpath_lowering.cpp index e8f80032..68ca1157 100644 --- a/ecmascript/compiler/slowpath_lowering.cpp +++ b/ecmascript/compiler/slowpath_lowering.cpp @@ -204,12 +204,6 @@ GateRef SlowPathLowering::GetConstPool(GateRef jsFunc) return builder_.Load(VariableType::JS_ANY(), jsFunc, builder_.IntPtr(JSFunction::CONSTANT_POOL_OFFSET)); } -// labelmanager must be initialized -GateRef SlowPathLowering::GetCurrentEnv(GateRef jsFunc) -{ - return builder_.Load(VariableType::JS_ANY(), jsFunc, builder_.IntPtr(JSFunction::LEXICAL_ENV_OFFSET)); -} - // labelmanager must be initialized GateRef SlowPathLowering::GetObjectFromConstPool(GateRef jsFunc, GateRef index) { @@ -269,7 +263,7 @@ void SlowPathLowering::Lower(GateRef gate) LowerCallIRangeDyn(gate, glue); break; case LDLEXENVDYN_PREF: - LowerLexicalEnv(gate, glue, jsFunc); + LowerLexicalEnv(gate, glue); break; case GETUNMAPPEDARGS_PREF: LowerGetUnmappedArgs(gate, glue); @@ -529,13 +523,13 @@ void SlowPathLowering::Lower(GateRef gate) LowerDefineAsyncFunc(gate, glue, jsFunc); break; case NEWLEXENVDYN_PREF_IMM16: - LowerNewLexicalEnvDyn(gate, glue, jsFunc); + LowerNewLexicalEnvDyn(gate, glue); break; case NEWLEXENVWITHNAMEDYN_PREF_IMM16_IMM16: LowerNewLexicalEnvWithNameDyn(gate, glue, jsFunc); break; case POPLEXENVDYN_PREF: - LowerPopLexicalEnv(gate, glue, jsFunc); + LowerPopLexicalEnv(gate, glue); break; case LDSUPERBYVALUE_PREF_V8_V8: LowerLdSuperByValue(gate, glue, jsFunc); @@ -600,12 +594,12 @@ void SlowPathLowering::Lower(GateRef gate) case LDLEXVARDYN_PREF_IMM4_IMM4: case LDLEXVARDYN_PREF_IMM8_IMM8: case LDLEXVARDYN_PREF_IMM16_IMM16: - LowerLdLexVarDyn(gate, jsFunc); + LowerLdLexVarDyn(gate, glue); break; case STLEXVARDYN_PREF_IMM4_IMM4_V8: case STLEXVARDYN_PREF_IMM8_IMM8_V8: case STLEXVARDYN_PREF_IMM16_IMM16_V8: - LowerStLexVarDyn(gate, glue, jsFunc); + LowerStLexVarDyn(gate, glue); break; case CREATEOBJECTHAVINGMETHOD_PREF_IMM16: LowerCreateObjectHavingMethod(gate, glue, jsFunc); @@ -703,10 +697,10 @@ void SlowPathLowering::LowerLoadStr(GateRef gate, GateRef glue) ReplaceHirToCall(gate, newGate); } -void SlowPathLowering::LowerLexicalEnv(GateRef gate, GateRef glue, GateRef jsFunc) +void SlowPathLowering::LowerLexicalEnv(GateRef gate, GateRef glue) { const int id = RTSTUB_ID(GetAotLexicalEnv); - GateRef newGate = LowerCallRuntime(glue, id, {jsFunc}); + GateRef newGate = LowerCallRuntime(glue, id, {}); ReplaceHirToCall(gate, newGate, true); } @@ -810,8 +804,10 @@ void SlowPathLowering::LowerCallArg0Dyn(GateRef gate, GateRef glue) GateRef actualArgc = builder_.Int32(ComputeCallArgc(gate, EcmaOpcode::CALLARG0DYN_PREF_V8)); GateRef newTarget = builder_.Undefined(); GateRef thisObj = builder_.Undefined(); - LowerToJSCall(gate, glue, {glue, actualArgc, acc_.GetValueIn(gate, 0), newTarget, thisObj, - acc_.GetValueIn(gate, 1)}); + GateRef func = acc_.GetValueIn(gate, 0); + GateRef env = builder_.GetLexicalEnv(func); + GateRef bcOffset = acc_.GetValueIn(gate, 1); + LowerToJSCall(gate, glue, {glue, env, actualArgc, func, newTarget, thisObj, bcOffset}); } void SlowPathLowering::LowerCallArg1Dyn(GateRef gate, GateRef glue) @@ -822,8 +818,10 @@ void SlowPathLowering::LowerCallArg1Dyn(GateRef gate, GateRef glue) GateRef actualArgc = builder_.Int32(ComputeCallArgc(gate, EcmaOpcode::CALLARG1DYN_PREF_V8_V8)); GateRef newTarget = builder_.Undefined(); GateRef thisObj = builder_.Undefined(); - LowerToJSCall(gate, glue, {glue, actualArgc, - acc_.GetValueIn(gate, 0), newTarget, thisObj, acc_.GetValueIn(gate, 1), acc_.GetValueIn(gate, 2)}); + GateRef func = acc_.GetValueIn(gate, 0); + GateRef env = builder_.GetLexicalEnv(func); + GateRef bcOffset = acc_.GetValueIn(gate, 2); // 2: bytecode offset + LowerToJSCall(gate, glue, {glue, env, actualArgc, func, newTarget, thisObj, acc_.GetValueIn(gate, 1), bcOffset}); } void SlowPathLowering::LowerCallArgs2Dyn(GateRef gate, GateRef glue) @@ -834,9 +832,11 @@ void SlowPathLowering::LowerCallArgs2Dyn(GateRef gate, GateRef glue) GateRef actualArgc = builder_.Int32(ComputeCallArgc(gate, EcmaOpcode::CALLARGS2DYN_PREF_V8_V8_V8)); GateRef newTarget = builder_.Undefined(); GateRef thisObj = builder_.Undefined(); - LowerToJSCall(gate, glue, {glue, actualArgc, - acc_.GetValueIn(gate, 0), newTarget, thisObj, acc_.GetValueIn(gate, 1), acc_.GetValueIn(gate, 2), - acc_.GetValueIn(gate, 3)}); + GateRef func = acc_.GetValueIn(gate, 0); + GateRef env = builder_.GetLexicalEnv(func); + GateRef bcOffset = acc_.GetValueIn(gate, 3); // 3: bytecode offset + LowerToJSCall(gate, glue, {glue, env, actualArgc, func, newTarget, thisObj, acc_.GetValueIn(gate, 1), + acc_.GetValueIn(gate, 2), bcOffset}); } void SlowPathLowering::LowerCallArgs3Dyn(GateRef gate, GateRef glue) @@ -847,9 +847,11 @@ void SlowPathLowering::LowerCallArgs3Dyn(GateRef gate, GateRef glue) GateRef actualArgc = builder_.Int32(ComputeCallArgc(gate, EcmaOpcode::CALLARGS3DYN_PREF_V8_V8_V8_V8)); GateRef newTarget = builder_.Undefined(); GateRef thisObj = builder_.Undefined(); - LowerToJSCall(gate, glue, {glue, actualArgc, - acc_.GetValueIn(gate, 0), newTarget, thisObj, acc_.GetValueIn(gate, 1), - acc_.GetValueIn(gate, 2), acc_.GetValueIn(gate, 3)}); + GateRef func = acc_.GetValueIn(gate, 0); + GateRef env = builder_.GetLexicalEnv(func); + GateRef bcOffset = acc_.GetValueIn(gate, 4); // 4: bytecode offset + LowerToJSCall(gate, glue, {glue, env, actualArgc, func, newTarget, thisObj, acc_.GetValueIn(gate, 1), + acc_.GetValueIn(gate, 2), acc_.GetValueIn(gate, 3), bcOffset}); } void SlowPathLowering::LowerCallIThisRangeDyn(GateRef gate, GateRef glue) @@ -862,13 +864,16 @@ void SlowPathLowering::LowerCallIThisRangeDyn(GateRef gate, GateRef glue) GateRef callTarget = acc_.GetValueIn(gate, 0); GateRef thisObj = acc_.GetValueIn(gate, 1); GateRef newTarget = builder_.Undefined(); + GateRef env = builder_.GetLexicalEnv(callTarget); vec.emplace_back(glue); + vec.emplace_back(env); vec.emplace_back(actualArgc); vec.emplace_back(callTarget); vec.emplace_back(newTarget); vec.emplace_back(thisObj); // add common args - for (size_t i = fixedInputsNum; i < acc_.GetNumValueIn(gate); i++) { + size_t numIns = acc_.GetNumValueIn(gate); + for (size_t i = fixedInputsNum; i < numIns; i++) { vec.emplace_back(acc_.GetValueIn(gate, i)); } LowerToJSCall(gate, glue, vec); @@ -893,7 +898,9 @@ void SlowPathLowering::LowerCallIRangeDyn(GateRef gate, GateRef glue) GateRef callTarget = acc_.GetValueIn(gate, 0); GateRef newTarget = builder_.Undefined(); GateRef thisObj = builder_.Undefined(); + GateRef env = builder_.GetLexicalEnv(callTarget); vec.emplace_back(glue); + vec.emplace_back(env); vec.emplace_back(actualArgc); vec.emplace_back(callTarget); vec.emplace_back(newTarget); @@ -1877,13 +1884,13 @@ void SlowPathLowering::LowerDefineAsyncFunc(GateRef gate, GateRef glue, GateRef ReplaceHirToSubCfg(gate, result, successControl, failControl); } -void SlowPathLowering::LowerNewLexicalEnvDyn(GateRef gate, GateRef glue, GateRef jsFunc) +void SlowPathLowering::LowerNewLexicalEnvDyn(GateRef gate, GateRef glue) { std::vector successControl; std::vector failControl; // 1: number of value inputs ASSERT(acc_.GetNumValueIn(gate) == 1); - GateRef lexEnv = LowerCallRuntime(glue, RTSTUB_ID(GetAotLexicalEnv), {jsFunc}, true); + GateRef lexEnv = LowerCallRuntime(glue, RTSTUB_ID(GetAotLexicalEnv), {}, true); GateRef result = LowerCallRuntime(glue, RTSTUB_ID(NewAotLexicalEnvDyn), {builder_.TaggedTypeNGC(acc_.GetValueIn(gate, 0)), lexEnv}, true); successControl.emplace_back(builder_.GetState()); @@ -1899,10 +1906,10 @@ void SlowPathLowering::LowerNewLexicalEnvWithNameDyn(GateRef gate, GateRef glue, std::vector failControl; // 2: number of value inputs ASSERT(acc_.GetNumValueIn(gate) == 2); - GateRef lexEnv = LowerCallRuntime(glue, RTSTUB_ID(GetAotLexicalEnv), {jsFunc}, true); + GateRef lexEnv = LowerCallRuntime(glue, RTSTUB_ID(GetAotLexicalEnv), {}, true); auto args = { builder_.TaggedTypeNGC(acc_.GetValueIn(gate, 0)), builder_.TaggedTypeNGC(acc_.GetValueIn(gate, 1)), - lexEnv}; + lexEnv, jsFunc}; GateRef result = LowerCallRuntime(glue, RTSTUB_ID(NewAotLexicalEnvWithNameDyn), args, true); successControl.emplace_back(builder_.GetState()); successControl.emplace_back(builder_.GetDepend()); @@ -1911,14 +1918,11 @@ void SlowPathLowering::LowerNewLexicalEnvWithNameDyn(GateRef gate, GateRef glue, ReplaceHirToSubCfg(gate, result, successControl, failControl, true); } -void SlowPathLowering::LowerPopLexicalEnv(GateRef gate, GateRef glue, GateRef jsFunc) +void SlowPathLowering::LowerPopLexicalEnv(GateRef gate, GateRef glue) { std::vector successControl; std::vector failControl; - GateRef result = LowerCallRuntime(glue, RTSTUB_ID(GetAotLexicalEnv), {jsFunc}, true); - GateRef index = builder_.Int32(LexicalEnv::PARENT_ENV_INDEX); - GateRef parentLexEnv = builder_.GetValueFromTaggedArray(VariableType::JS_ANY(), result, index); - builder_.SetLexicalEnvToFunction(glue, jsFunc, parentLexEnv); + LowerCallRuntime(glue, RTSTUB_ID(PopAotLexicalEnv), {}, true); successControl.emplace_back(builder_.GetState()); successControl.emplace_back(builder_.GetDepend()); failControl.emplace_back(Circuit::NullGate()); @@ -2496,13 +2500,14 @@ void SlowPathLowering::LowerStArraySpread(GateRef gate, GateRef glue) ReplaceHirToCall(gate, newGate); } -void SlowPathLowering::LowerLdLexVarDyn(GateRef gate, GateRef jsFunc) +void SlowPathLowering::LowerLdLexVarDyn(GateRef gate, GateRef glue) { // 2: number of value inputs ASSERT(acc_.GetNumValueIn(gate) == 2); GateRef level = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0)); GateRef slot = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 1)); - DEFVAlUE(currentEnv, (&builder_), VariableType::JS_ANY(), GetCurrentEnv(jsFunc)); + DEFVAlUE(currentEnv, (&builder_), VariableType::JS_ANY(), + LowerCallRuntime(glue, RTSTUB_ID(GetAotLexicalEnv), {}, true)); DEFVAlUE(i, (&builder_), VariableType::INT32(), builder_.Int32(0)); std::vector successControl; std::vector exceptionControl; @@ -2528,14 +2533,15 @@ void SlowPathLowering::LowerLdLexVarDyn(GateRef gate, GateRef jsFunc) ReplaceHirToSubCfg(gate, result, successControl, exceptionControl, true); } -void SlowPathLowering::LowerStLexVarDyn(GateRef gate, GateRef glue, GateRef jsFunc) +void SlowPathLowering::LowerStLexVarDyn(GateRef gate, GateRef glue) { // 3: number of value inputs ASSERT(acc_.GetNumValueIn(gate) == 3); GateRef level = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0)); GateRef slot = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 1)); GateRef value = acc_.GetValueIn(gate, 2); - DEFVAlUE(currentEnv, (&builder_), VariableType::JS_ANY(), GetCurrentEnv(jsFunc)); + DEFVAlUE(currentEnv, (&builder_), VariableType::JS_ANY(), + LowerCallRuntime(glue, RTSTUB_ID(GetAotLexicalEnv), {}, true)); DEFVAlUE(i, (&builder_), VariableType::INT32(), builder_.Int32(0)); std::vector successControl; std::vector exceptionControl; @@ -2986,59 +2992,20 @@ void SlowPathLowering::LowerGetUnmappedArgs(GateRef gate, GateRef glue) { GateRef actualArgc = bcBuilder_->GetCommonArgByIndex(CommonArgIdx::ACTUAL_ARGC); GateRef taggedArgc = builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(actualArgc)); - std::vector vec; - const size_t fixedArgs = 3; - GateRef argList = Circuit::GetCircuitRoot(OpCode(OpCode::ARG_LIST)); - auto uses = acc_.ConstUses(argList); - for (auto useIt = uses.begin(); useIt != uses.end(); useIt++) { - vec.emplace_back(*useIt); - } - std::vector args({vec.rbegin() + CommonArgIdx::NUM_OF_ARGS, vec.rend()}); - size_t argsNum = args.size() + fixedArgs; - args.insert(args.begin(), taggedArgc); - DEFVAlUE(unmappedObj, (&builder_), VariableType::JS_ANY(), builder_.Undefined()); - Label normalArgs(&builder_); - Label restArgs(&builder_); - Label successExit(&builder_); - Label exceptionExit(&builder_); - GateRef result; - std::vector successControl; - std::vector failControl; - builder_.Branch(builder_.Int32GreaterThan(actualArgc, builder_.Int32(argsNum)), &restArgs, &normalArgs); - builder_.Bind(&restArgs); - { - unmappedObj = LowerCallRuntime(glue, RTSTUB_ID(GetAotUnmapedArgsWithRestArgs), {taggedArgc}, true); - builder_.Branch(builder_.IsSpecial(*unmappedObj, JSTaggedValue::VALUE_EXCEPTION), - &exceptionExit, &successExit); - } - builder_.Bind(&normalArgs); - { - unmappedObj = LowerCallRuntime(glue, RTSTUB_ID(GetAotUnmapedArgs), args, true); - builder_.Branch(builder_.IsSpecial(*unmappedObj, JSTaggedValue::VALUE_EXCEPTION), - &exceptionExit, &successExit); - } - builder_.Bind(&successExit); - { - result = *unmappedObj; - successControl.emplace_back(builder_.GetState()); - successControl.emplace_back(builder_.GetDepend()); - } - builder_.Bind(&exceptionExit); - { - failControl.emplace_back(builder_.GetState()); - failControl.emplace_back(builder_.GetDepend()); - } - ReplaceHirToSubCfg(gate, result, successControl, failControl); + const int id = RTSTUB_ID(GetAotUnmapedArgs); + GateRef newGate = LowerCallRuntime(glue, id, {taggedArgc}); + ReplaceHirToCall(gate, newGate); } void SlowPathLowering::LowerCopyRestArgs(GateRef gate, GateRef glue) { GateRef actualArgc = bcBuilder_->GetCommonArgByIndex(CommonArgIdx::ACTUAL_ARGC); - GateRef restIdx = acc_.GetValueIn(gate, 0); GateRef taggedArgc = builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(actualArgc)); - GateRef taggedRestId = builder_.TaggedTypeNGC(restIdx); - int id = RTSTUB_ID(CopyAotRestArgs); - GateRef newGate = LowerCallRuntime(glue, id, {taggedArgc, taggedRestId}); + GateRef restIdx = acc_.GetValueIn(gate, 0); + GateRef taggedRestIdx = builder_.TaggedTypeNGC(restIdx); + + const int id = RTSTUB_ID(CopyAotRestArgs); + GateRef newGate = LowerCallRuntime(glue, id, {taggedArgc, taggedRestIdx}); ReplaceHirToCall(gate, newGate); } } // namespace panda::ecmascript diff --git a/ecmascript/compiler/slowpath_lowering.h b/ecmascript/compiler/slowpath_lowering.h index 1800aa71..b458a066 100644 --- a/ecmascript/compiler/slowpath_lowering.h +++ b/ecmascript/compiler/slowpath_lowering.h @@ -133,8 +133,6 @@ private: // environment must be initialized GateRef GetConstPool(GateRef jsFunc); // environment must be initialized - GateRef GetCurrentEnv(GateRef jsFunc); - // environment must be initialized GateRef GetObjectFromConstPool(GateRef jsFunc, GateRef index); // environment must be initialized GateRef GetHomeObjectFromJSFunction(GateRef jsFunc); @@ -147,7 +145,7 @@ private: void LowerAsyncFunctionResolve(GateRef gate, GateRef glue); void LowerAsyncFunctionReject(GateRef gate, GateRef glue); void LowerLoadStr(GateRef gate, GateRef glue); - void LowerLexicalEnv(GateRef gate, GateRef glue, GateRef jsFunc); + void LowerLexicalEnv(GateRef gate, GateRef glue); void LowerStGlobalVar(GateRef gate, GateRef glue); void LowerTryLdGlobalByName(GateRef gate, GateRef glue); void LowerGetIterator(GateRef gate, GateRef glue); @@ -226,9 +224,9 @@ private: void LowerDefineFuncDyn(GateRef gate, GateRef glue, GateRef jsFunc); void LowerDefineGeneratorFunc(GateRef gate, GateRef glue, GateRef jsFunc); void LowerDefineAsyncFunc(GateRef gate, GateRef glue, GateRef jsFunc); - void LowerNewLexicalEnvDyn(GateRef gate, GateRef glue, GateRef jsFunc); + void LowerNewLexicalEnvDyn(GateRef gate, GateRef glue); void LowerNewLexicalEnvWithNameDyn(GateRef gate, GateRef glue, GateRef jsFunc); - void LowerPopLexicalEnv(GateRef gate, GateRef glue, GateRef jsFunc); + void LowerPopLexicalEnv(GateRef gate, GateRef glue); void LowerLdSuperByValue(GateRef gate, GateRef glue, GateRef jsFunc); void LowerStSuperByValue(GateRef gate, GateRef glue, GateRef jsFunc); void LowerTryStGlobalByName(GateRef gate, GateRef glue); @@ -249,8 +247,8 @@ private: void LowerStObjByValue(GateRef gate, GateRef glue); void LowerCreateGeneratorObj(GateRef gate, GateRef glue); void LowerStArraySpread(GateRef gate, GateRef glue); - void LowerLdLexVarDyn(GateRef gate, GateRef jsFunc); - void LowerStLexVarDyn(GateRef gate, GateRef glue, GateRef jsFunc); + void LowerLdLexVarDyn(GateRef gate, GateRef glue); + void LowerStLexVarDyn(GateRef gate, GateRef glue); void LowerCreateObjectHavingMethod(GateRef gate, GateRef glue, GateRef jsFunc); void LowerLdHomeObject(GateRef gate, GateRef jsFunc); void LowerDefineClassWithBuffer(GateRef gate, GateRef glue, GateRef jsFunc); diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index fad2c24b..a7386b49 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -4018,26 +4018,27 @@ GateRef Stub::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNumArgs, { GateRef newTarget = Undefined(); GateRef thisValue = Undefined(); + GateRef lexEnv = builder_.GetLexicalEnv(func); GateRef realNumArgs = Int32Add(actualNumArgs, Int32(NUM_MANDATORY_JSFUNC_ARGS)); switch (mode) { case JSCallMode::CALL_ARG0: result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), - { glue, realNumArgs, func, newTarget, thisValue}); + { glue, lexEnv, realNumArgs, func, newTarget, thisValue}); Jump(&exit); break; case JSCallMode::CALL_ARG1: result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), - { glue, realNumArgs, func, newTarget, thisValue, data[0] }); + { glue, lexEnv, realNumArgs, func, newTarget, thisValue, data[0] }); Jump(&exit); break; case JSCallMode::CALL_ARG2: result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), - { glue, realNumArgs, func, newTarget, thisValue, data[0], data[1] }); + { glue, lexEnv, realNumArgs, func, newTarget, thisValue, data[0], data[1] }); Jump(&exit); break; case JSCallMode::CALL_ARG3: result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), - { glue, realNumArgs, func, newTarget, thisValue, + { glue, lexEnv, realNumArgs, func, newTarget, thisValue, data[0], data[1], data[2] }); // 2: args2 Jump(&exit); break; @@ -4056,12 +4057,12 @@ GateRef Stub::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNumArgs, break; case JSCallMode::CALL_GETTER: result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), - { glue, realNumArgs, func, newTarget, data[0]}); + { glue, lexEnv, realNumArgs, func, newTarget, data[0]}); Jump(&exit); break; case JSCallMode::CALL_SETTER: result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), - { glue, realNumArgs, func, newTarget, data[0], data[1]}); + { glue, lexEnv, realNumArgs, func, newTarget, data[0], data[1]}); Jump(&exit); break; default: diff --git a/ecmascript/compiler/test_stubs.cpp b/ecmascript/compiler/test_stubs.cpp index 7bd4d436..b74a8381 100644 --- a/ecmascript/compiler/test_stubs.cpp +++ b/ecmascript/compiler/test_stubs.cpp @@ -27,18 +27,20 @@ void FooAOTStub::GenerateCircuit(const CompilationConfig *cfg) { Stub::GenerateCircuit(cfg); GateRef glue = PtrArgument(0); - GateRef argc = Int32Argument(1); - GateRef calltarget = TaggedArgument(2); - GateRef newtarget = TaggedArgument(3); - GateRef thisObj = TaggedArgument(4); - GateRef a = TaggedArgument(5); - GateRef b = TaggedArgument(6); - GateRef bcOffset = Int32Argument(1); + GateRef env = TaggedArgument(1); + GateRef argc = Int32Argument(2); + GateRef calltarget = TaggedArgument(3); + GateRef newtarget = TaggedArgument(4); + GateRef thisObj = TaggedArgument(5); + GateRef a = TaggedArgument(6); + GateRef b = TaggedArgument(7); + GateRef bcOffset = Int32(1); (void)calltarget; GateRef barIndex = IntToTaggedNGC(Int32(CommonStubCSigns::BarAOT)); GateRef numArgs = IntToTaggedNGC(Int32(2)); GateRef barfunc = CallRuntime(glue, RTSTUB_ID(DefineAotFunc), {barIndex, numArgs}); - GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, argc, barfunc, newtarget, thisObj, a, b, bcOffset}); + GateRef result = + CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, argc, barfunc, newtarget, thisObj, a, b, bcOffset}); Return(result); } @@ -46,12 +48,13 @@ void BarAOTStub::GenerateCircuit(const CompilationConfig *cfg) { Stub::GenerateCircuit(cfg); GateRef glue = PtrArgument(0); - [[maybe_unused]] GateRef argc = Int32Argument(1); - [[maybe_unused]] GateRef calltarget = TaggedArgument(2); - [[maybe_unused]] GateRef newtarget = TaggedArgument(3); - [[maybe_unused]] GateRef thisObj = TaggedArgument(4); - GateRef a = TaggedArgument(5); - GateRef b = TaggedArgument(6); + [[maybe_unused]] GateRef env = TaggedArgument(1); + [[maybe_unused]] GateRef argc = Int32Argument(2); + [[maybe_unused]] GateRef calltarget = TaggedArgument(3); + [[maybe_unused]] GateRef newtarget = TaggedArgument(4); + [[maybe_unused]] GateRef thisObj = TaggedArgument(5); + GateRef a = TaggedArgument(6); + GateRef b = TaggedArgument(7); GateRef result = CallRuntime(glue, RTSTUB_ID(Add2Dyn), {a, b}); Return(result); } @@ -60,18 +63,20 @@ void Foo1AOTStub::GenerateCircuit(const CompilationConfig *cfg) { Stub::GenerateCircuit(cfg); GateRef glue = PtrArgument(0); - GateRef argc = Int32Argument(1); - GateRef calltarget = TaggedArgument(2); - GateRef newtarget = TaggedArgument(3); - GateRef thisObj = TaggedArgument(4); - GateRef a = TaggedArgument(5); - GateRef b = TaggedArgument(6); - GateRef bcOffset = Int32Argument(1); + GateRef env = TaggedArgument(1); + GateRef argc = Int32Argument(2); + GateRef calltarget = TaggedArgument(3); + GateRef newtarget = TaggedArgument(4); + GateRef thisObj = TaggedArgument(5); + GateRef a = TaggedArgument(6); + GateRef b = TaggedArgument(7); + GateRef bcOffset = Int32(1); (void)calltarget; GateRef barIndex = IntToTaggedTypeNGC(Int32(CommonStubCSigns::Bar1AOT)); GateRef numArgs = IntToTaggedTypeNGC(Int32(3)); GateRef barfunc = CallRuntime(glue, RTSTUB_ID(DefineAotFunc), {barIndex, numArgs}); - GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, argc, barfunc, newtarget, thisObj, a, b, bcOffset}); + GateRef result = + CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, argc, barfunc, newtarget, thisObj, a, b, bcOffset}); Return(result); } @@ -79,17 +84,19 @@ void Bar1AOTStub::GenerateCircuit(const CompilationConfig *cfg) { Stub::GenerateCircuit(cfg); GateRef glue = PtrArgument(0); - GateRef argc = Int32Argument(1); - GateRef calltarget = TaggedArgument(2); - GateRef newtarget = TaggedArgument(3); - GateRef thisObj = TaggedArgument(4); + GateRef env = TaggedArgument(1); + GateRef argc = Int32Argument(2); + GateRef calltarget = TaggedArgument(3); + GateRef newtarget = TaggedArgument(4); + GateRef thisObj = TaggedArgument(5); + (void)env; (void)argc; (void)calltarget; (void)newtarget; (void)thisObj; - GateRef a = TaggedArgument(5); - GateRef b = TaggedArgument(6); - GateRef c = TaggedArgument(7); + GateRef a = TaggedArgument(6); + GateRef b = TaggedArgument(7); + GateRef c = TaggedArgument(8); GateRef result = CallRuntime(glue, RTSTUB_ID(Add2Dyn), {a, b}); GateRef result2 = CallRuntime(glue, RTSTUB_ID(Add2Dyn), {result, c}); Return(result2); @@ -99,19 +106,20 @@ void Foo2AOTStub::GenerateCircuit(const CompilationConfig *cfg) { Stub::GenerateCircuit(cfg); GateRef glue = PtrArgument(0); - GateRef argc = Int32Argument(1); - GateRef calltarget = TaggedArgument(2); - GateRef newtarget = TaggedArgument(3); - GateRef thisObj = TaggedArgument(4); - GateRef a = TaggedArgument(5); - GateRef b = TaggedArgument(6); - GateRef bcOffset = Int32Argument(1); + GateRef env = TaggedArgument(1); + GateRef argc = Int32Argument(2); + GateRef calltarget = TaggedArgument(3); + GateRef newtarget = TaggedArgument(4); + GateRef thisObj = TaggedArgument(5); + GateRef a = TaggedArgument(6); + GateRef b = TaggedArgument(7); + GateRef bcOffset = Int32(1); (void)calltarget; GateRef actualArgC = Int32Add(argc, Int32(1)); GateRef barIndex = IntToTaggedTypeNGC(Int32(CommonStubCSigns::BarAOT)); GateRef numArgs = IntToTaggedTypeNGC(Int32(2)); GateRef barfunc = CallRuntime(glue, RTSTUB_ID(DefineAotFunc), {barIndex, numArgs}); - GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, actualArgC, barfunc, newtarget, thisObj, + GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, actualArgC, barfunc, newtarget, thisObj, a, b, Undefined(), bcOffset}); Return(result); } @@ -120,17 +128,18 @@ void FooNativeAOTStub::GenerateCircuit(const CompilationConfig *cfg) { Stub::GenerateCircuit(cfg); GateRef glue = PtrArgument(0); - GateRef argc = Int32Argument(1); - GateRef calltarget = TaggedArgument(2); - GateRef newtarget = TaggedArgument(3); - GateRef thisObj = TaggedArgument(4); - GateRef a = TaggedArgument(5); - GateRef b = TaggedArgument(6); - GateRef bcOffset = Int32Argument(1); + GateRef env = TaggedArgument(1); + GateRef argc = Int32Argument(2); + GateRef calltarget = TaggedArgument(3); + GateRef newtarget = TaggedArgument(4); + GateRef thisObj = TaggedArgument(5); + GateRef a = TaggedArgument(6); + GateRef b = TaggedArgument(7); + GateRef bcOffset = Int32(1); (void)calltarget; GateRef actualArgC = Int32Add(argc, Int32(1)); GateRef printfunc = CallRuntime(glue, RTSTUB_ID(GetPrintFunc), {}); - GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, actualArgC, printfunc, newtarget, thisObj, + GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, actualArgC, printfunc, newtarget, thisObj, a, b, Undefined(), bcOffset}); Return(result); } @@ -139,22 +148,23 @@ void FooBoundAOTStub::GenerateCircuit(const CompilationConfig *cfg) { Stub::GenerateCircuit(cfg); GateRef glue = PtrArgument(0); - GateRef argc = Int32Argument(1); - GateRef calltarget = TaggedArgument(2); - GateRef newtarget = TaggedArgument(3); - GateRef thisObj = TaggedArgument(4); - GateRef a = TaggedArgument(5); - GateRef b = TaggedArgument(6); + GateRef env = TaggedArgument(1); + GateRef argc = Int32Argument(2); + GateRef calltarget = TaggedArgument(3); + GateRef newtarget = TaggedArgument(4); + GateRef thisObj = TaggedArgument(5); + GateRef a = TaggedArgument(6); + GateRef b = TaggedArgument(7); GateRef bindArguments = IntToTaggedTypeNGC(Int32(37)); - GateRef bcOffset = Int32Argument(1); + GateRef bcOffset = Int32(1); (void)calltarget; GateRef numArgs = IntToTaggedTypeNGC(Int32(2)); GateRef barIndex = IntToTaggedTypeNGC(Int32(CommonStubCSigns::BarAOT)); GateRef barfunc = CallRuntime(glue, RTSTUB_ID(DefineAotFunc), {barIndex, numArgs}); GateRef bindfunc = CallRuntime(glue, RTSTUB_ID(GetBindFunc), {barfunc}); - GateRef newjsfunc = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, Int32(5), bindfunc, newtarget, barfunc, + GateRef newjsfunc = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, Int32(5), bindfunc, newtarget, barfunc, Int64(0x02), bindArguments, bcOffset}); - GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, argc, newjsfunc, newtarget, thisObj, + GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, argc, newjsfunc, newtarget, thisObj, a, b, bcOffset}); Return(result); } @@ -163,13 +173,14 @@ void FooProxyAOTStub::GenerateCircuit(const CompilationConfig *cfg) { Stub::GenerateCircuit(cfg); GateRef glue = PtrArgument(0); - GateRef argc = Int32Argument(1); - [[maybe_unused]] GateRef calltarget = TaggedArgument(2); - GateRef newtarget = TaggedArgument(3); - GateRef thisObj = TaggedArgument(4); - GateRef a = TaggedArgument(5); - GateRef b = TaggedArgument(6); - GateRef bcOffset = Int32Argument(1); + GateRef env = TaggedArgument(1); + GateRef argc = Int32Argument(2); + [[maybe_unused]] GateRef calltarget = TaggedArgument(3); + GateRef newtarget = TaggedArgument(4); + GateRef thisObj = TaggedArgument(5); + GateRef a = TaggedArgument(6); + GateRef b = TaggedArgument(7); + GateRef bcOffset = Int32(1); GateRef barIndex = IntToTaggedTypeNGC(Int32(CommonStubCSigns::BarAOT)); GateRef numArgs = IntToTaggedTypeNGC(Int32(2)); @@ -177,7 +188,7 @@ void FooProxyAOTStub::GenerateCircuit(const CompilationConfig *cfg) GateRef proxyfunc = CallRuntime(glue, RTSTUB_ID(DefineProxyFunc), {barfunc}); GateRef result = - CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, argc, proxyfunc, newtarget, thisObj, a, b, bcOffset}); + CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, argc, proxyfunc, newtarget, thisObj, a, b, bcOffset}); Return(result); } @@ -185,13 +196,14 @@ void FooProxy2AOTStub::GenerateCircuit(const CompilationConfig *cfg) { Stub::GenerateCircuit(cfg); GateRef glue = PtrArgument(0); - GateRef argc = Int32Argument(1); - [[maybe_unused]] GateRef calltarget = TaggedArgument(2); - GateRef newtarget = TaggedArgument(3); - GateRef thisObj = TaggedArgument(4); - GateRef a = TaggedArgument(5); - GateRef b = TaggedArgument(6); - GateRef bcOffset = Int32Argument(1); + GateRef env = TaggedArgument(1); + GateRef argc = Int32Argument(2); + [[maybe_unused]] GateRef calltarget = TaggedArgument(3); + GateRef newtarget = TaggedArgument(4); + GateRef thisObj = TaggedArgument(5); + GateRef a = TaggedArgument(6); + GateRef b = TaggedArgument(7); + GateRef bcOffset = Int32(1); GateRef barIndex = IntToTaggedTypeNGC(Int32(CommonStubCSigns::Bar2AOT)); GateRef numArgs = IntToTaggedTypeNGC(Int32(2)); @@ -200,7 +212,7 @@ void FooProxy2AOTStub::GenerateCircuit(const CompilationConfig *cfg) GateRef proxyfunc = CallRuntime(glue, RTSTUB_ID(DefineProxyFunc2), {barfunc, proxyHandler}); GateRef result = - CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, argc, proxyfunc, newtarget, thisObj, a, b, bcOffset}); + CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, argc, proxyfunc, newtarget, thisObj, a, b, bcOffset}); Return(result); } @@ -208,10 +220,11 @@ void Bar2AOTStub::GenerateCircuit(const CompilationConfig *cfg) { Stub::GenerateCircuit(cfg); [[maybe_unused]] GateRef glue = PtrArgument(0); - [[maybe_unused]] GateRef argc = Int32Argument(1); - [[maybe_unused]] GateRef calltarget = TaggedArgument(2); - [[maybe_unused]] GateRef newtarget = TaggedArgument(3); - [[maybe_unused]] GateRef thisObj = TaggedArgument(4); + [[maybe_unused]] GateRef env = TaggedArgument(1); + [[maybe_unused]] GateRef argc = Int32Argument(2); + [[maybe_unused]] GateRef calltarget = TaggedArgument(3); + [[maybe_unused]] GateRef newtarget = TaggedArgument(4); + [[maybe_unused]] GateRef thisObj = TaggedArgument(5); CallRuntime(glue, RTSTUB_ID(DumpTaggedType), {thisObj}); Return(thisObj); } diff --git a/ecmascript/compiler/test_stubs.h b/ecmascript/compiler/test_stubs.h index 3281136f..8415378f 100644 --- a/ecmascript/compiler/test_stubs.h +++ b/ecmascript/compiler/test_stubs.h @@ -39,8 +39,8 @@ namespace panda::ecmascript::kungfu { class FooAOTStub : public Stub { public: - // 7 : 7 means argument counts - explicit FooAOTStub(Circuit *circuit) : Stub("FooAOT", 7, circuit) + // 8 : 8 means argument counts + explicit FooAOTStub(Circuit *circuit) : Stub("FooAOT", 8, circuit) { } ~FooAOTStub() = default; @@ -51,8 +51,8 @@ public: class BarAOTStub : public Stub { public: - // 7 : 7 means argument counts - explicit BarAOTStub(Circuit *circuit) : Stub("BarAOT", 7, circuit) + // 8 : 8 means argument counts + explicit BarAOTStub(Circuit *circuit) : Stub("BarAOT", 8, circuit) { } ~BarAOTStub() = default; @@ -63,8 +63,8 @@ public: class Foo1AOTStub : public Stub { public: - // 7 : 7 means argument counts - explicit Foo1AOTStub(Circuit *circuit) : Stub("Foo1AOT", 7, circuit) + // 8 : 8 means argument counts + explicit Foo1AOTStub(Circuit *circuit) : Stub("Foo1AOT", 8, circuit) { } ~Foo1AOTStub() = default; @@ -75,8 +75,8 @@ public: class Foo2AOTStub : public Stub { public: - // 7 : 7 means argument counts - explicit Foo2AOTStub(Circuit *circuit) : Stub("Foo2AOT", 7, circuit) + // 8 : 8 means argument counts + explicit Foo2AOTStub(Circuit *circuit) : Stub("Foo2AOT", 8, circuit) { } ~Foo2AOTStub() = default; @@ -87,8 +87,8 @@ public: class FooNativeAOTStub : public Stub { public: - // 7 : 7 means argument counts - explicit FooNativeAOTStub(Circuit *circuit) : Stub("FooNativeAOT", 7, circuit) + // 8 : 8 means argument counts + explicit FooNativeAOTStub(Circuit *circuit) : Stub("FooNativeAOT", 8, circuit) { } ~FooNativeAOTStub() = default; @@ -99,8 +99,8 @@ public: class FooBoundAOTStub : public Stub { public: - // 7 : 7 means argument counts - explicit FooBoundAOTStub(Circuit *circuit) : Stub("FooBoundAOT", 7, circuit) + // 8 : 8 means argument counts + explicit FooBoundAOTStub(Circuit *circuit) : Stub("FooBoundAOT", 8, circuit) { } ~FooBoundAOTStub() = default; @@ -111,8 +111,8 @@ public: class Bar1AOTStub : public Stub { public: - // 8 : 8 means argument counts - explicit Bar1AOTStub(Circuit *circuit) : Stub("Bar1AOT", 8, circuit) + // 9 : 9 means argument counts + explicit Bar1AOTStub(Circuit *circuit) : Stub("Bar1AOT", 9, circuit) { } ~Bar1AOTStub() = default; @@ -123,8 +123,8 @@ public: class FooProxyAOTStub : public Stub { public: - // 7 : 7 means argument counts - explicit FooProxyAOTStub(Circuit *circuit) : Stub("FooProxyAOT", 7, circuit) + // 8 : 8 means argument counts + explicit FooProxyAOTStub(Circuit *circuit) : Stub("FooProxyAOT", 8, circuit) { } ~FooProxyAOTStub() = default; @@ -135,8 +135,8 @@ public: class FooProxy2AOTStub : public Stub { public: - // 7 : 7 means argument counts - explicit FooProxy2AOTStub(Circuit *circuit) : Stub("FooProxy2AOTStub", 7, circuit) + // 8 : 8 means argument counts + explicit FooProxy2AOTStub(Circuit *circuit) : Stub("FooProxy2AOTStub", 8, circuit) { } ~FooProxy2AOTStub() = default; @@ -147,8 +147,8 @@ public: class Bar2AOTStub : public Stub { public: - // 5 : 5 means argument counts - explicit Bar2AOTStub(Circuit *circuit) : Stub("Bar2AOT", 5, circuit) + // 6 : 6 means argument counts + explicit Bar2AOTStub(Circuit *circuit) : Stub("Bar2AOT", 6, circuit) { } ~Bar2AOTStub() = default; diff --git a/ecmascript/compiler/test_stubs_signature.cpp b/ecmascript/compiler/test_stubs_signature.cpp index 182136a6..e39d5a24 100644 --- a/ecmascript/compiler/test_stubs_signature.cpp +++ b/ecmascript/compiler/test_stubs_signature.cpp @@ -19,11 +19,12 @@ namespace panda::ecmascript::kungfu { DEF_CALL_SIGNATURE(FooAOT) { // 7 : 7 input parameters - CallSignature fooAot("FooAOT", 0, 7, + CallSignature fooAot("FooAOT", 0, 8, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY()); *callSign = fooAot; - std::array params = { // 7 : 7 input parameters + std::array params = { // 8 : 8 input parameters VariableType::NATIVE_POINTER(), + VariableType::JS_ANY(), // lexenv VariableType::INT32(), VariableType::JS_ANY(), // calltarget VariableType::JS_ANY(), // newTarget @@ -38,11 +39,12 @@ DEF_CALL_SIGNATURE(FooAOT) DEF_CALL_SIGNATURE(Foo1AOT) { // 7 : 7 input parameters - CallSignature foo1Aot("Foo1AOT", 0, 7, + CallSignature foo1Aot("Foo1AOT", 0, 8, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY()); *callSign = foo1Aot; - std::array params = { // 7 : 7 input parameters + std::array params = { // 8 : 8 input parameters VariableType::NATIVE_POINTER(), + VariableType::JS_ANY(), // lexenv VariableType::INT32(), VariableType::JS_ANY(), // calltarget VariableType::JS_ANY(), // newTarget @@ -57,11 +59,12 @@ DEF_CALL_SIGNATURE(Foo1AOT) DEF_CALL_SIGNATURE(Foo2AOT) { // 7 : 7 input parameters - CallSignature foo2Aot("Foo2AOT", 0, 7, + CallSignature foo2Aot("Foo2AOT", 0, 8, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY()); *callSign = foo2Aot; - std::array params = { // 7 : 7 input parameters + std::array params = { // 8 : 8 input parameters VariableType::NATIVE_POINTER(), + VariableType::JS_ANY(), // lexenv VariableType::INT32(), VariableType::JS_ANY(), // calltarget VariableType::JS_ANY(), // newTarget @@ -76,11 +79,12 @@ DEF_CALL_SIGNATURE(Foo2AOT) DEF_CALL_SIGNATURE(FooNativeAOT) { // 7 : 7 input parameters - CallSignature foo2Aot("FooNativeAOT", 0, 7, + CallSignature foo2Aot("FooNativeAOT", 0, 8, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY()); *callSign = foo2Aot; - std::array params = { // 7 : 7 input parameters + std::array params = { // 8 : 8 input parameters VariableType::NATIVE_POINTER(), + VariableType::JS_ANY(), // lexenv VariableType::INT32(), VariableType::JS_ANY(), // calltarget VariableType::JS_ANY(), // newTarget @@ -95,11 +99,12 @@ DEF_CALL_SIGNATURE(FooNativeAOT) DEF_CALL_SIGNATURE(FooBoundAOT) { // 7 : 7 input parameters - CallSignature foo2Aot("FooBoundAOT", 0, 7, + CallSignature foo2Aot("FooBoundAOT", 0, 8, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY()); *callSign = foo2Aot; - std::array params = { // 7 : 7 input parameters + std::array params = { // 8 : 8 input parameters VariableType::NATIVE_POINTER(), + VariableType::JS_ANY(), // lexenv VariableType::INT32(), VariableType::JS_ANY(), // calltarget VariableType::JS_ANY(), // newTarget @@ -114,11 +119,12 @@ DEF_CALL_SIGNATURE(FooBoundAOT) DEF_CALL_SIGNATURE(Bar1AOT) { // 8 : 8 input parameters - CallSignature barAot("Bar1AOT", 0, 8, + CallSignature barAot("Bar1AOT", 0, 9, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY()); *callSign = barAot; - std::array params = { // 8 : 8 input parameters + std::array params = { // 9 : 9 input parameters VariableType::NATIVE_POINTER(), + VariableType::JS_ANY(), // lexenv VariableType::INT32(), VariableType::JS_ANY(), // calltarget VariableType::JS_ANY(), // newTarget @@ -134,11 +140,12 @@ DEF_CALL_SIGNATURE(Bar1AOT) DEF_CALL_SIGNATURE(BarAOT) { // 7 : 7 input parameters - CallSignature barAot("BarAOT", 0, 7, + CallSignature barAot("BarAOT", 0, 8, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY()); *callSign = barAot; - std::array params = { // 7 : 7 input parameters + std::array params = { // 8 : 8 input parameters VariableType::NATIVE_POINTER(), + VariableType::JS_ANY(), // lexEnv VariableType::INT32(), VariableType::JS_ANY(), // calltarget VariableType::JS_ANY(), // newTarget @@ -153,11 +160,12 @@ DEF_CALL_SIGNATURE(BarAOT) DEF_CALL_SIGNATURE(FooProxyAOT) { // 8 : 8 input parameters - CallSignature fooProxyAot("FooProxyAOT", 0, 7, + CallSignature fooProxyAot("FooProxyAOT", 0, 8, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY()); *callSign = fooProxyAot; - std::array params = { // 7 : 7 input parameters + std::array params = { // 8 : 8 input parameters VariableType::NATIVE_POINTER(), + VariableType::JS_ANY(), // lexEnv VariableType::INT32(), VariableType::JS_ANY(), // calltarget VariableType::JS_ANY(), // newTarget @@ -172,11 +180,12 @@ DEF_CALL_SIGNATURE(FooProxyAOT) DEF_CALL_SIGNATURE(FooProxy2AOT) { // 8 : 8 input parameters - CallSignature FooProxy2AOT("FooProxy2AOT", 0, 7, + CallSignature FooProxy2AOT("FooProxy2AOT", 0, 8, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY()); *callSign = FooProxy2AOT; - std::array params = { // 7 : 7 input parameters + std::array params = { // 8 : 8 input parameters VariableType::NATIVE_POINTER(), + VariableType::JS_ANY(), // lexEnv VariableType::INT32(), VariableType::JS_ANY(), // calltarget VariableType::JS_ANY(), // newTarget @@ -191,11 +200,12 @@ DEF_CALL_SIGNATURE(FooProxy2AOT) DEF_CALL_SIGNATURE(Bar2AOT) { // 7 : 7 input parameters - CallSignature bar2Aot("Bar2AOT", 0, 5, + CallSignature bar2Aot("Bar2AOT", 0, 6, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY()); *callSign = bar2Aot; - std::array params = { // 5 : 5 input parameters + std::array params = { // 6 : 6 input parameters VariableType::NATIVE_POINTER(), + VariableType::JS_ANY(), // lexenv VariableType::INT32(), VariableType::JS_ANY(), // calltarget VariableType::JS_ANY(), // newTarget diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index c9952e39..864c9070 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -1270,12 +1270,13 @@ HWTEST_F_L0(StubTest, JSCallTest2) auto glue = thread->GetGlueAddr(); int x = 1; int y = 2; - JSTaggedType argV[5] = { + JSTaggedType argV[6] = { foo1target.GetRawData(), JSTaggedValue::Undefined().GetRawData(), JSTaggedValue::Undefined().GetRawData(), JSTaggedValue(x).GetRawData(), JSTaggedValue(y).GetRawData(), + JSTaggedValue::Undefined().GetRawData(), }; auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry); @@ -1291,12 +1292,13 @@ HWTEST_F_L0(StubTest, JSCallNativeTest) auto glue = thread->GetGlueAddr(); int x = 1; int y = 2; - JSTaggedType argV[5] = { + JSTaggedType argV[6] = { footarget.GetRawData(), JSTaggedValue::Undefined().GetRawData(), JSTaggedValue::Undefined().GetRawData(), JSTaggedValue(x).GetRawData(), JSTaggedValue(y).GetRawData(), + JSTaggedValue::Undefined().GetRawData(), }; auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry); auto result = reinterpret_cast(entry)(glue, @@ -1311,12 +1313,13 @@ HWTEST_F_L0(StubTest, JSCallBoundTest) auto glue = thread->GetGlueAddr(); int x = 1; int y = 2; - JSTaggedType argV[5] = { + JSTaggedType argV[6] = { footarget.GetRawData(), JSTaggedValue::Undefined().GetRawData(), JSTaggedValue::Undefined().GetRawData(), JSTaggedValue(x).GetRawData(), JSTaggedValue(y).GetRawData(), + JSTaggedValue::Undefined().GetRawData(), }; auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry); @@ -1333,19 +1336,20 @@ HWTEST_F_L0(StubTest, JSCallTest3) auto glue = thread->GetGlueAddr(); int x = 1; int y = 2; - JSTaggedType argV[6] = { + JSTaggedType argV[7] = { foo2target.GetRawData(), JSTaggedValue::Undefined().GetRawData(), JSTaggedValue::Undefined().GetRawData(), JSTaggedValue(x).GetRawData(), JSTaggedValue(y).GetRawData(), JSTaggedValue::Undefined().GetRawData(), + JSTaggedValue::Undefined().GetRawData(), }; JSThread::GlueData::GetCOStubEntriesOffset(false); JSThread::GlueData::GetCOStubEntriesOffset(true); auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry); auto result = reinterpret_cast(entry)(glue, - reinterpret_cast(thread->GetCurrentSPFrame()), 5, 5, argV, fooProxyEntry); + reinterpret_cast(thread->GetCurrentSPFrame()), 6, 6, argV, fooProxyEntry); EXPECT_EQ(result, JSTaggedValue(3.0).GetRawData()); } diff --git a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp index 1064d529..b5ec71fe 100644 --- a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp +++ b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp @@ -169,6 +169,7 @@ void AssemblerStubs::JSFunctionEntry(ExtendedAssembler *assembler) Register argVEnd(X9); Register argC(X8, W); Register argValue(X10); + Register env(X11); Label copyArgLoop; // expectedNumArgs <= actualNumArgs @@ -177,6 +178,7 @@ void AssemblerStubs::JSFunctionEntry(ExtendedAssembler *assembler) __ Cbz(argC, &invokeCompiledJSFunction); __ Sub(argVEnd.W(), argC, Immediate(1)); __ Add(argVEnd, argV, Operand(argVEnd.W(), UXTW, 3)); + __ Ldr(env, MemoryOperand(argVEnd, FRAME_SLOT_SIZE)); __ Bind(©ArgLoop); __ Ldr(argValue, MemoryOperand(argVEnd, -FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); @@ -186,14 +188,16 @@ void AssemblerStubs::JSFunctionEntry(ExtendedAssembler *assembler) } __ Bind(&invokeCompiledJSFunction); { + Register env(X11); __ Str(actualNumArgs, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); + __ Str(env, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); __ Blr(codeAddr); } - // pop argV argC + // pop argV // 3 : 3 means argC * 8 __ Add(sp, sp, Operand(tmp, UXTW, 3)); - __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE)); + __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE * 2)); // 2: pop argc and env // pop prevLeaveFrameFp to restore thread->currentFrame_ __ Ldr(prevFp, MemoryOperand(sp, FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); @@ -235,15 +239,17 @@ void AssemblerStubs::OptimizedCallOptimized(ExtendedAssembler *assembler) Register sp(SP); __ SaveFpAndLr(); // Construct frame - Register frameType(X5); + Register frameType(X6); __ Mov(frameType, Immediate(static_cast(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME))); __ Str(frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); + Register env(X5); + __ Str(env, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // callee save Register tmp(X19); __ Str(tmp, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - Register count(X5, W); + Register count(X6, W); Register actualNumArgs(X2, W); Label copyArguments; __ Mov(count, expectedNumArgs); @@ -284,15 +290,16 @@ void AssemblerStubs::OptimizedCallOptimized(ExtendedAssembler *assembler) Register codeAddr(X3); __ Bind(&invokeCompiledJSFunction); __ Str(actualNumArgs, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); + __ Str(env, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); __ Blr(codeAddr); // pop argv // 3 : 3 means count * 8 __ Add(sp, sp, Operand(saveNumArgs, UXTW, 3)); - __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE)); + __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE * 2)); // 2: pop argc and env // callee restore __ Ldr(saveNumArgs, MemoryOperand(sp, FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); // desconstruct frame - __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE)); + __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE * 2)); // 2: skip type and env __ RestoreFpAndLr(); __ Ret(); } @@ -354,7 +361,7 @@ void AssemblerStubs::CallBuiltinTrampoline(ExtendedAssembler *assembler) // construct leave frame and callee save Register frameType(X1); - __ Mov(frameType, Immediate(static_cast(FrameType::LEAVE_FRAME))); + __ Mov(frameType, Immediate(static_cast(FrameType::BUILTIN_CALL_LEAVE_FRAME))); // 2 : 2 means pair __ Stp(nativeFuncAddr, frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); @@ -369,13 +376,11 @@ void AssemblerStubs::CallBuiltinTrampoline(ExtendedAssembler *assembler) __ Sub(thread, glue, glueToThread); // thread __ Str(thread, MemoryOperand(sp, 0)); Register argC(X0); - // 1 : 1 means argC id - __ Ldr(argC, MemoryOperand(fp, GetStackArgOffSetToFp(1))); // argc + __ Ldr(argC, MemoryOperand(fp, GetStackArgOffSetToFp(BuiltinsLeaveFrameArgId::ARGC))); // load argc __ Sub(argC, argC, Immediate(NUM_MANDATORY_JSFUNC_ARGS)); __ Str(argC, MemoryOperand(sp, EcmaRuntimeCallInfo::GetNumArgsOffset())); Register argV(X0); - // 2 : 2 means argV id - __ Add(argV, fp, Immediate(GetStackArgOffSetToFp(2))); // argV + __ Add(argV, fp, Immediate(GetStackArgOffSetToFp(BuiltinsLeaveFrameArgId::ARGV))); // argV __ Str(argV, MemoryOperand(sp, EcmaRuntimeCallInfo::GetStackArgsOffset())); Register callInfo(X0); @@ -425,7 +430,7 @@ void AssemblerStubs::JSCall(ExtendedAssembler *assembler) __ BindAssemblerStub(RTSTUB_ID(JSCall)); Register jsfunc(X1); Register sp(SP); - __ Ldr(jsfunc, MemoryOperand(sp, FRAME_SLOT_SIZE)); + __ Ldr(jsfunc, MemoryOperand(sp, FRAME_SLOT_SIZE * 2)); // 2: skip env and argc JSCallBody(assembler, jsfunc); } @@ -464,14 +469,14 @@ void AssemblerStubs::JSCallBody(ExtendedAssembler *assembler, Register jsfunc) Label callNativeMethod; Label callOptimizedMethod; __ Ldr(method, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET)); - __ Ldr(actualArgC, MemoryOperand(sp, 0)); + __ Ldr(actualArgC, MemoryOperand(sp, FRAME_SLOT_SIZE)); __ Ldr(callField, MemoryOperand(method, JSMethod::GetCallFieldOffset(false))); __ Tbnz(callField, JSMethod::IsNativeBit::START_BIT, &callNativeMethod); __ Tbnz(callField, JSMethod::IsAotCodeBit::START_BIT, &callOptimizedMethod); { Register argV(X5); - // 8 : 8 mean argV = sp + 8 - __ Add(argV, sp, Immediate(8)); + // argV = sp + 16 + __ Add(argV, sp, Immediate(DOUBLE_SLOT_SIZE)); OptimizedCallAsmInterpreter(assembler); } @@ -490,6 +495,7 @@ void AssemblerStubs::JSCallBody(ExtendedAssembler *assembler, Register jsfunc) Register arg2(X2); Register codeAddress(X3); Register argV(X4); + Register env(X5); Label directCallCodeEntry; __ Mov(Register(X5), jsfunc); __ Mov(arg2, actualArgC); @@ -498,9 +504,10 @@ void AssemblerStubs::JSCallBody(ExtendedAssembler *assembler, Register jsfunc) LogicalImmediate::Create(JSMethod::NumArgsBits::Mask() >> JSMethod::NumArgsBits::START_BIT, RegWSize)); __ Add(expectedNumArgs, callField.W(), Immediate(NUM_MANDATORY_JSFUNC_ARGS)); __ Cmp(arg2.W(), expectedNumArgs); - // 8 : 8 mean argV = sp + 8 - __ Add(argV, sp, Immediate(8)); + // argV = sp + 16 + __ Add(argV, sp, Immediate(DOUBLE_SLOT_SIZE)); __ Ldr(codeAddress, MemoryOperand(Register(X5), JSFunctionBase::CODE_ENTRY_OFFSET)); + __ Ldr(env, MemoryOperand(sp, 0)); __ B(Condition::HS, &directCallCodeEntry); __ CallAssemblerStub(RTSTUB_ID(OptimizedCallOptimized), true); __ Bind(&directCallCodeEntry); @@ -528,8 +535,10 @@ void AssemblerStubs::JSCallBody(ExtendedAssembler *assembler, Register jsfunc) __ Mov(frameType, Immediate(static_cast(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME))); __ Str(frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); Register argVEnd(X6); - __ Add(argVEnd, fp, Immediate(GetStackArgOffSetToFp(0))); + __ Add(argVEnd, fp, Immediate(GetStackArgOffSetToFp(1))); __ Ldr(actualArgC, MemoryOperand(argVEnd, 0)); + Register envReg(X11); + __ Ldr(envReg, MemoryOperand(argVEnd, -8)); // -8: get env // callee save Register tmp(X19); __ Str(tmp, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); @@ -589,9 +598,10 @@ void AssemblerStubs::JSCallBody(ExtendedAssembler *assembler, Register jsfunc) __ Ldr(boundTarget, MemoryOperand(jsfunc, JSBoundFunction::BOUND_TARGET_OFFSET)); // 2 : 2 means pair __ Stp(realArgC.X(), boundTarget, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); + __ Str(envReg, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); } __ CallAssemblerStub(RTSTUB_ID(JSCall), false); - __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE)); + __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE * 2)); // 2: skip argc and env // 3 : 3 means 2^3 = 8 __ Add(sp, sp, Operand(realArgC, UXTW, 3)); __ Ldr(tmp, MemoryOperand(sp, FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); @@ -604,8 +614,8 @@ void AssemblerStubs::JSCallBody(ExtendedAssembler *assembler, Register jsfunc) // input: x1(calltarget) // output: glue:x0 argc:x1 calltarget:x2 argv:x3 __ Mov(Register(X2), jsfunc); - __ Ldr(Register(X1), MemoryOperand(sp, 0)); - __ Add(X3, sp, Immediate(FRAME_SLOT_SIZE)); + __ Ldr(Register(X1), MemoryOperand(sp, FRAME_SLOT_SIZE)); // 8: skip env + __ Add(X3, sp, Immediate(FRAME_SLOT_SIZE * 2)); // 2: get argv Register proxyCallInternalId(Register(X9).W()); Register codeAddress(X10); diff --git a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.h b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.h index 1df2b033..5a6d8121 100644 --- a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.h +++ b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.h @@ -24,7 +24,9 @@ namespace panda::ecmascript::aarch64 { using Label = panda::ecmascript::Label; class AssemblerStubs { public: - static const int FRAME_SLOT_SIZE = 8; + static constexpr int FRAME_SLOT_SIZE = 8; + static constexpr int DOUBLE_SLOT_SIZE = 16; + enum BuiltinsLeaveFrameArgId : unsigned {CODE_ADDRESS = 0, ENV, ARGC, ARGV}; static inline int64_t GetStackArgOffSetToFp(unsigned argId) { // +--------------------------+ @@ -32,10 +34,12 @@ public: // +--------------------------+ --- // | argc | ^ // |--------------------------| arguments + // | env | | + // |--------------------------| | // | codeAddress | | // |--------------------------| | // | returnAddr | | - // |--------------------------| Fixed OptimizedLeaveFrame + // |--------------------------| Fixed OptimizedBuiltinLeaveFrame // | callsiteFp | | // |--------------------------| | // | frameType | v diff --git a/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp b/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp index 24d05ac4..37c476f7 100644 --- a/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp +++ b/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp @@ -101,7 +101,7 @@ void AssemblerStubsX64::JSFunctionEntry(ExtendedAssembler *assembler) // 16 bytes align check __ Movl(expectedNumArgsReg, r14); __ Testb(1, r14); - __ Jne(&lAlign16Bytes); + __ Je(&lAlign16Bytes); __ Pushq(0); // push zero to align 16 bytes stack __ Bind(&lAlign16Bytes); @@ -137,13 +137,15 @@ void AssemblerStubsX64::JSFunctionEntry(ExtendedAssembler *assembler) __ Jne(&lCopyLoop); __ Pushq(r14); + __ Movq(Operand(argvReg, r14, Scale::Times8, 0), actualNumArgsReg); + __ Push(actualNumArgsReg); // env __ Movq(glueReg, rax); // mov glue to rax __ Callq(codeAddrReg); // then call jsFunction __ Leaq(Operand(r14, Scale::Times8, 0), actualNumArgsReg); // Note: fixed for 3 extra arguments __ Addq(actualNumArgsReg, rsp); - __ Addq(8, rsp); // 8: skip r14 + __ Addq(16, rsp); // 16: skip r14 and env __ Testb(1, r14); // stack 16bytes align check - __ Jne(&lPopFrame); + __ Je(&lPopFrame); __ Addq(8, rsp); // 8: align byte } @@ -159,13 +161,14 @@ void AssemblerStubsX64::JSFunctionEntry(ExtendedAssembler *assembler) } } -// uint64_t OptimizedCallOptimized(uintptr_t glue, uintptr_t codeAddr, uint32_t actualNumArgs, -// uint32_t expectedNumArgs, uintptr_t argv) +// uint64_t OptimizedCallOptimized(uintptr_t glue, uint32_t expectedNumArgs, +// uint32_t actualNumArgs, uintptr_t codeAddr, uintptr_t argv, uintptr_t lexEnv) // Input: %rdi - glue // %rsi - codeAddr // %rdx - actualNumArgs // %rcx - expectedNumArgs // %r8 - argv +// %r9 - lexEnv // sp[0 * 8] - argc // sp[1 * 8] - argv[0] @@ -185,6 +188,7 @@ void AssemblerStubsX64::OptimizedCallOptimized(ExtendedAssembler *assembler) Register actualNumArgsReg = rdx; Register codeAddrReg = rsi; Register argvReg = r8; + Register envReg = r9; Label lAlign16Bytes1; Label lCopyExtraAument1; @@ -194,6 +198,7 @@ void AssemblerStubsX64::OptimizedCallOptimized(ExtendedAssembler *assembler) __ Pushq(rbp); __ Movq(rsp, rbp); __ Pushq(static_cast(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME)); + __ Pushq(envReg); // callee save __ Pushq(r14); __ Pushq(rbx); @@ -230,11 +235,13 @@ void AssemblerStubsX64::OptimizedCallOptimized(ExtendedAssembler *assembler) __ Addq(-1, rax); __ Jne(&lCopyLoop1); __ Pushq(actualNumArgsReg); // actual argc + __ Pushq(envReg); + __ Movq(glueReg, rax); // mov glue to rax __ Callq(codeAddrReg); // then call jsFunction __ Leaq(Operand(r14, Scale::Times8, 0), codeAddrReg); __ Addq(codeAddrReg, rsp); - __ Addq(8, rsp); // 8: skip actualNumArgsReg + __ Addq(DOUBLE_SLOT_SIZE, rsp); // skip actualNumArgsReg and envReg __ Testb(1, r14); // stack 16bytes align check __ Jne(&lPopFrame1); __ Addq(8, rsp); // 8: align byte @@ -243,7 +250,7 @@ void AssemblerStubsX64::OptimizedCallOptimized(ExtendedAssembler *assembler) __ Addq(8, rsp); // 8: skip rax __ Popq(rbx); __ Popq(r14); - __ Addq(8, rsp); // 8: skip frame type + __ Addq(DOUBLE_SLOT_SIZE, rsp); // skip frame type, env reg __ Pop(rbp); __ Ret(); } @@ -294,7 +301,7 @@ void AssemblerStubsX64::CallBuiltinTrampoline(ExtendedAssembler *assembler) __ Pushq(rbp); __ Movq(rsp, rbp); __ Movq(rbp, Operand(glueReg, JSThread::GlueData::GetLeaveFrameOffset(false))); // save to thread->leaveFrame_ - __ Pushq(static_cast(FrameType::LEAVE_FRAME)); + __ Pushq(static_cast(FrameType::BUILTIN_CALL_LEAVE_FRAME)); // callee save __ Pushq(r10); @@ -314,12 +321,12 @@ void AssemblerStubsX64::CallBuiltinTrampoline(ExtendedAssembler *assembler) __ Movq(threadReg, Operand(rsp, EcmaRuntimeCallInfo::GetThreadOffset())); // thread_ // get numArgs __ Movq(0, rax); - __ Movl(Operand(rdx, 8), rax); // 8: sp + 8 actualArgc + __ Movl(Operand(rdx, DOUBLE_SLOT_SIZE), rax); // sp + 16 actualArgc __ Subl(3, rax); // 3: size __ Movq(rax, Operand(rsp, EcmaRuntimeCallInfo::GetNumArgsOffset())); // actualArgc // get gpr data __ Movq(rdx, rbx); - __ Addq(16, rbx); // 16: argv[0] + __ Addq(TRIPLE_SLOT_SIZE, rbx); // argv[0] __ Movq(rbx, Operand(rsp, EcmaRuntimeCallInfo::GetStackArgsOffset())); // argv0 __ Movq(rsp, rdi); @@ -372,7 +379,7 @@ void AssemblerStubsX64::JSProxyCallInternalWithArgV(ExtendedAssembler *assembler { __ Movq(glueReg, rdi); glueReg = rdi; - __ Movq(Operand(rsp, 16), rax); // 16: get jsFunc + __ Movq(Operand(rsp, TRIPLE_SLOT_SIZE), rax); // get jsFunc } __ Bind(&lJSCallStart); Register jsFuncReg = rax; @@ -436,14 +443,14 @@ void AssemblerStubsX64::JSProxyCallInternalWithArgV(ExtendedAssembler *assembler Register argV = r9; { __ Mov(Operand(jsFuncReg, JSFunctionBase::METHOD_OFFSET), jsMethod); // get method - __ Movl(Operand(rsp, 8), argc); // 8: sp + 8 actual argc + __ Movl(Operand(rsp, DOUBLE_SLOT_SIZE), argc); // sp + 16 actual argc __ Mov(Operand(jsMethod, JSMethod::GetCallFieldOffset(false)), methodCallField); // get call field __ Btq(JSMethod::IsNativeBit::START_BIT, methodCallField); // is native __ Jb(&lCallNativeMethod); __ Btq(JSMethod::IsAotCodeBit::START_BIT, methodCallField); // is aot __ Jb(&lCallOptimziedMethod); __ Movq(rsp, argV); - __ Addq(16, argV); // 16: sp + 16 argv + __ Addq(TRIPLE_SLOT_SIZE, argV); // sp + 24 argv OptimizedCallAsmInterpreter(assembler); } @@ -457,9 +464,11 @@ void AssemblerStubsX64::JSProxyCallInternalWithArgV(ExtendedAssembler *assembler __ Addl(NUM_MANDATORY_JSFUNC_ARGS, methodCallField); // add mandatory argument __ Mov(Operand(jsFuncReg, JSFunctionBase::CODE_ENTRY_OFFSET), codeAddrReg); // get codeAddress __ Movq(rsp, r8); + Register envReg = r9; + __ Movq(Operand(r8, DOUBLE_SLOT_SIZE), envReg); // get env argvReg = r8; - __ Addq(16, argvReg); // 16: sp + 8 argv - __ Cmpl(expectedNumArgsReg, argc); // expectedNumArgs <= actualNumArgs + __ Addq(TRIPLE_SLOT_SIZE, argvReg); // get argv + __ Cmpl(expectedNumArgsReg, rdx); // expectedNumArgs <= actualNumArgs __ Jg(&lDirectCallCodeEntry); __ CallAssemblerStub(RTSTUB_ID(OptimizedCallOptimized), true); } @@ -489,8 +498,10 @@ void AssemblerStubsX64::JSProxyCallInternalWithArgV(ExtendedAssembler *assembler __ Pushq(static_cast(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME)); __ Pushq(r10); // callee save __ Movq(rsp, rdx); - __ Addq(32, rdx); // 32: sp + 32 argv + __ Addq(QUINTUPLE_SLOT_SIZE, rdx); // sp + 40 argv __ Mov(Operand(rdx, 0), rax); // get origin argc + Register envReg = r9; + __ Mov(Operand(rdx, -FRAME_SLOT_SIZE), envReg); // get env __ Movq(rax, r10); // get bound target __ Mov(Operand(jsFuncReg, JSBoundFunction::BOUND_ARGUMENTS_OFFSET), rcx); @@ -500,7 +511,7 @@ void AssemblerStubsX64::JSProxyCallInternalWithArgV(ExtendedAssembler *assembler // 16 bytes align check __ Testb(1, r10); - __ Jne(&lAlign16Bytes2); + __ Je(&lAlign16Bytes2); __ PushAlignBytes(); // push zero to align 16 bytes stack } @@ -544,17 +555,20 @@ void AssemblerStubsX64::JSProxyCallInternalWithArgV(ExtendedAssembler *assembler __ Mov(Operand(jsFuncReg, JSBoundFunction::BOUND_TARGET_OFFSET), rax); // callTarget __ Pushq(rax); __ Pushq(r10); // push actual arguments + Register envReg = r9; + __ Pushq(envReg); __ Movq(rdi, rax); __ Callq(&jsCall); // call JSCall __ Leaq(Operand(r10, Scale::Times8, 8), rcx); // 8: offset __ Addq(rcx, rsp); __ Testb(1, r10); // stack 16bytes align check - __ Jne(&lPopFrame2); + __ Je(&lPopFrame2); __ Addq(8, rsp); // 8: sp + 8 } __ Bind(&lPopFrame2); { + __ Addq(FRAME_SLOT_SIZE, rsp); // skip r9 __ Pop(r10); __ Addq(8, rsp); // 8: sp + 8 __ Pop(rbp); @@ -572,7 +586,8 @@ void AssemblerStubsX64::JSProxyCallInternalWithArgV(ExtendedAssembler *assembler __ Ret(); } -// uint64_t JSCall(uintptr_t glue, uint32_t argc, JSTaggedType calltarget, JSTaggedType new, JSTaggedType this, ...) +// uint64_t JSCall(uintptr_t glue, JSTaggedType env, uint32_t argc, JSTaggedType calltarget, JSTaggedType new, +// JSTaggedType this, ...) // webkit_jscc calling convention call js function() // Input: %rax - glue // stack layout: @@ -593,13 +608,17 @@ void AssemblerStubsX64::JSProxyCallInternalWithArgV(ExtendedAssembler *assembler // +--------------------------+ --- // | jsfunction | ^ // |--------------------------| Fixed -// | argc | OptimizedFrame +// | argc | OptimizedJSFunctionFrame +// |--------------------------| | +// | lexEnv | | // |--------------------------| | // | returnAddr | | // |--------------------------| | // | callsiteFp | | // |--------------------------| | -// | frameType | v +// | frameType | | +// |--------------------------| | +// | lexEnv | v // +--------------------------+ --- void AssemblerStubsX64::JSCall(ExtendedAssembler *assembler) { @@ -625,7 +644,7 @@ void AssemblerStubsX64::JSCall(ExtendedAssembler *assembler) { __ Movq(glueReg, rdi); glueReg = rdi; - __ Movq(Operand(rsp, 16), rax); // 16: sp + 16 get jsFunc + __ Movq(Operand(rsp, TRIPLE_SLOT_SIZE), rax); // sp + 24 get jsFunc } __ Bind(&lJSCallStart); Register jsFuncReg = rax; @@ -689,14 +708,14 @@ void AssemblerStubsX64::JSCall(ExtendedAssembler *assembler) Register argV = r9; { __ Mov(Operand(jsFuncReg, JSFunctionBase::METHOD_OFFSET), jsMethod); // get method - __ Movl(Operand(rsp, 8), argc); // 8: sp + 8 actual argc + __ Movl(Operand(rsp, DOUBLE_SLOT_SIZE), argc); // sp + 16 actual argc __ Mov(Operand(jsMethod, JSMethod::GetCallFieldOffset(false)), methodCallField); // get call field __ Btq(JSMethod::IsNativeBit::START_BIT, methodCallField); // is native __ Jb(&lCallNativeMethod); __ Btq(JSMethod::IsAotCodeBit::START_BIT, methodCallField); // is aot __ Jb(&lCallOptimziedMethod); __ Movq(rsp, argV); - __ Addq(16, argV); // 16: sp + 16 argv + __ Addq(TRIPLE_SLOT_SIZE, argV); // sp + 24 argv OptimizedCallAsmInterpreter(assembler); } @@ -710,8 +729,10 @@ void AssemblerStubsX64::JSCall(ExtendedAssembler *assembler) __ Addl(NUM_MANDATORY_JSFUNC_ARGS, methodCallField); // add mandatory argumentr __ Mov(Operand(jsFuncReg, JSFunctionBase::CODE_ENTRY_OFFSET), codeAddrReg); // get codeAddress __ Movq(rsp, r8); + Register envReg = r9; + __ Movq(Operand(r8, 16), envReg); // 16: get env Register argvReg = r8; - __ Addq(16, argvReg); // 16: sp + 16 argv + __ Addq(24, argvReg); // 24: sp + 24 argv __ Cmpl(expectedNumArgsReg, rdx); // expectedNumArgs <= actualNumArgs __ Jge(&lDirectCallCodeEntry); __ CallAssemblerStub(RTSTUB_ID(OptimizedCallOptimized), true); @@ -742,8 +763,10 @@ void AssemblerStubsX64::JSCall(ExtendedAssembler *assembler) __ Pushq(static_cast(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME)); __ Pushq(r10); // callee save __ Movq(rsp, rdx); - __ Addq(32, rdx); // 32: sp + 32 argv + __ Addq(QUINTUPLE_SLOT_SIZE, rdx); // sp + 40 argv __ Mov(Operand(rdx, 0), rax); // get origin argc + Register envReg = r9; + __ Mov(Operand(rdx, -FRAME_SLOT_SIZE), envReg); // get env __ Movq(rax, r10); // get bound target __ Mov(Operand(jsFuncReg, JSBoundFunction::BOUND_ARGUMENTS_OFFSET), rcx); @@ -753,7 +776,7 @@ void AssemblerStubsX64::JSCall(ExtendedAssembler *assembler) // 16 bytes align check __ Testb(1, r10); - __ Jne(&lAlign16Bytes2); + __ Je(&lAlign16Bytes2); __ PushAlignBytes(); // push zero to align 16 bytes stack } @@ -797,17 +820,20 @@ void AssemblerStubsX64::JSCall(ExtendedAssembler *assembler) __ Mov(Operand(jsFuncReg, JSBoundFunction::BOUND_TARGET_OFFSET), rax); // callTarget __ Pushq(rax); __ Pushq(r10); // push actual arguments + Register envReg = r9; + __ Pushq(envReg); __ Movq(rdi, rax); __ Callq(&jsCall); // call JSCall __ Leaq(Operand(r10, Scale::Times8, 8), rcx); // 8: disp __ Addq(rcx, rsp); __ Testb(1, r10); // stack 16bytes align check - __ Jne(&lPopFrame2); + __ Je(&lPopFrame2); __ Addq(8, rsp); // 8: align byte } __ Bind(&lPopFrame2); { + __ Addq(8, rsp); // 8: sp + 8 __ Pop(r10); __ Addq(8, rsp); // 8: sp + 8 __ Pop(rbp); @@ -816,7 +842,7 @@ void AssemblerStubsX64::JSCall(ExtendedAssembler *assembler) __ Bind(&lJSProxy); __ Movq(jsFuncReg, rdx); // calltarget __ Movq(rsp, rcx); - __ Addq(8, rcx); // 8: sp + 8 skip returnAddr + __ Addq(DOUBLE_SLOT_SIZE, rcx); // sp + 16 skip returnAddr __ Mov(Operand(rcx, 0), rsi); // get origin argc __ Addq(8, rcx); // 8: sp + 8 argv __ Movq(kungfu::CommonStubCSigns::JsProxyCallInternal, r9); diff --git a/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.h b/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.h index 1499572f..26aaba1f 100644 --- a/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.h +++ b/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.h @@ -23,6 +23,11 @@ namespace panda::ecmascript::x64 { class AssemblerStubsX64 { public: + static constexpr int FRAME_SLOT_SIZE = 8; + static constexpr int DOUBLE_SLOT_SIZE = 16; + static constexpr int TRIPLE_SLOT_SIZE = 24; + static constexpr int QUADRUPLE_SLOT_SIZE = 32; + static constexpr int QUINTUPLE_SLOT_SIZE = 40; static void CallRuntime(ExtendedAssembler *assembler); static void JSFunctionEntry(ExtendedAssembler *assembler); diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 8b9bd7f0..9e685caf 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -360,13 +360,15 @@ EcmaVM::CpuProfilingScope::~CpuProfilingScope() JSTaggedValue EcmaVM::InvokeEcmaAotEntrypoint(JSHandle mainFunc, const JSPandaFile *jsPandaFile) { fileLoader_->UpdateJSMethods(mainFunc, jsPandaFile); - std::vector args(6, JSTaggedValue::Undefined().GetRawData()); // 6: number of para + std::vector args(7, JSTaggedValue::Undefined().GetRawData()); // 7: number of para args[0] = mainFunc.GetTaggedValue().GetRawData(); auto entry = thread_->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry); + JSTaggedValue env = mainFunc->GetLexicalEnv(); + args[6] = env.GetRawData(); // 6: last arg is env. auto res = reinterpret_cast(entry)(thread_->GetGlueAddr(), reinterpret_cast(thread_->GetCurrentSPFrame()), - static_cast(args.size()), - static_cast(args.size()), + static_cast(args.size()) - 1, + static_cast(args.size()) - 1, args.data(), mainFunc->GetCodeEntry()); return JSTaggedValue(res); diff --git a/ecmascript/frames.cpp b/ecmascript/frames.cpp index 5d77b5be..71629574 100644 --- a/ecmascript/frames.cpp +++ b/ecmascript/frames.cpp @@ -37,6 +37,11 @@ FrameIterator::FrameIterator(JSTaggedType *sp, const JSThread *thread) : current } } +int FrameIterator::ComputeDelta() const +{ + return stackmapParser_->GetFuncFpDelta(optimizedReturnAddr_); +} + void FrameIterator::Advance() { ASSERT(!Done()); @@ -84,6 +89,13 @@ void FrameIterator::Advance() current_ = frame->GetPrevFrameFp(); break; } + case FrameType::BUILTIN_CALL_LEAVE_FRAME : { + auto frame = GetFrame(); + optimizedCallSiteSp_ = GetPrevFrameCallSiteSp(); + optimizedReturnAddr_ = frame->GetReturnAddr(); + current_ = frame->GetPrevFrameFp(); + break; + } case FrameType::INTERPRETER_FRAME: case FrameType::INTERPRETER_FAST_NEW_FRAME : { auto frame = GetFrame(); @@ -156,6 +168,10 @@ uintptr_t FrameIterator::GetPrevFrameCallSiteSp(uintptr_t curPc) const auto frame = GetFrame(); return frame->GetCallSiteSp(); } + case FrameType::BUILTIN_CALL_LEAVE_FRAME: { + auto frame = GetFrame(); + return frame->GetCallSiteSp(); + } case FrameType::BUILTIN_FRAME_WITH_ARGV: { auto frame = GetFrame(); return frame->GetCallSiteSp(); @@ -224,13 +240,19 @@ ARK_INLINE void OptimizedFrame::GCIterate(const FrameIterator &it, ARK_INLINE JSTaggedType* OptimizedJSFunctionFrame::GetArgv(const FrameIterator &it) const { - auto thread = it.GetThread(); - ASSERT(thread != nullptr); - int delta = thread->GetEcmaVM()->GetFileLoader()->GetStackMapParser()->GetFuncFpDelta(it.GetOptimizedReturnAddr()); - uintptr_t *preFrameSp = ComputePrevFrameSp(it.GetSp(), delta); + uintptr_t *preFrameSp = ComputePrevFrameSp(it); return GetArgv(preFrameSp); } +ARK_INLINE uintptr_t* OptimizedJSFunctionFrame::ComputePrevFrameSp(const FrameIterator &it) const +{ + const JSTaggedType *sp = it.GetSp(); + int delta = it.ComputeDelta(); + uintptr_t *preFrameSp = reinterpret_cast(const_cast(sp)) + + delta / sizeof(uintptr_t); + return preFrameSp; +} + ARK_INLINE void OptimizedJSFunctionFrame::GCIterate(const FrameIterator &it, const RootVisitor &v0, const RootRangeVisitor &v1, @@ -238,13 +260,13 @@ ARK_INLINE void OptimizedJSFunctionFrame::GCIterate(const FrameIterator &it, bool isVerifying) const { OptimizedJSFunctionFrame *frame = OptimizedJSFunctionFrame::GetFrameFromSp(it.GetSp()); + uintptr_t *envPtr = reinterpret_cast(frame); + uintptr_t envslot = ToUintPtr(envPtr); + v0(Root::ROOT_FRAME, ObjectSlot(envslot)); - const JSThread *thread = it.GetThread(); - ASSERT(thread != nullptr); - int delta = thread->GetEcmaVM()->GetFileLoader()->GetStackMapParser()->GetFuncFpDelta(it.GetOptimizedReturnAddr()); - uintptr_t *preFrameSp = frame->ComputePrevFrameSp(it.GetSp(), delta); + uintptr_t *preFrameSp = frame->ComputePrevFrameSp(it); - auto argc = *(reinterpret_cast(preFrameSp)); + auto argc = frame->GetArgc(preFrameSp); JSTaggedType *argv = frame->GetArgv(reinterpret_cast(preFrameSp)); if (argc > 0) { uintptr_t start = ToUintPtr(argv); // argv @@ -364,6 +386,22 @@ ARK_INLINE void OptimizedWithArgvLeaveFrame::GCIterate(const FrameIterator &it, } } +ARK_INLINE void OptimizedBuiltinLeaveFrame::GCIterate(const FrameIterator &it, + [[maybe_unused]] const RootVisitor &v0, + const RootRangeVisitor &v1, + [[maybe_unused]] ChunkMap *derivedPointers, + [[maybe_unused]] bool isVerifying) const +{ + const JSTaggedType *sp = it.GetSp(); + OptimizedBuiltinLeaveFrame *frame = OptimizedBuiltinLeaveFrame::GetFrameFromSp(sp); + if (frame->argc > 0) { + JSTaggedType *argv = reinterpret_cast(&frame->argc + 1); + uintptr_t start = ToUintPtr(argv); // argv + uintptr_t end = ToUintPtr(argv + frame->argc); + v1(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end)); + } +} + ARK_INLINE void BuiltinWithArgvFrame::GCIterate(const FrameIterator &it, [[maybe_unused]] const RootVisitor &v0, const RootRangeVisitor &v1, diff --git a/ecmascript/frames.h b/ecmascript/frames.h index 7121a7cd..4a1c13ff 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -106,6 +106,19 @@ // | callSiteSp | v // +--------------------------+ +// Optimized JSFunction Frame Frame(alias OptimizedJSFunctionFrame) layout +// +--------------------------+ +// | calleesave registers | ^ +// |----------------------| | +// | returnaddress | Fixed +// |----------------------| OptimizedJSFunctionFrame +// | prevFp | | +// |----------------------| | +// | frameType | | +// |----------------------| | +// | lexEnv | v +// +--------------------------+ + // Optimized Entry Frame(alias OptimizedEntryFrame) layout // +--------------------------+ // | returnaddress | ^ @@ -194,12 +207,13 @@ // | calleesave registers | ^ ^ // |----------------------| | | // | returnaddress | Fixed | -// |----------------------| OptimizedFrame | +// |----------------------| OptimizedJSFunctionFrame | // | prevFp | | | // |----------------------| | baz's frame Header // | frameType | | | // |----------------------| | | -// | callsitesp | v V +// | lexEnv | | V +// +--------------------------+ // +--------------------------+---------------------------+ // | ............. | // +--------------------------+---------------------------+ @@ -249,17 +263,18 @@ enum class FrameType: uintptr_t { OPTIMIZED_JS_FUNCTION_FRAME = 2, LEAVE_FRAME = 3, LEAVE_FRAME_WITH_ARGV = 4, - INTERPRETER_FRAME = 5, - ASM_INTERPRETER_FRAME = 6, - INTERPRETER_CONSTRUCTOR_FRAME = 7, - BUILTIN_FRAME = 8, - BUILTIN_FRAME_WITH_ARGV = 9, - BUILTIN_ENTRY_FRAME = 10, - INTERPRETER_FAST_NEW_FRAME = 11, - INTERPRETER_ENTRY_FRAME = 12, - ASM_INTERPRETER_ENTRY_FRAME = 13, - ASM_INTERPRETER_BRIDGE_FRAME = 14, - OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME = 15, + BUILTIN_CALL_LEAVE_FRAME = 5, + INTERPRETER_FRAME = 6, + ASM_INTERPRETER_FRAME = 7, + INTERPRETER_CONSTRUCTOR_FRAME = 8, + BUILTIN_FRAME = 9, + BUILTIN_FRAME_WITH_ARGV = 10, + BUILTIN_ENTRY_FRAME = 11, + INTERPRETER_FAST_NEW_FRAME = 12, + INTERPRETER_ENTRY_FRAME = 13, + ASM_INTERPRETER_ENTRY_FRAME = 14, + ASM_INTERPRETER_BRIDGE_FRAME = 15, + OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME = 16, INTERPRETER_BEGIN = INTERPRETER_FRAME, INTERPRETER_END = INTERPRETER_FAST_NEW_FRAME, @@ -269,7 +284,7 @@ enum class FrameType: uintptr_t { enum class ReservedSlots: int { OPTIMIZED_RESERVED_SLOT = 1, - OPTIMIZED_JS_FUNCTION_RESERVED_SLOT = 1, + OPTIMIZED_JS_FUNCTION_RESERVED_SLOT = 2, OPTIMIZED_ENTRY_RESERVED_SLOT = 2, }; @@ -358,13 +373,16 @@ STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame), OptimizedJSFunctionArgConfigFrame::SizeArch32, OptimizedJSFunctionArgConfigFrame::SizeArch64); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) -struct OptimizedJSFunctionFrame : public base::AlignedStruct { public: + static constexpr size_t ENV_SLOT_DIFF = 2; enum class Index : size_t { - TypeIndex = 0, + EnvIndex = 0, + TypeIndex, PrevFpIndex, ReturnAddrIndex, NumOfMembers @@ -375,15 +393,16 @@ public: { return prevFp; } - uintptr_t* ComputePrevFrameSp(const JSTaggedType *sp, int delta) const - { - uintptr_t *preFrameSp = reinterpret_cast(const_cast(sp)) - + delta / sizeof(uintptr_t); - return preFrameSp; - } + uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const; + JSTaggedType* GetArgv(uintptr_t *preFrameSp) const { - return reinterpret_cast(preFrameSp + sizeof(uint64_t) / sizeof(uintptr_t)); + return reinterpret_cast(preFrameSp + ENV_SLOT_DIFF * sizeof(uint64_t) / sizeof(uintptr_t)); + } + + size_t GetArgc(uintptr_t *preFrameSp) const + { + return *(preFrameSp + sizeof(uint64_t) / sizeof(uintptr_t)); } JSTaggedType* GetArgv(const FrameIterator &it) const; @@ -395,7 +414,25 @@ public: void GCIterate( const FrameIterator &it, const RootVisitor &v0, const RootRangeVisitor &v1, ChunkMap *derivedPointers, bool isVerifying) const; + + inline JSTaggedValue GetEnv() const + { + return env; + } + inline void SetEnv(JSTaggedValue lexEnv) + { + env = lexEnv; + } + friend class FrameIterator; + +private: + static OptimizedJSFunctionFrame* GetFrameFromSp(const JSTaggedType *sp) + { + return reinterpret_cast(reinterpret_cast(sp) + - MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp)); + } // dynamic callee saveregisters for x86-64 + alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; [[maybe_unused]] alignas(EAS) FrameType type {0}; alignas(EAS) JSTaggedType *prevFp {nullptr}; alignas(EAS) uintptr_t returnAddr {0}; @@ -404,13 +441,6 @@ public: // argv[0] // argv[1] // ... argv[n - 1] - friend class FrameIterator; -private: - static OptimizedJSFunctionFrame* GetFrameFromSp(const JSTaggedType *sp) - { - return reinterpret_cast(reinterpret_cast(sp) - - MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp)); - } }; STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame), OptimizedJSFunctionFrame::SizeArch32, OptimizedJSFunctionFrame::SizeArch64); @@ -802,6 +832,39 @@ struct OptimizedWithArgvLeaveFrame { ChunkMap *derivedPointers, bool isVerifying) const; }; +struct OptimizedBuiltinLeaveFrame { +public: + static OptimizedBuiltinLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) + { + return reinterpret_cast(reinterpret_cast(sp) - + MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp)); + } + uintptr_t GetCallSiteSp() const + { + return ToUintPtr(this) + MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, argRuntimeId); + } + inline JSTaggedType* GetPrevFrameFp() const + { + return reinterpret_cast(callsiteFp); + } + uintptr_t GetReturnAddr() const + { + return returnAddr; + } + void GCIterate( + const FrameIterator &it, const RootVisitor &v0, const RootRangeVisitor &v1, + ChunkMap *derivedPointers, bool isVerifying) const; + +private: + [[maybe_unused]] FrameType type; + uintptr_t callsiteFp; // thread sp set here + uintptr_t returnAddr; + [[maybe_unused]] uint64_t argRuntimeId; + JSTaggedValue env; + uint64_t argc; + // argv[0]...argv[argc-1] dynamic according to agc +}; + struct BuiltinFrame : public base::AlignedStructGCIterate(it, v0, v1, derivedPointers, isVerifying); break; } + case FrameType::BUILTIN_CALL_LEAVE_FRAME: { + auto frame = it.GetFrame(); + frame->GCIterate(it, v0, v1, derivedPointers, isVerifying); + break; + } case FrameType::BUILTIN_FRAME_WITH_ARGV: { auto frame = it.GetFrame(); frame->GCIterate(it, v0, v1, derivedPointers, isVerifying); @@ -408,8 +415,8 @@ void FrameHandler::CollectBCOffsetInfo() thread_->GetEcmaVM()->ClearExceptionBCList(); JSTaggedType *current = const_cast(thread_->GetLastLeaveFrame()); FrameIterator it(current, thread_); - ASSERT(it.GetFrameType() == FrameType::LEAVE_FRAME); - auto leaveFrame = it.GetFrame(); + ASSERT(it.GetFrameType() == FrameType::BUILTIN_CALL_LEAVE_FRAME); + auto leaveFrame = it.GetFrame(); auto returnAddr = leaveFrame->GetReturnAddr(); // skip native function, need to fixit later. it.Advance(); @@ -428,11 +435,12 @@ void FrameHandler::CollectBCOffsetInfo() returnAddr = frame->GetReturnAddr(); break; } - case FrameType::LEAVE_FRAME: { - auto frame = it.GetFrame(); + case FrameType::BUILTIN_CALL_LEAVE_FRAME: { + auto frame = it.GetFrame(); returnAddr = frame->GetReturnAddr(); break; } + case FrameType::LEAVE_FRAME: case FrameType::OPTIMIZED_ENTRY_FRAME: case FrameType::ASM_INTERPRETER_ENTRY_FRAME: case FrameType::ASM_INTERPRETER_FRAME: diff --git a/ecmascript/stubs/runtime_stubs-inl.h b/ecmascript/stubs/runtime_stubs-inl.h index 22284664..d5859e1b 100644 --- a/ecmascript/stubs/runtime_stubs-inl.h +++ b/ecmascript/stubs/runtime_stubs-inl.h @@ -20,6 +20,7 @@ #include "ecmascript/builtins/builtins_regexp.h" #include "ecmascript/llvm_stackmap_parser.h" #include "ecmascript/ecma_string_table.h" +#include "ecmascript/file_loader.h" #include "ecmascript/global_dictionary-inl.h" #include "ecmascript/global_env.h" #include "ecmascript/ic/profile_type_info.h" @@ -35,6 +36,8 @@ #include "ecmascript/module/js_module_manager.h" #include "ecmascript/template_string.h" #include "ecmascript/ts_types/ts_loader.h" +#include "ecmascript/jspandafile/literal_data_extractor.h" +#include "ecmascript/jspandafile/scope_info_extractor.h" namespace panda::ecmascript { static constexpr size_t FIXED_NUM_ARGS = 3; @@ -1575,14 +1578,18 @@ JSTaggedValue RuntimeStubs::RuntimeNewLexicalEnvWithNameDyn(JSThread *thread, ui return newEnv.GetTaggedValue(); } -JSTaggedValue RuntimeStubs::RuntimeGetAotUnmapedArgs(JSThread *thread, uint32_t actualNumArgs, uintptr_t argv) +JSTaggedValue RuntimeStubs::RuntimeGetAotUnmapedArgs(JSThread *thread, uint32_t actualNumArgs) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle argumentsList = factory->NewTaggedArray(actualNumArgs - FIXED_NUM_ARGS); - for (uint32_t i = 0; i < actualNumArgs - FIXED_NUM_ARGS; ++i) { + + auto argv = GetActualArgv(thread); + int idx = 0; + for (uint32_t i = FIXED_NUM_ARGS; i < actualNumArgs; ++i) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - JSTaggedType arg = reinterpret_cast(argv)[i + 1]; // skip actualNumArgs - argumentsList->Set(thread, i, JSTaggedValue(arg)); + JSTaggedType arg = reinterpret_cast(argv)[i]; + JSTaggedValue args = JSTaggedValue(arg); + argumentsList->Set(thread, idx++, args); } return RuntimeGetUnmapedJSArgumentObj(thread, argumentsList); } @@ -1652,36 +1659,41 @@ JSTaggedValue RuntimeStubs::RuntimeNewAotLexicalEnvDyn(JSThread *thread, uint16_ newEnv->SetParentEnv(thread, currentLexEnv.GetTaggedValue()); newEnv->SetScopeInfo(thread, JSTaggedValue::Hole()); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - return newEnv.GetTaggedValue(); + JSTaggedValue taggedEnv = newEnv.GetTaggedValue(); + RuntimeSetAotLexEnv(thread, taggedEnv); + return taggedEnv; } JSTaggedValue RuntimeStubs::RuntimeNewAotLexicalEnvWithNameDyn(JSThread *thread, uint16_t numVars, uint16_t scopeId, - JSHandle ¤tLexEnv) + JSHandle ¤tLexEnv, + JSHandle &func) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle newEnv = factory->NewLexicalEnv(numVars); newEnv->SetParentEnv(thread, currentLexEnv.GetTaggedValue()); - JSTaggedValue scopeInfo = ScopeInfoExtractor::GenerateScopeInfo(thread, scopeId); + JSTaggedValue scopeInfo = RuntimeGenerateAotScopeInfo(thread, scopeId, func.GetTaggedValue()); newEnv->SetScopeInfo(thread, scopeInfo); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - return newEnv.GetTaggedValue(); + JSTaggedValue taggedEnv = newEnv.GetTaggedValue(); + RuntimeSetAotLexEnv(thread, taggedEnv); + return taggedEnv; } -JSTaggedValue RuntimeStubs::RuntimeCopyAotRestArgs(JSThread *thread, uint32_t autualArgc, uint32_t restId) +JSTaggedValue RuntimeStubs::RuntimeCopyAotRestArgs(JSThread *thread, uint32_t actualArgc, uint32_t restIndex) { - auto leaveFrame = const_cast(thread->GetLastLeaveFrame()); - auto frame = OptimizedLeaveFrame::GetFrameFromSp(leaveFrame); - uint32_t actualRestNum = autualArgc - restId - FIXED_NUM_ARGS; + uint32_t actualRestNum = actualArgc - FIXED_NUM_ARGS - restIndex; JSHandle restArray = JSArray::ArrayCreate(thread, JSTaggedNumber(actualRestNum)); - JSTaggedType *argv = frame->GetJsFuncFrameArgv(thread); + + auto argv = GetActualArgv(thread); + int idx = 0; JSMutableHandle element(thread, JSTaggedValue::Undefined()); - for (uint32_t i = 0; i < actualRestNum; ++i) { + + for (uint32_t i = FIXED_NUM_ARGS + restIndex; i < actualArgc; ++i) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - JSTaggedType arg = argv[i + FIXED_NUM_ARGS + restId]; - [[maybe_unused]]auto a = JSTaggedValue(arg); + JSTaggedType arg = reinterpret_cast(argv)[i]; element.Update(JSTaggedValue(arg)); - JSObject::SetProperty(thread, restArray, i, element, true); + JSObject::SetProperty(thread, restArray, idx++, element, true); } RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return restArray.GetTaggedValue(); @@ -1753,5 +1765,69 @@ JSTaggedValue RuntimeStubs::RuntimeAotNewObjWithIHClass(JSThread *thread, uintpt return object; } + +JSTaggedValue RuntimeStubs::RuntimeGetAotLexEnv(JSThread *thread) +{ + [[maybe_unused]] DisallowGarbageCollection noGc; + auto optimizedJSFunctionFrame = GetOptimizedJSFunctionFrame(thread); + return optimizedJSFunctionFrame->GetEnv(); +} + +void RuntimeStubs::RuntimeSetAotLexEnv(JSThread *thread, JSTaggedValue lexEnv) +{ + auto optimizedJSFunctionFrame = GetOptimizedJSFunctionFrame(thread); + optimizedJSFunctionFrame->SetEnv(lexEnv); +} + +JSTaggedValue RuntimeStubs::RuntimeGenerateAotScopeInfo(JSThread *thread, uint16_t scopeId, JSTaggedValue func) +{ + EcmaVM *ecmaVm = thread->GetEcmaVM(); + ObjectFactory *factory = ecmaVm->GetFactory(); + JSMethod *method = ECMAObject::Cast(func.GetTaggedObject())->GetCallTarget(); + const JSPandaFile *jsPandaFile = method->GetJSPandaFile(); + JSHandle elementsLiteral = LiteralDataExtractor::GetDatasIgnoreType(thread, jsPandaFile, scopeId); + ASSERT(elementsLiteral->GetLength() > 0); + size_t length = elementsLiteral->GetLength(); + + auto buffer = ecmaVm->GetNativeAreaAllocator()->New(); + auto scopeDebugInfo = static_cast(buffer); + + for (size_t i = 1; i < length; i += 2) { // 2: Each literal buffer contains a pair of key-value. + JSTaggedValue val = elementsLiteral->Get(i); + ASSERT(val.IsString()); + CString name = ConvertToString(EcmaString::Cast(val.GetTaggedObject())); + int32_t slot = elementsLiteral->Get(i + 1).GetInt(); + if (scopeDebugInfo == nullptr) { + return JSTaggedValue::Hole(); + } + scopeDebugInfo->scopeInfo.insert(std::make_pair(name, slot)); + } + + auto freeObjFunc = NativeAreaAllocator::FreeObjectFunc; + auto allocator = ecmaVm->GetNativeAreaAllocator(); + JSHandle pointer = factory->NewJSNativePointer(buffer, freeObjFunc, allocator); + return pointer.GetTaggedValue(); +} + +JSTaggedType *RuntimeStubs::GetActualArgv(JSThread *thread) +{ + JSTaggedType *current = const_cast(thread->GetLastLeaveFrame()); + ASSERT(FrameHandler::GetFrameType(current) == FrameType::LEAVE_FRAME); + FrameIterator it(current, thread); + it.Advance(); + ASSERT(it.GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME); + auto optimizedJSFunctionFrame = it.GetFrame(); + return optimizedJSFunctionFrame->GetArgv(it); +} + +OptimizedJSFunctionFrame *RuntimeStubs::GetOptimizedJSFunctionFrame(JSThread *thread) +{ + JSTaggedType *current = const_cast(thread->GetLastLeaveFrame()); + ASSERT(FrameHandler::GetFrameType(current) == FrameType::LEAVE_FRAME); + FrameIterator it(current, thread); + it.Advance(); + ASSERT(it.GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME); + return it.GetFrame(); +} } // namespace panda::ecmascript #endif // ECMASCRIPT_STUBS_RUNTIME_STUBS_INL_H diff --git a/ecmascript/stubs/runtime_stubs.cpp b/ecmascript/stubs/runtime_stubs.cpp index e9c6067b..05a3ac85 100644 --- a/ecmascript/stubs/runtime_stubs.cpp +++ b/ecmascript/stubs/runtime_stubs.cpp @@ -1542,7 +1542,7 @@ DEF_RUNTIME_STUBS(GetAotUnmapedArgs) { RUNTIME_STUBS_HEADER(GetAotUnmapedArgs); JSTaggedValue actualNumArgs = GetArg(argv, argc, 0); - return RuntimeGetAotUnmapedArgs(thread, actualNumArgs.GetInt(), argv).GetRawData(); + return RuntimeGetAotUnmapedArgs(thread, actualNumArgs.GetInt()).GetRawData(); } DEF_RUNTIME_STUBS(GetAotUnmapedArgsWithRestArgs) @@ -1555,8 +1555,7 @@ DEF_RUNTIME_STUBS(GetAotUnmapedArgsWithRestArgs) DEF_RUNTIME_STUBS(GetAotLexicalEnv) { RUNTIME_STUBS_HEADER(GetAotLexicalEnv); - JSFunction *jsFunc = GetPtrArg(argv, argc, 0); - return jsFunc->GetLexicalEnv().GetRawData(); + return RuntimeGetAotLexEnv(thread).GetRawData(); } DEF_RUNTIME_STUBS(NewAotLexicalEnvDyn) @@ -1570,19 +1569,30 @@ DEF_RUNTIME_STUBS(NewAotLexicalEnvDyn) DEF_RUNTIME_STUBS(NewAotLexicalEnvWithNameDyn) { RUNTIME_STUBS_HEADER(NewAotLexicalEnvWithNameDyn); - JSTaggedValue numVars = GetArg(argv, argc, 0); - JSTaggedValue scopeId = GetArg(argv, argc, 1); + JSTaggedValue taggedNumVars = GetArg(argv, argc, 0); + JSTaggedValue taggedScopeId = GetArg(argv, argc, 1); JSHandle currentLexEnv = GetHArg(argv, argc, 2); - return RuntimeNewAotLexicalEnvWithNameDyn(thread, static_cast(numVars.GetInt()), - static_cast(scopeId.GetInt()), currentLexEnv).GetRawData(); + JSHandle func = GetHArg(argv, argc, 3); + uint16_t numVars = static_cast(taggedNumVars.GetInt()); + uint16_t scopeId = static_cast(taggedScopeId.GetInt()); + return RuntimeNewAotLexicalEnvWithNameDyn(thread, numVars, scopeId, currentLexEnv, func).GetRawData(); +} + +DEF_RUNTIME_STUBS(PopAotLexicalEnv) +{ + RUNTIME_STUBS_HEADER(PopAotLexicalEnv); + JSTaggedValue currentLexenv = RuntimeGetAotLexEnv(thread); + JSTaggedValue parentLexenv = LexicalEnv::Cast(currentLexenv.GetTaggedObject())->GetParentEnv(); + RuntimeSetAotLexEnv(thread, parentLexenv); + return JSTaggedValue::VALUE_HOLE; } DEF_RUNTIME_STUBS(CopyAotRestArgs) { RUNTIME_STUBS_HEADER(CopyAotRestArgs); JSTaggedValue actualArgc = GetArg(argv, argc, 0); - JSTaggedValue restId = GetArg(argv, argc, 1); - return RuntimeCopyAotRestArgs(thread, actualArgc.GetInt(), restId.GetInt()).GetRawData(); + JSTaggedValue restIndex = GetArg(argv, argc, 1); + return RuntimeCopyAotRestArgs(thread, actualArgc.GetInt(), restIndex.GetInt()).GetRawData(); } DEF_RUNTIME_STUBS(NewAotObjDynRange) @@ -1616,6 +1626,37 @@ DEF_RUNTIME_STUBS(AotNewObjWithIHClass) return RuntimeAotNewObjWithIHClass(thread, argv, argc).GetRawData(); } +DEF_RUNTIME_STUBS(LdAotLexVarDyn) +{ + RUNTIME_STUBS_HEADER(LdAotLexVarDyn); + JSTaggedValue level = GetArg(argv, argc, 0); + JSTaggedValue slot = GetArg(argv, argc, 1); + JSTaggedValue env = RuntimeGetAotLexEnv(thread); + for (int32_t i = 0; i < level.GetInt(); i++) { + JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv(); + ASSERT(!taggedParentEnv.IsUndefined()); + env = taggedParentEnv; + } + return LexicalEnv::Cast(env.GetTaggedObject())->GetProperties(slot.GetInt()).GetRawData(); +} + +DEF_RUNTIME_STUBS(StAotLexVarDyn) +{ + RUNTIME_STUBS_HEADER(StAotLexVarDyn); + JSTaggedValue level = GetArg(argv, argc, 0); + JSTaggedValue slot = GetArg(argv, argc, 1); + JSTaggedValue value = GetArg(argv, argc, 2); + JSTaggedValue env = RuntimeGetAotLexEnv(thread); + + for (int32_t i = 0; i < level.GetInt(); i++) { + JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv(); + ASSERT(!taggedParentEnv.IsUndefined()); + env = taggedParentEnv; + } + LexicalEnv::Cast(env.GetTaggedObject())->SetProperties(thread, slot.GetInt(), value); + return JSTaggedValue::VALUE_HOLE; +} + JSTaggedType RuntimeStubs::CreateArrayFromList([[maybe_unused]]uintptr_t argGlue, int32_t argc, JSTaggedValue *argvPtr) { auto thread = JSThread::GlueToJSThread(argGlue); diff --git a/ecmascript/stubs/runtime_stubs.h b/ecmascript/stubs/runtime_stubs.h index 42418ddb..0e42ce1d 100644 --- a/ecmascript/stubs/runtime_stubs.h +++ b/ecmascript/stubs/runtime_stubs.h @@ -17,6 +17,7 @@ #define ECMASCRIPT_RUNTIME_STUBS_H #include "ecmascript/compiler/call_signature.h" +#include "ecmascript/frames.h" #include "ecmascript/stubs/test_runtime_stubs.h" #include "ecmascript/ecma_macros.h" #include "ecmascript/js_tagged_value.h" @@ -226,7 +227,10 @@ using JSFunctionEntryType = uint64_t (*)(uintptr_t glue, uintptr_t prevFp, uint3 V(NewAotObjDynRange) \ V(GetTypeArrayPropertyByIndex) \ V(SetTypeArrayPropertyByIndex) \ - V(AotNewObjWithIHClass) + V(AotNewObjWithIHClass) \ + V(PopAotLexicalEnv) \ + V(LdAotLexVarDyn) \ + V(StAotLexVarDyn) #define RUNTIME_STUB_LIST(V) \ RUNTIME_ASM_STUB_LIST(V) \ @@ -467,20 +471,26 @@ private: static inline JSTaggedValue RuntimeThrowSyntaxError(JSThread *thread, const char *message); static inline JSTaggedValue RuntimeLdBigInt(JSThread *thread, const JSHandle &numberBigInt); static inline JSTaggedValue RuntimeNewLexicalEnvWithNameDyn(JSThread *thread, uint16_t numVars, uint16_t scopeId); - static inline JSTaggedValue RuntimeGetAotUnmapedArgs(JSThread *thread, uint32_t actualNumArgs, uintptr_t argv); + static inline JSTaggedValue RuntimeGetAotUnmapedArgs(JSThread *thread, uint32_t actualNumArgs); static inline JSTaggedValue RuntimeGetAotUnmapedArgsWithRestArgs(JSThread *thread, uint32_t actualNumArgs); static inline JSTaggedValue RuntimeGetUnmapedJSArgumentObj(JSThread *thread, const JSHandle &argumentsList); static inline JSTaggedValue RuntimeNewAotLexicalEnvDyn(JSThread *thread, uint16_t numVars, JSHandle ¤tLexEnv); static inline JSTaggedValue RuntimeNewAotLexicalEnvWithNameDyn(JSThread *thread, uint16_t numVars, uint16_t scopeId, - JSHandle ¤tLexEnv); - static inline JSTaggedValue RuntimeCopyAotRestArgs(JSThread *thread, uint32_t autualArgc, uint32_t restId); + JSHandle ¤tLexEnv, + JSHandle &func); + static inline JSTaggedValue RuntimeCopyAotRestArgs(JSThread *thread, uint32_t actualArgc, uint32_t restIndex); static inline JSTaggedValue RuntimeSuspendAotGenerator(JSThread *thread, const JSHandle &genObj, const JSHandle &value); static inline JSTaggedValue RuntimeNewAotObjDynRange(JSThread *thread, uintptr_t argv, uint32_t argc); static inline JSTaggedValue RuntimeAotNewObjWithIHClass(JSThread *thread, uintptr_t argv, uint32_t argc); + static inline JSTaggedValue RuntimeGetAotLexEnv(JSThread *thread); + static inline void RuntimeSetAotLexEnv(JSThread *thread, JSTaggedValue lexEnv); + static inline JSTaggedValue RuntimeGenerateAotScopeInfo(JSThread *thread, uint16_t scopeId, JSTaggedValue func); + static inline JSTaggedType *GetActualArgv(JSThread *thread); + static inline OptimizedJSFunctionFrame *GetOptimizedJSFunctionFrame(JSThread *thread); }; } // namespace panda::ecmascript #endif diff --git a/test/aottest/BUILD.gn b/test/aottest/BUILD.gn index 19b21f12..bda37a33 100644 --- a/test/aottest/BUILD.gn +++ b/test/aottest/BUILD.gn @@ -48,8 +48,10 @@ group("ark_aot_test") { "mul:mulAotAction", "neg:negAotAction", "new:newAotAction", + "newlexenv:newlexenvAotAction", "not:notAotAction", "or:orAotAction", + "poplexenv:poplexenvAotAction", "setobjectwithproto:setobjectwithprotoAotAction", "shl:shlAotAction", "shr:shrAotAction", @@ -68,6 +70,7 @@ group("ark_aot_test") { "strictnotequal:strictnotequalAotAction", "sub:subAotAction", "throw:throwAotAction", + "throwundefindeifhole:throwundefindeifholeAotAction", "tonumber:tonumberAotAction", "trystglobalbynameprefid32:trystglobalbynameprefid32AotAction", "typeof:typeofAotAction",