From e222260f9bfff893e49de47b151c82570aac3b63 Mon Sep 17 00:00:00 2001 From: getingke Date: Mon, 4 Jul 2022 09:44:07 +0800 Subject: [PATCH] fixed for rewrite assembler stub for aarch64 Signed-off-by: getingke Change-Id: I9b5982bc1268725e7882fd95eeb2ba07f2851b6d --- .../assembler/aarch64/assembler_aarch64.h | 11 + ecmascript/compiler/call_signature.cpp | 38 -- ecmascript/compiler/call_signature.h | 2 - ecmascript/compiler/tests/BUILD.gn | 2 +- .../trampoline/aarch64/assembler_stubs.cpp | 456 ++++++++---------- .../trampoline/aarch64/assembler_stubs.h | 9 +- .../trampoline/x64/assembler_stubs_x64.cpp | 40 +- .../trampoline/x64/assembler_stubs_x64.h | 2 - ecmascript/stubs/runtime_stubs.h | 2 - test/aottest/calls/calls.ts | 25 +- test/aottest/calls/expect_output.txt | 8 +- 11 files changed, 248 insertions(+), 347 deletions(-) diff --git a/ecmascript/compiler/assembler/aarch64/assembler_aarch64.h b/ecmascript/compiler/assembler/aarch64/assembler_aarch64.h index 016f787da0..2b95ad3f5a 100644 --- a/ecmascript/compiler/assembler/aarch64/assembler_aarch64.h +++ b/ecmascript/compiler/assembler/aarch64/assembler_aarch64.h @@ -57,6 +57,17 @@ public: { return reg_ != RegisterId::INVALID_REG; } + + inline bool operator !=(const Register &other) + { + return reg_ != other.GetId(); + } + + inline bool operator ==(const Register &other) + { + return reg_ == other.GetId() && type_ == other.GetType(); + } + private: RegisterId reg_; RegisterType type_; diff --git a/ecmascript/compiler/call_signature.cpp b/ecmascript/compiler/call_signature.cpp index bf6237e086..35b7a37bb0 100644 --- a/ecmascript/compiler/call_signature.cpp +++ b/ecmascript/compiler/call_signature.cpp @@ -604,23 +604,6 @@ DEF_CALL_SIGNATURE(JSFunctionEntry) callSign->SetCallConv(CallSignature::CallConv::CCallConv); } -DEF_CALL_SIGNATURE(CallBuiltinTrampoline) -{ - /* 3 : 3 input parameters */ - CallSignature CallBuiltinTrampoline("CallBuiltinTrampoline", 0, 3, - ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY()); - *callSign = CallBuiltinTrampoline; - std::array params = { /* 3 : 3 input parameters */ - VariableType::NATIVE_POINTER(), // glue - VariableType::NATIVE_POINTER(), // codeAddress - VariableType::INT32(), // argc - }; - callSign->SetVariadicArgs(true); - callSign->SetParameters(params.data()); - callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC); - callSign->SetCallConv(CallSignature::CallConv::CCallConv); -} - DEF_CALL_SIGNATURE(ResumeRspAndDispatch) { // 8 : 8 input parameters @@ -808,27 +791,6 @@ DEF_CALL_SIGNATURE(CallSetter) PUSH_CALL_ARGS_AND_DISPATCH_NATIVE_RANGE_SIGNATURE(CallSetter) } -DEF_CALL_SIGNATURE(CallOptimizedJSFunction) -{ - // 6 : 6 input parameters - CallSignature CallOptimizedJSFunction("CallOptimizedJSFunction", 0, 6, - ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY()); - *callSign = CallOptimizedJSFunction; - // 6 : 6 input parameters - std::array params = { - VariableType::NATIVE_POINTER(), // glue - VariableType::NATIVE_POINTER(), // prevFp - VariableType::JS_ANY(), // jsfunc - VariableType::INT32(), // actualNumArgs - VariableType::JS_ANY(), // this - VariableType::JS_ANY(), // new_target - }; - callSign->SetVariadicArgs(true); - callSign->SetParameters(params.data()); - callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC); - callSign->SetCallConv(CallSignature::CallConv::CCallConv); -} - DEF_CALL_SIGNATURE(JSCallWithArgV) { // 6 : 6 input parameters diff --git a/ecmascript/compiler/call_signature.h b/ecmascript/compiler/call_signature.h index bee33e67e3..7cab36b11a 100644 --- a/ecmascript/compiler/call_signature.h +++ b/ecmascript/compiler/call_signature.h @@ -328,7 +328,6 @@ private: V(PushCallNewAndDispatch) \ V(CallGetter) \ V(CallSetter) \ - V(CallOptimizedJSFunction) \ V(JSCallWithArgV) \ V(ResumeRspAndDispatch) \ V(ResumeRspAndReturn) \ @@ -351,7 +350,6 @@ private: V(CallIRangeDyn) \ V(JSCall) \ V(JSFunctionEntry) \ - V(CallBuiltinTrampoline) \ V(JSProxyCallInternalWithArgV) \ V(CreateArrayFromList) \ V(JSObjectGetMethod) \ diff --git a/ecmascript/compiler/tests/BUILD.gn b/ecmascript/compiler/tests/BUILD.gn index c44e08ae92..dcf74e1f4d 100644 --- a/ecmascript/compiler/tests/BUILD.gn +++ b/ecmascript/compiler/tests/BUILD.gn @@ -222,7 +222,7 @@ host_unittest_action("CircuitOptimizerTest") { ] if (compile_llvm_online) { - lib_dirs = [ "//third_party/llvm-project/build/lib" ] + lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] } else { lib_dirs = [ "//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/build/lib" ] diff --git a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp index 91ed8b6ae1..76e8923f85 100644 --- a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp +++ b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp @@ -102,6 +102,21 @@ void AssemblerStubs::CallRuntime(ExtendedAssembler *assembler) __ Ret(); } +void AssemblerStubs::IncreaseStackForArguments(ExtendedAssembler *assembler, Register argc, Register fp) +{ + Register sp(SP); + __ Mov(fp, sp); + __ Add(argc, argc, Immediate(2)); // 2 : 2 means numArgs + env + __ Sub(fp, fp, Operand(argc, UXTW, 3)); + Label aligned; + __ Tst(fp, LogicalImmediate::Create(0xf, RegXSize)); // 0xf: 0x1111 + __ B(Condition::EQ, &aligned); + __ Sub(fp, fp, Immediate(FRAME_SLOT_SIZE)); + __ Bind(&aligned); + __ Mov(sp, fp); + __ Add(fp, fp, Operand(argc, UXTW, 3)); +} + // uint64_t JSFunctionEntry(uintptr_t glue, uintptr_t prevFp, uint32_t expectedNumArgs, // uint32_t actualNumArgs, const JSTaggedType argV[], uintptr_t codeAddr) // Input: %x0 - glue @@ -131,84 +146,54 @@ void AssemblerStubs::JSFunctionEntry(ExtendedAssembler *assembler) Register argV(X4); Register codeAddr(X5); Register sp(SP); - Register fp(X29); + Register fp(X6); + Label copyArguments; __ BindAssemblerStub(RTSTUB_ID(JSFunctionEntry)); - __ Str(Register(X30), MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - __ CalleeSave(); - __ Str(fp, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - __ Mov(fp, sp); - - Register frameType(X19); - // construct frame - __ Mov(frameType, Immediate(static_cast(FrameType::OPTIMIZED_ENTRY_FRAME))); - __ Stp(prevFp, frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); - - Label copyUndefined; - Label copyArguments; - Register tmp(X19, W); - __ Mov(glue, Register(X0)); - __ Mov(tmp, expectedNumArgs.W()); - __ Cmp(tmp, actualNumArgs.W()); - __ B(Condition::LS, ©Arguments); - Register count(X9, W); - Register undefValue(X8); - __ Mov(count, tmp.W()); - __ Mov(undefValue, Immediate(JSTaggedValue::VALUE_UNDEFINED)); - - __ Bind(©Undefined); - __ Sub(count, count, Immediate(1)); - __ Cmp(count, actualNumArgs.W()); - __ Str(undefValue, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - __ B(Condition::HI, ©Undefined); + PushAotEntryFrame(assembler, prevFp); + Register argC(X7); + __ Cmp(expectedNumArgs, actualNumArgs); + __ CMov(argC, expectedNumArgs, actualNumArgs, Condition::HI); + IncreaseStackForArguments(assembler, argC, fp); Label invokeCompiledJSFunction; - __ Bind(©Arguments); { - Register argVEnd(X9); - Register argC(X8, W); - Register argValue(X10); - Register env(X11); - Label copyArgLoop; - - // expectedNumArgs <= actualNumArgs - __ Cmp(tmp.W(), actualNumArgs.W()); - __ CMov(argC, tmp.W(), actualNumArgs.W(), Condition::LO); - __ 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)); - __ Subs(argC, argC, Immediate(1)); - __ Str(argValue, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - __ B(Condition::NE, ©ArgLoop); + TempRegister1Scope scope1(assembler); + TempRegister2Scope scope2(assembler); + Register argc = __ TempRegister1(); + Register undefinedValue = __ TempRegister2(); + __ Subs(argc, expectedNumArgs, Operand(actualNumArgs)); + __ B(Condition::LS, ©Arguments); + PushUndefinedWithArgc(assembler, argc, undefinedValue, fp, nullptr); + } + __ Bind(©Arguments); + __ Cbz(actualNumArgs, &invokeCompiledJSFunction); + { + TempRegister1Scope scope1(assembler); + TempRegister2Scope scope2(assembler); + Register argc = __ TempRegister1(); + Register argValue = __ TempRegister2(); + __ Mov(argc, actualNumArgs); + __ PushArgsWithArgv(argc, argV, argValue, fp, &invokeCompiledJSFunction); } __ Bind(&invokeCompiledJSFunction); { - Register env(X11); - __ Str(actualNumArgs, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - __ Str(env, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); + TempRegister1Scope scope1(assembler); + Register env = __ TempRegister1(); + __ Mov(Register(X19), expectedNumArgs); + __ Ldr(env, MemoryOperand(argV, actualNumArgs, UXTW, 3)); + __ Str(actualNumArgs, MemoryOperand(sp, FRAME_SLOT_SIZE)); + __ Str(env, MemoryOperand(sp, 0)); __ Blr(codeAddr); } // pop argV // 3 : 3 means argC * 8 - __ Add(sp, sp, Operand(tmp, UXTW, 3)); - __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE * 2)); // 2: pop argc and env + __ Ldr(actualNumArgs, MemoryOperand(sp, FRAME_SLOT_SIZE)); + PopAotArgs(assembler, Register(X19), actualNumArgs); // pop prevLeaveFrameFp to restore thread->currentFrame_ - __ Ldr(prevFp, MemoryOperand(sp, FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); - __ Str(prevFp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); - - // pop entry frame type and c-fp - __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE)); - __ Ldr(fp, MemoryOperand(sp, FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); - - __ CalleeRestore(); - // restore return address - __ Ldr(Register(X30), MemoryOperand(sp, FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); + PopAotEntryFrame(assembler, glue); __ Ret(); } @@ -219,6 +204,7 @@ void AssemblerStubs::JSFunctionEntry(ExtendedAssembler *assembler) // %w2 - actualNumArgs // %x3 - codeAddr // %x4 - argv +// %x5 - env // sp[0 * 8] - argc // sp[1 * 8] - argv[0] @@ -235,71 +221,54 @@ void AssemblerStubs::OptimizedCallOptimized(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(OptimizedCallOptimized)); Register expectedNumArgs(X1); - Register sp(SP); - __ SaveFpAndLr(); - // Construct frame - 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(X6, W); Register actualNumArgs(X2, W); + Register codeAddr(X3); + Register argV(X4); + Register env(X5); + Register fp(X6); + Register sp(SP); Label copyArguments; - __ Mov(count, expectedNumArgs); - __ Cmp(count, actualNumArgs); - __ B(Condition::LS, ©Arguments); - - Register undefValue(X8); - __ Mov(undefValue, Immediate(JSTaggedValue::VALUE_UNDEFINED)); - Label copyUndefined; - __ Bind(©Undefined); - __ Sub(count, count, Immediate(1)); - __ Str(undefValue, MemoryOperand(sp, -FRAME_SLOT_SIZE, PREINDEX)); - __ Cmp(count, actualNumArgs); - __ B(Condition::HI, ©Undefined); - Label invokeCompiledJSFunction; - Register saveNumArgs(X19); - __ Bind(©Arguments); - { - __ Cmp(expectedNumArgs.W(), actualNumArgs.W()); - __ CMov(count, expectedNumArgs.W(), actualNumArgs.W(), Condition::LO); - __ Cbz(count, &invokeCompiledJSFunction); - Register argVEnd(X4); - Register argValue(X10); - Label copyArgLoop; - __ Mov(saveNumArgs, expectedNumArgs); - __ Subs(count, count, Immediate(1)); - // 3 : 3 means count * 8 - __ Add(argVEnd, argVEnd, Operand(count, UXTW, 3)); - __ Bind(©ArgLoop); - __ Ldr(argValue, MemoryOperand(argVEnd, -FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); - __ Subs(count, count, Immediate(1)); - __ Str(argValue, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - __ B(Condition::PL, ©ArgLoop); + // construct frame + PushOptimizedJSFunctionFrame(assembler); + Register argC(X7); + __ Cmp(expectedNumArgs, actualNumArgs); + __ CMov(argC, expectedNumArgs, actualNumArgs, Condition::HI); + IncreaseStackForArguments(assembler, argC, fp); + { + TempRegister1Scope scope1(assembler); + TempRegister2Scope scope2(assembler); + Register tmp = __ TempRegister1(); + Register undefinedValue = __ TempRegister2(); + __ Subs(tmp, expectedNumArgs, actualNumArgs); + __ B(Condition::LS, ©Arguments); + PushUndefinedWithArgc(assembler, tmp, undefinedValue, fp, nullptr); + } + __ Bind(©Arguments); + __ Cbz(actualNumArgs, &invokeCompiledJSFunction); + { + TempRegister1Scope scope1(assembler); + TempRegister2Scope scope2(assembler); + Register argc = __ TempRegister1(); + Register argValue = __ TempRegister2(); + __ Mov(argc, actualNumArgs); + __ PushArgsWithArgv(argc, argV, argValue, fp, &invokeCompiledJSFunction); + } + __ Bind(&invokeCompiledJSFunction); + { + __ Mov(Register(X19), expectedNumArgs); + __ Str(actualNumArgs, MemoryOperand(sp, FRAME_SLOT_SIZE)); + __ Str(env, MemoryOperand(sp, 0)); + __ Blr(codeAddr); } - 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 * 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 * 2)); // 2: skip type and env - __ RestoreFpAndLr(); + // pop argV argC + // 3 : 3 means argC * 8 + __ Ldr(actualNumArgs, MemoryOperand(sp, FRAME_SLOT_SIZE)); + PopAotArgs(assembler, Register(X19), actualNumArgs); + // pop prevLeaveFrameFp to restore thread->currentFrame_ + PopOptimizedJSFunctionFrame(assembler); __ Ret(); } @@ -317,6 +286,49 @@ void AssemblerStubs::OptimizedCallAsmInterpreter(ExtendedAssembler *assembler) } } +void AssemblerStubs::PushLeaveFrame(ExtendedAssembler *assembler, Register glue, bool isBuiltin) +{ + TempRegister2Scope temp2Scope(assembler); + Register frameType = __ TempRegister2(); + Register fp(X6); + Register sp(SP); + Register prevfp(X29); + + // construct leave frame + if (isBuiltin) { + __ Mov(frameType, Immediate(static_cast(FrameType::BUILTIN_CALL_LEAVE_FRAME))); + // current sp is not 16bytes aligned because native code address has pushed. + __ Mov(fp, sp); + __ Sub(sp, sp, Immediate(3 * FRAME_SLOT_SIZE)); // 3 : 3 for 16bytes align + __ Stp(prevfp, Register(X30), MemoryOperand(fp, -2 * FRAME_SLOT_SIZE, PREINDEX)); + __ Str(frameType, MemoryOperand(fp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); + __ Add(prevfp, sp, Immediate(FRAME_SLOT_SIZE)); + } else { + __ Mov(frameType, Immediate(static_cast(FrameType::LEAVE_FRAME))); + __ SaveFpAndLr(); + __ Stp(Register(X19), frameType, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); + } + // save to thread currentLeaveFrame_; + __ Str(prevfp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); +} + + +void AssemblerStubs::PopLeaveFrame(ExtendedAssembler *assembler, bool isBuiltin) +{ + Register sp(SP); + Register fp(X6); + TempRegister2Scope temp2Scope(assembler); + Register frameType = __ TempRegister2(); + if (isBuiltin) { + __ Add(fp, sp, Immediate(FRAME_SLOT_SIZE)); // skip frame type + __ Add(sp, sp, Immediate(3 * FRAME_SLOT_SIZE)); + __ Ldp(Register(X29), Register(X30), MemoryOperand(fp, 2 * FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); + } else { + __ Ldp(Register(X19), frameType, MemoryOperand(sp, 2 * FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); + __ RestoreFpAndLr(); + } +} + // uint64_t CallBuiltinTrampoline(uintptr_t glue, uintptr_t codeAddress, uint32_t argc, ...) // webkit_jscc calling convention call runtime_id's runtion function(c-abi) // Input: @@ -350,33 +362,20 @@ void AssemblerStubs::OptimizedCallAsmInterpreter(ExtendedAssembler *assembler) void AssemblerStubs::CallBuiltinTrampoline(ExtendedAssembler *assembler) { - __ BindAssemblerStub(RTSTUB_ID(CallBuiltinTrampoline)); - __ SaveFpAndLr(); - // save to thread currentLeaveFrame_; Register fp(X29); Register glue(X0); Register sp(SP); - __ Str(fp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); + Register nativeFuncAddr(X4); - Register nativeFuncAddr(X19); + PushLeaveFrame(assembler, glue, true); - // construct leave frame and callee save - Register frameType(X1); - __ 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)); - - // load runtime trampoline address - __ Ldr(nativeFuncAddr, MemoryOperand(fp, GetStackArgOffSetToFp(BuiltinsLeaveFrameArgId::CODE_ADDRESS))); __ Str(glue, MemoryOperand(fp, GetStackArgOffSetToFp(BuiltinsLeaveFrameArgId::ENV))); // thread (instead of env) - __ Add(Register(X0), fp, Immediate(GetStackArgOffSetToFp(BuiltinsLeaveFrameArgId::ENV))); __ Blr(nativeFuncAddr); // descontruct leave frame and callee save register - __ Ldp(nativeFuncAddr, frameType, MemoryOperand(sp, 2 * FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); - __ RestoreFpAndLr(); - __ Add(sp, sp, Immediate(8)); // 8 : 8 skip native code address + PopLeaveFrame(assembler, true); + __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE)); // skip native code address __ Ret(); } @@ -470,7 +469,7 @@ void AssemblerStubs::JSCallBody(ExtendedAssembler *assembler, Register jsfunc) __ Ldr(nativeFuncAddr, MemoryOperand(method, JSMethod::GetNativePointerOffset())); // -8 : -8 means sp increase step __ Str(nativeFuncAddr, MemoryOperand(sp, -8, AddrMode::PREINDEX)); - __ CallAssemblerStub(RTSTUB_ID(CallBuiltinTrampoline), true); + CallBuiltinTrampoline(assembler); } __ Bind(&callOptimizedMethod); @@ -488,8 +487,7 @@ 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); - // argV = sp + 16 - __ Add(argV, sp, Immediate(DOUBLE_SLOT_SIZE)); + __ Add(argV, sp, Immediate(2 * FRAME_SLOT_SIZE)); // 2 : 2 means skip argc and env __ Ldr(codeAddress, MemoryOperand(Register(X5), JSFunctionBase::CODE_ENTRY_OFFSET)); __ Ldr(env, MemoryOperand(sp, 0)); __ B(Condition::HS, &directCallCodeEntry); @@ -512,85 +510,68 @@ void AssemblerStubs::JSCallBody(ExtendedAssembler *assembler, Register jsfunc) __ Bind(&jsBoundFunction); { - __ SaveFpAndLr(); // construct frame - Register frameType(X5); - Register fp(X29); - __ 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(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)); + PushOptimizedJSFunctionFrame(assembler); + Register basefp(X29); + Register fp = __ AvailableRegister1(); + Register env(X5); + + Register argV(X6); + __ Add(argV, basefp, Immediate(GetStackArgOffSetToFp(0))); + __ Ldr(actualArgC, MemoryOperand(argV, FRAME_SLOT_SIZE)); + __ Ldr(env, MemoryOperand(argV, 0)); Register boundLength(X2); - Register realArgC(X19, W); + Register realArgC(X7, W); Label copyBoundArgument; - Label copyArgument; Label pushCallTarget; // get bound arguments __ Ldr(boundLength, MemoryOperand(jsfunc, JSBoundFunction::BOUND_ARGUMENTS_OFFSET)); // get bound length __ Ldr(boundLength, MemoryOperand(boundLength, TaggedArray::LENGTH_OFFSET)); __ Add(realArgC, boundLength.W(), actualArgC.W()); - // 3 : 3 mean *8 - __ Add(argVEnd, argVEnd, Operand(actualArgC.W(), UXTW, 3)); + __ Mov(Register(X19), realArgC); + IncreaseStackForArguments(assembler, realArgC, fp); __ Sub(actualArgC.W(), actualArgC.W(), Immediate(NUM_MANDATORY_JSFUNC_ARGS)); __ Cmp(actualArgC.W(), Immediate(0)); __ B(Condition::EQ, ©BoundArgument); - __ Bind(©Argument); { - Register argValue(X5); - __ Ldr(argValue, MemoryOperand(argVEnd, -FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); - __ Str(argValue, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - __ Sub(actualArgC.W(), actualArgC.W(), Immediate(1)); - __ Cmp(actualArgC.W(), Immediate(0)); - __ B(Condition::NE, ©Argument); + TempRegister1Scope scope1(assembler); + Register tmp = __ TempRegister1(); + // 2 : 2 means numArgs and env + __ Add(argV, argV, Immediate((NUM_MANDATORY_JSFUNC_ARGS + 2) *FRAME_SLOT_SIZE)); + __ PushArgsWithArgv(actualArgC, argV, tmp, fp, nullptr); } __ Bind(©BoundArgument); { Register boundArgs(X4); - Label copyBoundArgumentLoop; __ Ldr(boundArgs, MemoryOperand(jsfunc, JSBoundFunction::BOUND_ARGUMENTS_OFFSET)); __ Add(boundArgs, boundArgs, Immediate(TaggedArray::DATA_OFFSET)); __ Cmp(boundLength.W(), Immediate(0)); __ B(Condition::EQ, &pushCallTarget); - __ Sub(boundLength.W(), boundLength.W(), Immediate(1)); - // 3 : 3 means 2^3 = 8 - __ Add(boundArgs, boundArgs, Operand(boundLength.W(), UXTW, 3)); - __ Bind(©BoundArgumentLoop); { - Register boundargValue(X5); - __ Ldr(boundargValue, MemoryOperand(boundArgs, -FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); - __ Str(boundargValue, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - __ Subs(boundLength.W(), boundLength.W(), Immediate(1)); - __ B(Condition::PL, ©BoundArgumentLoop); + TempRegister1Scope scope1(assembler); + Register tmp = __ TempRegister1(); + __ PushArgsWithArgv(boundLength, boundArgs, tmp, fp, nullptr); } } __ Bind(&pushCallTarget); { - Register thisObj(X5); + Register thisObj(X4); Register newTarget(X6); Register boundTarget(X7); __ Ldr(thisObj, MemoryOperand(jsfunc, JSBoundFunction::BOUND_THIS_OFFSET)); __ Mov(newTarget, Immediate(JSTaggedValue::VALUE_UNDEFINED)); - __ Stp(newTarget, thisObj, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); + __ Stp(newTarget, thisObj, MemoryOperand(fp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); __ 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)); + __ Stp(Register(X19), boundTarget, MemoryOperand(fp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); + __ Str(env, MemoryOperand(fp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); } __ CallAssemblerStub(RTSTUB_ID(JSCall), false); - __ 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)); - __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE)); - __ RestoreFpAndLr(); + + PopAotArgs(assembler, Register(X19), Register(X19)); + PopOptimizedJSFunctionFrame(assembler); __ Ret(); } __ Bind(&jsProxy); @@ -1830,11 +1811,26 @@ void AssemblerStubs::PushMandatoryJSArgs(ExtendedAssembler *assembler, Register __ Str(jsfunc, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); } -void AssemblerStubs::PopAotArgs(ExtendedAssembler *assembler, Register expectedNumArgs) +void AssemblerStubs::PopAotArgs(ExtendedAssembler *assembler, Register expectedNumArgs, Register actualNumArgs) { Register sp(SP); - __ Add(sp, sp, Operand(expectedNumArgs, UXTW, 3)); // 3 : 3 means *8 + Register fp(X6); + Label aligned; + if (expectedNumArgs != actualNumArgs) { + TempRegister1Scope scop1(assembler); + Register tmp = __ TempRegister1(); + __ Cmp(expectedNumArgs, actualNumArgs); + __ CMov(tmp, expectedNumArgs, actualNumArgs, Condition::HI); + __ Add(sp, sp, Operand(tmp, UXTW, 3)); // 3 : 3 means *8 + } else { + __ Add(sp, sp, Operand(expectedNumArgs, UXTW, 3)); // 3 : 3 means *8 + } + __ Add(sp, sp, Immediate(2 * FRAME_SLOT_SIZE)); // 2 : 2 means skip numArgs and env + __ Mov(fp, sp); + __ Tst(fp, LogicalImmediate::Create(0xf, RegXSize)); // 0xf: 0x1111 + __ B(Condition::EQ, &aligned); __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE)); + __ Bind(&aligned); } void AssemblerStubs::PushAotEntryFrame(ExtendedAssembler *assembler, Register prevFp) @@ -1842,16 +1838,13 @@ void AssemblerStubs::PushAotEntryFrame(ExtendedAssembler *assembler, Register pr Register fp(X29); Register sp(SP); TempRegister2Scope temp2Scope(assembler); - __ Str(Register(X30), MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - __ CalleeSave(); - __ Str(fp, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - __ Mov(fp, sp); - + __ SaveFpAndLr(); Register frameType = __ TempRegister2(); // construct frame __ Mov(frameType, Immediate(static_cast(FrameType::OPTIMIZED_ENTRY_FRAME))); // 2 : 2 means pairs __ Stp(prevFp, frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); + __ CalleeSave(); } void AssemblerStubs::PopAotEntryFrame(ExtendedAssembler *assembler, Register glue) @@ -1859,59 +1852,38 @@ void AssemblerStubs::PopAotEntryFrame(ExtendedAssembler *assembler, Register glu Register fp(X29); Register sp(SP); Register prevFp(X1); + __ CalleeRestore(); + // pop prevLeaveFrameFp to restore thread->currentFrame_ __ Ldr(prevFp, MemoryOperand(sp, FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); __ Str(prevFp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); - // pop entry frame type and c-fp + // pop entry frame type __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE)); - __ Ldr(fp, MemoryOperand(sp, FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); - - __ CalleeRestore(); // restore return address - __ Ldr(Register(X30), MemoryOperand(sp, FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); + __ RestoreFpAndLr(); } -void AssemblerStubs::CallOptimizedJSFunction(ExtendedAssembler *assembler) +void AssemblerStubs::PushOptimizedJSFunctionFrame(ExtendedAssembler *assembler) { - __ BindAssemblerStub(RTSTUB_ID(CallOptimizedJSFunction)); Register sp(SP); - Register glue(X0); - Register prevFp(X1); - Register jsfunc(X2); - Register actualNumArgs(X3); - Register thisObj(X4); - Register newTarget(X5); - Register arg0(X6); - Register arg1(X7); - Register codeAddr = __ AvailableRegister1(); - Register expectedNumArgs(X19); - Label pushCallThis; - Register argV(prevFp); - // save arg0, arg1 to stack - // 2 : 2 means pairs - __ Stp(arg0, arg1, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - { - TempRegister1Scope temp1Scope(assembler); - Register tmp = __ TempRegister1(); - __ Mov(tmp, sp); - PushAotEntryFrame(assembler, prevFp); - __ Mov(argV, tmp); - } + TempRegister2Scope temp2Scope(assembler); + Register frameType = __ TempRegister2(); + __ SaveFpAndLr(); + // construct frame + __ Mov(frameType, Immediate(static_cast(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME))); + // 2 : 2 means pairs. X19 means calleesave and 16bytes align + __ Stp(Register(X19), frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); +} - PushArgsWithArgV(assembler, jsfunc, actualNumArgs, argV, &pushCallThis); - __ Bind(&pushCallThis); - __ Add(expectedNumArgs, expectedNumArgs, Immediate(NUM_MANDATORY_JSFUNC_ARGS)); - __ Add(actualNumArgs, actualNumArgs, Immediate(NUM_MANDATORY_JSFUNC_ARGS)); - PushMandatoryJSArgs(assembler, jsfunc, thisObj, newTarget); - __ Str(actualNumArgs, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - __ Ldr(codeAddr, MemoryOperand(jsfunc, JSFunctionBase::CODE_ENTRY_OFFSET)); - __ Blr(codeAddr); // then call jsFunction - PopAotArgs(assembler, expectedNumArgs); - PopAotEntryFrame(assembler, glue); - // pop arg0, arg1 from stack - __ Add(sp, sp, Immediate(2 * FRAME_SLOT_SIZE)); // 2 : 2 means pairs - __ Ret(); +void AssemblerStubs::PopOptimizedJSFunctionFrame(ExtendedAssembler *assembler) +{ + TempRegister2Scope temp2Scope(assembler); + Register sp(SP); + Register frameType = __ TempRegister2(); + // 2 : 2 means pop call site sp and type + __ Ldp(Register(X19), frameType, MemoryOperand(sp, FRAME_SLOT_SIZE * 2, AddrMode::POSTINDEX)); + __ RestoreFpAndLr(); } void AssemblerStubs::PushOptimizedFrame(ExtendedAssembler *assembler, Register callSiteSp) @@ -1928,9 +1900,7 @@ void AssemblerStubs::PushOptimizedFrame(ExtendedAssembler *assembler, Register c void AssemblerStubs::PopOptimizedFrame(ExtendedAssembler *assembler) { - Register fp(X29); Register sp(SP); - Register prevFp(X1); // 2 : 2 means pop call site sp and type __ Add(sp, sp, Immediate(2 * FRAME_SLOT_SIZE)); __ RestoreFpAndLr(); @@ -1952,10 +1922,12 @@ void AssemblerStubs::JSCallWithArgV(ExtendedAssembler *assembler) __ Mov(callsiteSp, sp); PushOptimizedFrame(assembler, callsiteSp); __ Cbz(actualNumArgs, &pushCallThis); - TempRegister1Scope scope1(assembler); - Register tmp = __ TempRegister1(); - __ Mov(tmp, actualNumArgs); - CopyArgumentWithArgV(assembler, tmp, argV); + { + TempRegister1Scope scope1(assembler); + Register tmp = __ TempRegister1(); + __ Mov(tmp, actualNumArgs); + CopyArgumentWithArgV(assembler, tmp, argV); + } __ Bind(&pushCallThis); PushMandatoryJSArgs(assembler, jsfunc, thisObj, newTarget); __ Add(actualNumArgs, actualNumArgs, Immediate(NUM_MANDATORY_JSFUNC_ARGS)); @@ -1963,7 +1935,7 @@ void AssemblerStubs::JSCallWithArgV(ExtendedAssembler *assembler) __ CallAssemblerStub(RTSTUB_ID(JSCall), false); __ Ldr(actualNumArgs, MemoryOperand(sp, 0)); - PopAotArgs(assembler, actualNumArgs); + PopAotArgs(assembler, actualNumArgs, actualNumArgs); PopOptimizedFrame(assembler); __ Ret(); } diff --git a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.h b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.h index 18a29ead91..5c86e21071 100644 --- a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.h +++ b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.h @@ -104,8 +104,6 @@ public: static void CallSetter(ExtendedAssembler *assembler); - static void CallOptimizedJSFunction(ExtendedAssembler *assembler); - static void JSCallWithArgV(ExtendedAssembler *assembler); private: @@ -169,11 +167,16 @@ private: static void CopyArgumentWithArgV(ExtendedAssembler *assembler, Register argc, Register argV); static void PushMandatoryJSArgs(ExtendedAssembler *assembler, Register jsfunc, Register thisObj, Register newTarget); - static void PopAotArgs(ExtendedAssembler *assembler, Register expectedNumArgs); + static void PopAotArgs(ExtendedAssembler *assembler, Register expectedNumArgs, Register actualNumArgs); static void PushAotEntryFrame(ExtendedAssembler *assembler, Register prevFp); static void PopAotEntryFrame(ExtendedAssembler *assembler, Register glue); static void PushOptimizedFrame(ExtendedAssembler *assembler, Register callSiteSp); static void PopOptimizedFrame(ExtendedAssembler *assembler); + static void IncreaseStackForArguments(ExtendedAssembler *assembler, Register argC, Register fp); + static void PushOptimizedJSFunctionFrame(ExtendedAssembler *assembler); + static void PopOptimizedJSFunctionFrame(ExtendedAssembler *assembler); + static void PushLeaveFrame(ExtendedAssembler *assembler, Register glue, bool isBuiltin); + static void PopLeaveFrame(ExtendedAssembler *assembler, bool isBuiltin); }; } // namespace panda::ecmascript::x64 #endif // ECMASCRIPT_COMPILER_ASSEMBLER_MODULE_X64_H diff --git a/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp b/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp index 7793d29537..5691a7c75d 100644 --- a/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp +++ b/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp @@ -298,7 +298,6 @@ void AssemblerStubsX64::OptimizedCallAsmInterpreter(ExtendedAssembler *assembler // current sp - 8: type void AssemblerStubsX64::CallBuiltinTrampoline(ExtendedAssembler *assembler) { - __ BindAssemblerStub(RTSTUB_ID(CallBuiltinTrampoline)); Register glueReg = rax; __ Pushq(rbp); __ Movq(rsp, rbp); @@ -475,7 +474,7 @@ void AssemblerStubsX64::JSProxyCallInternalWithArgV(ExtendedAssembler *assembler __ Push(nativePointer); // native code address __ Push(rax); // pc __ Movq(glueReg, rax); - __ CallAssemblerStub(RTSTUB_ID(CallBuiltinTrampoline), true); + CallBuiltinTrampoline(assembler); } __ Bind(&lJSBoundFunction); @@ -741,7 +740,7 @@ void AssemblerStubsX64::JSCall(ExtendedAssembler *assembler) __ Push(nativePointer); // native code address __ Push(rax); // pc __ Movq(glueReg, rax); - __ CallAssemblerStub(RTSTUB_ID(CallBuiltinTrampoline), true); + CallBuiltinTrampoline(assembler); } __ Bind(&lJSBoundFunction); @@ -1955,41 +1954,6 @@ void AssemblerStubsX64::StackOverflowCheck([[maybe_unused]] ExtendedAssembler *a { } -void AssemblerStubsX64::CallOptimizedJSFunction(ExtendedAssembler *assembler) -{ - __ BindAssemblerStub(RTSTUB_ID(CallOptimizedJSFunction)); - Register glue(rdi); - Register prevFp(rsi); - Register jsfunc(rdx); - Register actualNumArgs(rcx); - Register thisObj(r8); - Register newTarget(r9); - Register codeAddr = __ AvailableRegister1(); - Register expectedNumArgs(r14); - Label pushCallThis; - TempRegisterScope scope(assembler); - Register argV(prevFp); - - __ Movq(rsp, rax); - __ Addq(8, rax); // 8 : 8 means argV offset to rsp - PushAotEntryFrame(assembler, prevFp); - __ Movq(rax, argV); - - PushArgsWithArgV(assembler, jsfunc, actualNumArgs, argV, &pushCallThis); - __ Bind(&pushCallThis); - __ Addq(NUM_MANDATORY_JSFUNC_ARGS, expectedNumArgs); // r14 - __ Addq(NUM_MANDATORY_JSFUNC_ARGS, actualNumArgs); - PushMandatoryJSArgs(assembler, jsfunc, thisObj, newTarget); - __ Addq(NUM_MANDATORY_JSFUNC_ARGS, actualNumArgs); - __ Pushq(actualNumArgs); - __ Movq(glue, rax); // mov glue to rax - __ Movq(Operand(jsfunc, JSFunctionBase::CODE_ENTRY_OFFSET), codeAddr); - __ Callq(codeAddr); // then call jsFunction - PopAotArgs(assembler, expectedNumArgs); - PopAotEntryFrame(assembler, glue); - __ Ret(); -} - void AssemblerStubsX64::PushMandatoryJSArgs(ExtendedAssembler *assembler, Register jsfunc, Register thisObj, Register newTarget) { diff --git a/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.h b/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.h index 479977a9e3..0d1c257669 100644 --- a/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.h +++ b/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.h @@ -82,8 +82,6 @@ public: static void ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler); - static void CallOptimizedJSFunction(ExtendedAssembler *assembler); - static void JSCallWithArgV(ExtendedAssembler *assembler); private: diff --git a/ecmascript/stubs/runtime_stubs.h b/ecmascript/stubs/runtime_stubs.h index 0e42ce1dad..a66454575a 100644 --- a/ecmascript/stubs/runtime_stubs.h +++ b/ecmascript/stubs/runtime_stubs.h @@ -50,7 +50,6 @@ using JSFunctionEntryType = uint64_t (*)(uintptr_t glue, uintptr_t prevFp, uint3 V(PushCallNewAndDispatchNative) \ V(PushCallIRangeAndDispatchNative) \ V(PushCallIThisRangeAndDispatch) \ - V(CallOptimizedJSFunction) \ V(JSCallWithArgV) \ V(ResumeRspAndDispatch) \ V(ResumeRspAndReturn) \ @@ -62,7 +61,6 @@ using JSFunctionEntryType = uint64_t (*)(uintptr_t glue, uintptr_t prevFp, uint3 V(JSCall) \ V(JSProxyCallInternalWithArgV) \ V(JSFunctionEntry) \ - V(CallBuiltinTrampoline) \ V(OptimizedCallOptimized) #define RUNTIME_STUB_WITHOUT_GC_LIST(V) \ diff --git a/test/aottest/calls/calls.ts b/test/aottest/calls/calls.ts index 352a82b64e..e155b5fba6 100644 --- a/test/aottest/calls/calls.ts +++ b/test/aottest/calls/calls.ts @@ -12,31 +12,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -declare function print(str:any):string; +declare function print(str: any): string; -function foo() -{ +function foo() { return "pass"; } -function foo1(a:any) -{ - return "pass"; +function foo1(a: any) { + return a + 1; } -function foo2(a:any, b:any) -{ - return "pass"; +function foo2(a: any, b: any) { + return a + b; } -function foo3(a:any, b:any, c:any) -{ - return "pass"; +function foo3(a: any, b: any, c: any) { + return a + b + c; } -function foo4(a:any, b:any, c:any, d:any) -{ - return "pass"; +function foo4(a: any, b: any, c: any, d: any) { + return a + b + c + d; } print(foo()); diff --git a/test/aottest/calls/expect_output.txt b/test/aottest/calls/expect_output.txt index 423bcc3c05..694b2edf96 100644 --- a/test/aottest/calls/expect_output.txt +++ b/test/aottest/calls/expect_output.txt @@ -12,7 +12,7 @@ # limitations under the License. pass -pass -pass -pass -pass +2 +3 +6 +10