mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 16:13:49 +00:00
fixed for asm interpreter call aot code
Signed-off-by: getingke <getingke@huawei.com> Change-Id: I93f24a015a058cbfe4453717bb80f2c31f63aa48
This commit is contained in:
parent
90ebfae1d8
commit
1bf120c82f
@ -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
|
||||||
|
@ -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) \
|
||||||
|
@ -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);
|
||||||
|
@ -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),
|
||||||
|
@ -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, ©Arguments);
|
||||||
|
{
|
||||||
|
[[maybe_unused]] TempRegister2Scope scope2(assembler);
|
||||||
|
Register undefinedValue = __ TempRegister2();
|
||||||
|
PushUndefinedWithArgc(assembler, tmp, undefinedValue, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
__ Bind(©Arguments);
|
||||||
|
{
|
||||||
|
__ 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(©ArgLoop);
|
||||||
|
__ 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, ©ArgLoop);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
@ -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
|
||||||
|
@ -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(©Arguments);
|
||||||
|
__ Subq(actualNumArgs, tmp);
|
||||||
|
PushUndefinedWithArgc(assembler, tmp);
|
||||||
|
}
|
||||||
|
__ Bind(©Arguments);
|
||||||
|
{
|
||||||
|
__ 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
|
||||||
|
@ -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
|
||||||
|
@ -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) \
|
||||||
|
Loading…
Reference in New Issue
Block a user