!1658 Refactor Entry frame

Merge pull request !1658 from 孙哲/master
This commit is contained in:
openharmony_ci 2022-06-24 06:21:00 +00:00 committed by Gitee
commit 6561159387
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
7 changed files with 240 additions and 436 deletions

View File

@ -97,10 +97,10 @@ void ExtendedAssembler::RestoreLrAndFp()
Ldp(Register(X30), Register(X29), MemoryOperand(sp, 16, POSTINDEX)); // 16: 2 registers
}
void ExtendedAssembler::PushArgsWithArgv(Register argc, Register argv, Register op, panda::ecmascript::Label *next)
void ExtendedAssembler::PushArgsWithArgv(Register argc, Register argv, Register op,
Register fp, panda::ecmascript::Label *next)
{
Label loopBeginning;
Register sp(SP);
if (next != nullptr) {
Cmp(argc.W(), Immediate(0));
B(Condition::LS, next);
@ -108,20 +108,30 @@ void ExtendedAssembler::PushArgsWithArgv(Register argc, Register argv, Register
Add(argv, argv, Operand(argc.W(), UXTW, 3)); // 3: argc * 8
Bind(&loopBeginning);
Ldr(op, MemoryOperand(argv, -8, PREINDEX)); // -8: 8 bytes
Str(op, MemoryOperand(sp, -8, PREINDEX)); // -8: 8 bytes
Str(op, MemoryOperand(fp, -8, PREINDEX)); // -8: 8 bytes
Sub(argc.W(), argc.W(), Immediate(1));
Cbnz(argc.W(), &loopBeginning);
}
void ExtendedAssembler::PushArgc(int32_t argc, Register op)
void ExtendedAssembler::PushArgc(int32_t argc, Register op, Register fp)
{
Mov(op, Immediate(JSTaggedValue(argc).GetRawData()));
Str(op, MemoryOperand(Register(SP), -8, PREINDEX)); // -8: 8 bytes
Str(op, MemoryOperand(fp, -8, PREINDEX)); // -8: 8 bytes
}
void ExtendedAssembler::PushArgc(Register argc, Register op)
void ExtendedAssembler::PushArgc(Register argc, Register op, Register fp)
{
Orr(op, argc, LogicalImmediate::Create(JSTaggedValue::TAG_INT, RegXSize));
Str(op, MemoryOperand(Register(SP), -8, PREINDEX)); // -8: 8 bytes
Str(op, MemoryOperand(fp, -8, PREINDEX)); // -8: 8 bytes
}
void ExtendedAssembler::Align16(Register fp)
{
Label aligned;
Tst(fp, LogicalImmediate::Create(0xf, RegXSize)); // 0xf: 0x1111
B(Condition::EQ, &aligned);
// 8: frame slot size
Sub(fp, fp, Immediate(8));
Bind(&aligned);
}
} // namespace panda::ecmascript::aarch64

View File

@ -37,9 +37,11 @@ public:
void RestoreFpAndLr();
void SaveLrAndFp();
void RestoreLrAndFp();
void PushArgsWithArgv(Register argc, Register argv, Register op, panda::ecmascript::Label *next);
void PushArgc(int32_t argc, Register op);
void PushArgc(Register argc, Register op);
void PushArgsWithArgv(Register argc, Register argv, Register op,
Register fp, panda::ecmascript::Label *next);
void PushArgc(int32_t argc, Register op, Register fp);
void PushArgc(Register argc, Register op, Register fp);
void Align16(Register fp);
Register TempRegister1()
{

View File

@ -686,9 +686,12 @@ void AssemblerStubs::CallRuntimeWithArgv(ExtendedAssembler *assembler)
// Generate code for entering asm interpreter
// c++ calling convention
// Input: %X0 - glue
// %X1 - argc
// %X2 - argv(<callTarget, newTarget, this> are at the beginning of argv)
// Input: glue - %X0
// callTarget - %X1
// method - %X2
// callField - %X3
// argc - %X4
// argv - %X5(<callTarget, newTarget, this> are at the beginning of argv)
void AssemblerStubs::AsmInterpreterEntry(ExtendedAssembler *assembler)
{
__ BindAssemblerStub(RTSTUB_ID(AsmInterpreterEntry));
@ -704,29 +707,26 @@ void AssemblerStubs::AsmInterpreterEntry(ExtendedAssembler *assembler)
}
}
// Input: glueRegister - %X0
// argcRegister - %X1
// argvRegister - %X2(<callTarget, newTarget, this> are at the beginning of argv)
// prevSpRegister - %X29
// Input: glue - %X0
// callTarget - %X1
// method - %X2
// callField - %X3
// argc - %X4
// argv - %X5(<callTarget, newTarget, this> are at the beginning of argv)
void AssemblerStubs::JSCallDispatch(ExtendedAssembler *assembler)
{
Label notJSFunction;
Label callNativeEntry;
Label callJSFunctionEntry;
Label pushArgsSlowPath;
Label callJSProxyEntry;
Label notCallable;
Register glueRegister(X0);
Register argcRegister(X1, W);
Register argvRegister(X2);
Register prevSpRegister(X29);
Register callTargetRegister(X3);
Register methodRegister(X4);
Register bitFieldRegister(X5);
Register tempRegister(X6); // can not be used to store any variable
Register functionTypeRegister(X7, W);
__ Ldr(callTargetRegister, MemoryOperand(argvRegister, 0));
Register argcRegister(X4, W);
Register argvRegister(X5);
Register callTargetRegister(X1);
Register callFieldRegister(X3);
Register bitFieldRegister(X16);
Register tempRegister(X17); // can not be used to store any variable
Register functionTypeRegister(X18, W);
__ Ldr(tempRegister, MemoryOperand(callTargetRegister, 0)); // hclass
__ Ldr(bitFieldRegister, MemoryOperand(tempRegister, JSHClass::BIT_FIELD_OFFSET));
__ And(functionTypeRegister, bitFieldRegister.W(), LogicalImmediate::Create(0xFF, RegWSize));
@ -741,39 +741,17 @@ void AssemblerStubs::JSCallDispatch(ExtendedAssembler *assembler)
__ Tst(bitFieldRegister,
LogicalImmediate::Create(static_cast<int64_t>(1ULL << JSHClass::CallableBit::START_BIT), RegXSize));
__ B(Condition::EQ, &notCallable);
__ Mov(tempRegister.W(), Immediate(static_cast<int64_t>(JSType::JS_PROXY)));
__ Cmp(functionTypeRegister, tempRegister.W());
__ B(Condition::EQ, &callJSProxyEntry);
// bound function branch, default native
__ Ldr(methodRegister, MemoryOperand(callTargetRegister, JSFunctionBase::METHOD_OFFSET));
// fall through
}
__ Bind(&callNativeEntry);
CallNativeEntry(assembler);
__ Bind(&callJSProxyEntry);
{
__ Ldr(methodRegister, MemoryOperand(callTargetRegister, JSProxy::METHOD_OFFSET));
__ B(&callNativeEntry);
}
__ Bind(&callJSFunctionEntry);
{
__ Ldr(methodRegister, MemoryOperand(callTargetRegister, JSFunctionBase::METHOD_OFFSET));
Register callFieldRegister(X7);
__ Ldr(callFieldRegister, MemoryOperand(methodRegister, JSMethod::GetCallFieldOffset(false)));
__ Tbnz(callFieldRegister, JSMethod::IsNativeBit::START_BIT, &callNativeEntry);
Register declaredNumArgsRegister(X9);
GetDeclaredNumArgsFromCallField(assembler, callFieldRegister, declaredNumArgsRegister);
__ Cmp(declaredNumArgsRegister.W(), argcRegister);
__ B(Condition::NE, &pushArgsSlowPath);
// fast path
__ PushFpAndLr();
Register fpRegister(X10);
__ Mov(fpRegister, Register(SP));
PushArgsFastPath(assembler, glueRegister, argcRegister, argvRegister, callTargetRegister, methodRegister,
prevSpRegister, fpRegister, callFieldRegister);
__ Bind(&pushArgsSlowPath);
PushArgsSlowPath(assembler, glueRegister, declaredNumArgsRegister, argcRegister, argvRegister,
callTargetRegister, methodRegister, prevSpRegister, callFieldRegister);
__ Add(argvRegister, argvRegister, Immediate(BuiltinFrame::RESERVED_CALL_ARGCOUNT * JSTaggedValue::TaggedTypeSize()));
JSCallCommonEntry(assembler, JSCallMode::CALL_ENTRY);
}
__ Bind(&notCallable);
{
@ -801,8 +779,8 @@ void AssemblerStubs::JSCallCommonEntry(ExtendedAssembler *assembler, JSCallMode
Register thisRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG2);
[[maybe_unused]] TempRegister1Scope scope(assembler);
Register tempArgcRegister = __ TempRegister1();
__ PushArgc(argcRegister, tempArgcRegister);
__ Str(thisRegister, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ PushArgc(argcRegister, tempArgcRegister, fpRegister);
__ Str(thisRegister, MemoryOperand(fpRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
jumpSize = 0;
}
@ -840,6 +818,7 @@ void AssemblerStubs::JSCallCommonEntry(ExtendedAssembler *assembler, JSCallMode
void AssemblerStubs::JSCallCommonFastPath(ExtendedAssembler *assembler, JSCallMode mode, Label *pushCallThis)
{
auto argc = kungfu::AssemblerModule::GetArgcFromJSCallMode(mode);
Register fpRegister = __ AvailableRegister1();
// call range
if (argc < 0) {
Register numRegister = __ AvailableRegister2();
@ -848,19 +827,19 @@ void AssemblerStubs::JSCallCommonFastPath(ExtendedAssembler *assembler, JSCallMo
__ Mov(numRegister, argcRegister);
[[maybe_unused]] TempRegister1Scope scope(assembler);
Register opRegister = __ TempRegister1();
__ PushArgsWithArgv(numRegister, argvRegister, opRegister, pushCallThis);
__ PushArgsWithArgv(numRegister, argvRegister, opRegister, fpRegister, pushCallThis);
} else if (argc > 0) {
Register arg0 = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG0);
Register arg1 = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1);
Register arg2 = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG2);
if (argc > 2) { // 2: call arg2
__ Str(arg2, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Str(arg2, MemoryOperand(fpRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
}
if (argc > 1) {
__ Str(arg1, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Str(arg1, MemoryOperand(fpRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
}
if (argc > 0) {
__ Str(arg0, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Str(arg0, MemoryOperand(fpRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
}
}
}
@ -871,7 +850,7 @@ void AssemblerStubs::JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMo
Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD);
Register argcRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGC);
Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGV);
Register fpRegister = __ AvailableRegister1();
Register arg0 = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG0);
Register arg1 = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1);
Label noExtraEntry;
@ -885,9 +864,9 @@ void AssemblerStubs::JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMo
[[maybe_unused]] TempRegister1Scope scope1(assembler);
Register tempArgcRegister = __ TempRegister1();
if (argc >= 0) {
__ PushArgc(argc, tempArgcRegister);
__ PushArgc(argc, tempArgcRegister, fpRegister);
} else {
__ PushArgc(argcRegister, tempArgcRegister);
__ PushArgc(argcRegister, tempArgcRegister, fpRegister);
}
// fall through
}
@ -897,7 +876,8 @@ void AssemblerStubs::JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMo
{
[[maybe_unused]] TempRegister1Scope scope(assembler);
Register tempRegister = __ TempRegister1();
PushUndefinedWithArgc(assembler, declaredNumArgsRegister, tempRegister, nullptr);
PushUndefinedWithArgc(assembler,
declaredNumArgsRegister, tempRegister, fpRegister, nullptr);
}
__ B(fastPathEntry);
return;
@ -911,7 +891,7 @@ void AssemblerStubs::JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMo
}
[[maybe_unused]] TempRegister2Scope scope2(assembler);
Register tempRegister = __ TempRegister2();
PushUndefinedWithArgc(assembler, diffRegister, tempRegister, &pushArgsEntry);
PushUndefinedWithArgc(assembler, diffRegister, tempRegister, fpRegister, &pushArgsEntry);
__ B(fastPathEntry);
}
// declare < actual
@ -930,19 +910,19 @@ void AssemblerStubs::JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMo
if (argc < 0) {
[[maybe_unused]] TempRegister1Scope scope(assembler);
Register opRegister = __ TempRegister1();
__ PushArgsWithArgv(declaredNumArgsRegister, argvRegister, opRegister, nullptr);
__ PushArgsWithArgv(declaredNumArgsRegister, argvRegister, opRegister, fpRegister, nullptr);
} else if (argc > 0) {
Label pushArgs0;
if (argc > 2) { // 2: call arg2
// decalare is 2 or 1 now
__ Cmp(declaredNumArgsRegister, Immediate(1));
__ B(Condition::EQ, &pushArgs0);
__ Str(arg1, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Str(arg1, MemoryOperand(fpRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
}
if (argc > 1) {
__ Bind(&pushArgs0);
// decalare is is 1 now
__ Str(arg0, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Str(arg0, MemoryOperand(fpRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
}
}
__ B(pushCallThis);
@ -958,8 +938,34 @@ Register AssemblerStubs::GetThisRegsiter(ExtendedAssembler *assembler, JSCallMod
return __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1);
case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
case JSCallMode::CALL_THIS_WITH_ARGV:
case JSCallMode::CALL_FROM_AOT:
return __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG2);
case JSCallMode::CALL_FROM_AOT:
case JSCallMode::CALL_ENTRY: {
Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1);
Register thisRegister = __ AvailableRegister2();
__ Ldur(thisRegister, MemoryOperand(argvRegister, -FRAME_SLOT_SIZE));
return thisRegister;
}
default:
UNREACHABLE();
}
return INVALID_REG;
}
Register AssemblerStubs::GetNewTargetRegsiter(ExtendedAssembler *assembler, JSCallMode mode)
{
switch (mode) {
case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
case JSCallMode::CALL_THIS_WITH_ARGV:
return __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET);
case JSCallMode::CALL_FROM_AOT:
case JSCallMode::CALL_ENTRY: {
Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1);
Register newTargetRegister = __ AvailableRegister2();
// 2: new Target index
__ Ldur(newTargetRegister, MemoryOperand(argvRegister, -2 * FRAME_SLOT_SIZE));
return newTargetRegister;
}
default:
UNREACHABLE();
}
@ -1051,33 +1057,45 @@ void AssemblerStubs::CallNativeWithArgv(ExtendedAssembler *assembler, bool callN
Register opArgc(X8);
Register opArgv(X9);
Register temp(X10);
Register stackArgs(X11);
Register sp(SP);
Register fpRegister(X11);
Register spRegister(SP);
Label pushThis;
PushBuiltinFrame(assembler, glue, FrameType::BUILTIN_FRAME_WITH_ARGV, temp);
PushBuiltinFrame(assembler, glue, FrameType::BUILTIN_FRAME_WITH_ARGV, temp, argc);
StackOverflowCheck(assembler);
__ Str(argc, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Mov(fpRegister, spRegister);
__ Mov(opArgc, argc);
__ Mov(opArgv, argv);
__ PushArgsWithArgv(opArgc, opArgv, temp, &pushThis);
__ PushArgsWithArgv(opArgc, opArgv, temp, fpRegister, &pushThis);
__ Bind(&pushThis);
__ Str(thisObj, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // this
// newTarget
if (callNew) {
__ Str(callTarget, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
// 16: this & newTarget
__ Stp(callTarget, thisObj, MemoryOperand(fpRegister, -16, AddrMode::PREINDEX));
} else {
__ Mov(temp, Immediate(JSTaggedValue::VALUE_UNDEFINED));
__ Str(temp, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
// 16: this & newTarget
__ Stp(temp, thisObj, MemoryOperand(fpRegister, -16, AddrMode::PREINDEX));
}
__ Str(callTarget, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // callTarget
__ Mov(stackArgs, sp);
// callTarget
__ Str(callTarget, MemoryOperand(fpRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Mov(spRegister, fpRegister);
CallNativeInternal(assembler, glue, argc, stackArgs, nativeCode);
Label call;
Label notAligned;
__ Tst(fpRegister, LogicalImmediate::Create(0xf, RegXSize)); // 0xf: 0x1111
__ B(Condition::NE, &notAligned);
// 16: xzr & stackArgs
__ Stp(fpRegister, Register(Zero), MemoryOperand(spRegister, -16, AddrMode::PREINDEX));
__ B(&call);
__ Bind(&notAligned);
// push stackArgs
__ Stur(fpRegister, MemoryOperand(fpRegister, -FRAME_SLOT_SIZE));
__ Sub(Register(SP), Register(SP), Immediate(FRAME_SLOT_SIZE));
__ Bind(&call);
CallNativeInternal(assembler, glue, argc, nativeCode);
__ Ret();
}
@ -1115,30 +1133,39 @@ void AssemblerStubs::PushCallArgsAndDispatchNative(ExtendedAssembler *assembler)
Register temp(X6);
Register fp(FP);
PushBuiltinFrame(assembler, glue, FrameType::BUILTIN_FRAME, temp);
PushBuiltinFrame(assembler, glue, FrameType::BUILTIN_FRAME, temp, argv);
__ Ldr(nativeCode, MemoryOperand(fp, BuiltinFrame::GetNativeCodeToFpDelta(false)));
__ Ldr(argc, MemoryOperand(fp, BuiltinFrame::GetNumArgsToFpDelta(false)));
__ Add(argv, fp, Immediate(BuiltinFrame::GetStackArgsToFpDelta(false)));
CallNativeInternal(assembler, glue, argc, argv, nativeCode);
CallNativeInternal(assembler, glue, argc, nativeCode);
__ Ret();
}
void AssemblerStubs::PushBuiltinFrame(ExtendedAssembler *assembler, Register glue, FrameType type, Register op)
void AssemblerStubs::PushBuiltinFrame(ExtendedAssembler *assembler, Register glue,
FrameType type, Register op, Register next)
{
__ SaveFpAndLr();
__ Str(Register(FP), MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
__ Mov(op, Immediate(static_cast<int32_t>(type)));
__ Str(op, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
if (type == FrameType::BUILTIN_FRAME) {
// push stack args
__ Add(next, Register(FP), Immediate(BuiltinFrame::GetStackArgsToFpDelta(false)));
// 16: type & next
__ Stp(next, op, MemoryOperand(Register(SP), -16, AddrMode::PREINDEX));
} else {
// 16: type & next
__ Stp(next, op, MemoryOperand(Register(SP), -16, AddrMode::PREINDEX));
}
}
void AssemblerStubs::CallNativeInternal(ExtendedAssembler *assembler, Register glue, Register numArgs,
Register stackArgs, Register nativeCode)
void AssemblerStubs::CallNativeInternal(ExtendedAssembler *assembler, Register glue,
Register numArgs, Register nativeCode)
{
GlueToThread(assembler, glue, glue);
ConstructEcmaRuntimeCallInfo(assembler, glue, numArgs, stackArgs);
__ And(numArgs, numArgs, LogicalImmediate::Create(0x00000000FFFFFFFF, RegXSize));
// 16: numArgs & glue
__ Stp(glue, numArgs, MemoryOperand(Register(SP), -16, AddrMode::PREINDEX));
// rsp is ecma callinfo base
__ Mov(Register(X0), Register(SP));
__ Blr(nativeCode);
@ -1415,13 +1442,14 @@ void AssemblerStubs::GeneratorReEnterAsmInterpDispatch(ExtendedAssembler *assemb
__ Ldr(nRegsRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_NREGS_OFFSET));
__ Ldr(regsArrayRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_REGS_ARRAY_OFFSET));
__ Add(regsArrayRegister, regsArrayRegister, Immediate(TaggedArray::DATA_OFFSET));
__ PushArgsWithArgv(nRegsRegister, regsArrayRegister, temp, &pushFrameState);
__ PushArgsWithArgv(nRegsRegister, regsArrayRegister, temp, fpRegister, &pushFrameState);
__ Bind(&pushFrameState);
__ Mov(newSp, spRegister);
__ Mov(newSp, fpRegister);
// push frame state
PushGeneratorFrameState(assembler, prevSpRegister, fpRegister, callTarget, method, contextRegister, pc, temp);
__ Align16(fpRegister);
__ Mov(Register(SP), fpRegister);
// call bc stub
CallBCStub(assembler, newSp, glue, callTarget, method, pc, temp);
}
@ -1430,7 +1458,7 @@ void AssemblerStubs::PushCallThis(ExtendedAssembler *assembler, JSCallMode mode)
{
Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD);
Register callTargetRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET);
Register sp(SP);
Register fpRegister = __ AvailableRegister1();
Label pushVregs;
Label pushNewTarget;
@ -1446,10 +1474,10 @@ void AssemblerStubs::PushCallThis(ExtendedAssembler *assembler, JSCallMode mode)
[[maybe_unused]] TempRegister1Scope scope1(assembler);
Register tempRegister = __ TempRegister1();
__ Mov(tempRegister, Immediate(JSTaggedValue::VALUE_UNDEFINED));
__ Str(tempRegister, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Str(tempRegister, MemoryOperand(fpRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
} else {
Register thisRegister = GetThisRegsiter(assembler, mode);
__ Str(thisRegister, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Str(thisRegister, MemoryOperand(fpRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
}
__ Bind(&pushNewTarget);
{
@ -1458,15 +1486,16 @@ void AssemblerStubs::PushCallThis(ExtendedAssembler *assembler, JSCallMode mode)
[[maybe_unused]] TempRegister1Scope scope1(assembler);
Register newTarget = __ TempRegister1();
__ Mov(newTarget, Immediate(JSTaggedValue::VALUE_UNDEFINED));
__ Str(newTarget, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Str(newTarget, MemoryOperand(fpRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
} else {
__ Str(callTargetRegister, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
Register newTargetRegister = GetNewTargetRegsiter(assembler, mode);
__ Str(newTargetRegister, MemoryOperand(fpRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
}
}
__ Bind(&pushCallTarget);
{
__ Tbz(callFieldRegister, JSMethod::HaveFuncBit::START_BIT, &pushVregs);
__ Str(callTargetRegister, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Str(callTargetRegister, MemoryOperand(fpRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
}
__ Bind(&pushVregs);
{
@ -1488,12 +1517,13 @@ void AssemblerStubs::PushVregs(ExtendedAssembler *assembler)
// args register can be reused now.
Register numVregsRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG0);
GetNumVregsFromCallField(assembler, callFieldRegister, numVregsRegister);
PushUndefinedWithArgc(assembler, numVregsRegister, tempRegister, &pushFrameStateAndCall);
PushUndefinedWithArgc(assembler, numVregsRegister,
tempRegister, fpRegister, &pushFrameStateAndCall);
// fall through
__ Bind(&pushFrameStateAndCall);
{
Register newSpRegister = __ AvailableRegister2();
__ Mov(newSpRegister, Register(SP));
__ Mov(newSpRegister, fpRegister);
StackOverflowCheck(assembler);
@ -1502,6 +1532,8 @@ void AssemblerStubs::PushVregs(ExtendedAssembler *assembler)
PushFrameState(assembler, prevSpRegister, fpRegister, callTargetRegister, methodRegister, pcRegister,
tempRegister);
__ Align16(fpRegister);
__ Mov(Register(SP), fpRegister);
DispatchCall(assembler, pcRegister, newSpRegister);
}
}
@ -1537,15 +1569,15 @@ void AssemblerStubs::DispatchCall(ExtendedAssembler *assembler, Register pcRegis
void AssemblerStubs::PushFrameState(ExtendedAssembler *assembler, Register prevSp, Register fp,
Register callTarget, Register method, Register pc, Register op)
{
Register sp(SP);
__ Mov(op, Immediate(static_cast<int32_t>(FrameType::ASM_INTERPRETER_FRAME)));
__ Stp(prevSp, op, MemoryOperand(sp, -16, AddrMode::PREINDEX)); // -16: frame type & prevSp
__ Stp(prevSp, op, MemoryOperand(fp, -16, AddrMode::PREINDEX)); // -16: frame type & prevSp
__ Ldr(pc, MemoryOperand(method, JSMethod::GetBytecodeArrayOffset(false)));
__ Stp(fp, pc, MemoryOperand(sp, -16, AddrMode::PREINDEX)); // -16: pc & fp
__ Mov(op, Register(SP));
__ Stp(op, pc, MemoryOperand(fp, -16, AddrMode::PREINDEX)); // -16: pc & fp
__ Ldr(op, MemoryOperand(callTarget, JSFunction::LEXICAL_ENV_OFFSET));
__ Stp(op, Register(Zero), MemoryOperand(sp, -16, AddrMode::PREINDEX)); // -16: jumpSizeAfterCall & env
__ Stp(op, Register(Zero), MemoryOperand(fp, -16, AddrMode::PREINDEX)); // -16: jumpSizeAfterCall & env
__ Mov(op, Immediate(JSTaggedValue::VALUE_HOLE));
__ Stp(callTarget, op, MemoryOperand(sp, -16, AddrMode::PREINDEX)); // -16: acc & callTarget
__ Stp(callTarget, op, MemoryOperand(fp, -16, AddrMode::PREINDEX)); // -16: acc & callTarget
}
void AssemblerStubs::GetNumVregsFromCallField(ExtendedAssembler *assembler, Register callField, Register numVregs)
@ -1566,7 +1598,7 @@ void AssemblerStubs::GetDeclaredNumArgsFromCallField(ExtendedAssembler *assemble
}
void AssemblerStubs::PushUndefinedWithArgc(ExtendedAssembler *assembler, Register argc, Register temp,
panda::ecmascript::Label *next)
Register fp, panda::ecmascript::Label *next)
{
if (next != nullptr) {
__ Cmp(argc.W(), Immediate(0));
@ -1575,7 +1607,7 @@ void AssemblerStubs::PushUndefinedWithArgc(ExtendedAssembler *assembler, Registe
Label loopBeginning;
__ Mov(temp, Immediate(JSTaggedValue::VALUE_UNDEFINED));
__ Bind(&loopBeginning);
__ Str(temp, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Str(temp, MemoryOperand(fp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Sub(argc.W(), argc.W(), Immediate(1));
__ Cbnz(argc.W(), &loopBeginning);
}
@ -1585,17 +1617,6 @@ void AssemblerStubs::GlueToThread(ExtendedAssembler *assembler, Register glue, R
__ Sub(thread, glue, Immediate(JSThread::GetGlueDataOffset()));
}
void AssemblerStubs::ConstructEcmaRuntimeCallInfo(ExtendedAssembler *assembler, Register thread, Register numArgs,
Register stackArgs)
{
Register sp(SP);
__ Sub(sp, sp, Immediate(sizeof(EcmaRuntimeCallInfo)));
__ Str(thread, MemoryOperand(sp, EcmaRuntimeCallInfo::GetThreadOffset()));
__ And(numArgs, numArgs, LogicalImmediate::Create(0x00000000FFFFFFFF, RegXSize));
__ Str(numArgs, MemoryOperand(sp, EcmaRuntimeCallInfo::GetNumArgsOffset()));
__ Str(stackArgs, MemoryOperand(sp, EcmaRuntimeCallInfo::GetStackArgsOffset()));
}
void AssemblerStubs::StackOverflowCheck([[maybe_unused]] ExtendedAssembler *assembler)
{
}
@ -1615,7 +1636,6 @@ void AssemblerStubs::PushAsmInterpEntryFrame(ExtendedAssembler *assembler, bool
Register frameTypeRegister = __ TempRegister2();
if (saveLeave) {
__ Str(glue, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
// prev managed fp is leave frame or nullptr(the first frame)
__ Ldr(prevFrameRegister, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
__ Mov(frameTypeRegister, Immediate(static_cast<int64_t>(FrameType::ASM_INTERPRETER_ENTRY_FRAME)));
@ -1628,7 +1648,8 @@ void AssemblerStubs::PushAsmInterpEntryFrame(ExtendedAssembler *assembler, bool
// 2 : 2 means pair
__ Stp(prevFrameRegister, frameTypeRegister, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Str(Register(Zero), MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // pc
// 2 : pc & glue
__ Stp(glue, Register(Zero), MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // pc
}
void AssemblerStubs::PopAsmInterpEntryFrame(ExtendedAssembler *assembler, bool saveLeave)
@ -1639,15 +1660,17 @@ void AssemblerStubs::PopAsmInterpEntryFrame(ExtendedAssembler *assembler, bool s
Register prevFrameRegister = __ TempRegister1();
[[maybe_unused]] TempRegister2Scope scope2(assembler);
Register glue = __ TempRegister2();
// skip pc
__ Add(sp, sp, Immediate(FRAME_SLOT_SIZE));
__ Ldr(prevFrameRegister, MemoryOperand(sp, FRAME_SLOT_SIZE, AddrMode::POSTINDEX));
// skip frame type
__ Add(sp, sp, Immediate(FRAME_SLOT_SIZE));
if (saveLeave) {
// 2: glue & pc
__ Ldp(glue, Register(Zero), MemoryOperand(sp, 2 * FRAME_SLOT_SIZE, AddrMode::POSTINDEX));
} else {
// 2: glue & pc
__ Add(sp, sp, Immediate(2 * FRAME_SLOT_SIZE));
}
// 2: skip frame type & prev
__ Ldp(prevFrameRegister, Register(Zero), MemoryOperand(sp, 2 * FRAME_SLOT_SIZE, AddrMode::POSTINDEX));
if (saveLeave) {
__ RestoreFpAndLr();
__ Ldr(glue, MemoryOperand(sp, FRAME_SLOT_SIZE, AddrMode::POSTINDEX));
__ Str(prevFrameRegister, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
} else {
__ RestoreLrAndFp();
@ -1661,10 +1684,9 @@ void AssemblerStubs::PushGeneratorFrameState(ExtendedAssembler *assembler, Regis
Register &fpRegister, Register &callTargetRegister, Register &methodRegister,
Register &contextRegister, Register &pcRegister, Register &operatorRegister)
{
Register sp(SP);
__ Mov(operatorRegister, Immediate(static_cast<int64_t>(FrameType::ASM_INTERPRETER_FRAME)));
// 2 : frameType and prevSp
__ Stp(prevSpRegister, operatorRegister, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Stp(prevSpRegister, operatorRegister, MemoryOperand(fpRegister, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Ldr(pcRegister, MemoryOperand(methodRegister, JSMethod::GetBytecodeArrayOffset(false)));
// offset need 8 align, GENERATOR_NREGS_OFFSET instead of GENERATOR_BC_OFFSET_OFFSET
__ Ldr(operatorRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_NREGS_OFFSET));
@ -1673,23 +1695,21 @@ void AssemblerStubs::PushGeneratorFrameState(ExtendedAssembler *assembler, Regis
__ Add(pcRegister, operatorRegister, pcRegister);
__ Add(pcRegister, pcRegister, Immediate(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8)));
// pc and fp
__ Stp(fpRegister, pcRegister, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // 2 : 2 means pair
__ Mov(operatorRegister, Register(SP));
__ Stp(operatorRegister, pcRegister, MemoryOperand(fpRegister, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // 2 : 2 means pair
// jumpSizeAfterCall
__ Str(Register(Zero), MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Str(Register(Zero), MemoryOperand(fpRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Ldr(operatorRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_LEXICALENV_OFFSET));
// env
__ Str(operatorRegister, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Str(operatorRegister, MemoryOperand(fpRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Ldr(operatorRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_ACC_OFFSET));
// 2 : acc and callTarget
__ Stp(callTargetRegister, operatorRegister, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Stp(callTargetRegister, operatorRegister, MemoryOperand(fpRegister, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
}
void AssemblerStubs::CallBCStub(ExtendedAssembler *assembler, Register &newSp, Register &glue,
Register &callTarget, Register &method, Register &pc, Register &temp)
{
Register sp(SP);
// caller save newSp register to restore rsp after call
__ Str(newSp, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
// prepare call entry
__ Mov(Register(X19), glue); // X19 - glue
__ Mov(Register(FP), newSp); // FP - sp
@ -1710,137 +1730,28 @@ void AssemblerStubs::CallBCStub(ExtendedAssembler *assembler, Register &newSp, R
void AssemblerStubs::CallNativeEntry(ExtendedAssembler *assembler)
{
Register glue(X0);
Register argc(X1);
Register argv(X2);
Register method(X4);
Register function(X3);
Register argc(X4);
Register argv(X5);
Register method(X2);
Register function(X1);
Register nativeCode(X7);
Register temp(X9);
Register sp(SP);
__ Str(function, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
// 16: function & align
__ Stp(function, Register(Zero), MemoryOperand(sp, -16, AddrMode::PREINDEX));
// 16: skip nativeCode & argc
__ Sub(sp, sp, Immediate(16));
PushBuiltinFrame(assembler, glue, FrameType::BUILTIN_ENTRY_FRAME, temp);
PushBuiltinFrame(assembler, glue, FrameType::BUILTIN_ENTRY_FRAME, temp, argv);
// get native pointer
__ Ldr(nativeCode, MemoryOperand(method, JSMethod::GetBytecodeArrayOffset(false)));
CallNativeInternal(assembler, glue, argc, argv, nativeCode);
CallNativeInternal(assembler, glue, argc, nativeCode);
// 24: skip function
__ Add(sp, sp, Immediate(24));
// 32: skip function
__ Add(sp, sp, Immediate(32));
__ Ret();
}
// Input: glue - %X0
// argc - %X1
// argv - %X2(<callTarget, newTarget, this> are at the beginning of argv)
// callTarget - %X3
// method - %X4
// prevSp - %X29
// fp - %10
// callField - %X7
void AssemblerStubs::PushArgsFastPath(ExtendedAssembler *assembler,
Register &glue, Register &argc, Register &argv, Register &callTarget,
Register &method, Register &prevSp, Register &fp, Register &callField)
{
Label pushCallThis;
Label pushNewTarget;
Label pushCallTarget;
Label pushVregs;
Label pushFrameState;
Register sp(SP);
Register argvOnlyHaveArgs(X11);
__ Add(argvOnlyHaveArgs, argv, Immediate(BuiltinFrame::RESERVED_CALL_ARGCOUNT * JSTaggedValue::TaggedTypeSize()));
Register tempRegister(X12);
__ PushArgsWithArgv(argc, argvOnlyHaveArgs, tempRegister, &pushCallThis);
__ Bind(&pushCallThis);
__ Tst(callField, LogicalImmediate::Create(CALL_TYPE_MASK, RegXSize));
__ B(Condition::EQ, &pushVregs);
__ Tst(callField, LogicalImmediate::Create(JSMethod::HaveThisBit::Mask(), RegXSize));
__ B(Condition::EQ, &pushNewTarget);
__ Ldr(tempRegister, MemoryOperand(argv, 16)); // 16: skip callTarget, newTarget
__ Str(tempRegister, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Bind(&pushNewTarget);
__ Tst(callField, LogicalImmediate::Create(JSMethod::HaveNewTargetBit::Mask(), RegXSize));
__ B(Condition::EQ, &pushCallTarget);
__ Ldr(tempRegister, MemoryOperand(argv, 8)); // 8: skip callTarget
__ Str(tempRegister, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Bind(&pushCallTarget);
__ Tst(callField, LogicalImmediate::Create(JSMethod::HaveFuncBit::Mask(), RegXSize));
__ B(Condition::EQ, &pushVregs);
__ Str(callTarget, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Bind(&pushVregs);
{
Register numVregsRegister(X13);
GetNumVregsFromCallField(assembler, callField, numVregsRegister);
__ Cbz(numVregsRegister.W(), &pushFrameState);
PushUndefinedWithArgc(assembler, numVregsRegister, tempRegister, &pushFrameState);
}
__ Bind(&pushFrameState);
Register newSpRegister(X14);
__ Mov(newSpRegister, sp);
StackOverflowCheck(assembler);
Register pcRegister(X11);
PushFrameState(assembler, prevSp, fp, callTarget, method, pcRegister, tempRegister);
CallBCStub(assembler, newSpRegister, glue, callTarget, method, pcRegister, tempRegister);
}
// Input: glueRegister - %X0
// declaredNumArgsRegister - %X9
// argcRegister - %X1
// argvRegister - %X2(<callTarget, newTarget, this> are at the beginning of argv)
// callTargetRegister - %X3
// methodRegister - %X4
// prevSpRegister - %X29
// callFieldRegister - %X7
void AssemblerStubs::PushArgsSlowPath(ExtendedAssembler *assembler, Register &glueRegister,
Register &declaredNumArgsRegister, Register &argcRegister, Register &argvRegister, Register &callTargetRegister,
Register &methodRegister, Register &prevSpRegister, Register &callFieldRegister)
{
Label jumpToFastPath;
Label haveExtra;
Label pushUndefined;
Register fpRegister(X10);
Register tempRegister(X12);
__ PushFpAndLr();
__ Mov(fpRegister, Register(SP));
__ Tst(callFieldRegister, LogicalImmediate::Create(JSMethod::HaveExtraBit::Mask(), RegXSize));
__ B(Condition::NE, &haveExtra);
__ Mov(tempRegister.W(), declaredNumArgsRegister.W());
__ Sub(declaredNumArgsRegister.W(), declaredNumArgsRegister.W(), argcRegister.W());
__ Cmp(declaredNumArgsRegister.W(), Immediate(0));
__ B(Condition::GT, &pushUndefined);
__ Mov(argcRegister.W(), tempRegister.W()); // actual = std::min(declare, actual)
__ B(&jumpToFastPath);
// fall through
__ Bind(&haveExtra);
{
Register tempArgcRegister(X13);
__ PushArgc(argcRegister, tempArgcRegister);
__ Sub(declaredNumArgsRegister.W(), declaredNumArgsRegister.W(), argcRegister.W());
__ Cmp(declaredNumArgsRegister.W(), Immediate(0));
__ B(Condition::LE, &jumpToFastPath);
// fall through
}
__ Bind(&pushUndefined);
{
PushUndefinedWithArgc(assembler, declaredNumArgsRegister, tempRegister, &jumpToFastPath);
// fall through
}
__ Bind(&jumpToFastPath);
PushArgsFastPath(assembler, glueRegister, argcRegister, argvRegister, callTargetRegister, methodRegister,
prevSpRegister, fpRegister, callFieldRegister);
}
void AssemblerStubs::PushArgsWithArgV(ExtendedAssembler *assembler, Register jsfunc,
Register actualNumArgs, Register argV, Label *pushCallThis)
{
@ -1861,7 +1772,7 @@ void AssemblerStubs::PushArgsWithArgV(ExtendedAssembler *assembler, Register jsf
{
[[maybe_unused]] TempRegister2Scope scope2(assembler);
Register undefinedValue = __ TempRegister2();
PushUndefinedWithArgc(assembler, tmp, undefinedValue, nullptr);
PushUndefinedWithArgc(assembler, tmp, undefinedValue, Register(SP), nullptr);
}
__ Bind(&copyArguments);

View File

@ -110,15 +110,17 @@ private:
static void PushCallThis(ExtendedAssembler *assembler, JSCallMode mode);
static Register GetThisRegsiter(ExtendedAssembler *assembler, JSCallMode mode);
static Register GetNewTargetRegsiter(ExtendedAssembler *assembler, JSCallMode mode);
static void PushVregs(ExtendedAssembler *assembler);
static void DispatchCall(ExtendedAssembler *assembler, Register pc, Register newSp);
static void CallNativeInternal(ExtendedAssembler *assembler, Register glue, Register numArgs, Register stackArgs,
static void CallNativeInternal(ExtendedAssembler *assembler, Register glue, Register numArgs,
Register nativeCode);
static void PushBuiltinFrame(ExtendedAssembler *assembler, Register glue, FrameType type, Register op);
static void PushBuiltinFrame(ExtendedAssembler *assembler, Register glue,
FrameType type, Register op, Register next);
static void PushFrameState(ExtendedAssembler *assembler, Register prevSp, Register fp, Register callTarget,
Register method, Register pc, Register op);
@ -134,15 +136,12 @@ private:
Register declaredNumArgs);
static void PushUndefinedWithArgc(ExtendedAssembler *assembler, Register argc, Register temp,
panda::ecmascript::Label *next);
Register fp, panda::ecmascript::Label *next);
static void SaveFpAndJumpSize(ExtendedAssembler *assembler, Immediate jumpSize);
static void GlueToThread(ExtendedAssembler *assembler, Register glue, Register thread);
static void ConstructEcmaRuntimeCallInfo(ExtendedAssembler *assembler, Register thread, Register numArgs,
Register stackArgs);
static void StackOverflowCheck([[maybe_unused]] ExtendedAssembler *assembler);
static void PushAsmInterpEntryFrame(ExtendedAssembler *assembler, bool saveLeave);
@ -159,14 +158,6 @@ private:
static void CallNativeEntry(ExtendedAssembler *assembler);
static void CallNativeWithArgv(ExtendedAssembler *assembler, bool callNew);
static void PushArgsFastPath(ExtendedAssembler *assembler,
Register &glue, Register &argc, Register &argv, Register &callTarget,
Register &method, Register &prevSp, Register &fp, Register &callField);
static void PushArgsSlowPath(ExtendedAssembler *assembler, Register &glueRegister,
Register &declaredNumArgsRegister, Register &argcRegister, Register &argvRegister, Register &callTargetRegister,
Register &methodRegister, Register &prevSpRegister, Register &callFieldRegister);
static void OptimizedCallAsmInterpreter(ExtendedAssembler *assembler);
static void PushArgsWithArgV(ExtendedAssembler *assembler, Register jsfunc,
Register actualNumArgs, Register argV, Label *pushCallThis);

View File

@ -892,10 +892,12 @@ void AssemblerStubsX64::CallRuntimeWithArgv(ExtendedAssembler *assembler)
}
// Generate code for Entering asm interpreter
// c++ calling convention
// Input: %rdi - glue
// %rsi - argc
// %rdx - argv(<callTarget, newTarget, this> are at the beginning of argv)
// Input: glue - %rdi
// callTarget - %rsi
// method - %rdx
// callField - %rcx
// argc - %r8
// argv - %r9(<callTarget, newTarget, this> are at the beginning of argv)
void AssemblerStubsX64::AsmInterpreterEntry(ExtendedAssembler *assembler)
{
__ BindAssemblerStub(RTSTUB_ID(AsmInterpreterEntry));
@ -962,28 +964,24 @@ void AssemblerStubsX64::GeneratorReEnterAsmInterpDispatch(ExtendedAssembler *ass
CallBCStub(assembler, newSpRegister, glueRegister, callTargetRegister, methodRegister, pcRegister);
}
// Input: glueRegister - %rdi
// argcRegister - %rsi
// argvRegister - %rdx(<callTarget, newTarget, this> are at the beginning of argv)
// prevSpRegister - %rbp
// Input: glue - %rdi
// callTarget - %rsi
// method - %rdx
// callField - %rcx
// argc - %r8
// argv - %r9(<callTarget, newTarget, this> are at the beginning of argv)
// prevSp - %rbp
void AssemblerStubsX64::JSCallDispatch(ExtendedAssembler *assembler)
{
Label notJSFunction;
Label callNativeEntry;
Label callJSFunctionEntry;
Label pushArgsSlowPath;
Label callJSProxyEntry;
Label notCallable;
Register glueRegister = rdi;
Register argcRegister = rsi;
Register argvRegister = rdx;
Register prevSpRegister = rbp;
Register callTargetRegister = r9;
Register methodRegister = rcx;
Register callTargetRegister = rsi;
Register argvRegister = r9;
Register bitFieldRegister = r12;
Register tempRegister = r11; // can not be used to store any variable
__ Movq(Operand(rdx, 0), callTargetRegister);
__ Movq(Operand(callTargetRegister, 0), tempRegister); // hclass
__ Movq(Operand(tempRegister, JSHClass::BIT_FIELD_OFFSET), bitFieldRegister);
__ Cmpb(static_cast<int32_t>(JSType::JS_FUNCTION_BEGIN), bitFieldRegister);
@ -994,38 +992,19 @@ void AssemblerStubsX64::JSCallDispatch(ExtendedAssembler *assembler)
{
__ Testq(static_cast<int64_t>(1ULL << JSHClass::CallableBit::START_BIT), bitFieldRegister);
__ Jz(&notCallable);
__ Cmpb(static_cast<int32_t>(JSType::JS_PROXY), bitFieldRegister);
__ Je(&callJSProxyEntry);
// bound function branch, default native
__ Movq(Operand(callTargetRegister, JSFunctionBase::METHOD_OFFSET), methodRegister);
// fall through
}
__ Bind(&callNativeEntry);
CallNativeEntry(assembler);
__ Bind(&callJSProxyEntry);
{
__ Movq(Operand(callTargetRegister, JSProxy::METHOD_OFFSET), methodRegister);
__ Jmp(&callNativeEntry);
}
__ Bind(&callJSFunctionEntry);
{
__ Movq(Operand(callTargetRegister, JSFunctionBase::METHOD_OFFSET), methodRegister);
Register callFieldRegister = r14;
__ Movq(Operand(methodRegister, JSMethod::GetCallFieldOffset(false)), callFieldRegister);
Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD);
__ Btq(JSMethod::IsNativeBit::START_BIT, callFieldRegister);
__ Jb(&callNativeEntry);
Register declaredNumArgsRegister = r11;
GetDeclaredNumArgsFromCallField(assembler, callFieldRegister, declaredNumArgsRegister);
__ Cmpq(declaredNumArgsRegister, argcRegister);
__ Jne(&pushArgsSlowPath);
// fast path
Register fpRegister = r10;
__ Movq(rsp, fpRegister);
PushArgsFastPath(assembler, glueRegister, argcRegister, argvRegister, callTargetRegister, methodRegister,
prevSpRegister, fpRegister, callFieldRegister);
__ Bind(&pushArgsSlowPath);
PushArgsSlowPath(assembler, glueRegister, declaredNumArgsRegister, argcRegister, argvRegister,
callTargetRegister, methodRegister, prevSpRegister, callFieldRegister);
__ Leaq(Operand(argvRegister, BuiltinFrame::RESERVED_CALL_ARGCOUNT * JSTaggedValue::TaggedTypeSize()),
argvRegister);
JSCallCommonEntry(assembler, JSCallMode::CALL_ENTRY);
}
__ Bind(&notCallable);
{
@ -1045,117 +1024,6 @@ void AssemblerStubsX64::JSCallDispatch(ExtendedAssembler *assembler)
}
}
// Input: glueRegister - %rdi
// argcRegister - %rsi
// argvRegister - %rdx(<callTarget, newTarget, this> are at the beginning of argv)
// callTargetRegister - %r9
// methodRegister - %rcx
// prevSpRegister - %rbp
// fpRegister - %r10
// callFieldRegister - %r14
void AssemblerStubsX64::PushArgsFastPath(ExtendedAssembler *assembler, Register glueRegister,
Register argcRegister, Register argvRegister, Register callTargetRegister, Register methodRegister,
Register prevSpRegister, Register fpRegister, Register callFieldRegister)
{
Label pushCallThis;
Label pushNewTarget;
Label pushCallTarget;
Label pushVregs;
Label pushFrameState;
__ Cmpq(0, argcRegister);
__ Jbe(&pushCallThis); // skip push args
Register argvOnlyHaveArgsRegister = r12;
__ Leaq(Operand(argvRegister, BuiltinFrame::RESERVED_CALL_ARGCOUNT * JSTaggedValue::TaggedTypeSize()),
argvOnlyHaveArgsRegister);
Register tempRegister = r11;
__ PushArgsWithArgv(argcRegister, argvOnlyHaveArgsRegister, tempRegister); // args
__ Bind(&pushCallThis);
__ Testb(CALL_TYPE_MASK, callFieldRegister);
__ Jz(&pushVregs);
__ Testq(JSMethod::HaveThisBit::Mask(), callFieldRegister);
__ Jz(&pushNewTarget);
__ Movq(Operand(argvRegister, 16), tempRegister); // 16: skip callTarget, newTarget
__ Pushq(tempRegister); // this
__ Bind(&pushNewTarget);
__ Testq(JSMethod::HaveNewTargetBit::Mask(), callFieldRegister);
__ Jz(&pushCallTarget);
__ Movq(Operand(argvRegister, 8), tempRegister); // 8: skip callTarget
__ Pushq(tempRegister); // newTarget
__ Bind(&pushCallTarget);
__ Testq(JSMethod::HaveFuncBit::Mask(), callFieldRegister);
__ Jz(&pushVregs);
__ Pushq(callTargetRegister); // callTarget
__ Bind(&pushVregs);
{
Register numVregsRegister = r11;
GetNumVregsFromCallField(assembler, callFieldRegister, numVregsRegister);
__ Cmpq(0, numVregsRegister);
__ Jz(&pushFrameState);
PushUndefinedWithArgc(assembler, numVregsRegister);
}
__ Bind(&pushFrameState);
Register newSpRegister = r8;
__ Movq(rsp, newSpRegister);
StackOverflowCheck(assembler);
Register pcRegister = r12; // reuse r12
PushFrameState(assembler, prevSpRegister, fpRegister, callTargetRegister, methodRegister, pcRegister, tempRegister);
CallBCStub(assembler, newSpRegister, glueRegister, callTargetRegister, methodRegister, pcRegister);
}
// Input: glueRegister - %rdi
// declaredNumArgsRegister - %r11
// argcRegister - %rsi
// argvRegister - %rdx(<callTarget, newTarget, this> are at the beginning of argv)
// callTargetRegister - %r9
// methodRegister - %rcx
// prevSpRegister - %rbp
// callFieldRegister - %r14
void AssemblerStubsX64::PushArgsSlowPath(ExtendedAssembler *assembler, Register glueRegister,
Register declaredNumArgsRegister, Register argcRegister, Register argvRegister, Register callTargetRegister,
Register methodRegister, Register prevSpRegister, Register callFieldRegister)
{
Label jumpToFastPath;
Label haveExtra;
Label pushUndefined;
Register fpRegister = r10;
Register tempRegister = r12;
__ Movq(rsp, fpRegister);
__ Testq(JSMethod::HaveExtraBit::Mask(), callFieldRegister);
__ Jnz(&haveExtra);
__ Movq(declaredNumArgsRegister, tempRegister);
__ Subq(argcRegister, declaredNumArgsRegister);
__ Cmpq(0, declaredNumArgsRegister);
__ Jg(&pushUndefined);
__ Movq(tempRegister, argcRegister); // std::min(declare, actual)
__ Jmp(&jumpToFastPath);
// fall through
__ Bind(&haveExtra);
{
Register tempArgcRegister = r15;
__ PushArgc(argcRegister, tempArgcRegister);
__ Subq(argcRegister, declaredNumArgsRegister);
__ Cmpq(0, declaredNumArgsRegister);
__ Jle(&jumpToFastPath);
// fall through
}
__ Bind(&pushUndefined);
{
PushUndefinedWithArgc(assembler, declaredNumArgsRegister);
// fall through
}
__ Bind(&jumpToFastPath);
PushArgsFastPath(assembler, glueRegister, argcRegister, argvRegister, callTargetRegister, methodRegister,
prevSpRegister, fpRegister, callFieldRegister);
}
void AssemblerStubsX64::PushFrameState(ExtendedAssembler *assembler, Register prevSpRegister, Register fpRegister,
Register callTargetRegister, Register methodRegister, Register pcRegister, Register operatorRegister)
{
@ -1527,6 +1395,7 @@ Register AssemblerStubsX64::GetThisRegsiter(ExtendedAssembler *assembler, JSCall
case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
case JSCallMode::CALL_THIS_WITH_ARGV:
return __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG2);
case JSCallMode::CALL_ENTRY:
case JSCallMode::CALL_FROM_AOT: {
Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1);
Register thisRegister = __ AvailableRegister2();
@ -1539,6 +1408,26 @@ Register AssemblerStubsX64::GetThisRegsiter(ExtendedAssembler *assembler, JSCall
return rInvalid;
}
Register AssemblerStubsX64::GetNewTargetRegsiter(ExtendedAssembler *assembler, JSCallMode mode)
{
switch (mode) {
case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
case JSCallMode::CALL_THIS_WITH_ARGV:
return __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET);
case JSCallMode::CALL_FROM_AOT:
case JSCallMode::CALL_ENTRY: {
Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1);
Register newTargetRegister = __ AvailableRegister2();
// 16: new Target offset
__ Movq(Operand(argvRegister, -16), newTargetRegister);
return newTargetRegister;
}
default:
UNREACHABLE();
}
return rInvalid;
}
// Input: %r14 - callField
// %rdi - argv
void AssemblerStubsX64::PushCallThis(ExtendedAssembler *assembler,
@ -1574,7 +1463,8 @@ void AssemblerStubsX64::PushCallThis(ExtendedAssembler *assembler,
if (!haveNewTarget) {
__ Pushq(JSTaggedValue::Undefined().GetRawData());
} else {
__ Pushq(callTargetRegister);
Register newTargetRegister = GetNewTargetRegsiter(assembler, mode);
__ Pushq(newTargetRegister);
}
}
// fall through
@ -1736,10 +1626,10 @@ void AssemblerStubsX64::CallNativeWithArgv(ExtendedAssembler *assembler, bool ca
void AssemblerStubsX64::CallNativeEntry(ExtendedAssembler *assembler)
{
Register glue = rdi;
Register argc = rsi;
Register argv = rdx;
Register method = rcx;
Register function = r9;
Register argc = r8;
Register argv = r9;
Register method = rdx;
Register function = rsi;
Register nativeCode = r10;
__ Push(function);

View File

@ -82,12 +82,6 @@ public:
static void JSCallWithArgV(ExtendedAssembler *assembler);
private:
static void PushArgsFastPath(ExtendedAssembler *assembler, Register glueRegister, Register argcRegister,
Register argvRegister, Register callTargetRegister, Register methodRegister, Register prevSpRegister,
Register fpRegister, Register callFieldRegister);
static void PushArgsSlowPath(ExtendedAssembler *assembler, Register glueRegister,
Register declaredNumArgsRegister, Register argcRegister, Register argvRegister, Register callTargetRegister,
Register methodRegister, Register prevSpRegister, Register callFieldRegister);
static void PushFrameState(ExtendedAssembler *assembler, Register prevSpRegister, Register fpRegister,
Register callTargetRegister, Register methodRegister, Register pcRegister, Register operatorRegister);
static void PushGeneratorFrameState(ExtendedAssembler *assembler, Register prevSpRegister,
@ -111,6 +105,7 @@ private:
static void StackOverflowCheck(ExtendedAssembler *assembler);
static void PushCallThis(ExtendedAssembler *assembler, JSCallMode mode);
static Register GetThisRegsiter(ExtendedAssembler *assembler, JSCallMode mode);
static Register GetNewTargetRegsiter(ExtendedAssembler *assembler, JSCallMode mode);
static void PushVregs(ExtendedAssembler *assembler);
static void DispatchCall(ExtendedAssembler *assembler, Register pcRegister, Register newSpRegister);
static void CallNativeEntry(ExtendedAssembler *assemblSer);

View File

@ -187,7 +187,8 @@ using panda::ecmascript::kungfu::CommonStubCSigns;
#define GET_ACC() (acc) // NOLINT(cppcoreguidelines-macro-usage)
#define SET_ACC(val) (acc = val); // NOLINT(cppcoreguidelines-macro-usage)
using InterpreterEntry = JSTaggedType (*)(uintptr_t glue, uint32_t argc, uintptr_t argv);
using InterpreterEntry = JSTaggedType (*)(uintptr_t glue, ECMAObject *callTarget,
JSMethod *method, uint64_t callField, uint32_t argc, uintptr_t argv);
using GeneratorReEnterInterpEntry = JSTaggedType (*)(uintptr_t glue, JSTaggedType context);
void InterpreterAssembly::InitStackFrame(JSThread *thread)
@ -217,7 +218,11 @@ JSTaggedValue InterpreterAssembly::Execute(EcmaRuntimeCallInfo *info)
size_t argc = info->GetArgsNumber();
uintptr_t argv = reinterpret_cast<uintptr_t>(info->GetArgs());
auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_AsmInterpreterEntry);
auto acc = reinterpret_cast<InterpreterEntry>(entry)(thread->GetGlueAddr(), argc, argv);
ECMAObject *callTarget = reinterpret_cast<ECMAObject*>(info->GetFunctionValue().GetTaggedObject());
JSMethod *method = callTarget->GetCallTarget();
auto acc = reinterpret_cast<InterpreterEntry>(entry)(thread->GetGlueAddr(),
callTarget, method, method->GetCallField(), argc, argv);
auto sp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame());
ASSERT(FrameHandler::GetFrameType(sp) == FrameType::INTERPRETER_ENTRY_FRAME);
auto prevEntry = InterpretedEntryFrame::GetFrameFromSp(sp)->GetPrevFrameFp();