mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2025-03-01 08:48:03 +00:00
Enable x86 Assembler
1. x86 assembler replaces JSCall, JSCallArgV, JSFunctionEntry, OptimizedCallOptimized, CallNativeTrampoline assembly code of x86 call.S debugged and enabled to the official code. 2. Delete the relevant code in call.S. issue:https://gitee.com/openharmony/ark_js_runtime/issues/I57UHX Signed-off-by: wanyanglan <wanyanglan1@huawei.com> Change-Id: I69b9aad1f52d486ba6d96248aa1a5a2d0a44f318
This commit is contained in:
parent
671382bfb6
commit
11ddfd964e
8
BUILD.gn
8
BUILD.gn
@ -193,9 +193,6 @@ config("ark_jsruntime_common_config") {
|
||||
defines += [ "PANDA_USE_MUSL" ]
|
||||
}
|
||||
}
|
||||
if (enable_test_stub) {
|
||||
defines += [ "ECMASCRIPT_ENABLE_TEST_STUB" ]
|
||||
}
|
||||
|
||||
if (build_public_version) {
|
||||
defines += [ "IS_PUBLIC_VERSION" ]
|
||||
@ -484,6 +481,7 @@ ecma_source = [
|
||||
"ecmascript/ts_types/ts_type_table.cpp",
|
||||
"ecmascript/ts_types/ts_loader.cpp",
|
||||
"ecmascript/ts_types/ts_obj_layout_info.cpp",
|
||||
"ecmascript/stubs/test_runtime_stubs.cpp",
|
||||
]
|
||||
|
||||
if (!is_mingw && !is_mac) {
|
||||
@ -491,10 +489,6 @@ if (!is_mingw && !is_mac) {
|
||||
ecma_source += [ "ecmascript/tooling/interface/file_stream.cpp" ]
|
||||
}
|
||||
|
||||
if (enable_test_stub) {
|
||||
ecma_source += [ "ecmascript/stubs/test_runtime_stubs.cpp" ]
|
||||
}
|
||||
|
||||
ecma_debugger_source = []
|
||||
if (!is_mingw && !is_mac) {
|
||||
ecma_debugger_source += [
|
||||
|
@ -60,18 +60,13 @@ source_set("libark_jsoptimizer_set") {
|
||||
"rt_call_signature.cpp",
|
||||
"scheduler.cpp",
|
||||
"stub.cpp",
|
||||
"test_stubs.cpp",
|
||||
"test_stubs_signature.cpp",
|
||||
"trampoline/x64/assembler_stubs_x64.cpp",
|
||||
"type.cpp",
|
||||
"verifier.cpp",
|
||||
]
|
||||
|
||||
if (enable_test_stub) {
|
||||
sources += [
|
||||
"test_stubs.cpp",
|
||||
"test_stubs_signature.cpp",
|
||||
]
|
||||
}
|
||||
|
||||
public_configs = [
|
||||
":include_llvm",
|
||||
"$js_root:ark_jsruntime_compiler_config",
|
||||
|
@ -460,54 +460,5 @@ HWTEST_F_L0(AssemblerX64Test, Emit4)
|
||||
ASSERT_EQ(value, 0xCCU);
|
||||
ecmascript::kungfu::LLVMAssembler::Disassemble(masm.GetBegin(), masm.GetCurrentPosition());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(AssemblerX64Test, JSFunctionEntry)
|
||||
{
|
||||
x64::AssemblerX64 masm(chunk_);
|
||||
x64::ExtendedAssemblerX64 *assemblerX64 = static_cast<ExtendedAssemblerX64 *>(&masm);
|
||||
x64::AssemblerStubsX64::JSFunctionEntry(assemblerX64);
|
||||
ecmascript::kungfu::LLVMAssembler::Disassemble(masm.GetBegin(), masm.GetCurrentPosition());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(AssemblerX64Test, OptimizedCallOptimized)
|
||||
{
|
||||
x64::AssemblerX64 masm(chunk_);
|
||||
x64::ExtendedAssemblerX64 *assemblerX64 = static_cast<ExtendedAssemblerX64 *>(&masm);
|
||||
x64::AssemblerStubsX64::OptimizedCallOptimized(assemblerX64);
|
||||
ecmascript::kungfu::LLVMAssembler::Disassemble(masm.GetBegin(), masm.GetCurrentPosition());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(AssemblerX64Test, CallNativeTrampoline)
|
||||
{
|
||||
x64::AssemblerX64 masm(chunk_);
|
||||
x64::ExtendedAssemblerX64 *assemblerX64 = static_cast<ExtendedAssemblerX64 *>(&masm);
|
||||
x64::AssemblerStubsX64::CallNativeTrampoline(assemblerX64);
|
||||
ecmascript::kungfu::LLVMAssembler::Disassemble(masm.GetBegin(), masm.GetCurrentPosition());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(AssemblerX64Test, JSCallWithArgv)
|
||||
{
|
||||
x64::AssemblerX64 masm(chunk_);
|
||||
x64::ExtendedAssemblerX64 *assemblerX64 = static_cast<ExtendedAssemblerX64 *>(&masm);
|
||||
x64::AssemblerStubsX64::JSCallWithArgv(assemblerX64);
|
||||
ecmascript::kungfu::LLVMAssembler::Disassemble(masm.GetBegin(), masm.GetCurrentPosition());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(AssemblerX64Test, JSCall)
|
||||
{
|
||||
x64::AssemblerX64 masm(chunk_);
|
||||
x64::ExtendedAssemblerX64 *assemblerX64 = static_cast<ExtendedAssemblerX64 *>(&masm);
|
||||
x64::AssemblerStubsX64::JSCall(assemblerX64);
|
||||
ecmascript::kungfu::LLVMAssembler::Disassemble(masm.GetBegin(), masm.GetCurrentPosition());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(AssemblerX64Test, CallRuntimeWithArgv)
|
||||
{
|
||||
x64::AssemblerX64 masm(chunk_);
|
||||
x64::ExtendedAssemblerX64 *assemblerX64 = static_cast<ExtendedAssemblerX64 *>(&masm);
|
||||
x64::AssemblerStubsX64::CallRuntimeWithArgv(assemblerX64);
|
||||
ecmascript::kungfu::LLVMAssembler::Disassemble(masm.GetBegin(), masm.GetCurrentPosition());
|
||||
}
|
||||
|
||||
#undef __
|
||||
} // namespace panda::test
|
||||
|
@ -1006,4 +1006,23 @@ DEF_CALL_SIGNATURE(JSObjectGetMethod)
|
||||
callSign->SetTailCall(false);
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(JSFunctionEntry)
|
||||
{
|
||||
// 6 : 6 input parameters
|
||||
CallSignature jsFunctionEntry("JSFunctionEntry", 0, 6, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
|
||||
*callSign = jsFunctionEntry;
|
||||
std::array<VariableType, 6> params = { /* 6 : 6 input parameters */
|
||||
VariableType::NATIVE_POINTER(), // glue
|
||||
VariableType::NATIVE_POINTER(), // prevFp
|
||||
VariableType::INT32(), // expectedNumArgs
|
||||
VariableType::INT32(), // actualNumArgs
|
||||
VariableType::JS_ANY(), // argv
|
||||
VariableType::NATIVE_POINTER(), // codeAddr
|
||||
};
|
||||
callSign->SetVariadicArgs(true);
|
||||
callSign->SetParameters(params.data());
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
callSign->SetCallConv(CallSignature::CallConv::CCallConv);
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -336,6 +336,7 @@ private:
|
||||
V(CreateArrayFromList) \
|
||||
V(JSObjectGetMethod) \
|
||||
V(JsProxyCallInternal) \
|
||||
V(JSFunctionEntry) \
|
||||
TEST_STUB_SIGNATRUE_LIST(V)
|
||||
|
||||
#define DECL_CALL_SIGNATURE(name) \
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
using namespace panda::ecmascript;
|
||||
#ifndef NDEBUG
|
||||
void FooAOTStub::GenerateCircuit(const CompilationConfig *cfg)
|
||||
{
|
||||
Stub::GenerateCircuit(cfg);
|
||||
@ -205,4 +206,5 @@ void Bar2AOTStub::GenerateCircuit(const CompilationConfig *cfg)
|
||||
CallRuntime(glue, RTSTUB_ID(DumpTaggedType), {thisObj});
|
||||
Return(thisObj);
|
||||
}
|
||||
#endif
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -21,8 +21,7 @@
|
||||
namespace panda::ecmascript::kungfu {
|
||||
#define IGNORE_TEST_STUB(name, count)
|
||||
|
||||
#ifdef ECMASCRIPT_ENABLE_TEST_STUB
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define TEST_STUB_LIST(V) \
|
||||
V(FooAOT, 7) \
|
||||
V(Foo1AOT, 7) \
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "ecmascript/compiler/call_signature.h"
|
||||
namespace panda::ecmascript::kungfu {
|
||||
#ifndef NDEBUG
|
||||
DEF_CALL_SIGNATURE(FooAOT)
|
||||
{
|
||||
// 7 : 7 input parameters
|
||||
@ -204,4 +205,5 @@ DEF_CALL_SIGNATURE(Bar2AOT)
|
||||
callSign->SetVariadicArgs(true);
|
||||
callSign->SetCallConv(CallSignature::CallConv::WebKitJSCallConv);
|
||||
}
|
||||
#endif
|
||||
} // namespace panda::ecmascript::kungfu
|
@ -16,7 +16,7 @@
|
||||
#define ECMASCRIPT_COMPILER_TEST_STUBS_SIGNATURE_H
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
#ifdef ECMASCRIPT_ENABLE_TEST_STUB
|
||||
#ifndef NDEBUG
|
||||
#define TEST_STUB_SIGNATRUE_LIST(V) \
|
||||
V(FooAOT) \
|
||||
V(BarAOT) \
|
||||
|
@ -113,6 +113,7 @@ host_unittest_action("StubTest") {
|
||||
|
||||
deps = [
|
||||
"$ark_root/libpandabase:libarkbase",
|
||||
"//ark/js_runtime/ecmascript/compiler:gen_stub_file(${host_toolchain})",
|
||||
"//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer_test",
|
||||
sdk_libc_secshared_dep,
|
||||
]
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "llvm/IRReader/IRReader.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "ecmascript/compiler/assembler_module.h"
|
||||
|
||||
namespace panda::test {
|
||||
using namespace panda::coretypes;
|
||||
@ -46,7 +47,7 @@ class StubTest : public testing::Test {
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
|
||||
TestHelper::CreateEcmaVMWithScope(instance, thread, scope, true);
|
||||
BytecodeStubCSigns::Initialize();
|
||||
CommonStubCSigns::Initialize();
|
||||
RuntimeStubCSigns::Initialize();
|
||||
@ -1240,7 +1241,7 @@ HWTEST_F_L0(StubTest, FastEqualTest)
|
||||
EXPECT_EQ(resI, expectI);
|
||||
}
|
||||
|
||||
#ifdef ECMASCRIPT_ENABLE_TEST_STUB
|
||||
#ifndef NDEBUG
|
||||
HWTEST_F_L0(StubTest, JSCallTest)
|
||||
{
|
||||
auto fooEntry = thread->GetFastStubEntry(CommonStubCSigns::FooAOT);
|
||||
@ -1256,12 +1257,14 @@ HWTEST_F_L0(StubTest, JSCallTest)
|
||||
JSTaggedValue(y).GetRawData(),
|
||||
JSTaggedValue::Undefined().GetRawData(),
|
||||
};
|
||||
auto result = JSFunctionEntry(glue, reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()), 5, 5,
|
||||
argV, fooEntry);
|
||||
auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry);
|
||||
|
||||
auto result = reinterpret_cast<JSFunctionEntryType>(entry)(glue,
|
||||
reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()), 5, 5, argV, fooEntry);
|
||||
EXPECT_EQ(result, JSTaggedValue(3.0).GetRawData());
|
||||
|
||||
auto result1 = JSFunctionEntry(glue, reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()), 5, 6,
|
||||
argV, fooEntry);
|
||||
auto result1 = reinterpret_cast<JSFunctionEntryType>(entry)(glue,
|
||||
reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()), 5, 6, argV, fooEntry);
|
||||
EXPECT_EQ(result1, JSTaggedValue(3.0).GetRawData());
|
||||
}
|
||||
|
||||
@ -1280,8 +1283,9 @@ HWTEST_F_L0(StubTest, JSCallTest1)
|
||||
JSTaggedValue(y).GetRawData(),
|
||||
JSTaggedValue::Undefined().GetRawData(),
|
||||
};
|
||||
auto result = JSFunctionEntry(glue, reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()), 5, 5,
|
||||
argV, foo2Entry);
|
||||
auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry);
|
||||
auto result = reinterpret_cast<JSFunctionEntryType>(entry)(glue,
|
||||
reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()), 5, 5, argV, foo2Entry);
|
||||
EXPECT_EQ(result, JSTaggedValue(3.0).GetRawData());
|
||||
}
|
||||
|
||||
@ -1299,8 +1303,10 @@ HWTEST_F_L0(StubTest, JSCallTest2)
|
||||
JSTaggedValue(x).GetRawData(),
|
||||
JSTaggedValue(y).GetRawData(),
|
||||
};
|
||||
auto result = JSFunctionEntry(glue, reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()), 5, 5,
|
||||
argV, foo1Entry);
|
||||
|
||||
auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry);
|
||||
auto result = reinterpret_cast<JSFunctionEntryType>(entry)(glue,
|
||||
reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()), 5, 5, argV, foo1Entry);
|
||||
EXPECT_EQ(result, 0x7ff9000000000000UL);
|
||||
}
|
||||
|
||||
@ -1318,8 +1324,9 @@ HWTEST_F_L0(StubTest, JSCallNativeTest)
|
||||
JSTaggedValue(x).GetRawData(),
|
||||
JSTaggedValue(y).GetRawData(),
|
||||
};
|
||||
auto result = JSFunctionEntry(glue, reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()), 5, 5,
|
||||
argV, fooEntry);
|
||||
auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry);
|
||||
auto result = reinterpret_cast<JSFunctionEntryType>(entry)(glue,
|
||||
reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()), 5, 5, argV, fooEntry);
|
||||
EXPECT_EQ(result, JSTaggedValue::Undefined().GetRawData());
|
||||
}
|
||||
|
||||
@ -1337,8 +1344,10 @@ HWTEST_F_L0(StubTest, JSCallBoundTest)
|
||||
JSTaggedValue(x).GetRawData(),
|
||||
JSTaggedValue(y).GetRawData(),
|
||||
};
|
||||
auto result = JSFunctionEntry(glue, reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()), 5, 5,
|
||||
argV, fooEntry);
|
||||
|
||||
auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry);
|
||||
auto result = reinterpret_cast<JSFunctionEntryType>(entry)(glue,
|
||||
reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()), 5, 5, argV, fooEntry);
|
||||
EXPECT_EQ(result, JSTaggedValue(38.0).GetRawData());
|
||||
}
|
||||
|
||||
@ -1360,8 +1369,9 @@ HWTEST_F_L0(StubTest, JSCallTest3)
|
||||
};
|
||||
JSThread::GlueData::GetCOStubEntriesOffset(false);
|
||||
JSThread::GlueData::GetCOStubEntriesOffset(true);
|
||||
auto result = JSFunctionEntry(glue, reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()),
|
||||
5, 5, argV, fooProxyEntry);
|
||||
auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry);
|
||||
auto result = reinterpret_cast<JSFunctionEntryType>(entry)(glue,
|
||||
reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()), 5, 5, argV, fooProxyEntry);
|
||||
EXPECT_EQ(result, JSTaggedValue(3.0).GetRawData());
|
||||
}
|
||||
|
||||
@ -1383,8 +1393,9 @@ HWTEST_F_L0(StubTest, JSCallTest4)
|
||||
};
|
||||
JSThread::GlueData::GetCOStubEntriesOffset(false);
|
||||
JSThread::GlueData::GetCOStubEntriesOffset(true);
|
||||
[[maybe_unused]] auto result = JSFunctionEntry(glue, reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()),
|
||||
5, 5, argV, fooProxyEntry);
|
||||
auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry);
|
||||
[[maybe_unused]] auto result = reinterpret_cast<JSFunctionEntryType>(entry)(glue,
|
||||
reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()), 5, 5, argV, fooProxyEntry);
|
||||
}
|
||||
#endif
|
||||
} // namespace panda::test
|
||||
|
@ -93,7 +93,7 @@ void AssemblerStubsX64::JSFunctionEntry(ExtendedAssemblerX64 *assembler)
|
||||
// construct the frame
|
||||
__ Pushq(rbp);
|
||||
__ Movq(rsp, rbp);
|
||||
__ Pushq(static_cast<int32_t>(FrameType::OPTIMIZED_FRAME));
|
||||
__ Pushq(static_cast<int32_t>(FrameType::OPTIMIZED_ENTRY_FRAME));
|
||||
__ Pushq(prevFpReg);
|
||||
|
||||
// 16 bytes align check
|
||||
@ -103,48 +103,58 @@ void AssemblerStubsX64::JSFunctionEntry(ExtendedAssemblerX64 *assembler)
|
||||
__ Pushq(0); // push zero to align 16 bytes stack
|
||||
|
||||
__ Bind(&lAlign16Bytes);
|
||||
// expectedNumArgs > actualNumArgs
|
||||
__ Movl(expectedNumArgsReg, rbx); // save expectedNumArgs
|
||||
__ Cmpl(actualNumArgsReg, expectedNumArgsReg);
|
||||
__ Jbe(&lCopyArguments);
|
||||
__ Movl(actualNumArgsReg, rax);
|
||||
__ Movl(rbx, expectedNumArgsReg);
|
||||
{
|
||||
// expectedNumArgs > actualNumArgs
|
||||
__ Movl(expectedNumArgsReg, rbx); // save expectedNumArgs
|
||||
__ Cmpl(actualNumArgsReg, expectedNumArgsReg);
|
||||
__ Jbe(&lCopyArguments);
|
||||
__ Movl(actualNumArgsReg, rax);
|
||||
__ Movl(rbx, expectedNumArgsReg);
|
||||
}
|
||||
|
||||
__ Bind(&lCopyExtraAument); // copy undefined value to stack
|
||||
__ Pushq(JSTaggedValue::VALUE_UNDEFINED);
|
||||
__ Addq(-1, expectedNumArgsReg);
|
||||
__ Cmpq(rax, expectedNumArgsReg);
|
||||
__ Ja(&lCopyExtraAument);
|
||||
{
|
||||
__ Pushq(JSTaggedValue::VALUE_UNDEFINED);
|
||||
__ Addq(-1, expectedNumArgsReg);
|
||||
__ Cmpq(rax, expectedNumArgsReg);
|
||||
__ Ja(&lCopyExtraAument);
|
||||
}
|
||||
|
||||
__ Bind(&lCopyArguments);
|
||||
__ Cmpl(actualNumArgsReg, rbx);
|
||||
__ CMovbe(rbx, actualNumArgsReg);
|
||||
__ Movl(actualNumArgsReg, rax); // rax -> actualNumArgsReg
|
||||
{
|
||||
__ Cmpl(actualNumArgsReg, rbx);
|
||||
__ CMovbe(rbx, actualNumArgsReg);
|
||||
__ Movl(actualNumArgsReg, rax); // rax -> actualNumArgsReg
|
||||
}
|
||||
|
||||
__ Bind(&lCopyLoop);
|
||||
__ Movq(Operand(argvReg, rax, Scale::Times8, -8), actualNumArgsReg); // -8 : disp
|
||||
__ Pushq(actualNumArgsReg);
|
||||
__ Addq(-1, rax);
|
||||
__ Jne(&lCopyLoop);
|
||||
{
|
||||
__ Movq(Operand(argvReg, rax, Scale::Times8, -8), actualNumArgsReg); // -8 : disp
|
||||
__ Pushq(actualNumArgsReg);
|
||||
__ Addq(-1, rax);
|
||||
__ Jne(&lCopyLoop);
|
||||
|
||||
__ Pushq(r14);
|
||||
__ Movq(glueReg, rax); // mov glue to rax
|
||||
__ Callq(codeAddrReg); // then call jsFunction
|
||||
__ Leaq(Operand(r14, Scale::Times8, 0), actualNumArgsReg); // Note: fixed for 3 extra arguments
|
||||
__ Addq(actualNumArgsReg, rsp);
|
||||
__ Addq(8, rsp); // 8: skip r14
|
||||
__ Testb(1, r14); // stack 16bytes align check
|
||||
__ Jne(&lPopFrame);
|
||||
__ Addq(8, rsp); // 8: align byte
|
||||
__ Pushq(r14);
|
||||
__ Movq(glueReg, rax); // mov glue to rax
|
||||
__ Callq(codeAddrReg); // then call jsFunction
|
||||
__ Leaq(Operand(r14, Scale::Times8, 0), actualNumArgsReg); // Note: fixed for 3 extra arguments
|
||||
__ Addq(actualNumArgsReg, rsp);
|
||||
__ Addq(8, rsp); // 8: skip r14
|
||||
__ Testb(1, r14); // stack 16bytes align check
|
||||
__ Jne(&lPopFrame);
|
||||
__ Addq(8, rsp); // 8: align byte
|
||||
}
|
||||
|
||||
__ Bind(&lPopFrame);
|
||||
__ Popq(prevFpReg);
|
||||
__ Addq(8, rsp); // 8: frame type
|
||||
__ Popq(rbp);
|
||||
__ Popq(glueReg); // caller restore
|
||||
__ PopCppCalleeSaveRegisters(); // callee restore
|
||||
__ Movq(prevFpReg, Operand(glueReg, JSThread::GlueData::GetLeaveFrameOffset(false)));
|
||||
__ Ret();
|
||||
{
|
||||
__ Popq(prevFpReg);
|
||||
__ Addq(8, rsp); // 8: frame type
|
||||
__ Popq(rbp);
|
||||
__ Popq(glueReg); // caller restore
|
||||
__ PopCppCalleeSaveRegisters(); // callee restore
|
||||
__ Movq(prevFpReg, Operand(glueReg, JSThread::GlueData::GetLeaveFrameOffset(false)));
|
||||
__ Ret();
|
||||
}
|
||||
}
|
||||
|
||||
// uint64_t OptimizedCallOptimized(uintptr_t glue, uint32_t expectedNumArgs,
|
||||
@ -283,14 +293,13 @@ void AssemblerStubsX64::CallNativeTrampoline(ExtendedAssemblerX64 *assembler)
|
||||
__ Addq(16, rdx); // 16 : for rbp & return address
|
||||
// load native pointer address
|
||||
__ Movq(Operand(rdx, 0), r10); // r10 -> argv[0]
|
||||
__ Subq(8, rsp); // 8: align 16 bytes
|
||||
__ Subq(sizeof(EcmaRuntimeCallInfo), rsp);
|
||||
|
||||
// construct ecma_runtime_call_info
|
||||
// get thread
|
||||
Register threadReg = rax;
|
||||
__ Subq(JSThread::GetGlueDataOffset(), threadReg);
|
||||
__ Movq(threadReg, Operand(rsp, 0)); // thread_
|
||||
__ Movq(threadReg, Operand(rsp, EcmaRuntimeCallInfo::GetThreadOffset())); // thread_
|
||||
// get numArgs
|
||||
__ Movq(0, rax);
|
||||
__ Movl(Operand(rdx, 8), rax); // 8: sp + 8 actualArgc
|
||||
@ -304,8 +313,7 @@ void AssemblerStubsX64::CallNativeTrampoline(ExtendedAssemblerX64 *assembler)
|
||||
|
||||
__ Movq(rsp, rdi);
|
||||
__ Callq(r10);
|
||||
__ Addq(ASM_GLUE_ECMA_RUNTIME_CALLINFO_SIZE, rsp);
|
||||
__ Addq(8, rsp); // 8: sp + 8 align 16bytes
|
||||
__ Addq(sizeof(EcmaRuntimeCallInfo), rsp);
|
||||
__ Popq(rbx);
|
||||
__ Pop(r10);
|
||||
__ Addq(8, rsp); // 8: sp + 8
|
||||
@ -324,7 +332,7 @@ void AssemblerStubsX64::CallNativeTrampoline(ExtendedAssemblerX64 *assembler)
|
||||
// %rsi - argc
|
||||
// %rdx - calltarget
|
||||
// %rcx - argV (calltarget, newtarget, thisObj, ...)
|
||||
void AssemblerStubsX64::JSCallWithArgv(ExtendedAssemblerX64 *assembler)
|
||||
void AssemblerStubsX64::JSCallWithArgV(ExtendedAssemblerX64 *assembler)
|
||||
{
|
||||
Label jsCall;
|
||||
Label lJSCallStart;
|
||||
@ -374,21 +382,20 @@ void AssemblerStubsX64::JSCallWithArgv(ExtendedAssemblerX64 *assembler)
|
||||
__ Movq(Operand(jsFuncReg, 0), rax); // get jsHclass
|
||||
Register jsHclassReg = rax;
|
||||
__ Movl(Operand(jsHclassReg, JSHClass::BIT_FIELD_OFFSET), rax);
|
||||
__ Btl(JSHClass::BIT_FIELD1_OFFSET, rax); // IsCallable
|
||||
__ Btl(JSHClass::CallableBit::START_BIT, rax); // IsCallable
|
||||
__ Jnb(&lNonCallable);
|
||||
|
||||
__ Shll(24, rax); // objectType << 24
|
||||
__ Leal(Operand(rax, -50331649), rdx); // -50331649: disp
|
||||
__ Cmpl(0x9FFFFFF, rdx); // 0x9FFFFFF: is Jsfunction
|
||||
__ Jae(&lNotJSFunction); // objecttype in (0x04 ~ 0x0c)
|
||||
__ Jmp(&lJSFunctionCall);
|
||||
__ Cmpb(static_cast<int32_t>(JSType::JS_FUNCTION_BEGIN), rax);
|
||||
__ Jb(&lNotJSFunction);
|
||||
__ Cmpb(static_cast<int32_t>(JSType::JS_FUNCTION_END), rax);
|
||||
__ Jbe(&lJSFunctionCall);
|
||||
}
|
||||
|
||||
__ Bind(&lNotJSFunction);
|
||||
{
|
||||
__ Cmpl(0xd000000, rax); // 0xd000000: IsJsBoundFunction
|
||||
__ Cmpb(static_cast<uint8_t>(JSType::JS_BOUND_FUNCTION), rax); // IsBoundFunction
|
||||
__ Je(&lJSBoundFunction);
|
||||
__ Cmpl(0x4f000000, rax); // 0x4f000000: IsJsProxy
|
||||
__ Cmpb(static_cast<uint8_t>(JSType::JS_PROXY), rax); // IsJsProxy
|
||||
__ Je(&lJSProxy);
|
||||
}
|
||||
|
||||
@ -420,9 +427,9 @@ void AssemblerStubsX64::JSCallWithArgv(ExtendedAssemblerX64 *assembler)
|
||||
__ Mov(Operand(jsFuncReg, JSFunctionBase::METHOD_OFFSET), jsMethod); // get method
|
||||
__ Movl(Operand(rsp, 8), argc); // 8: sp + 8 actual argc
|
||||
__ Mov(Operand(jsMethod, JSMethod::GetCallFieldOffset(false)), methodCallField); // get call field
|
||||
__ Btq(JSMethod::IsNativeBit::SIZE, methodCallField); // is native
|
||||
__ Btq(JSMethod::IsNativeBit::START_BIT, methodCallField); // is native
|
||||
__ Jb(&lCallNativeMethod);
|
||||
__ Btq(JSMethod::IsAotCodeBit::SIZE, methodCallField); // is aot
|
||||
__ Btq(JSMethod::IsAotCodeBit::START_BIT, methodCallField); // is aot
|
||||
__ Jb(&lCallOptimziedMethod);
|
||||
__ Int3();
|
||||
__ Ret();
|
||||
@ -633,21 +640,20 @@ void AssemblerStubsX64::JSCall(ExtendedAssemblerX64 *assembler)
|
||||
__ Movq(Operand(jsFuncReg, 0), rax); // get jsHclass
|
||||
Register jsHclassReg = rax;
|
||||
__ Movl(Operand(jsHclassReg, JSHClass::BIT_FIELD_OFFSET), rax);
|
||||
__ Btl(JSHClass::BIT_FIELD1_OFFSET, rax); // IsCallable
|
||||
__ Btl(JSHClass::CallableBit::START_BIT, rax); // IsCallable
|
||||
__ Jnb(&lNonCallable);
|
||||
|
||||
__ Shll(24, rax); // objectType << 24
|
||||
__ Leal(Operand(rax, -50331649), rdx); // -50331649: disp
|
||||
__ Cmpl(0x9FFFFFF, rdx); // 0x9FFFFFF: is jsfunction
|
||||
__ Jae(&lNotJSFunction); // objecttype in (0x04 ~ 0x0c)
|
||||
__ Jmp(&lJSFunctionCall);
|
||||
__ Cmpb(static_cast<int32_t>(JSType::JS_FUNCTION_BEGIN), rax);
|
||||
__ Jb(&lNotJSFunction);
|
||||
__ Cmpb(static_cast<int32_t>(JSType::JS_FUNCTION_END), rax);
|
||||
__ Jbe(&lJSFunctionCall); // objecttype in (0x04 ~ 0x0c)
|
||||
}
|
||||
|
||||
__ Bind(&lNotJSFunction);
|
||||
{
|
||||
__ Cmpl(0xd000000, rax); // 0xd000000: IsJsBoundFunction
|
||||
__ Cmpb(static_cast<uint8_t>(JSType::JS_BOUND_FUNCTION), rax); // IsBoundFunction
|
||||
__ Je(&lJSBoundFunction);
|
||||
__ Cmpl(0x4f000000, rax); // 0x4f000000: IsJsProxy
|
||||
__ Cmpb(static_cast<uint8_t>(JSType::JS_PROXY), rax); // IsJsProxy
|
||||
__ Je(&lJSProxy);
|
||||
}
|
||||
|
||||
@ -679,9 +685,9 @@ void AssemblerStubsX64::JSCall(ExtendedAssemblerX64 *assembler)
|
||||
__ Mov(Operand(jsFuncReg, JSFunctionBase::METHOD_OFFSET), jsMethod); // get method
|
||||
__ Movl(Operand(rsp, 8), argc); // 8: sp + 8 actual argc
|
||||
__ Mov(Operand(jsMethod, JSMethod::GetCallFieldOffset(false)), methodCallField); // get call field
|
||||
__ Btq(JSMethod::IsNativeBit::SIZE, methodCallField); // is native
|
||||
__ Btq(JSMethod::IsNativeBit::START_BIT, methodCallField); // is native
|
||||
__ Jb(&lCallNativeMethod);
|
||||
__ Btq(JSMethod::IsAotCodeBit::SIZE, methodCallField); // is aot
|
||||
__ Btq(JSMethod::IsAotCodeBit::START_BIT, methodCallField); // is aot
|
||||
__ Jb(&lCallOptimziedMethod);
|
||||
__ Int3();
|
||||
__ Ret();
|
||||
@ -807,10 +813,10 @@ void AssemblerStubsX64::JSCall(ExtendedAssemblerX64 *assembler)
|
||||
}
|
||||
__ Bind(&lJSProxy);
|
||||
__ Movq(rsp, rcx);
|
||||
__ Addq(8, rcx); // 8: sp + 8
|
||||
__ Addq(8, rcx); // 8: sp + 8 skip returnAddr
|
||||
__ Mov(Operand(rcx, 0), rsi); // get origin argc
|
||||
__ Movq(r8, rdx); // 8: slot size
|
||||
__ Addq(8, rcx); // argv
|
||||
__ Movq(r8, rdx); // call
|
||||
__ Addq(8, rcx); // 8: sp + 8 argv
|
||||
__ Movq(kungfu::CommonStubCSigns::JsProxyCallInternal, r9);
|
||||
__ Movq(Operand(rdi, r9, Scale::Times8, JSThread::GlueData::GetCOStubEntriesOffset(false)), r8);
|
||||
__ Jmp(r8);
|
||||
|
@ -27,11 +27,7 @@ public:
|
||||
|
||||
static void JSFunctionEntry(ExtendedAssemblerX64 *assembler);
|
||||
|
||||
static void OptimizedCallOptimized(ExtendedAssemblerX64 *assembler);
|
||||
|
||||
static void CallNativeTrampoline(ExtendedAssemblerX64 *assembler);
|
||||
|
||||
static void JSCallWithArgv(ExtendedAssemblerX64 *assembler);
|
||||
static void JSCallWithArgV(ExtendedAssemblerX64 *assembler);
|
||||
|
||||
static void JSCall(ExtendedAssemblerX64 *assembler);
|
||||
|
||||
@ -76,6 +72,8 @@ public:
|
||||
static void ResumeCaughtFrameAndDispatch(ExtendedAssemblerX64 *assembler);
|
||||
|
||||
private:
|
||||
static void OptimizedCallOptimized(ExtendedAssemblerX64 *assembler);
|
||||
static void CallNativeTrampoline(ExtendedAssemblerX64 *assembler);
|
||||
static void PushArgsFastPath(ExtendedAssemblerX64 *assembler, Register glueRegister, Register argcRegister,
|
||||
Register argvRegister, Register callTargetRegister, Register methodRegister, Register prevSpRegister,
|
||||
Register fpRegister, Register callFieldRegister);
|
||||
|
@ -55,7 +55,6 @@ public:
|
||||
Chunk *chunk_ {nullptr};
|
||||
};
|
||||
|
||||
#define __ masm.
|
||||
HWTEST_F_L0(AssemblerStubsTest, JSFunctionEntry)
|
||||
{
|
||||
x64::AssemblerX64 masm(chunk_);
|
||||
@ -64,27 +63,11 @@ HWTEST_F_L0(AssemblerStubsTest, JSFunctionEntry)
|
||||
ecmascript::kungfu::LLVMAssembler::Disassemble(masm.GetBegin(), masm.GetCurrentPosition());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(AssemblerStubsTest, OptimizedCallOptimized)
|
||||
{
|
||||
x64::AssemblerX64 masm(chunk_);
|
||||
x64::ExtendedAssemblerX64 *assemblerX64 = static_cast<ExtendedAssemblerX64 *>(&masm);
|
||||
x64::AssemblerStubsX64::OptimizedCallOptimized(assemblerX64);
|
||||
ecmascript::kungfu::LLVMAssembler::Disassemble(masm.GetBegin(), masm.GetCurrentPosition());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(AssemblerStubsTest, CallNativeTrampoline)
|
||||
{
|
||||
x64::AssemblerX64 masm(chunk_);
|
||||
x64::ExtendedAssemblerX64 *assemblerX64 = static_cast<ExtendedAssemblerX64 *>(&masm);
|
||||
x64::AssemblerStubsX64::CallNativeTrampoline(assemblerX64);
|
||||
ecmascript::kungfu::LLVMAssembler::Disassemble(masm.GetBegin(), masm.GetCurrentPosition());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(AssemblerStubsTest, JSCallWithArgv)
|
||||
{
|
||||
x64::AssemblerX64 masm(chunk_);
|
||||
x64::ExtendedAssemblerX64 *assemblerX64 = static_cast<ExtendedAssemblerX64 *>(&masm);
|
||||
x64::AssemblerStubsX64::JSCallWithArgv(assemblerX64);
|
||||
x64::AssemblerStubsX64::JSCallWithArgV(assemblerX64);
|
||||
ecmascript::kungfu::LLVMAssembler::Disassemble(masm.GetBegin(), masm.GetCurrentPosition());
|
||||
}
|
||||
|
||||
@ -103,5 +86,4 @@ HWTEST_F_L0(AssemblerStubsTest, CallRuntimeWithArgv)
|
||||
x64::AssemblerStubsX64::CallRuntimeWithArgv(assemblerX64);
|
||||
ecmascript::kungfu::LLVMAssembler::Disassemble(masm.GetBegin(), masm.GetCurrentPosition());
|
||||
}
|
||||
#undef __
|
||||
} // namespace panda::test
|
||||
|
@ -396,12 +396,14 @@ JSTaggedValue EcmaVM::InvokeEcmaAotEntrypoint(JSHandle<JSFunction> mainFunc, con
|
||||
UpdateMethodInFunc(mainFunc, jsPandaFile);
|
||||
std::vector<JSTaggedType> args(6, JSTaggedValue::Undefined().GetRawData()); // 6: number of para
|
||||
args[0] = mainFunc.GetTaggedValue().GetRawData();
|
||||
auto res = JSFunctionEntry(thread_->GetGlueAddr(),
|
||||
reinterpret_cast<uintptr_t>(thread_->GetCurrentSPFrame()),
|
||||
static_cast<uint32_t>(args.size()),
|
||||
static_cast<uint32_t>(args.size()),
|
||||
args.data(),
|
||||
mainFunc->GetCodeEntry());
|
||||
|
||||
auto entry = thread_->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry);
|
||||
auto res = reinterpret_cast<JSFunctionEntryType>(entry)(thread_->GetGlueAddr(),
|
||||
reinterpret_cast<uintptr_t>(thread_->GetCurrentSPFrame()),
|
||||
static_cast<uint32_t>(args.size()),
|
||||
static_cast<uint32_t>(args.size()),
|
||||
args.data(),
|
||||
mainFunc->GetCodeEntry());
|
||||
return JSTaggedValue(res);
|
||||
}
|
||||
|
||||
|
@ -526,9 +526,6 @@ public:
|
||||
static_assert(MEMBER_OFFSET(GlueData, rtStubEntries_) == ASM_GLUE_RUNTIME_FUNCTIONS_OFFSET);
|
||||
static_assert(MEMBER_OFFSET(GlueData, currentFrame_) == ASM_GLUE_CURRENT_FRAME_OFFSET);
|
||||
static_assert(MEMBER_OFFSET(GlueData, leaveFrame_) == ASM_GLUE_LEAVE_FRAME_OFFSET);
|
||||
#ifdef ECMASCRIPT_ENABLE_TEST_STUB
|
||||
static_assert(MEMBER_OFFSET(GlueData, coStubEntries_) == ASM_GLUE_COMSTUB_ENTRY_OFFSET);
|
||||
#endif
|
||||
STATIC_ASSERT_EQ_ARCH(sizeof(GlueData), GlueData::SizeArch32, GlueData::SizeArch64);
|
||||
|
||||
private:
|
||||
|
@ -103,7 +103,11 @@ extern "C" void ResumeCaughtFrameAndDispatch(uintptr_t glue, uintptr_t pc, uintp
|
||||
V(PushCallIThisRangeAndDispatchSlowPath) \
|
||||
V(ResumeRspAndDispatch) \
|
||||
V(ResumeRspAndReturn) \
|
||||
V(ResumeCaughtFrameAndDispatch)
|
||||
V(ResumeCaughtFrameAndDispatch) \
|
||||
V(JSFunctionEntry) \
|
||||
V(JSCall) \
|
||||
V(JSCallWithArgV) \
|
||||
V(CallRuntimeWithArgv)
|
||||
|
||||
#define RUNTIME_STUB_WITHOUT_GC_LIST(V) \
|
||||
V(DebugPrint) \
|
||||
@ -113,9 +117,6 @@ extern "C" void ResumeCaughtFrameAndDispatch(uintptr_t glue, uintptr_t pc, uintp
|
||||
V(DoubleToInt) \
|
||||
V(FloatMod) \
|
||||
V(FindElementWithCache) \
|
||||
V(CallRuntimeWithArgv) \
|
||||
V(JSCall) \
|
||||
V(JSCallWithArgV) \
|
||||
V(JSObjectGetMethod) \
|
||||
V(CreateArrayFromList) \
|
||||
V(StringsAreEquals) \
|
||||
|
@ -55,6 +55,7 @@ JSTaggedType RuntimeStubs::name(uintptr_t argGlue, uint32_t argc, uintptr_t argv
|
||||
ASSERT((index) < argc); \
|
||||
type name = reinterpret_cast<type>(*(reinterpret_cast<JSTaggedType *>(argv) + (index)))
|
||||
|
||||
#ifndef NDEBUG
|
||||
DEF_RUNTIME_STUBS(DefineAotFunc)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(DefineAotFunc);
|
||||
@ -163,4 +164,5 @@ DEF_RUNTIME_STUBS(DumpTaggedType)
|
||||
value->D();
|
||||
return value.GetTaggedValue().GetRawData();
|
||||
}
|
||||
#endif
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -16,7 +16,7 @@
|
||||
#ifndef ECMASCRIPT_TEST_RUNTIME_STUBS_H
|
||||
#define ECMASCRIPT_TEST_RUNTIME_STUBS_H
|
||||
namespace panda::ecmascript {
|
||||
#ifdef ECMASCRIPT_ENABLE_TEST_STUB
|
||||
#ifndef NDEBUG
|
||||
#define TEST_RUNTIME_STUB_GC_LIST(V) \
|
||||
V(DefineAotFunc) \
|
||||
V(GetPrintFunc) \
|
||||
|
@ -79,10 +79,14 @@ public:
|
||||
}
|
||||
|
||||
// If you want to call once create, you can refer to BuiltinsMathTest for detail.
|
||||
static void CreateEcmaVMWithScope(EcmaVM *&instance, JSThread *&thread, EcmaHandleScope *&scope)
|
||||
static void CreateEcmaVMWithScope(EcmaVM *&instance, JSThread *&thread, EcmaHandleScope *&scope,
|
||||
bool tryLoadStubFile = false)
|
||||
{
|
||||
JSRuntimeOptions options;
|
||||
options.SetEnableForceGC(true);
|
||||
if (tryLoadStubFile) {
|
||||
options.SetEnableStubAot(true);
|
||||
}
|
||||
instance = JSNApi::CreateEcmaVM(options);
|
||||
instance->SetEnableForceGC(true);
|
||||
ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM";
|
||||
|
@ -156,12 +156,6 @@
|
||||
#define MESSAGE_STRING_NON_CALLABLE_ID (0xffff000000000005)
|
||||
#define RUNTIME_ID_THROW_TYPE_ERROR (0x16)
|
||||
|
||||
// com stub
|
||||
#ifdef PANDA_TARGET_64
|
||||
#define ASM_GLUE_COMSTUB_ENTRY_OFFSET (0xdf0)
|
||||
#else
|
||||
#define ASM_GLUE_COMSTUB_ENTRY_OFFSET (0x708)
|
||||
#endif
|
||||
#define JSPROXY_CALL_INTERNAL_INDEX (0x15)
|
||||
|
||||
#define ASM_NUM_MANDATORY_JSFUNC_ARGS (3)
|
||||
|
@ -25,5 +25,8 @@ extern "C" JSTaggedType JSFunctionEntry(uintptr_t glue, uintptr_t prevFp, uint32
|
||||
uint32_t actualNumArgs, const JSTaggedType argV[], uintptr_t codeAddr);
|
||||
extern "C" JSTaggedType OptimizedCallOptimized(uintptr_t glue, uint32_t expectedNumArgs,
|
||||
uint32_t actualNumArgs, uintptr_t codeAddr, ...);
|
||||
|
||||
using JSFunctionEntryType = uint64_t (*)(uintptr_t glue, uintptr_t prevFp, uint32_t expectedNumArgs,
|
||||
uint32_t actualNumArgs, const JSTaggedType argV[], uintptr_t codeAddr);
|
||||
} // panda::ecmascript
|
||||
#endif // ECMASCRIPT_BRIDGE_H
|
||||
|
@ -122,63 +122,6 @@
|
||||
// %r8 - argV
|
||||
// %r9 - codeAddr
|
||||
JSFunctionEntry:
|
||||
PUSH_GENERAL_REGS
|
||||
// construct the frame
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp // set frame pointer
|
||||
pushq $JS_ENTRY_FRAME_TYPE // optimized entry frame type
|
||||
pushq %rsi // prev managed fp
|
||||
|
||||
// 16 bytes align check
|
||||
movl %edx, %r14d
|
||||
testb $1, %r14b
|
||||
jne .LAlign16Bytes
|
||||
pushq $0 // push zero to align 16 bytes stack
|
||||
|
||||
.LAlign16Bytes:
|
||||
// expectedNumArgs > actualNumArgs
|
||||
movl %edx, %ebx // save expectedNumArgs
|
||||
cmpl %ecx, %edx
|
||||
jbe .LCopyArguments
|
||||
movl %ecx, %eax
|
||||
movl %ebx, %edx
|
||||
|
||||
.LCopyExtraAument: // copy undefined value to stack
|
||||
pushq $JSUNDEFINED
|
||||
|
||||
addq $-1, %rdx
|
||||
cmpq %rax, %rdx
|
||||
ja .LCopyExtraAument
|
||||
|
||||
.LCopyArguments:
|
||||
cmpl %ecx, %ebx
|
||||
cmovbe %ebx, %ecx
|
||||
movl %ecx, %eax
|
||||
|
||||
.LCopyLoop:
|
||||
movq -8(%r8, %rax, 8), %rcx
|
||||
pushq %rcx
|
||||
|
||||
addq $-1, %rax
|
||||
jne .LCopyLoop
|
||||
|
||||
push %r14
|
||||
movq %rdi, %rax // move glue to rax
|
||||
call *%r9 // then call jsFunction
|
||||
leaq (,%r14,8), %rcx // NOTE: fixed for 3 extra arguments
|
||||
addq %rcx, %rsp
|
||||
addq $8, %rsp
|
||||
testb $1, %r14b // stack 16bytes align check
|
||||
jne .LPopFrame
|
||||
addq $8, %rsp
|
||||
|
||||
.LPopFrame:
|
||||
popq %rsi // pop prev-managed frame
|
||||
addq $8, %rsp
|
||||
popq %rbp
|
||||
|
||||
POP_GENERAL_REGS
|
||||
movq %rsi, ASM_GLUE_LEAVE_FRAME_OFFSET(%rdi) // restore thread->leaveFrame_
|
||||
ret
|
||||
|
||||
|
||||
@ -204,64 +147,6 @@ JSFunctionEntry:
|
||||
// sp[- 8(N - 1)] - arg[0]
|
||||
|
||||
OptimizedCallOptimized:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp // set frame pointer
|
||||
pushq $OPTIMIZE_FRAME_TYPE
|
||||
//callee save
|
||||
pushq %r14
|
||||
pushq %rbx
|
||||
pushq %rax
|
||||
|
||||
// 16 bytes align check
|
||||
movl %esi, %r14d
|
||||
testb $1, %r14b
|
||||
jne .LAlign16Bytes1
|
||||
pushq $0 // push zero to align 16 bytes stack
|
||||
|
||||
.LAlign16Bytes1:
|
||||
// expectedNumArgs > actualNumArgs
|
||||
movl %esi, %ebx // save expectedNumArgs
|
||||
cmpl %edx, %esi
|
||||
jbe .LCopyArguments1
|
||||
movl %edx, %eax
|
||||
movl %ebx, %esi
|
||||
|
||||
.LCopyExtraAument1: // copy undefined value to stack
|
||||
pushq $JSUNDEFINED
|
||||
|
||||
addq $-1, %rsi
|
||||
cmpq %rax, %rsi
|
||||
ja .LCopyExtraAument1
|
||||
|
||||
.LCopyArguments1:
|
||||
cmpl %edx, %ebx
|
||||
cmovbe %ebx, %edx
|
||||
movl %edx, %eax
|
||||
|
||||
.LCopyLoop1:
|
||||
movq -8(%r8, %rax, 8), %rbx
|
||||
pushq %rbx
|
||||
|
||||
addq $-1, %rax
|
||||
jne .LCopyLoop1
|
||||
|
||||
pushq %rdx // actual argc
|
||||
movq %rdi, %rax // move glue to rax
|
||||
callq *%rcx // then call jsFunction
|
||||
leaq (,%r14,8), %rcx
|
||||
addq %rcx, %rsp
|
||||
addq $8, %rsp
|
||||
|
||||
testb $1, %r14b // stack 16bytes align check
|
||||
jne .LPopFrame1
|
||||
addq $8, %rsp
|
||||
|
||||
.LPopFrame1:
|
||||
addq $8, %rsp
|
||||
popq %rbx
|
||||
popq %r14
|
||||
addq $8, %rsp
|
||||
pop %rbp
|
||||
ret
|
||||
|
||||
// uint64_t CallNativeTrampoline(uintptr_t glue, uintptr_t codeAddress, uint32_t argc, ...);
|
||||
@ -298,47 +183,6 @@ OptimizedCallOptimized:
|
||||
.global CallNativeTrampoline
|
||||
.type CallNativeTrampoline, %function
|
||||
CallNativeTrampoline:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp // set frame pointer
|
||||
movq %rbp, ASM_GLUE_LEAVE_FRAME_OFFSET(%rax) // save to thread->leaveFrame_
|
||||
pushq $LEAVE_FRAME_TYPE
|
||||
|
||||
// callee save
|
||||
pushq %r10
|
||||
pushq %rbx
|
||||
|
||||
movq %rbp, %rdx
|
||||
addq $16, %rdx // 16 : for rbp & return address
|
||||
|
||||
// load native pointer address
|
||||
movq (%rdx), %r10
|
||||
subq $ASM_GLUE_ECMA_RUNTIME_CALLINFO_SIZE, %rsp
|
||||
|
||||
// construct ecma_runtime_call_info
|
||||
// get thread
|
||||
subq $ASM_GLUE_TO_THREAD_OFFSET, %rax
|
||||
movq %rax, (%rsp) // thread_
|
||||
// get numArgs
|
||||
movq $0, %rax
|
||||
movl 8(%rdx), %eax
|
||||
subl $3, %eax
|
||||
movq %rax, ECMA_RUNTIME_CALLINFO_NUMARGS_OFFSET(%rsp) // numArgs
|
||||
// get gpr data
|
||||
movq %rdx, %rbx
|
||||
addq $16, %rbx
|
||||
movq %rbx, ECMA_RUNTIME_CALLINFO_STACKARGS_OFFSET(%rsp)
|
||||
movq $0, ECMA_RUNTIME_CALLINFO_DATA_OFFSET(%rsp)
|
||||
|
||||
movq %rsp, %rdi
|
||||
call *%r10
|
||||
addq $ASM_GLUE_ECMA_RUNTIME_CALLINFO_SIZE, %rsp
|
||||
popq %rbx
|
||||
popq %r10
|
||||
addq $8, %rsp
|
||||
popq %rbp
|
||||
popq %rdx // load pc
|
||||
addq $8, %rsp // skip code address
|
||||
pushq %rdx // save pc
|
||||
ret
|
||||
|
||||
// uint64_t CallRuntime(uintptr_t glue, uint64_t runtime_id, uint64_t argc, ...);
|
||||
@ -455,177 +299,8 @@ CallRuntime:
|
||||
.type JSCall, %function
|
||||
|
||||
JSCallWithArgV:
|
||||
mov %rdx, (%rcx)
|
||||
mov %rdx, %rax
|
||||
jmp .LJSCallStart
|
||||
ret
|
||||
JSCall:
|
||||
mov %rax, %rdi
|
||||
mov 16(%rsp), %rax // get jsfunc
|
||||
.LJSCallStart:
|
||||
movabs $TAGGED_MASK, %rdx // IsTaggedInt
|
||||
and %rax, %rdx
|
||||
cmp $0x0, %rdx
|
||||
jne .LNonCallable
|
||||
cmp $0x0, %rax // IsHole
|
||||
je .LNonCallable
|
||||
movabs $TAGGED_SPECIAL_VALUE, %rdx
|
||||
and %rax, %rdx // IsSpecial
|
||||
cmp $0x0, %rdx
|
||||
jne .LNonCallable
|
||||
|
||||
mov %rax, %r8 // save jsfunc
|
||||
mov (%rax), %rax // get jshclass
|
||||
movl JS_HCLASS_BITFIELD_OFFSET(%rax), %eax
|
||||
btl $JS_HCLASS_BITFIELD_CALLABLE_BIT, %eax // IsCallable
|
||||
jnb .LNonCallable
|
||||
|
||||
shll $24, %eax // objecttype << 24
|
||||
leal -50331649(%rax), %edx
|
||||
cmpl $0x9FFFFFF, %edx
|
||||
jae .LNotJSFunction // objecttype in (0x04 ~ 0x0c)
|
||||
jmp .LJSFunctionCall
|
||||
.LNotJSFunction:
|
||||
cmpl $0xd000000, %eax // IsJsBoundFunction
|
||||
je .LJSBoundFunction
|
||||
cmpl $0x50000000, %eax // IsJsProxy
|
||||
je .LJSProxy
|
||||
|
||||
.LNonCallable:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp // set frame pointer
|
||||
pushq $OPTIMIZE_FRAME_TYPE // set frame type
|
||||
mov $MESSAGE_STRING_NON_CALLABLE_ID, %rax
|
||||
pushq %rax //message id
|
||||
pushq $1 //argc
|
||||
pushq $RUNTIME_ID_THROW_TYPE_ERROR //runtime id
|
||||
mov %rcx, %rax // glue
|
||||
call CallRuntime
|
||||
movabs $TAGGED_VALUE_EXCEPTION, %rax // reteurn exception
|
||||
addq $32, %rsp
|
||||
pop %rbp
|
||||
ret
|
||||
|
||||
// %rdi -- glue
|
||||
// %r8 -- jsfunc
|
||||
.LJSFunctionCall:
|
||||
mov JS_FUNCTION_METHOD_OFFSET(%r8), %rsi // get method
|
||||
movl 8(%rsp), %edx // Actual argc
|
||||
mov JS_METHOD_CALLFIELD_OFFSET(%rsi), %rax // get call field
|
||||
btq $JS_METHOD_CALL_FIELD_NATIVE_BIT, %rax // is native
|
||||
jb .LCallNativeMethod
|
||||
btq $JS_METHOD_CALL_FIELD_AOT_BIT, %rax // is aot
|
||||
jb .LCallOptimziedMethod
|
||||
// todo: need to fix it // is bytecode
|
||||
int3
|
||||
ret
|
||||
|
||||
.LCallOptimziedMethod:
|
||||
mov JS_FUNCTION_CODE_ENTRY_OFFSET(%r8), %rcx // get codeaddress
|
||||
shr $JS_METHOD_NUM_ARGS_SHIFT, %rax
|
||||
andl $ASM_JS_METHOD_NUM_ARGS_MASK, %eax
|
||||
addl $ASM_NUM_MANDATORY_JSFUNC_ARGS, %eax // add mandatory arguments
|
||||
mov %eax, %esi // expected numbers
|
||||
movq %rsp, %r8
|
||||
addq $16, %r8 // r8 argv
|
||||
cmpl %esi, %edx // expectedNumArgs <= actualNumArgs
|
||||
jg .LDirectCallCodeEntry
|
||||
jmp OptimizedCallOptimized
|
||||
.LDirectCallCodeEntry:
|
||||
mov %rdi, %rax
|
||||
jmp *%rcx
|
||||
|
||||
.LCallNativeMethod:
|
||||
pop %rax // pc
|
||||
mov JS_FUNCTION_METHOD_OFFSET(%r8), %rsi // get method
|
||||
mov JS_METHOD_NATIVE_POINTER_OFFSET(%rsi), %rsi // get native pointer
|
||||
push %rsi // native code address
|
||||
push %rax // pc
|
||||
mov %rdi, %rax
|
||||
jmp CallNativeTrampoline
|
||||
|
||||
// input
|
||||
// %rdi -- glue
|
||||
// %r8 -- jsfunc
|
||||
.LJSBoundFunction:
|
||||
// construct frame
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp // set frame pointer
|
||||
pushq $OPTIMIZE_FRAME_TYPE // set frame type
|
||||
|
||||
// callee save
|
||||
pushq %r10
|
||||
|
||||
mov %rsp, %rdx
|
||||
addq $32, %rdx
|
||||
mov (%rdx), %rax // get origin argc
|
||||
mov %rax, %r10
|
||||
|
||||
// get bound target
|
||||
mov JS_FUNCTION_BOUND_ARG_OFFSET(%r8), %rcx
|
||||
// get bound length
|
||||
mov TAGGED_ARRAY_LENGTH_OFFSET(%rcx), %rcx
|
||||
addq %rcx, %r10
|
||||
|
||||
// 16 bytes align check
|
||||
testb $1, %r10b
|
||||
jne .LAlign16Bytes2
|
||||
pushq $0 // push zero to align 16 bytes stack
|
||||
|
||||
.LAlign16Bytes2:
|
||||
subq $ASM_NUM_MANDATORY_JSFUNC_ARGS, %rax
|
||||
cmp $0, %rax
|
||||
je .LCopyBoundArgument
|
||||
.LCopyArgument2:
|
||||
movq 24(%rdx, %rax, 8), %rcx
|
||||
pushq %rcx
|
||||
|
||||
addq $-1, %rax
|
||||
jne .LCopyArgument2
|
||||
|
||||
// get bound target
|
||||
mov JS_FUNCTION_BOUND_ARG_OFFSET(%r8), %rdx
|
||||
// get bound length
|
||||
mov TAGGED_ARRAY_LENGTH_OFFSET(%rdx), %rax
|
||||
addq $TAGGED_ARRAY_DATA_OFFSET, %rdx
|
||||
.LCopyBoundArgument:
|
||||
cmp $0, %rax
|
||||
je .LPushCallTarget
|
||||
.LCopyBoundArgumentLoop:
|
||||
addq $-1, %rax
|
||||
movq (%rdx, %rax, 8), %rcx
|
||||
pushq %rcx
|
||||
jne .LCopyBoundArgumentLoop
|
||||
.LPushCallTarget:
|
||||
mov JS_FUNCTION_BOUND_THIS_OFFSET(%r8), %rax // thisObj
|
||||
pushq %rax
|
||||
pushq $JSUNDEFINED // newtarget
|
||||
mov JS_FUNCTION_BOUND_TARGET_OFFSET(%r8), %rax // calltarget
|
||||
pushq %rax
|
||||
pushq %r10 // push actual arguments
|
||||
mov %rdi, %rax
|
||||
call JSCall
|
||||
leaq 8(, %r10, 8), %rcx
|
||||
addq %rcx, %rsp
|
||||
|
||||
testb $1, %r10b // stack 16bytes align check
|
||||
jne .LPopFrame2
|
||||
addq $8, %rsp
|
||||
|
||||
.LPopFrame2:
|
||||
pop %r10
|
||||
addq $8, %rsp
|
||||
pop %rbp
|
||||
ret
|
||||
.LJSProxy:
|
||||
mov %rsp, %rcx
|
||||
addq $8, %rcx
|
||||
mov (%rcx), %rsi // get origin argc
|
||||
mov %r8, %rdx // calltarget
|
||||
addq $8, %rcx // argv
|
||||
|
||||
movq $JSPROXY_CALL_INTERNAL_INDEX, %r9
|
||||
movq ASM_GLUE_COMSTUB_ENTRY_OFFSET(%rdi, %r9, 8), %r8
|
||||
jmp *%r8
|
||||
ret
|
||||
|
||||
// ==================================================================================
|
||||
|
@ -22,7 +22,6 @@ if (!defined(ark_independent_build)) {
|
||||
}
|
||||
compile_llvm_online = false
|
||||
run_with_asan = false
|
||||
enable_test_stub = false
|
||||
enable_bytrace = true
|
||||
asan_lib_path = "/usr/lib/llvm-10/lib/clang/10.0.0/lib/linux"
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user