fixed for asm interpreter call aot code

Signed-off-by: getingke <getingke@huawei.com>
Change-Id: I93f24a015a058cbfe4453717bb80f2c31f63aa48
This commit is contained in:
getingke 2022-06-17 18:26:05 +08:00
parent 90ebfae1d8
commit 1bf120c82f
9 changed files with 488 additions and 4 deletions

View File

@ -803,6 +803,47 @@ DEF_CALL_SIGNATURE(CallSetter)
PUSH_CALL_ARGS_AND_DISPATCH_NATIVE_RANGE_SIGNATURE(CallSetter) PUSH_CALL_ARGS_AND_DISPATCH_NATIVE_RANGE_SIGNATURE(CallSetter)
} }
DEF_CALL_SIGNATURE(AotCallArgs)
{
// 6 : 6 input parameters
CallSignature aotCallArgs("AotCallArgs", 0, 6,
ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
*callSign = aotCallArgs;
// 6 : 6 input parameters
std::array<VariableType, 6> params = {
VariableType::NATIVE_POINTER(), // glue
VariableType::NATIVE_POINTER(), // sp
VariableType::JS_ANY(), // jsfunc
VariableType::INT32(), // actualNumArgs
VariableType::JS_ANY(), // this
VariableType::JS_ANY(), // new
};
callSign->SetVariadicArgs(true);
callSign->SetParameters(params.data());
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
callSign->SetCallConv(CallSignature::CallConv::CCallConv);
}
DEF_CALL_SIGNATURE(AotCallWithArgV)
{
// 1 : 1 input parameters
CallSignature aotCallWithArgV("AotCallWithArgV", 0, 6,
ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
*callSign = aotCallWithArgV;
// 1 : 1 input parameters
std::array<VariableType, 6> params = {
VariableType::NATIVE_POINTER(), // glue
VariableType::NATIVE_POINTER(), // sp
VariableType::JS_ANY(), // jsfunc
VariableType::INT32(), // actualNumArgs
VariableType::JS_ANY(), // this
VariableType::NATIVE_POINTER(), // argV
};
callSign->SetParameters(params.data());
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
callSign->SetCallConv(CallSignature::CallConv::CCallConv);
}
DEF_CALL_SIGNATURE(DebugPrint) DEF_CALL_SIGNATURE(DebugPrint)
{ {
// 1 : 1 input parameters // 1 : 1 input parameters

View File

@ -328,6 +328,8 @@ private:
V(PushCallNewAndDispatch) \ V(PushCallNewAndDispatch) \
V(CallGetter) \ V(CallGetter) \
V(CallSetter) \ V(CallSetter) \
V(AotCallArgs) \
V(AotCallWithArgV) \
V(ResumeRspAndDispatch) \ V(ResumeRspAndDispatch) \
V(ResumeRspAndReturn) \ V(ResumeRspAndReturn) \
V(ResumeCaughtFrameAndDispatch) \ V(ResumeCaughtFrameAndDispatch) \

View File

@ -353,7 +353,7 @@ DECLARE_ASM_HANDLER(HandleNewObjDynRangePrefImm16V8)
GateRef firstArgRegIdx = ZExtInt8ToInt16(ReadInst8_3(pc)); GateRef firstArgRegIdx = ZExtInt8ToInt16(ReadInst8_3(pc));
GateRef firstArgOffset = Int16(2); GateRef firstArgOffset = Int16(2);
GateRef ctor = GetVregValue(sp, ZExtInt16ToPtr(firstArgRegIdx)); GateRef ctor = GetVregValue(sp, ZExtInt16ToPtr(firstArgRegIdx));
GateRef actualNumArgs = ZExtInt16ToPtr(Int16Sub(numArgs, firstArgOffset)); GateRef actualNumArgs = ZExtInt16ToInt32(Int16Sub(numArgs, firstArgOffset));
Label ctorIsHeapObject(env); Label ctorIsHeapObject(env);
Label ctorIsJSFunction(env); Label ctorIsJSFunction(env);
@ -409,7 +409,7 @@ DECLARE_ASM_HANDLER(HandleNewObjDynRangePrefImm16V8)
PtrAdd(firstArgRegIdx, firstArgOffset), IntPtr(8))); // 8: skip function&this PtrAdd(firstArgRegIdx, firstArgOffset), IntPtr(8))); // 8: skip function&this
res = JSCallDispatch(glue, ctor, actualNumArgs, res = JSCallDispatch(glue, ctor, actualNumArgs,
JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV, JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV,
{ actualNumArgs, argv, *thisObj }); { ChangeInt32ToIntPtr(actualNumArgs), argv, *thisObj });
Jump(&threadCheck); Jump(&threadCheck);
} }
Bind(&slowPath); Bind(&slowPath);

View File

@ -575,7 +575,7 @@ GateRef Stub::CallGetterHelper(GateRef glue, GateRef receiver, GateRef holder, G
} }
Bind(&objNotUndefined); Bind(&objNotUndefined);
{ {
auto retValue = JSCallDispatch(glue, getter, IntPtr(0), auto retValue = JSCallDispatch(glue, getter, Int32(0),
JSCallMode::CALL_GETTER, { receiver }); JSCallMode::CALL_GETTER, { receiver });
Label noPendingException(env); Label noPendingException(env);
Branch(HasPendingException(glue), &exit, &noPendingException); Branch(HasPendingException(glue), &exit, &noPendingException);
@ -623,7 +623,7 @@ GateRef Stub::CallSetterHelper(GateRef glue, GateRef receiver, GateRef accessor,
} }
Bind(&objNotUndefined); Bind(&objNotUndefined);
{ {
auto retValue = JSCallDispatch(glue, setter, IntPtr(1), auto retValue = JSCallDispatch(glue, setter, Int32(1),
JSCallMode::CALL_SETTER, { receiver, value }); JSCallMode::CALL_SETTER, { receiver, value });
Label noPendingException(env); Label noPendingException(env);
Branch(HasPendingException(glue), &exit, &noPendingException); Branch(HasPendingException(glue), &exit, &noPendingException);
@ -4010,6 +4010,67 @@ GateRef Stub::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNumArgs,
sp = PtrArgument(static_cast<size_t>(InterpreterHandlerInputs::SP)); sp = PtrArgument(static_cast<size_t>(InterpreterHandlerInputs::SP));
} }
{ {
if (env->IsAsmInterp()) {
Label methodisAot(env);
Label methodNotAot(env);
GateRef isAotMask = Int64(static_cast<uint64_t>(1) << JSMethod::IsAotCodeBit::START_BIT);
Branch(Int64Equal(Int64And(callField, isAotMask), Int64(0)), &methodNotAot, &methodisAot);
Bind(&methodisAot);
{
GateRef newTarget = Undefined();
GateRef thisValue = Undefined();
switch (mode) {
case JSCallMode::CALL_ARG0:
result = CallNGCRuntime(glue, RTSTUB_ID(AotCallArgs),
{ glue, sp, func, actualNumArgs, thisValue, newTarget });
Jump(&exit);
break;
case JSCallMode::CALL_ARG1:
result = CallNGCRuntime(glue, RTSTUB_ID(AotCallArgs),
{ glue, sp, func, actualNumArgs,
thisValue, newTarget, data[0] });
Jump(&exit);
break;
case JSCallMode::CALL_ARG2:
result = CallNGCRuntime(glue, RTSTUB_ID(AotCallArgs),
{ glue, sp, func, actualNumArgs, thisValue, newTarget, data[0], data[1] });
Jump(&exit);
break;
case JSCallMode::CALL_ARG3:
result = CallNGCRuntime(glue, RTSTUB_ID(AotCallArgs),
{ glue, sp, func, actualNumArgs, thisValue,
newTarget, data[0], data[1], data[2] }); // 2: args2
Jump(&exit);
break;
case JSCallMode::CALL_THIS_WITH_ARGV:
thisValue = data[2]; // 2: this input
[[fallthrough]];
case JSCallMode::CALL_WITH_ARGV:
result = CallNGCRuntime(glue, RTSTUB_ID(AotCallWithArgV),
{ glue, sp, func, actualNumArgs, thisValue, data[1] });
Jump(&exit);
break;
case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
result = CallNGCRuntime(glue, RTSTUB_ID(AotCallWithArgV),
{ glue, sp, func, actualNumArgs, data[2], data[1]});
Jump(&exit);
break;
case JSCallMode::CALL_GETTER:
result = CallNGCRuntime(glue, RTSTUB_ID(AotCallArgs),
{ glue, sp, func, actualNumArgs, data[0], newTarget});
Jump(&exit);
break;
case JSCallMode::CALL_SETTER:
result = CallNGCRuntime(glue, RTSTUB_ID(AotCallArgs),
{ glue, sp, func, actualNumArgs, data[1], newTarget, data[0]});
Jump(&exit);
break;
default:
UNREACHABLE();
}
}
Bind(&methodNotAot);
}
switch (mode) { switch (mode) {
case JSCallMode::CALL_ARG0: case JSCallMode::CALL_ARG0:
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgs0AndDispatch), result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgs0AndDispatch),

View File

@ -1832,4 +1832,187 @@ void AssemblerStubs::PushArgsSlowPath(ExtendedAssembler *assembler, Register &gl
PushArgsFastPath(assembler, glueRegister, argcRegister, argvRegister, callTargetRegister, methodRegister, PushArgsFastPath(assembler, glueRegister, argcRegister, argvRegister, callTargetRegister, methodRegister,
prevSpRegister, fpRegister, callFieldRegister); prevSpRegister, fpRegister, callFieldRegister);
} }
void AssemblerStubs::PushArgsWithArgV(ExtendedAssembler *assembler, Register jsfunc,
Register actualNumArgs, Register argV, Label *pushCallThis)
{
Register expectedNumArgs(X19); // output
[[maybe_unused]] TempRegister1Scope scope1(assembler);
Register tmp = __ TempRegister1();
Label copyArguments;
// get expected num Args
__ Ldr(tmp, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET));
__ Ldr(tmp, MemoryOperand(tmp, JSMethod::GetCallFieldOffset(false)));
__ Lsr(tmp, tmp, JSMethod::NumArgsBits::START_BIT);
__ And(tmp.W(), tmp.W(),
LogicalImmediate::Create(JSMethod::NumArgsBits::Mask() >> JSMethod::NumArgsBits::START_BIT, RegWSize));
__ Mov(expectedNumArgs.W(), tmp.W());
__ Subs(tmp.W(), tmp.W(), actualNumArgs.W());
__ B(Condition::LS, &copyArguments);
{
[[maybe_unused]] TempRegister2Scope scope2(assembler);
Register undefinedValue = __ TempRegister2();
PushUndefinedWithArgc(assembler, tmp, undefinedValue, nullptr);
}
__ Bind(&copyArguments);
{
__ Mov(tmp, expectedNumArgs);
// expectedNumArgs <= actualNumArgs
__ Cmp(tmp.W(), actualNumArgs.W());
__ CMov(tmp, tmp.W(), actualNumArgs.W(), Condition::LO);
__ Cbz(tmp, pushCallThis);
CopyArgumentWithArgV(assembler, tmp, argV);
}
}
void AssemblerStubs::CopyArgumentWithArgV(ExtendedAssembler *assembler, Register argc, Register argV)
{
[[maybe_unused]] TempRegister2Scope scope2(assembler);
Register argVEnd = __ AvailableRegister1();
Register sp(SP);
Label copyArgLoop;
Register arg = __ TempRegister2();
__ Sub(argVEnd.W(), argc, Immediate(1));
__ Add(argVEnd, argV, Operand(argVEnd.W(), UXTW, 3));
__ Bind(&copyArgLoop);
__ Ldr(arg, MemoryOperand(argVEnd, -FRAME_SLOT_SIZE, AddrMode::POSTINDEX));
__ Subs(argc, argc, Immediate(1));
__ Str(arg, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ B(Condition::NE, &copyArgLoop);
}
void AssemblerStubs::PushMandatoryJSArgs(ExtendedAssembler *assembler, Register jsfunc,
Register thisObj, Register newTarget)
{
Register sp(SP);
__ Str(thisObj, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Str(newTarget, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Str(jsfunc, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
}
void AssemblerStubs::PopAotArgs(ExtendedAssembler *assembler, Register expectedNumArgs)
{
Register sp(SP);
__ Add(sp, sp, Operand(expectedNumArgs, UXTW, 3));
__ Add(sp, sp, Immediate(FRAME_SLOT_SIZE));
}
void AssemblerStubs::PushAotEntryFrame(ExtendedAssembler *assembler, Register prevFp)
{
Register fp(X29);
Register sp(SP);
TempRegister2Scope temp1Scope(assembler);
__ 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 = __ TempRegister2();;
// construct frame
__ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::OPTIMIZED_ENTRY_FRAME)));
__ Stp(prevFp, frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
}
void AssemblerStubs::PopAotEntryFrame(ExtendedAssembler *assembler, Register glue)
{
Register fp(X29);
Register sp(SP);
Register prevFp(X1);
// 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));
}
// AotCallArgs
// Input:
// x0 - glue
// x1 - sp
// x2 - jsfunc
// x3 - actualNumArgs
// x4 - thisObj
// x5 - newTarget
// ...
void AssemblerStubs::AotCallArgs(ExtendedAssembler *assembler)
{
__ BindAssemblerStub(RTSTUB_ID(AotCallArgs));
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
__ 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);
}
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));
__ Ret();
}
void AssemblerStubs::AotCallWithArgV(ExtendedAssembler *assembler)
{
__ BindAssemblerStub(RTSTUB_ID(AotCallWithArgV));
Register sp(SP);
Register glue(X0);
Register prevFp(X1);
Register jsfunc(X2);
Register actualNumArgs(X3);
Register thisObj(X4);
Register argV(X5);
Register codeAddr = __ AvailableRegister1();
Register expectedNumArgs(X19);
Label pushCallThis;
PushAotEntryFrame(assembler, prevFp);
PushArgsWithArgV(assembler, jsfunc, actualNumArgs, argV, &pushCallThis);
__ Bind(&pushCallThis);
__ Add(expectedNumArgs, expectedNumArgs, Immediate(NUM_MANDATORY_JSFUNC_ARGS));
__ Add(actualNumArgs, actualNumArgs, Immediate(NUM_MANDATORY_JSFUNC_ARGS));
{
[[maybe_unused]] TempRegister1Scope scope1(assembler);
Register newTarget = __ TempRegister1();
__ Mov(newTarget, JSTaggedValue::VALUE_UNDEFINED);
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);
__ Ret();
}
} // panda::ecmascript::aarch64 } // panda::ecmascript::aarch64

View File

@ -100,6 +100,10 @@ public:
static void CallSetter(ExtendedAssembler *assembler); static void CallSetter(ExtendedAssembler *assembler);
static void AotCallArgs(ExtendedAssembler *assembler);
static void AotCallWithArgV(ExtendedAssembler *assembler);
private: private:
static void JSCallBody(ExtendedAssembler *assembler, Register jsfunc); static void JSCallBody(ExtendedAssembler *assembler, Register jsfunc);
@ -164,6 +168,14 @@ private:
Register &declaredNumArgsRegister, Register &argcRegister, Register &argvRegister, Register &callTargetRegister, Register &declaredNumArgsRegister, Register &argcRegister, Register &argvRegister, Register &callTargetRegister,
Register &methodRegister, Register &prevSpRegister, Register &callFieldRegister); Register &methodRegister, Register &prevSpRegister, Register &callFieldRegister);
static void OptimizedCallAsmInterpreter(ExtendedAssembler *assembler); static void OptimizedCallAsmInterpreter(ExtendedAssembler *assembler);
static void PushArgsWithArgV(ExtendedAssembler *assembler, Register jsfunc,
Register actualNumArgs, Register argV, Label *pushCallThis);
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 PushAotEntryFrame(ExtendedAssembler *assembler, Register prevFp);
static void PopAotEntryFrame(ExtendedAssembler *assembler, Register glue);
}; };
} // namespace panda::ecmascript::x64 } // namespace panda::ecmascript::x64
#endif // ECMASCRIPT_COMPILER_ASSEMBLER_MODULE_X64_H #endif // ECMASCRIPT_COMPILER_ASSEMBLER_MODULE_X64_H

View File

@ -2029,6 +2029,17 @@ void AssemblerStubsX64::PushUndefinedWithArgc(ExtendedAssembler *assembler, Regi
__ Ja(&loopBeginning); __ Ja(&loopBeginning);
} }
void AssemblerStubsX64::CopyArgumentWithArgV(ExtendedAssembler *assembler, Register argc, Register argV)
{
Label loopBeginning;
Register arg = __ AvailableRegister1();
__ Bind(&loopBeginning);
__ Movq(Operand(argV, argc, Scale::Times8, -8), arg); // -8: stack index
__ Pushq(arg);
__ Subq(1, argc);
__ Ja(&loopBeginning);
}
void AssemblerStubsX64::HasPendingException([[maybe_unused]] ExtendedAssembler *assembler, void AssemblerStubsX64::HasPendingException([[maybe_unused]] ExtendedAssembler *assembler,
[[maybe_unused]] Register threadRegister) [[maybe_unused]] Register threadRegister)
{ {
@ -2037,5 +2048,165 @@ void AssemblerStubsX64::HasPendingException([[maybe_unused]] ExtendedAssembler *
void AssemblerStubsX64::StackOverflowCheck([[maybe_unused]] ExtendedAssembler *assembler) void AssemblerStubsX64::StackOverflowCheck([[maybe_unused]] ExtendedAssembler *assembler)
{ {
} }
// AotCallArgs
// Input:
// %rdi - glue
// %rsi - sp
// %rdx - jsfunc
// %rcx - actualNumArgs
// %r8 - thisObj
// %r9 - newTarget
// ...
void AssemblerStubsX64::AotCallArgs(ExtendedAssembler *assembler)
{
__ BindAssemblerStub(RTSTUB_ID(AotCallArgs));
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)
{
__ Pushq(thisObj);
__ Pushq(newTarget);
__ Pushq(jsfunc);
}
// output expectedNumArgs (r14)
void AssemblerStubsX64::PushArgsWithArgV(ExtendedAssembler *assembler, Register jsfunc,
Register actualNumArgs, Register argV, Label *pushCallThis)
{
Register expectedNumArgs(r14); // output
Register tmp(rax);
Label align16Bytes;
Label copyArguments;
// get expected num Args
__ Movq(Operand(jsfunc, JSFunctionBase::METHOD_OFFSET), tmp);
__ Movq(Operand(tmp, JSMethod::GetCallFieldOffset(false)), tmp);
__ Shr(JSMethod::NumArgsBits::START_BIT, tmp);
__ Andl(((1LU << JSMethod::NumArgsBits::SIZE) - 1), tmp);
__ Mov(tmp, expectedNumArgs);
__ Testb(1, expectedNumArgs);
__ Jne(&align16Bytes);
__ PushAlignBytes();
__ Bind(&align16Bytes);
{
__ Cmpq(actualNumArgs, expectedNumArgs);
__ Jbe(&copyArguments);
__ Subq(actualNumArgs, tmp);
PushUndefinedWithArgc(assembler, tmp);
}
__ Bind(&copyArguments);
{
__ Cmpq(actualNumArgs, expectedNumArgs);
__ Movq(actualNumArgs, tmp); // rax -> actualNumArgsReg
__ CMovbe(expectedNumArgs, tmp);
__ Cmpq(0, tmp);
__ Je(pushCallThis);
CopyArgumentWithArgV(assembler, tmp, argV);
}
}
void AssemblerStubsX64::PopAotArgs(ExtendedAssembler *assembler, Register expectedNumArgs)
{
__ Addq(1, expectedNumArgs);
__ Andq(~1, expectedNumArgs);
__ Leaq(Operand(expectedNumArgs, Scale::Times8, 0), expectedNumArgs);
__ Addq(expectedNumArgs, rsp);
__ Addq(8, rsp); // 8: skip r14
}
void AssemblerStubsX64::PushAotEntryFrame(ExtendedAssembler *assembler, Register prevFp)
{
__ PushCppCalleeSaveRegisters();
__ Pushq(rdi);
// construct optimized entry frame
__ Pushq(rbp);
__ Movq(rsp, rbp);
__ Pushq(static_cast<int64_t>(FrameType::OPTIMIZED_ENTRY_FRAME));
__ Pushq(prevFp);
}
void AssemblerStubsX64::PopAotEntryFrame(ExtendedAssembler *assembler, Register glue)
{
Register prevFp(rsi);
__ Popq(prevFp);
__ Addq(8, rsp); // 8: frame type
__ Popq(rbp);
__ Popq(glue); // caller restore
__ PopCppCalleeSaveRegisters(); // callee restore
__ Movq(prevFp, Operand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
}
// AotCallArgWithArgV
// Input:
// %rdi - glue
// %rsi - sp
// %rdx - jsfunc
// %rcx - actualNumArgs
// %r8 - this
// %r9 - argV
void AssemblerStubsX64::AotCallWithArgV(ExtendedAssembler *assembler)
{
__ BindAssemblerStub(RTSTUB_ID(AotCallWithArgV));
Register glue(rdi);
Register prevFp(rsi);
Register jsfunc(rdx);
Register actualNumArgs(rcx);
Register thisObj(r8);
Register argV(r9);
Register codeAddr = __ AvailableRegister1();
Register expectedNumArgs(r14);
Label pushCallThis;
PushAotEntryFrame(assembler, prevFp);
PushArgsWithArgV(assembler, jsfunc, actualNumArgs, argV, &pushCallThis);
__ Bind(&pushCallThis);
__ Addq(NUM_MANDATORY_JSFUNC_ARGS, expectedNumArgs); // r14
__ Addq(NUM_MANDATORY_JSFUNC_ARGS, actualNumArgs);
Register newTarget(r9);
__ Movq(JSTaggedValue::VALUE_UNDEFINED, newTarget);
PushMandatoryJSArgs(assembler, jsfunc, thisObj, newTarget);
__ 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();
}
#undef __ #undef __
} // namespace panda::ecmascript::x64 } // namespace panda::ecmascript::x64

View File

@ -77,6 +77,10 @@ public:
static void ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler); static void ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler);
static void AotCallArgs(ExtendedAssembler *assembler);
static void AotCallWithArgV(ExtendedAssembler *assembler);
private: private:
static void PushArgsFastPath(ExtendedAssembler *assembler, Register glueRegister, Register argcRegister, static void PushArgsFastPath(ExtendedAssembler *assembler, Register glueRegister, Register argcRegister,
Register argvRegister, Register callTargetRegister, Register methodRegister, Register prevSpRegister, Register argvRegister, Register callTargetRegister, Register methodRegister, Register prevSpRegister,
@ -119,6 +123,14 @@ private:
static void JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMode mode, static void JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMode mode,
Label *fastPathEntry, Label *pushCallThis); Label *fastPathEntry, Label *pushCallThis);
static void OptimizedCallAsmInterpreter(ExtendedAssembler *assembler); static void OptimizedCallAsmInterpreter(ExtendedAssembler *assembler);
static void PushArgsWithArgV(ExtendedAssembler *assembler, Register jsfunc,
Register actualNumArgs, Register argV, Label *pushCallThis);
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 PushAotEntryFrame(ExtendedAssembler *assembler, Register prevFp);
static void PopAotEntryFrame(ExtendedAssembler *assembler, Register glue);
}; };
} // namespace panda::ecmascript::x64 } // namespace panda::ecmascript::x64
#endif // ECMASCRIPT_COMPILER_ASSEMBLER_MODULE_X64_H #endif // ECMASCRIPT_COMPILER_ASSEMBLER_MODULE_X64_H

View File

@ -49,6 +49,8 @@ using JSFunctionEntryType = uint64_t (*)(uintptr_t glue, uintptr_t prevFp, uint3
V(PushCallNewAndDispatchNative) \ V(PushCallNewAndDispatchNative) \
V(PushCallIRangeAndDispatchNative) \ V(PushCallIRangeAndDispatchNative) \
V(PushCallIThisRangeAndDispatch) \ V(PushCallIThisRangeAndDispatch) \
V(AotCallArgs) \
V(AotCallWithArgV) \
V(ResumeRspAndDispatch) \ V(ResumeRspAndDispatch) \
V(ResumeRspAndReturn) \ V(ResumeRspAndReturn) \
V(ResumeCaughtFrameAndDispatch) \ V(ResumeCaughtFrameAndDispatch) \