!9510 add asmbirdge for AsmInterpreterEntry to call IR

Merge pull request !9510 from wpy111/master
This commit is contained in:
openharmony_ci 2024-09-26 21:12:49 +00:00 committed by Gitee
commit afe027a27d
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
10 changed files with 241 additions and 44 deletions

View File

@ -1826,21 +1826,26 @@ void AsmInterpreterCall::CallBCStub(ExtendedAssembler *assembler, Register &newS
void AsmInterpreterCall::CallNativeEntry(ExtendedAssembler *assembler)
{
Label callFastBuiltin;
Label callNativeBuiltin;
Register glue(X0);
Register argv(X5);
Register method(X2);
Register function(X1);
Register nativeCode(X7);
Register temp(X9);
Register callFieldRegister(X3);
// get native pointer
__ Ldr(nativeCode, MemoryOperand(method, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
__ Tbnz(callFieldRegister, MethodLiteral::IsFastBuiltinBit::START_BIT, &callFastBuiltin);
__ Bind(&callNativeBuiltin);
Register sp(SP);
// 2: function & align
__ Stp(function, Register(Zero), MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
// 2: skip argc & thread
__ Sub(sp, sp, Immediate(2 * FRAME_SLOT_SIZE));
PushBuiltinFrame(assembler, glue, FrameType::BUILTIN_ENTRY_FRAME, temp, argv);
// get native pointer
__ Ldr(nativeCode, MemoryOperand(method, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
__ Mov(temp, argv);
__ Sub(Register(X0), temp, Immediate(2 * FRAME_SLOT_SIZE)); // 2: skip argc & thread
CallNativeInternal(assembler, nativeCode);
@ -1848,6 +1853,91 @@ void AsmInterpreterCall::CallNativeEntry(ExtendedAssembler *assembler)
// 4: skip function
__ Add(sp, sp, Immediate(4 * FRAME_SLOT_SIZE));
__ Ret();
__ Bind(&callFastBuiltin);
CallFastBuiltin(assembler, &callNativeBuiltin);
}
void AsmInterpreterCall::CallFastBuiltin(ExtendedAssembler *assembler, Label *callNativeBuiltin)
{
Label lCall1;
Label lCall2;
Label lCall3;
Label callEntry;
Register sp(SP);
Register glue(X0);
Register function(X1);
Register method(X2);
Register argc(X4);
Register argv(X5);
Register nativeCode(X7);
Register builtinId = __ AvailableRegister1();
Register temp = __ AvailableRegister2();
// get builtinid
__ Ldr(builtinId, MemoryOperand(method, Method::EXTRA_LITERAL_INFO_OFFSET)); // get extra literal
__ And(builtinId.W(), builtinId.W(), LogicalImmediate::Create(0xff, RegWSize));
__ Cmp(builtinId.W(), Immediate(kungfu::BuiltinsStubCSigns::BUILTINS_CONSTRUCTOR_STUB_FIRST));
__ B(Condition::GE, callNativeBuiltin);
__ Cmp(argc, Immediate(3)); // 3: number of args
__ B(Condition::HI, callNativeBuiltin);
// get builtin func addr
__ Add(builtinId, glue, Operand(builtinId.W(), UXTW, FRAME_SLOT_SIZE_LOG2));
__ Ldr(builtinId, MemoryOperand(builtinId, JSThread::GlueData::GetBuiltinsStubEntriesOffset(false)));
// create frame
PushAsmBridgeFrame(assembler);
__ Mov(temp, function);
__ Mov(X1, nativeCode);
__ Mov(X2, temp);
__ Mov(temp, argv);
__ Mov(X5, argc);
__ Ldr(X3, MemoryOperand(temp, FRAME_SLOT_SIZE));
__ Ldr(X4, MemoryOperand(temp, DOUBLE_SLOT_SIZE));
__ Cmp(Register(X5), Immediate(0));
__ B(Condition::NE, &lCall1);
__ Mov(Register(X6), Immediate(JSTaggedValue::VALUE_UNDEFINED));
__ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED));
__ Stp(Register(X7), Register(X7), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, PREINDEX));
__ B(&callEntry);
__ Bind(&lCall1);
{
__ Cmp(Register(X5), Immediate(1));
__ B(Condition::NE, &lCall2);
__ Ldr(Register(X6), MemoryOperand(temp, TRIPLE_SLOT_SIZE));
__ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED)); // reset x7
__ Stp(Register(X7), Register(X7), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, PREINDEX));
__ B(&callEntry);
}
__ Bind(&lCall2);
{
__ Cmp(Register(X5), Immediate(2)); // 2: number of args
__ B(Condition::NE, &lCall3);
__ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED));
__ Stp(Register(X7), Register(X7), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, PREINDEX));
__ Ldp(Register(X6), Register(X7), MemoryOperand(temp, TRIPLE_SLOT_SIZE));
__ B(&callEntry);
}
__ Bind(&lCall3);
{
__ Ldr(Register(X7), MemoryOperand(temp, QUINTUPLE_SLOT_SIZE));
__ Stp(Register(X7), Register(X7), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, PREINDEX));
__ Ldp(Register(X6), Register(X7), MemoryOperand(temp, TRIPLE_SLOT_SIZE)); // get arg0 arg1
__ B(&callEntry);
}
__ Bind(&callEntry);
{
__ Blr(builtinId);
__ Add(sp, sp, Immediate(DOUBLE_SLOT_SIZE));
}
PopAsmBridgeFrame(assembler);
__ Ret();
}
void AsmInterpreterCall::ThrowStackOverflowExceptionAndReturn(ExtendedAssembler *assembler, Register glue,

View File

@ -187,5 +187,28 @@ void CommonCall::StackOverflowCheck(ExtendedAssembler *assembler, Register glue,
__ Cbz(op, stackOverflow);
__ Bind(&skipThrow);
}
void CommonCall::PushAsmBridgeFrame(ExtendedAssembler *assembler)
{
Register sp(SP);
TempRegister2Scope temp2Scope(assembler);
Register frameType = __ TempRegister2();
__ PushFpAndLr();
// construct frame
__ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::ASM_BRIDGE_FRAME)));
// 2 : 2 means pairs. X19 means calleesave and 16bytes align
__ Stp(Register(X19), frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
__ Add(Register(FP), sp, Immediate(DOUBLE_SLOT_SIZE));
}
void CommonCall::PopAsmBridgeFrame(ExtendedAssembler *assembler)
{
TempRegister2Scope temp2Scope(assembler);
Register sp(SP);
Register frameType = __ TempRegister2();
// 2 : 2 means pop call site sp and type
__ Ldp(Register(X19), frameType, MemoryOperand(sp, FRAME_SLOT_SIZE * 2, AddrMode::POSTINDEX));
__ RestoreFpAndLr();
}
#undef __
} // panda::ecmascript::aarch64

View File

@ -73,6 +73,8 @@ public:
Register op, Label *stackOverflow);
static void PushLeaveFrame(ExtendedAssembler *assembler, Register glue);
static void PopLeaveFrame(ExtendedAssembler *assembler);
static void PushAsmBridgeFrame(ExtendedAssembler *assembler);
static void PopAsmBridgeFrame(ExtendedAssembler *assembler);
};
class OptimizedCall : public CommonCall {
@ -127,8 +129,6 @@ private:
int64_t numExtraArgs = 0);
static void PushOptimizedArgsConfigFrame(ExtendedAssembler *assembler);
static void PopOptimizedArgsConfigFrame(ExtendedAssembler *assembler);
static void PushAsmBridgeFrame(ExtendedAssembler *assembler);
static void PopAsmBridgeFrame(ExtendedAssembler *assembler);
static void JSCallInternal(ExtendedAssembler *assembler, Register jsfunc, bool isNew = false);
static void CallBuiltinTrampoline(ExtendedAssembler *assembler);
static void CallBuiltinConstructorStub(ExtendedAssembler *assembler, Register builtinStub, Register argv,
@ -268,6 +268,8 @@ private:
static void CallNativeEntry(ExtendedAssembler *assembler);
static void CallFastBuiltin(ExtendedAssembler *assembler, Label *callNativeBuiltin);
static void CallNativeWithArgv(ExtendedAssembler *assembler, bool callNew, bool hasNewTarget = false);
static void PreserveMostCall(ExtendedAssembler* assembler);
friend class OptimizedCall;

View File

@ -1174,29 +1174,6 @@ void OptimizedCall::PopOptimizedArgsConfigFrame(ExtendedAssembler *assembler)
__ RestoreFpAndLr();
}
void OptimizedCall::PushAsmBridgeFrame(ExtendedAssembler *assembler)
{
Register sp(SP);
TempRegister2Scope temp2Scope(assembler);
Register frameType = __ TempRegister2();
__ PushFpAndLr();
// construct frame
__ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::ASM_BRIDGE_FRAME)));
// 2 : 2 means pairs. X19 means calleesave and 16bytes align
__ Stp(Register(X19), frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
__ Add(Register(FP), sp, Immediate(DOUBLE_SLOT_SIZE));
}
void OptimizedCall::PopAsmBridgeFrame(ExtendedAssembler *assembler)
{
TempRegister2Scope temp2Scope(assembler);
Register sp(SP);
Register frameType = __ TempRegister2();
// 2 : 2 means pop call site sp and type
__ Ldp(Register(X19), frameType, MemoryOperand(sp, FRAME_SLOT_SIZE * 2, AddrMode::POSTINDEX));
__ RestoreFpAndLr();
}
// * uint64_t PushOptimizedUnfoldArgVFrame(uintptr_t glue, uint32_t argc, JSTaggedType calltarget,
// JSTaggedType new, JSTaggedType this, JSTaggedType argV[])
// * cc calling convention call js function()

View File

@ -929,18 +929,24 @@ void AsmInterpreterCall::CallNativeWithArgv(ExtendedAssembler *assembler, bool c
void AsmInterpreterCall::CallNativeEntry(ExtendedAssembler *assembler)
{
Label callFastBuiltin;
Label callNativeBuiltin;
Register glue = rdi;
Register argv = r9;
Register method = rdx;
Register function = rsi;
Register nativeCode = r10;
Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD);
__ Movq(Operand(method, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET), nativeCode); // get native pointer
__ Btq(MethodLiteral::IsFastBuiltinBit::START_BIT, callFieldRegister);
__ Jb(&callFastBuiltin);
__ Bind(&callNativeBuiltin);
__ PushAlignBytes();
__ Push(function);
// 3: 24 means skip thread & argc & returnAddr
__ Subq(3 * FRAME_SLOT_SIZE, rsp);
PushBuiltinFrame(assembler, glue, FrameType::BUILTIN_ENTRY_FRAME);
__ Movq(Operand(method, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET), nativeCode); // get native pointer
__ Movq(argv, r11);
// 2: 16 means skip numArgs & thread
__ Subq(2 * FRAME_SLOT_SIZE, r11);
@ -952,6 +958,93 @@ void AsmInterpreterCall::CallNativeEntry(ExtendedAssembler *assembler)
// 5: 40 means skip function
__ Addq(5 * FRAME_SLOT_SIZE, rsp);
__ Ret();
__ Bind(&callFastBuiltin);
CallFastBuiltin(assembler, &callNativeBuiltin);
}
void AsmInterpreterCall::CallFastBuiltin(ExtendedAssembler *assembler, Label *callNativeBuiltin)
{
Label arg1;
Label arg2;
Label arg3;
Label callEntry;
Register glue = rdi;
Register argc = r8;
Register argv = r9;
Register method = rdx;
Register function = rsi;
Register nativeCode = r10;
Register temp = rax;
Register temp1 = r11;
// get builtins id
__ Movq(Operand(method, Method::EXTRA_LITERAL_INFO_OFFSET), temp1);
__ Shr(MethodLiteral::BuiltinIdBits::START_BIT, temp1);
__ Andl((1LU << MethodLiteral::BuiltinIdBits::SIZE) - 1, temp1);
__ Cmpl(static_cast<int32_t>(kungfu::BuiltinsStubCSigns::BUILTINS_CONSTRUCTOR_STUB_FIRST), temp1);
__ Jge(callNativeBuiltin);
__ Cmpq(Immediate(3), argc); // 3: number of args
__ Jg(callNativeBuiltin);
// create frame
PushAsmBridgeFrame(assembler);
// register args
__ Movq(function, temp);
__ Movq(nativeCode, rsi); // nativeCode is rsi
__ Movq(temp, rdx); // fun is rdx
__ Movq(argv, temp); // temp is argv
__ Movq(argc, r9); // argc is r9
__ Movq(Operand(temp, FRAME_SLOT_SIZE), rcx); // get new target
__ Movq(Operand(temp, FRAME_SLOT_SIZE * 2), r8); // 2: skip func & new target to get this target
__ Cmp(Immediate(0), r9);
__ Jne(&arg1);
__ Pushq(JSTaggedValue::VALUE_UNDEFINED);
__ Pushq(JSTaggedValue::VALUE_UNDEFINED);
__ Pushq(JSTaggedValue::VALUE_UNDEFINED);
__ Jmp(&callEntry);
__ Bind(&arg1);
{
__ Cmp(Immediate(1), r9);
__ Jne(&arg2);
__ Pushq(JSTaggedValue::VALUE_UNDEFINED);
__ Pushq(JSTaggedValue::VALUE_UNDEFINED);
__ Movq(Operand(temp, FRAME_SLOT_SIZE * 3), r10); // 3: get arg0
__ Pushq(r10);
__ Jmp(&callEntry);
}
__ Bind(&arg2);
{
__ Cmp(Immediate(2), r9); // 2: number of args
__ Jne(&arg3);
__ Pushq(JSTaggedValue::VALUE_UNDEFINED);
__ Movq(Operand(temp, FRAME_SLOT_SIZE * 4), r10); // 4: get arg1
__ Pushq(r10);
__ Movq(Operand(temp, FRAME_SLOT_SIZE * 3), r10); // 3: get arg0
__ Pushq(r10);
__ Jmp(&callEntry);
}
__ Bind(&arg3);
{
__ Movq(Operand(temp, FRAME_SLOT_SIZE * 5), r10); // 5: get arg2
__ Pushq(r10);
__ Movq(Operand(temp, FRAME_SLOT_SIZE * 4), r10); // 4: get arg1
__ Pushq(r10);
__ Movq(Operand(temp, FRAME_SLOT_SIZE * 3), r10); // 3: get arg0
__ Pushq(r10);
__ Jmp(&callEntry);
}
__ Bind(&callEntry);
{
__ Movq(Operand(glue, temp1, Times8, JSThread::GlueData::GetBuiltinsStubEntriesOffset(false)), temp1);
__ Callq(temp1);
__ Addq(QUADRUPLE_SLOT_SIZE, rsp);
__ Pop(rbp);
__ Ret();
}
}
// uint64_t PushCallArgsAndDispatchNative(uintptr_t codeAddress, uintptr_t glue, uint32_t argc, ...)

View File

@ -122,5 +122,18 @@ void CommonCall::StackOverflowCheck(ExtendedAssembler *assembler, Register glue,
}
__ Jle(stackOverflow);
}
void CommonCall::PushAsmBridgeFrame(ExtendedAssembler *assembler)
{
__ Pushq(rbp);
__ Pushq(static_cast<int32_t>(FrameType::ASM_BRIDGE_FRAME));
__ Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp);
}
void CommonCall::PopAsmBridgeFrame(ExtendedAssembler *assembler)
{
__ Addq(FRAME_SLOT_SIZE, rsp); // skip type
__ Popq(rbp);
}
#undef __
} // namespace panda::ecmascript::x64

View File

@ -46,6 +46,8 @@ public:
Register op1, Register op2, Label *stackOverflow);
static void StackOverflowCheck(ExtendedAssembler *assembler, Register glue, Register numArgs, Register op1,
Register op2, Label *stackOverflow);
static void PushAsmBridgeFrame(ExtendedAssembler *assembler);
static void PopAsmBridgeFrame(ExtendedAssembler *assembler);
};
class OptimizedCall : public CommonCall {
@ -97,9 +99,7 @@ private:
static void PopJSFunctionEntryFrame(ExtendedAssembler *assembler, Register glue);
static void PushOptimizedUnfoldArgVFrame(ExtendedAssembler *assembler, Register callSiteSp);
static void PopOptimizedUnfoldArgVFrame(ExtendedAssembler *assembler);
static void PushAsmBridgeFrame(ExtendedAssembler *assembler);
static void CallBuiltinTrampoline(ExtendedAssembler *assembler, Register temp);
static void PopAsmBridgeFrame(ExtendedAssembler *assembler);
static void CallBuiltinConstructorStub(ExtendedAssembler *assembler, Register builtinStub, Register argv,
Register glue, Register temp);
static void RemoveArgv(ExtendedAssembler *assembler, Register temp);
@ -212,7 +212,8 @@ private:
static void PushVregs(ExtendedAssembler *assembler, Label *stackOverflow, FrameTransitionType type);
static void DispatchCall(ExtendedAssembler *assembler, Register pcRegister, Register newSpRegister,
Register callTargetRegister, Register methodRegister, Register accRegister = rInvalid);
static void CallNativeEntry(ExtendedAssembler *assemblSer);
static void CallNativeEntry(ExtendedAssembler *assembler);
static void CallFastBuiltin(ExtendedAssembler *assembler, Label *callNativeBuiltin);
static void CallNativeWithArgv(ExtendedAssembler *assembler, bool callNew, bool hasNewTarget = false);
static void CallNativeInternal(ExtendedAssembler *assembler, Register nativeCode);
static bool PushBuiltinFrame(ExtendedAssembler *assembler, Register glue, FrameType type);

View File

@ -822,19 +822,6 @@ void OptimizedCall::FastCallToAsmInterBridge(ExtendedAssembler *assembler)
assembler, JSCallMode::CALL_FROM_AOT, FrameTransitionType::OTHER_TO_OTHER);
}
void OptimizedCall::PushAsmBridgeFrame(ExtendedAssembler *assembler)
{
__ Pushq(rbp);
__ Pushq(static_cast<int32_t>(FrameType::ASM_BRIDGE_FRAME));
__ Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp);
}
void OptimizedCall::PopAsmBridgeFrame(ExtendedAssembler *assembler)
{
__ Addq(FRAME_SLOT_SIZE, rsp); // skip type
__ Popq(rbp);
}
void OptimizedCall::JSCallCheck(ExtendedAssembler *assembler, Register jsFuncReg,
Label *lNonCallable, Label *lNotJSFunction, Label *lJSFunctionCall)
{

View File

@ -132,3 +132,12 @@ prototypeCallTest.call(0, 1);
prototypeCallTest.call(0, 1, 2);
prototypeCallTest.call(0, 1, 2, 3);
prototypeCallTest.call(0, 1, 2, 3, 4);
var x = [];
x[new Number(0)] = 0;
print(x[0]);
const reg = /bar/;
reg[Symbol.match] = false;
print('/bar/'.startsWith(reg));

View File

@ -35,3 +35,5 @@ undefined
1,2,3
0
1,2,3,4
0
true