fixed for rewrite assembler stub for aarch64

Signed-off-by: getingke <getingke@huawei.com>
Change-Id: I9b5982bc1268725e7882fd95eeb2ba07f2851b6d
This commit is contained in:
getingke 2022-07-04 09:44:07 +08:00
parent 5964359c1e
commit e222260f9b
11 changed files with 248 additions and 347 deletions

View File

@ -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_;

View File

@ -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<VariableType, 3> 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<VariableType, 6> 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

View File

@ -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) \

View File

@ -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" ]

View File

@ -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<int64_t>(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, &copyArguments);
Register count(X9, W);
Register undefValue(X8);
__ Mov(count, tmp.W());
__ Mov(undefValue, Immediate(JSTaggedValue::VALUE_UNDEFINED));
__ Bind(&copyUndefined);
__ Sub(count, count, Immediate(1));
__ Cmp(count, actualNumArgs.W());
__ Str(undefValue, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ B(Condition::HI, &copyUndefined);
PushAotEntryFrame(assembler, prevFp);
Register argC(X7);
__ Cmp(expectedNumArgs, actualNumArgs);
__ CMov(argC, expectedNumArgs, actualNumArgs, Condition::HI);
IncreaseStackForArguments(assembler, argC, fp);
Label invokeCompiledJSFunction;
__ Bind(&copyArguments);
{
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(&copyArgLoop);
__ 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, &copyArgLoop);
TempRegister1Scope scope1(assembler);
TempRegister2Scope scope2(assembler);
Register argc = __ TempRegister1();
Register undefinedValue = __ TempRegister2();
__ Subs(argc, expectedNumArgs, Operand(actualNumArgs));
__ B(Condition::LS, &copyArguments);
PushUndefinedWithArgc(assembler, argc, undefinedValue, fp, nullptr);
}
__ Bind(&copyArguments);
__ 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<int64_t>(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, &copyArguments);
Register undefValue(X8);
__ Mov(undefValue, Immediate(JSTaggedValue::VALUE_UNDEFINED));
Label copyUndefined;
__ Bind(&copyUndefined);
__ Sub(count, count, Immediate(1));
__ Str(undefValue, MemoryOperand(sp, -FRAME_SLOT_SIZE, PREINDEX));
__ Cmp(count, actualNumArgs);
__ B(Condition::HI, &copyUndefined);
Label invokeCompiledJSFunction;
Register saveNumArgs(X19);
__ Bind(&copyArguments);
{
__ 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(&copyArgLoop);
__ 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, &copyArgLoop);
// 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, &copyArguments);
PushUndefinedWithArgc(assembler, tmp, undefinedValue, fp, nullptr);
}
__ Bind(&copyArguments);
__ 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<int64_t>(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<int64_t>(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<int64_t>(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<int64_t>(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, &copyBoundArgument);
__ Bind(&copyArgument);
{
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, &copyArgument);
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(&copyBoundArgument);
{
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(&copyBoundArgumentLoop);
{
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, &copyBoundArgumentLoop);
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<int64_t>(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<int64_t>(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();
}

View File

@ -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

View File

@ -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)
{

View File

@ -82,8 +82,6 @@ public:
static void ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler);
static void CallOptimizedJSFunction(ExtendedAssembler *assembler);
static void JSCallWithArgV(ExtendedAssembler *assembler);
private:

View File

@ -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) \

View File

@ -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());

View File

@ -12,7 +12,7 @@
# limitations under the License.
pass
pass
pass
pass
pass
2
3
6
10