From 1bd26abdc969d5c81c0dff6e2c4fb8a0d532c103 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Mon, 11 Oct 2021 10:17:47 +0800 Subject: [PATCH 1/6] init Signed-off-by: surpassgoodchao --- BUILD.gn | 3 + ecmascript/compiler/BUILD.gn | 4 +- ecmascript/compiler/circuit_builder.cpp | 4 +- ecmascript/compiler/compile_llvm_lib.sh | 10 +- ecmascript/compiler/llvm/BUILD.gn | 23 + ecmascript/compiler/llvm/llvm.patch | 123 +++ .../llvm_stackmap_parser.cpp} | 56 +- .../llvm_stackmap_parser.h} | 21 +- ecmascript/compiler/llvm_ir_builder.cpp | 853 +++++++++++------- ecmascript/compiler/llvm_ir_builder.h | 94 +- ecmascript/compiler/tests/BUILD.gn | 3 +- ecmascript/compiler/tests/stub_tests.cpp | 55 +- ecmascript/frames.h | 212 ++++- ecmascript/interpreter/frame_handler.cpp | 90 +- ecmascript/interpreter/frame_handler.h | 30 +- ecmascript/interpreter/interpreter-inl.h | 38 +- ecmascript/interpreter/interpreter.h | 3 +- ecmascript/js_thread.cpp | 5 +- ecmascript/js_thread.h | 1 + ecmascript/runtime_trampolines.cpp | 31 + ecmascript/runtime_trampolines.h | 28 + ecmascript/tests/test_helper.h | 3 +- ecmascript/tooling/BUILD.gn | 1 + llvm.patch | 121 +++ 24 files changed, 1368 insertions(+), 444 deletions(-) create mode 100644 ecmascript/compiler/llvm/BUILD.gn create mode 100644 ecmascript/compiler/llvm/llvm.patch rename ecmascript/compiler/{llvm_stackmap_parse.cpp => llvm/llvm_stackmap_parser.cpp} (70%) rename ecmascript/compiler/{llvm_stackmap_parse.h => llvm/llvm_stackmap_parser.h} (88%) create mode 100644 llvm.patch diff --git a/BUILD.gn b/BUILD.gn index bea20a7536..7375b61f8b 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -381,6 +381,7 @@ source_set("libark_jsruntime_static") { deps = [ "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", + "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser", sdk_libc_secshared_dep, ] @@ -446,6 +447,8 @@ ohos_shared_library("libark_jsruntime_test") { } else { deps += [ "$ark_root/runtime:libarkruntime" ] } + deps += + [ "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser" ] output_extension = "so" subsystem_name = "test" diff --git a/ecmascript/compiler/BUILD.gn b/ecmascript/compiler/BUILD.gn index 0cfb8f7727..e9db2b7eb1 100644 --- a/ecmascript/compiler/BUILD.gn +++ b/ecmascript/compiler/BUILD.gn @@ -47,7 +47,6 @@ source_set("libark_jsoptimizer_static") { "llvm_codegen.cpp", "llvm_ir_builder.cpp", "llvm_mcjit_engine.cpp", - "llvm_stackmap_parse.cpp", "scheduler.cpp", "stub.cpp", "stub_descriptor.cpp", @@ -138,6 +137,7 @@ ohos_shared_library("libark_jsoptimizer") { deps = [ ":libark_jsoptimizer_static", "//ark/js_runtime:libark_jsruntime", + "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser", ] if (compile_llvm_online) { @@ -162,6 +162,8 @@ ohos_shared_library("libark_jsoptimizer_test") { if (is_standard_system) { deps += [ "$ark_root/runtime:libarkruntime_static" ] + deps += + [ "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser" ] } else { deps += [ "$ark_root/runtime:libarkruntime" ] } diff --git a/ecmascript/compiler/circuit_builder.cpp b/ecmascript/compiler/circuit_builder.cpp index 0fcc17683a..541311d2f5 100644 --- a/ecmascript/compiler/circuit_builder.cpp +++ b/ecmascript/compiler/circuit_builder.cpp @@ -365,7 +365,7 @@ AddrShift CircuitBuilder::NewCallGate(StubDescriptor *descriptor, AddrShift targ AddrShift CircuitBuilder::NewCallRuntimeGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, std::initializer_list args) { - ASSERT(descriptor->GetStubKind() == StubDescriptor::RUNTIME_STUB); + ASSERT(descriptor->GetStubKind() == StubDescriptor::CallStubKind::RUNTIME_STUB); std::vector inputs; auto dependEntry = Circuit::GetCircuitRoot(OpCode(OpCode::DEPEND_ENTRY)); inputs.push_back(dependEntry); @@ -382,7 +382,7 @@ AddrShift CircuitBuilder::NewCallRuntimeGate(StubDescriptor *descriptor, AddrShi AddrShift CircuitBuilder::NewCallRuntimeGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, AddrShift depend, std::initializer_list args) { - ASSERT(descriptor->GetStubKind() == StubDescriptor::RUNTIME_STUB); + ASSERT(descriptor->GetStubKind() == StubDescriptor::CallStubKind::RUNTIME_STUB); std::vector inputs; inputs.push_back(depend); inputs.push_back(target); diff --git a/ecmascript/compiler/compile_llvm_lib.sh b/ecmascript/compiler/compile_llvm_lib.sh index 58c117ed66..0891662c32 100755 --- a/ecmascript/compiler/compile_llvm_lib.sh +++ b/ecmascript/compiler/compile_llvm_lib.sh @@ -25,20 +25,24 @@ echo ${BIN_PATH} echo ${BASE_HOME} if [ ! -d ${BASE_HOME}/third_party/llvm-project ]; then + cd ${BASE_HOME}/third_party dd if=/dev/zero of=/tmp/mem.swap bs=1M count=4096 - git clone https://gitee.com/github-repos/llvm-project.git + git clone https://gitee.com/surpassgoodchao/llvm-project.git fi cd ${BASE_HOME}/third_party/llvm-project if [ ! -d "build" ];then + git checkout -b local llvmorg-10.0.1 + cp ../../ark/js_runtime/ecmascript/compiler/llvm/llvm.patch . + git apply --reject llvm.patch mkdir build && cd build - cmake -GNinja -DCMAKE_BUILD_TYPE=Release ../llvm + cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DBUILD_ARK_GC_SUPPORT=ON -DLLVM_ENABLE_TERMINFO=OFF DLLVM_STATIC_LINK_CXX_STDLIB=OFF -DLLVM_ENABLE_ZLIB=OFF ../llvm ninja else cd build if [ ! -d "lib" ]; then rm -rf * - cmake -GNinja -DCMAKE_BUILD_TYPE=Release ../llvm + cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DBUILD_ARK_GC_SUPPORT=ON -DLLVM_ENABLE_TERMINFO=OFF DLLVM_STATIC_LINK_CXX_STDLIB=OFF -DLLVM_ENABLE_ZLIB=OFF ../llvm ninja fi fi diff --git a/ecmascript/compiler/llvm/BUILD.gn b/ecmascript/compiler/llvm/BUILD.gn new file mode 100644 index 0000000000..5c930cd61b --- /dev/null +++ b/ecmascript/compiler/llvm/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//ark/js_runtime/js_runtime_config.gni") +import("//build/ohos.gni") + +ohos_shared_library("libllvm_stackmap_parser") { + sources = [ "llvm_stackmap_parser.cpp" ] + + output_extension = "so" + relative_install_dir = "ark" + subsystem_name = "ark" +} diff --git a/ecmascript/compiler/llvm/llvm.patch b/ecmascript/compiler/llvm/llvm.patch new file mode 100644 index 0000000000..73d0ec3ea1 --- /dev/null +++ b/ecmascript/compiler/llvm/llvm.patch @@ -0,0 +1,123 @@ +diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt +index 0e85afa82c7..54a9152e44f 100644 +--- a/llvm/CMakeLists.txt ++++ b/llvm/CMakeLists.txt +@@ -505,8 +505,15 @@ option(LLVM_BUILD_RUNTIME + "Build the LLVM runtime libraries." ON) + option(LLVM_BUILD_EXAMPLES + "Build the LLVM example programs. If OFF, just generate build targets." OFF) ++option(BUILD_ARK_GC_SUPPORT ++ "ARK support GC. If ON, support GC." OFF) ++if(BUILD_ARK_GC_SUPPORT) ++ add_definitions(-DARK_GC_SUPPORT) ++endif(ARK_SUPPORT_GC) ++ + option(LLVM_INCLUDE_EXAMPLES "Generate build targets for the LLVM examples" ON) + ++ + if(LLVM_BUILD_EXAMPLES) + add_definitions(-DBUILD_EXAMPLES) + endif(LLVM_BUILD_EXAMPLES) +diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp +index 1da20371caf..60d9af0d833 100644 +--- a/llvm/lib/Target/X86/X86FrameLowering.cpp ++++ b/llvm/lib/Target/X86/X86FrameLowering.cpp +@@ -31,6 +31,7 @@ + #include "llvm/Support/Debug.h" + #include "llvm/Target/TargetOptions.h" + #include ++#include + + using namespace llvm; + +@@ -1168,6 +1169,28 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, + else + MFI.setOffsetAdjustment(-StackSize); + } ++#ifdef ARK_GC_SUPPORT ++ // push marker ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) ++ { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ std::cout << __LINE__ << " marker:" << std::dec << marker << std::endl; ++ ++ BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH64i32)) ++ .addImm(marker) ++ .setMIFlag(MachineInstr::FrameSetup); ++ /*reserve thread.fp */ ++ if (marker == 1) { ++ BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH64i32)) ++ .addImm(marker) ++ .setMIFlag(MachineInstr::FrameSetup); ++ } ++ } ++#endif + + // For EH funclets, only allocate enough space for outgoing calls. Save the + // NumBytes value that we would've used for the parent frame. +@@ -1635,6 +1658,27 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, + uint64_t SEHStackAllocAmt = NumBytes; + + if (HasFP) { ++#ifdef ARK_GC_SUPPORT ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) ++ { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ ++ // pop marker ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), ++ MachineFramePtr) ++ .setMIFlag(MachineInstr::FrameDestroy); ++ if (marker == 1) { ++ // pop thread.fp ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), ++ MachineFramePtr) ++ .setMIFlag(MachineInstr::FrameDestroy); ++ } ++ } ++#endif + // Pop EBP. + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), + MachineFramePtr) +@@ -1993,8 +2037,33 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( + + if (hasFP(MF)) { + // emitPrologue always spills frame register the first thing. ++#ifdef ARK_GC_SUPPORT ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ if (marker == 1) { ++ SpillSlotOffset -= 3 * SlotSize; // add type and thread.fp ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ CalleeSavedFrameSize += 16; ++ } else { ++ SpillSlotOffset -= 2 * SlotSize; // add type ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ CalleeSavedFrameSize += 8; ++ } ++ } else { ++ SpillSlotOffset -= SlotSize; // add type and thread.fp ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ } ++#else + SpillSlotOffset -= SlotSize; + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++#endif + + // Since emitPrologue and emitEpilogue will handle spilling and restoring of + // the frame register, we can delete it from CSI list and not have to worry diff --git a/ecmascript/compiler/llvm_stackmap_parse.cpp b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp similarity index 70% rename from ecmascript/compiler/llvm_stackmap_parse.cpp rename to ecmascript/compiler/llvm/llvm_stackmap_parser.cpp index e49ed47e66..ddbb9eede2 100644 --- a/ecmascript/compiler/llvm_stackmap_parse.cpp +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp @@ -13,15 +13,15 @@ * limitations under the License. */ -#include "ecmascript/compiler/llvm_stackmap_parse.h" +#include "llvm_stackmap_parser.h" #include #include #include namespace kungfu { -std::string LocationTy::TypeToString(Kind location) const +std::string LocationTy::TypeToString(Kind loc) const { - switch (location) { + switch (loc) { case Kind::REGISTER: return "Register Reg Value in a register"; case Kind::DIRECT: @@ -37,18 +37,56 @@ std::string LocationTy::TypeToString(Kind location) const } } -bool LLVMStackMapParse::StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetType &info) +bool LLVMStackMapParser::StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetTypeVector &infos) { + bool found = false; for (auto it: callSiteInfos_) { if (it.first == funcAddr) { - info = it.second; - return true; + DwarfRegAndOffsetType info = it.second; + infos.push_back(info); + found = true; } } - return false; + return found; } -void LLVMStackMapParse::CalcCallSite() +bool LLVMStackMapParser::StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t frameFp, + std::vector &slotAddrs) +{ + DwarfRegAndOffsetTypeVector infos; + if (!StackMapByAddr(funcAddr, infos)) { + return false; + } +#ifdef PANDA_TARGET_AMD64 + uintptr_t *rbp = reinterpret_cast(frameFp); + uintptr_t returnAddr = *(rbp + 1); + uintptr_t *rsp = rbp + 2; // 2: rsp offset + rbp = reinterpret_cast(*rbp); + uintptr_t **address = nullptr; + for (auto &info: infos) { + if (info.first == 7) { // 7: rsp for x86_64 + address = reinterpret_cast(reinterpret_cast(rsp) + info.second); + // rbp + } else if (info.first == 6) { // 6: rbp for x86_64 + address = reinterpret_cast(reinterpret_cast(rbp) + info.second); + } else { + address = nullptr; + abort(); + } + std::cout << std::hex << "ref addr:" << address; + std::cout << " value:" << *address; + std::cout << " *value :" << **address << std::endl; + slotAddrs.push_back(reinterpret_cast(address)); + } +#else + (void)frameFp; + (void)slotAddrs; + abort(); +#endif + return true; +} + +void LLVMStackMapParser::CalcCallSite() { uint64_t recordNum = 0; for (size_t i = 0; i < llvmStackMap_.StkSizeRecords.size(); i++) { @@ -74,7 +112,7 @@ void LLVMStackMapParse::CalcCallSite() } } -bool LLVMStackMapParse::CalculateStackMap(const uint8_t *stackMapAddr) +bool LLVMStackMapParser::CalculateStackMap(const uint8_t *stackMapAddr) { stackMapAddr_ = stackMapAddr; if (!stackMapAddr_) { diff --git a/ecmascript/compiler/llvm_stackmap_parse.h b/ecmascript/compiler/llvm/llvm_stackmap_parser.h similarity index 88% rename from ecmascript/compiler/llvm_stackmap_parse.h rename to ecmascript/compiler/llvm/llvm_stackmap_parser.h index e22e554996..797a79140b 100644 --- a/ecmascript/compiler/llvm_stackmap_parse.h +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.h @@ -25,6 +25,7 @@ namespace kungfu { using OffsetType = int32_t; using DwarfRegType = uint16_t; using DwarfRegAndOffsetType = std::pair; +using DwarfRegAndOffsetTypeVector = std::vector; using Fun2InfoType = std::pair; struct Header { @@ -88,7 +89,7 @@ struct LocationTy { uint16_t Reserved_1; OffsetType OffsetOrSmallConstant; - std::string TypeToString(Kind location) const; + std::string TypeToString(Kind loc) const; void Print() const { @@ -132,7 +133,7 @@ struct StkMapRecordTy { class DataInfo { public: - explicit DataInfo(const uint8_t* data): data_(data), offset(0) {} + explicit DataInfo(const uint8_t *data): data_(data), offset(0) {} ~DataInfo() { data_ = nullptr; @@ -150,7 +151,7 @@ public: return offset; } private: - const uint8_t* data_; + const uint8_t *data_; unsigned int offset; }; @@ -177,11 +178,11 @@ struct LLVMStackMap { } }; -class LLVMStackMapParse { +class LLVMStackMapParser { public: - static LLVMStackMapParse& GetInstance() + static LLVMStackMapParser& GetInstance() { - static LLVMStackMapParse instance; + static LLVMStackMapParser instance; return instance; } bool CalculateStackMap(const uint8_t *stackMapAddr); @@ -189,15 +190,17 @@ public: { llvmStackMap_.Print(); } - bool StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetType &info); + bool StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetTypeVector &infos); + bool StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t frameFp, + std::vector &slotAddrs); private: - LLVMStackMapParse() + LLVMStackMapParser() { stackMapAddr_ = nullptr; callSiteInfos_.clear(); dataInfo_ = nullptr; } - ~LLVMStackMapParse() + ~LLVMStackMapParser() { stackMapAddr_ = nullptr; callSiteInfos_.clear(); diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 388aed1e90..36ea4d96f4 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -15,6 +15,7 @@ #include "ecmascript/compiler/llvm_ir_builder.h" +#include #include #include "ecmascript/compiler/circuit.h" @@ -80,6 +81,90 @@ int LLVMIRBuilder::FindBasicBlock(AddrShift gate) const return -1; } +void LLVMIRBuilder::AssignHandleMap() +{ + opCodeHandleMap_ = {{OpCode::STATE_ENTRY, &LLVMIRBuilder::HandleGoto}, + {OpCode::RETURN, &LLVMIRBuilder::HandleReturn}, + {OpCode::IF_BRANCH, &LLVMIRBuilder::HandleBranch}, {OpCode::SWITCH_BRANCH, &LLVMIRBuilder::HandleSwitch}, + {OpCode::ORDINARY_BLOCK, &LLVMIRBuilder::HandleGoto}, {OpCode::IF_TRUE, &LLVMIRBuilder::HandleGoto}, + {OpCode::IF_FALSE, &LLVMIRBuilder::HandleGoto}, {OpCode::SWITCH_CASE, &LLVMIRBuilder::HandleGoto}, + {OpCode::MERGE, &LLVMIRBuilder::HandleGoto}, {OpCode::DEFAULT_CASE, &LLVMIRBuilder::HandleGoto}, + {OpCode::LOOP_BEGIN, &LLVMIRBuilder::HandleGoto}, {OpCode::LOOP_BACK, &LLVMIRBuilder::HandleGoto}, + {OpCode::VALUE_SELECTOR_INT1, &LLVMIRBuilder::HandlePhi}, + {OpCode::VALUE_SELECTOR_INT32, &LLVMIRBuilder::HandlePhi}, + {OpCode::VALUE_SELECTOR_INT64, &LLVMIRBuilder::HandlePhi}, + {OpCode::VALUE_SELECTOR_FLOAT64, &LLVMIRBuilder::HandlePhi}, + {OpCode::CALL, &LLVMIRBuilder::HandleCall}, {OpCode::INT1_CALL, &LLVMIRBuilder::HandleCall}, + {OpCode::INT32_CALL, &LLVMIRBuilder::HandleCall}, {OpCode::FLOAT64_CALL, &LLVMIRBuilder::HandleCall}, + {OpCode::INT64_CALL, &LLVMIRBuilder::HandleCall}, {OpCode::ALLOCA, &LLVMIRBuilder::HandleAlloca}, + {OpCode::INT1_ARG, &LLVMIRBuilder::HandleParameter}, {OpCode::INT32_ARG, &LLVMIRBuilder::HandleParameter}, + {OpCode::INT64_ARG, &LLVMIRBuilder::HandleParameter}, + {OpCode::INT32_CONSTANT, &LLVMIRBuilder::HandleInt32Constant}, + {OpCode::JS_CONSTANT, &LLVMIRBuilder::HandleInt64Constant}, + {OpCode::INT64_CONSTANT, &LLVMIRBuilder::HandleInt64Constant}, + {OpCode::FLOAT64_CONSTANT, &LLVMIRBuilder::HandleFloat64Constant}, + {OpCode::ZEXT_INT1_TO_INT32, &LLVMIRBuilder::HandleZExtInt}, + {OpCode::ZEXT_INT32_TO_INT64, &LLVMIRBuilder::HandleZExtInt}, + {OpCode::ZEXT_INT1_TO_INT64, &LLVMIRBuilder::HandleZExtInt}, + {OpCode::SEXT_INT1_TO_INT32, &LLVMIRBuilder::HandleSExtInt}, + {OpCode::SEXT_INT1_TO_INT64, &LLVMIRBuilder::HandleSExtInt}, + {OpCode::SEXT_INT32_TO_INT64, &LLVMIRBuilder::HandleSExtInt}, + {OpCode::TRUNC_INT64_TO_INT1, &LLVMIRBuilder::HandleCastIntXToIntY}, + {OpCode::TRUNC_INT32_TO_INT1, &LLVMIRBuilder::HandleCastIntXToIntY}, + {OpCode::TRUNC_INT64_TO_INT32, &LLVMIRBuilder::HandleCastIntXToIntY}, + {OpCode::INT32_REV, &LLVMIRBuilder::HandleIntRev}, + {OpCode::INT64_REV, &LLVMIRBuilder::HandleIntRev}, + {OpCode::INT32_ADD, &LLVMIRBuilder::HandleIntAdd}, + {OpCode::INT64_ADD, &LLVMIRBuilder::HandleIntAdd}, + {OpCode::FLOAT64_ADD, &LLVMIRBuilder::HandleFloatAdd}, + {OpCode::FLOAT64_SUB, &LLVMIRBuilder::HandleFloatSub}, + {OpCode::FLOAT64_MUL, &LLVMIRBuilder::HandleFloatMul}, + {OpCode::FLOAT64_DIV, &LLVMIRBuilder::HandleFloatDiv}, + {OpCode::INT32_SUB, &LLVMIRBuilder::HandleIntSub}, + {OpCode::INT64_SUB, &LLVMIRBuilder::HandleIntSub}, + {OpCode::INT32_MUL, &LLVMIRBuilder::HandleIntMul}, + {OpCode::INT64_MUL, &LLVMIRBuilder::HandleIntMul}, + {OpCode::INT32_AND, &LLVMIRBuilder::HandleIntAnd}, + {OpCode::INT64_AND, &LLVMIRBuilder::HandleIntAnd}, + {OpCode::INT32_OR, &LLVMIRBuilder::HandleIntOr}, + {OpCode::INT64_OR, &LLVMIRBuilder::HandleIntOr}, + {OpCode::INT64_XOR, &LLVMIRBuilder::HandleIntXor}, + {OpCode::INT32_LSR, &LLVMIRBuilder::HandleIntLsr}, + {OpCode::INT64_LSR, &LLVMIRBuilder::HandleIntLsr}, + {OpCode::INT32_SLT, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT64_SLT, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT32_ULT, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT64_ULT, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT32_SLE, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT64_SLE, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT32_SGT, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT64_SGT, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT32_SGE, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT64_SGE, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT32_EQ, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT64_EQ, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::FLOAT64_EQ, &LLVMIRBuilder::HandleFloatOrDoubleCmp}, + {OpCode::INT32_NE, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT64_NE, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT32_LOAD, &LLVMIRBuilder::HandleLoad}, + {OpCode::INT64_LOAD, &LLVMIRBuilder::HandleLoad}, + {OpCode::INT32_STORE, &LLVMIRBuilder::HandleStore}, + {OpCode::INT64_STORE, &LLVMIRBuilder::HandleStore}, + {OpCode::INT32_TO_FLOAT64, &LLVMIRBuilder::HandleCastInt32ToDouble}, + {OpCode::INT64_TO_FLOAT64, &LLVMIRBuilder::HandleCastInt64ToDouble}, + {OpCode::FLOAT64_TO_INT64, &LLVMIRBuilder::HandleCastDoubleToInt}, + {OpCode::INT32_LSL, &LLVMIRBuilder::HandleIntLsl}, + {OpCode::INT64_LSL, &LLVMIRBuilder::HandleIntLsl}, + {OpCode::FLOAT64_SMOD, &LLVMIRBuilder::HandleFloatMod}, + {OpCode::INT32_SMOD, &LLVMIRBuilder::HandleIntMod}, + + }; + opCodeHandleIgnore= {OpCode::NOP, OpCode::CIRCUIT_ROOT, OpCode::DEPEND_ENTRY, + OpCode::FRAMESTATE_ENTRY, OpCode::RETURN_LIST, OpCode::THROW_LIST, + OpCode::CONSTANT_LIST, OpCode::ARG_LIST, OpCode::THROW, + OpCode::DEPEND_SELECTOR, OpCode::DEPEND_RELAY, OpCode::DEPEND_AND}; +} + void LLVMIRBuilder::Build() { LOG_ECMA(INFO) << "LLVM IR Builder Create Id Map of Blocks..."; @@ -89,8 +174,8 @@ void LLVMIRBuilder::Build() instIdMapBbId_[gateId] = bbIdx; } } - LOG_ECMA(INFO) << "LLVM IR Builder Visit Gate..."; + AssignHandleMap(); for (size_t bbIdx = 0; bbIdx < (*schedule_).size(); bbIdx++) { OperandsVector predecessors; for (auto in : circuit_->GetInVector((*schedule_)[bbIdx][0])) { @@ -105,310 +190,17 @@ void LLVMIRBuilder::Build() AddrShift gate = (*schedule_)[bbIdx][instIdx - 1]; std::vector ins = circuit_->GetInVector(gate); std::vector outs = circuit_->GetOutVector(gate); - switch (circuit_->GetOpCode(gate)) { - case OpCode::NOP: - break; - case OpCode::CIRCUIT_ROOT: - break; - case OpCode::STATE_ENTRY: { - int block = instIdMapBbId_[circuit_->GetId(gate)]; - int bbOut = instIdMapBbId_[circuit_->GetId(outs[0])]; - VisitGoto(block, bbOut); - break; - } - case OpCode::DEPEND_ENTRY: - break; - case OpCode::FRAMESTATE_ENTRY: - break; - case OpCode::RETURN_LIST: - break; - case OpCode::THROW_LIST: - break; - case OpCode::CONSTANT_LIST: - break; - case OpCode::ARG_LIST: - break; - case OpCode::RETURN: { - // [STATE] [DEPEND] [VALUE] [RETURN_LIST] - VisitReturn(gate, 1, ins); - break; - } - case OpCode::THROW: - break; - case OpCode::IF_BRANCH: { - AddrShift bTrue = (circuit_->GetOpCode(outs[0]) == OpCode::IF_TRUE) ? outs[0] : outs[1]; - AddrShift bFalse = (circuit_->GetOpCode(outs[0]) == OpCode::IF_FALSE) ? outs[0] : outs[1]; - int bbTrue = instIdMapBbId_[circuit_->GetId(bTrue)]; - int bbFalse = instIdMapBbId_[circuit_->GetId(bFalse)]; - VisitBranch(gate, ins[1], bbTrue, bbFalse); - break; - } - case OpCode::SWITCH_BRANCH: { - VisitSwitch(gate, ins[1], outs); - break; - } - case OpCode::ORDINARY_BLOCK: - case OpCode::IF_TRUE: - case OpCode::IF_FALSE: - case OpCode::SWITCH_CASE: - case OpCode::DEFAULT_CASE: { - int block = instIdMapBbId_[circuit_->GetId(gate)]; - int bbOut = instIdMapBbId_[circuit_->GetId(outs[0])]; - VisitGoto(block, bbOut); - break; - } - case OpCode::MERGE: { - int block = instIdMapBbId_[circuit_->GetId(gate)]; - int bbOut; - for (int i = 0; i < static_cast(outs.size()); i++) { - bbOut = instIdMapBbId_[circuit_->GetId(outs[i])]; - VisitGoto(block, bbOut); - } - break; - } - case OpCode::LOOP_BEGIN: { - int block = instIdMapBbId_[circuit_->GetId(gate)]; - int bbOut; - for (int i = 0; i < static_cast(outs.size()); i++) { - bbOut = instIdMapBbId_[circuit_->GetId(outs[i])]; - VisitGoto(block, bbOut); - } - break; - } - case OpCode::LOOP_BACK: { - int block = instIdMapBbId_[circuit_->GetId(gate)]; - int bbOut = instIdMapBbId_[circuit_->GetId(outs[0])]; - VisitGoto(block, bbOut); - break; - } - case OpCode::VALUE_SELECTOR_INT1: { - VisitPhi(gate, ins, MachineRep::K_BIT); - break; - } - case OpCode::VALUE_SELECTOR_INT32: { - VisitPhi(gate, ins, MachineRep::K_WORD32); - break; - } - case OpCode::VALUE_SELECTOR_INT64: { - VisitPhi(gate, ins, MachineRep::K_WORD64); - break; - } - case OpCode::VALUE_SELECTOR_FLOAT64: { - VisitPhi(gate, ins, MachineRep::K_FLOAT64); - break; - } - case OpCode::DEPEND_SELECTOR: - break; - case OpCode::DEPEND_RELAY: - break; - case OpCode::CALL: - case OpCode::INT1_CALL: - case OpCode::INT32_CALL: - case OpCode::INT64_CALL: { - VisitCall(gate, ins); - break; - } - case OpCode::ALLOCA: { - VisitAlloca(gate); - break; - } - case OpCode::INT1_ARG: // no break, fall through - case OpCode::INT32_ARG: // no break, fall through - case OpCode::INT64_ARG: { - VisitParameter(gate); - break; - } - case OpCode::INT32_CONSTANT: { - int32_t value = circuit_->GetBitField(gate); - VisitInt32Constant(gate, value); - break; - } - case OpCode::JS_CONSTANT: // no break, fall through - case OpCode::INT64_CONSTANT: { - int64_t value = circuit_->GetBitField(gate); - VisitInt64Constant(gate, value); - break; - } - case OpCode::FLOAT64_CONSTANT: { - int64_t value = circuit_->GetBitField(gate); - double doubleValue = bit_cast(value); // actual double value - VisitFloat64Constant(gate, doubleValue); - break; - } - case OpCode::ZEXT_INT1_TO_INT32: { - VisitZExtInt(gate, ins[0], MachineRep::K_WORD32); - break; - } - case OpCode::ZEXT_INT32_TO_INT64: // no break, fall through - case OpCode::ZEXT_INT1_TO_INT64: { - VisitZExtInt(gate, ins[0], MachineRep::K_WORD64); - break; - } - case OpCode::SEXT_INT1_TO_INT32: { - VisitSExtInt(gate, ins[0], MachineRep::K_WORD32); - break; - } - case OpCode::SEXT_INT1_TO_INT64: // no break, fall through - case OpCode::SEXT_INT32_TO_INT64: { - VisitSExtInt(gate, ins[0], MachineRep::K_WORD64); - break; - } - case OpCode::TRUNC_INT64_TO_INT1: - case OpCode::TRUNC_INT32_TO_INT1: { - VisitCastIntXToIntY(gate, ins[0], MachineRep::K_BIT); - break; - } - case OpCode::TRUNC_INT64_TO_INT32: { - VisitCastIntXToIntY(gate, ins[0], MachineRep::K_WORD32); - break; - } - case OpCode::INT32_REV: // no break, fall through - case OpCode::INT64_REV: { - VisitIntRev(gate, ins[0]); - break; - } - case OpCode::INT32_ADD: { - VisitIntAdd(gate, ins[0], ins[1], MachineRep::K_WORD32); - break; - } - case OpCode::INT64_ADD: { - VisitIntAdd(gate, ins[0], ins[1], MachineRep::K_WORD64); - break; - } - case OpCode::FLOAT64_ADD: { - VisitFloatAdd(gate, ins[0], ins[1]); - break; - } - case OpCode::FLOAT64_SUB: { - VisitFloatSub(gate, ins[0], ins[1]); - break; - } - case OpCode::FLOAT64_MUL: { - VisitFloatMul(gate, ins[0], ins[1]); - break; - } - case OpCode::FLOAT64_DIV: { - VisitFloatDiv(gate, ins[0], ins[1]); - break; - } - case OpCode::INT32_SUB: // no break, fall through - case OpCode::INT64_SUB: { - VisitIntSub(gate, ins[0], ins[1]); - break; - } - case OpCode::INT32_MUL: // no break, fall through - case OpCode::INT64_MUL: { - VisitIntMul(gate, ins[0], ins[1]); - break; - } - case OpCode::INT32_AND: // no break, fall through - case OpCode::INT64_AND: { - VisitIntAnd(gate, ins[0], ins[1]); - break; - } - case OpCode::INT32_OR: // no break, fall through - case OpCode::INT64_OR: { - VisitIntOr(gate, ins[0], ins[1]); - break; - } - case OpCode::INT64_XOR: { - VisitIntXor(gate, ins[0], ins[1]); - break; - } - case OpCode::INT32_LSR: // no break, fall through - case OpCode::INT64_LSR: { - VisitIntLsr(gate, ins[0], ins[1]); - break; - } - case OpCode::INT32_LSL: // no break, fall through - case OpCode::INT64_LSL: { - VisitIntLsl(gate, ins[0], ins[1]); - break; - } - case OpCode::INT32_SLT: // no break, fall through - case OpCode::INT64_SLT: { - VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntSLT); - break; - } - case OpCode::INT32_ULT: // no break, fall through - case OpCode::INT64_ULT: { - VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntULT); - break; - } - case OpCode::INT32_SLE: // no break, fall through - case OpCode::INT64_SLE: { - VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntSLE); - break; - } - case OpCode::INT32_SGT: // no break, fall through - case OpCode::INT64_SGT: { - VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntSGT); - break; - } - case OpCode::INT32_SGE: // no break, fall through - case OpCode::INT64_SGE: { - VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntSGE); - break; - } - case OpCode::INT32_EQ: // no break, fall through - case OpCode::INT64_EQ: { - VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntEQ); - break; - } - case OpCode::FLOAT64_EQ: { - VisitFloatOrDoubleCmp(gate, ins[0], ins[1], LLVMRealOEQ); - break; - } - case OpCode::INT32_NE: // no break, fall through - case OpCode::INT64_NE: { - VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntNE); - break; - } - case OpCode::INT32_LOAD: { - AddrShift base = ins[1]; - VisitLoad(gate, MachineRep::K_WORD32, base); - break; - } - case OpCode::INT64_LOAD: { - AddrShift base = ins[1]; - VisitLoad(gate, MachineRep::K_WORD64, base); - break; - } - case OpCode::INT32_STORE: { - VisitStore(gate, MachineRep::K_WORD32, ins[2], ins[1]); // 2:baseAddr gate, 1:data gate - break; - } - case OpCode::INT64_STORE: { - VisitStore(gate, MachineRep::K_WORD64, ins[2], ins[1]); // 2:baseAddr gate, 1:data gate - break; - } - case OpCode::INT32_TO_FLOAT64: { - VisitCastInt32ToDouble(gate, ins[0]); - break; - } - case OpCode::INT64_TO_FLOAT64: { - VisitCastInt64ToDouble(gate, ins[0]); - break; - } - case OpCode::FLOAT64_TO_INT64: { - VisitCastDoubleToInt(gate, ins[0]); - break; - } - case OpCode::DEPEND_AND: - break; - case OpCode::INT32_SMOD: { - VisitIntMod(gate, ins[0], ins[1]); - break; - } - case OpCode::FLOAT64_SMOD: { - VisitFloatMod(gate, ins[0], ins[1]); - break; - } - default: { - LOG_ECMA(ERROR) << "The gate below need to be translated "; - circuit_->Print(gate); - UNREACHABLE(); - } + std::cout << "instIdx :" << instIdx << std::endl; + circuit_->Print(gate); + auto found = opCodeHandleMap_.find(circuit_->GetOpCode(gate)); + if (found != opCodeHandleMap_.end()) { + (this->*(found->second))(gate); + continue; + } + if (opCodeHandleIgnore.find(circuit_->GetOpCode(gate)) == opCodeHandleIgnore.end()) { + LOG_ECMA(ERROR) << "The gate below need to be translated "; + circuit_->Print(gate); + UNREACHABLE(); } } } @@ -507,7 +299,7 @@ void LLVMIRBuilder::PrologueHandle(LLVMModuleRef &module, LLVMBuilderRef &builde return; } - LLVMValueRef baseAddr = LLVMCallingFp(module_, builder_); + LLVMValueRef llvmFpAddr = LLVMCallingFp(module_, builder_); /* current frame 0 pre rbp <-- rbp -8 type @@ -521,7 +313,8 @@ void LLVMIRBuilder::PrologueHandle(LLVMModuleRef &module, LLVMBuilderRef &builde LLVMValueRef rtbaseAddr = LLVMBuildIntToPtr(builder_, rtbaseoffset, LLVMPointerType(LLVMInt64Type(), 0), ""); LLVMValueRef threadFpValue = LLVMBuildLoad(builder_, rtbaseAddr, ""); - LLVMValueRef value = LLVMBuildStore(builder_, threadFpValue, baseAddr); + LLVMValueRef value = LLVMBuildStore(builder_, threadFpValue, + LLVMBuildIntToPtr(builder_, llvmFpAddr, LLVMPointerType(LLVMInt64Type(), 0), "cast")); LOG_ECMA(INFO) << "store value:" << value << " " << "value type" << LLVMTypeOf(value); } @@ -585,6 +378,24 @@ LLVMTypeRef LLVMIRBuilder::GetMachineRepType(MachineRep rep) const return dstType; } +void LLVMIRBuilder::HandleCall(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::CALL: + case OpCode::INT1_CALL: + case OpCode::INT32_CALL: + case OpCode::FLOAT64_CALL: + case OpCode::INT64_CALL: { + VisitCall(gate, ins); + break; + } + default: { + break; + } + } +} + void LLVMIRBuilder::VisitCall(AddrShift gate, const std::vector &inList) { int paraStartIndex = 2; @@ -626,6 +437,11 @@ void LLVMIRBuilder::VisitCall(AddrShift gate, const std::vector &inLi return; } +void LLVMIRBuilder::HandleAlloca(AddrShift gate) +{ + return VisitAlloca(gate); +} + void LLVMIRBuilder::VisitAlloca(AddrShift gate) { uint64_t sizeEnum = circuit_->GetBitField(gate); @@ -636,6 +452,32 @@ void LLVMIRBuilder::VisitAlloca(AddrShift gate) return; } +void LLVMIRBuilder::HandlePhi(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::VALUE_SELECTOR_INT1: { + VisitPhi(gate, ins, MachineRep::K_BIT); + break; + } + case OpCode::VALUE_SELECTOR_INT32: { + VisitPhi(gate, ins, MachineRep::K_WORD32); + break; + } + case OpCode::VALUE_SELECTOR_INT64: { + VisitPhi(gate, ins, MachineRep::K_WORD64); + break; + } + case OpCode::VALUE_SELECTOR_FLOAT64: { + VisitPhi(gate, ins, MachineRep::K_FLOAT64); + break; + } + default: { + break; + } + } +} + void LLVMIRBuilder::VisitPhi(AddrShift gate, const std::vector &srcGates, MachineRep rep) { LLVMTypeRef type = GetMachineRepType(rep); @@ -694,6 +536,12 @@ void LLVMIRBuilder::VisitReturn(AddrShift gate, AddrShift popCount, const std::v LLVMBuildRet(builder_, returnValue); } +void LLVMIRBuilder::HandleReturn(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitReturn(gate, 1, ins); +} + void LLVMIRBuilder::VisitBlock(int gate, const OperandsVector &predecessors) // NOLINTNEXTLINE(misc-unused-parameters) { LOG_ECMA(INFO) << " BBIdx:" << gate; @@ -721,6 +569,27 @@ void LLVMIRBuilder::VisitBlock(int gate, const OperandsVector &predecessors) // } } +void LLVMIRBuilder::HandleGoto(AddrShift gate) +{ + std::vector outs = circuit_->GetOutVector(gate); + int block = instIdMapBbId_[circuit_->GetId(gate)]; + int bbOut = instIdMapBbId_[circuit_->GetId(outs[0])]; + switch (circuit_->GetOpCode(gate)) { + case OpCode::MERGE: + case OpCode::LOOP_BEGIN: { + for (int i = 0; i < static_cast(outs.size()); i++) { + bbOut = instIdMapBbId_[circuit_->GetId(outs[i])]; + VisitGoto(block, bbOut); + } + break; + } + default: { + VisitGoto(block, bbOut); + break; + } + } +} + void LLVMIRBuilder::VisitGoto(int block, int bbOut) { if (block == bbOut) { @@ -737,6 +606,63 @@ void LLVMIRBuilder::VisitGoto(int block, int bbOut) EndCurrentBlock(); } +void LLVMIRBuilder::HandleInt32Constant(AddrShift gate) +{ + int32_t value = circuit_->GetBitField(gate); + VisitInt32Constant(gate, value); +} + +void LLVMIRBuilder::HandleInt64Constant(AddrShift gate) +{ + int64_t value = circuit_->GetBitField(gate); + VisitInt64Constant(gate, value); +} + +void LLVMIRBuilder::HandleFloat64Constant(AddrShift gate) +{ + int64_t value = circuit_->GetBitField(gate); + double doubleValue = bit_cast(value); // actual double value + VisitFloat64Constant(gate, doubleValue); +} + +void LLVMIRBuilder::HandleZExtInt(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::ZEXT_INT1_TO_INT32: { + VisitZExtInt(gate, ins[0], MachineRep::K_WORD32); + break; + } + case OpCode::ZEXT_INT32_TO_INT64: // no break, fall through + case OpCode::ZEXT_INT1_TO_INT64: { + VisitZExtInt(gate, ins[0], MachineRep::K_WORD64); + break; + } + default: { + break; + } + } +} + +void LLVMIRBuilder::HandleSExtInt(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::SEXT_INT1_TO_INT32: { + VisitSExtInt(gate, ins[0], MachineRep::K_WORD32); + break; + } + case OpCode::SEXT_INT1_TO_INT64: // no break, fall through + case OpCode::SEXT_INT32_TO_INT64: { + VisitSExtInt(gate, ins[0], MachineRep::K_WORD64); + break; + } + default: { + break; + } + } +} + void LLVMIRBuilder::VisitInt32Constant(AddrShift gate, int32_t value) const { LLVMValueRef llvmValue = LLVMConstInt(LLVMInt32Type(), value, 0); @@ -770,6 +696,11 @@ void LLVMIRBuilder::VisitFloat64Constant(AddrShift gate, double value) const LOG_ECMA(INFO) << "VisitFloat64Constant " << str; } +void LLVMIRBuilder::HandleParameter(AddrShift gate) +{ + return VisitParameter(gate); +} + void LLVMIRBuilder::VisitParameter(AddrShift gate) const { int argth = circuit_->LoadGatePtrConst(gate)->GetBitField(); @@ -788,6 +719,53 @@ void LLVMIRBuilder::VisitParameter(AddrShift gate) const LOG_ECMA(INFO) << "para arg:" << argth << "value IR:" << str; } +void LLVMIRBuilder::HandleBranch(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + AddrShift bTrue = (circuit_->GetOpCode(outs[0]) == OpCode::IF_TRUE) ? outs[0] : outs[1]; + AddrShift bFalse = (circuit_->GetOpCode(outs[0]) == OpCode::IF_FALSE) ? outs[0] : outs[1]; + int bbTrue = instIdMapBbId_[circuit_->GetId(bTrue)]; + int bbFalse = instIdMapBbId_[circuit_->GetId(bFalse)]; + VisitBranch(gate, ins[1], bbTrue, bbFalse); +} + +void LLVMIRBuilder::HandleIntMod(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitIntMod(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::VisitIntMod(AddrShift gate, AddrShift e1, AddrShift e2) const +{ + LOG_ECMA(INFO) << "int mod gate:" << gate; + LLVMValueRef e1Value = g_values[e1]; + LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LLVMValueRef e2Value = g_values[e2]; + LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LLVMValueRef result = LLVMBuildSRem(builder_, e1Value, e2Value, ""); + g_values[gate] = result; + LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); +} + +void LLVMIRBuilder::HandleFloatMod(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitFloatMod(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::VisitFloatMod(AddrShift gate, AddrShift e1, AddrShift e2) const +{ + LOG_ECMA(INFO) << "float mod gate:" << gate; + LLVMValueRef e1Value = g_values[e1]; + LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LLVMValueRef e2Value = g_values[e2]; + LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LLVMValueRef result = LLVMBuildFRem(builder_, e1Value, e2Value, ""); + g_values[gate] = result; + LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); +} + void LLVMIRBuilder::VisitBranch(AddrShift gate, AddrShift cmp, int btrue, int bfalse) { LOG_ECMA(INFO) << "cmp gate:" << cmp; @@ -810,6 +788,13 @@ void LLVMIRBuilder::VisitBranch(AddrShift gate, AddrShift cmp, int btrue, int bf g_values[gate] = result; } +void LLVMIRBuilder::HandleSwitch(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitSwitch(gate, ins[1], outs); +} + void LLVMIRBuilder::VisitSwitch(AddrShift gate, AddrShift input, const std::vector &outList) { LLVMValueRef cond = g_values[input]; @@ -889,6 +874,12 @@ void LLVMIRBuilder::VisitFloatOrDoubleCmp(AddrShift gate, AddrShift e1, AddrShif LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleIntRev(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitIntRev(gate, ins[0]); +} + void LLVMIRBuilder::VisitIntRev(AddrShift gate, AddrShift e1) const { LOG_ECMA(INFO) << "int sign invert gate:" << gate; @@ -899,6 +890,25 @@ void LLVMIRBuilder::VisitIntRev(AddrShift gate, AddrShift e1) const LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleIntAdd(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::INT32_ADD: { + VisitIntAdd(gate, ins[0], ins[1], MachineRep::K_WORD32); + break; + } + case OpCode::INT64_ADD: { + VisitIntAdd(gate, ins[0], ins[1], MachineRep::K_WORD64); + break; + } + default: { + break; + } + } +} + void LLVMIRBuilder::VisitIntAdd(AddrShift gate, AddrShift e1, AddrShift e2, MachineRep rep) const { LOG_ECMA(INFO) << "int add gate:" << gate; @@ -914,6 +924,13 @@ void LLVMIRBuilder::VisitIntAdd(AddrShift gate, AddrShift e1, AddrShift e2, Mach LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleFloatAdd(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitFloatAdd(gate, ins[0], ins[1]); +} + void LLVMIRBuilder::VisitFloatAdd(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "float add gate:" << gate; @@ -926,6 +943,161 @@ void LLVMIRBuilder::VisitFloatAdd(AddrShift gate, AddrShift e1, AddrShift e2) co LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleFloatSub(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitFloatSub(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::HandleFloatMul(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitFloatMul(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::HandleFloatDiv(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitFloatDiv(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::HandleIntSub(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitIntSub(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::HandleIntMul(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitIntMul(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::HandleIntOr(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitIntOr(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::HandleIntXor(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitIntXor(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::HandleIntLsr(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitIntLsr(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::HandleIntOrUintCmp(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::INT32_SLT: // no break, fall through + case OpCode::INT64_SLT: { + VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntSLT); + break; + } + case OpCode::INT32_ULT: // no break, fall through + case OpCode::INT64_ULT: { + VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntULT); + break; + } + case OpCode::INT32_SLE: // no break, fall through + case OpCode::INT64_SLE: { + VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntSLE); + break; + } + case OpCode::INT32_SGT: // no break, fall through + case OpCode::INT64_SGT: { + VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntSGT); + break; + } + case OpCode::INT32_SGE: // no break, fall through + case OpCode::INT64_SGE: { + VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntSGE); + break; + } + case OpCode::INT32_EQ: // no break, fall through + case OpCode::INT64_EQ: { + VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntEQ); + break; + } + case OpCode::INT32_NE: // no break, fall through + case OpCode::INT64_NE: { + VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntNE); + break; + } + default: { + break; + } + } +} + +void LLVMIRBuilder::HandleFloatOrDoubleCmp(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitFloatOrDoubleCmp(gate, ins[0], ins[1], LLVMRealOEQ); +} + +void LLVMIRBuilder::HandleLoad(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::INT32_LOAD: { + AddrShift base = ins[1]; + VisitLoad(gate, MachineRep::K_WORD32, base); + break; + } + case OpCode::INT64_LOAD: { + AddrShift base = ins[1]; + VisitLoad(gate, MachineRep::K_WORD64, base); + break; + } + default: { + break; + } + } +} + +void LLVMIRBuilder::HandleStore(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::INT32_STORE: { + VisitStore(gate, MachineRep::K_WORD32, ins[2], ins[1]); // 2:baseAddr gate, 1:data gate + break; + } + case OpCode::INT64_STORE: { + VisitStore(gate, MachineRep::K_WORD64, ins[2], ins[1]); // 2:baseAddr gate, 1:data gate + break; + } + default: { + break; + } + } +} + +void LLVMIRBuilder::HandleCastInt32ToDouble(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitCastInt32ToDouble(gate, ins[0]); +} + void LLVMIRBuilder::VisitFloatSub(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "float sub gate:" << gate; @@ -986,30 +1158,6 @@ void LLVMIRBuilder::VisitIntMul(AddrShift gate, AddrShift e1, AddrShift e2) cons LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } -void LLVMIRBuilder::VisitIntMod(AddrShift gate, AddrShift e1, AddrShift e2) const -{ - LOG_ECMA(INFO) << "int mod gate:" << gate; - LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); - LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); - LLVMValueRef result = LLVMBuildSRem(builder_, e1Value, e2Value, ""); - g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); -} - -void LLVMIRBuilder::VisitFloatMod(AddrShift gate, AddrShift e1, AddrShift e2) const -{ - LOG_ECMA(INFO) << "float mod gate:" << gate; - LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); - LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); - LLVMValueRef result = LLVMBuildFRem(builder_, e1Value, e2Value, ""); - g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); -} - void LLVMIRBuilder::VisitIntOr(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "int or gate:" << gate; @@ -1022,6 +1170,12 @@ void LLVMIRBuilder::VisitIntOr(AddrShift gate, AddrShift e1, AddrShift e2) const LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleIntAnd(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitIntAnd(gate, ins[0], ins[1]); +} + void LLVMIRBuilder::VisitIntAnd(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "int and gate:" << gate; @@ -1058,6 +1212,12 @@ void LLVMIRBuilder::VisitIntLsr(AddrShift gate, AddrShift e1, AddrShift e2) cons LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleIntLsl(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitIntLsl(gate, ins[0], ins[1]); +} + void LLVMIRBuilder::VisitIntLsl(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "int lsl gate:" << gate; @@ -1090,6 +1250,25 @@ void LLVMIRBuilder::VisitSExtInt(AddrShift gate, AddrShift e1, MachineRep rep) c LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleCastIntXToIntY(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::TRUNC_INT64_TO_INT1: + case OpCode::TRUNC_INT32_TO_INT1: { + VisitCastIntXToIntY(gate, ins[0], MachineRep::K_BIT); + break; + } + case OpCode::TRUNC_INT64_TO_INT32: { + VisitCastIntXToIntY(gate, ins[0], MachineRep::K_WORD32); + break; + } + default: { + break; + } + } +} + void LLVMIRBuilder::VisitCastIntXToIntY(AddrShift gate, AddrShift e1, MachineRep rep) const { LOG_ECMA(INFO) << "int cast2 int gate:" << gate; @@ -1110,6 +1289,12 @@ void LLVMIRBuilder::VisitCastInt32ToDouble(AddrShift gate, AddrShift e1) const LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleCastInt64ToDouble(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitCastInt64ToDouble(gate, ins[0]); +} + void LLVMIRBuilder::VisitCastInt64ToDouble(AddrShift gate, AddrShift e1) const { LOG_ECMA(INFO) << "int cast2 double gate:" << gate; @@ -1120,6 +1305,12 @@ void LLVMIRBuilder::VisitCastInt64ToDouble(AddrShift gate, AddrShift e1) const LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleCastDoubleToInt(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitCastDoubleToInt(gate, ins[0]); +} + void LLVMIRBuilder::VisitCastDoubleToInt(AddrShift gate, AddrShift e1) const { LOG_ECMA(INFO) << "double cast2 int gate:" << gate; diff --git a/ecmascript/compiler/llvm_ir_builder.h b/ecmascript/compiler/llvm_ir_builder.h index cd703fd7e3..43f43ef84c 100644 --- a/ecmascript/compiler/llvm_ir_builder.h +++ b/ecmascript/compiler/llvm_ir_builder.h @@ -31,6 +31,8 @@ namespace kungfu { using OperandsVector = std::set; class BasicBlock; using BasicBlockMap = std::map>; +class LLVMIRBuilder; +typedef void (LLVMIRBuilder::*HandleType)(AddrShift gate); enum class MachineRep { K_NONE, @@ -138,6 +140,49 @@ private: LLVMModuleRef module_; }; +#define OPCODES(V) \ + V(Call, (AddrShift gate, const std::vector &inList)) \ + V(Alloca, (AddrShift gate)) \ + V(Block, (int id, const OperandsVector &predecessors)) \ + V(Goto, (int block, int bbout)) \ + V(Parameter, (AddrShift gate) const ) \ + V(Int32Constant, (AddrShift gate, int32_t value) const ) \ + V(Int64Constant, (AddrShift gate, int64_t value) const ) \ + V(Float64Constant, (AddrShift gate, double value) const ) \ + V(ZExtInt, (AddrShift gate, AddrShift e1, MachineRep rep) const ) \ + V(SExtInt, (AddrShift gate, AddrShift e1, MachineRep rep) const ) \ + V(Load, (AddrShift gate, MachineRep rep, AddrShift base) const ) \ + V(Store, (AddrShift gate, MachineRep rep, AddrShift base, AddrShift value) const ) \ + V(IntRev, (AddrShift gate, AddrShift e1) const ) \ + V(IntAdd, (AddrShift gate, AddrShift e1, AddrShift e2, MachineRep rep) const ) \ + V(FloatAdd, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(FloatSub, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(FloatMul, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(FloatDiv, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(IntSub, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(IntMul, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(IntOr, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(IntAnd, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(IntXor, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(IntLsr, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(Int32LessThanOrEqual, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(IntOrUintCmp, (AddrShift gate, AddrShift e1, AddrShift e2, LLVMIntPredicate opcode) const ) \ + V(FloatOrDoubleCmp, (AddrShift gate, AddrShift e1, AddrShift e2, LLVMRealPredicate opcode) const ) \ + V(Branch, (AddrShift gate, AddrShift cmp, AddrShift btrue, AddrShift bfalse)) \ + V(Switch, (AddrShift gate, AddrShift input, const std::vector &outList)) \ + V(SwitchCase, (AddrShift gate, AddrShift switchBranch, AddrShift out)) \ + V(Phi, (AddrShift gate, const std::vector &srcGates, MachineRep rep)) \ + V(Return, (AddrShift gate, AddrShift popCount, const std::vector &operands) const ) \ + V(CastIntXToIntY, (AddrShift gate, AddrShift e1, MachineRep rep) const ) \ + V(CastInt32ToDouble, (AddrShift gate, AddrShift e1) const ) \ + V(CastInt64ToDouble, (AddrShift gate, AddrShift e1) const ) \ + V(CastDoubleToInt, (AddrShift gate, AddrShift e1) const ) \ + V(CastInt64ToPointer, (AddrShift gate, AddrShift e1) const ) \ + V(IntLsl, (AddrShift gate, AddrShift e1, AddrShift e2) const) \ + V(IntMod, (AddrShift gate, AddrShift e1, AddrShift e2) const) \ + V(FloatMod, (AddrShift gate, AddrShift e1, AddrShift e2) const) \ + + class LLVMIRBuilder { public: explicit LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit); @@ -149,46 +194,12 @@ public: ~LLVMIRBuilder() = default; private: - void VisitCall(AddrShift gate, const std::vector &inList); - void VisitAlloca(AddrShift gate); - void VisitBlock(int id, const OperandsVector &predecessors); - void VisitGoto(int block, int bbout); - void VisitParameter(AddrShift gate) const; - void VisitInt32Constant(AddrShift gate, int32_t value) const; - void VisitInt64Constant(AddrShift gate, int64_t value) const; - void VisitFloat64Constant(AddrShift gate, double value) const; - void VisitZExtInt(AddrShift gate, AddrShift e1, MachineRep rep) const; - void VisitSExtInt(AddrShift gate, AddrShift e1, MachineRep rep) const; - void VisitLoad(AddrShift gate, MachineRep rep, AddrShift base) const; - void VisitStore(AddrShift gate, MachineRep rep, AddrShift base, AddrShift value) const; - void VisitIntRev(AddrShift gate, AddrShift e1) const; - void VisitIntAdd(AddrShift gate, AddrShift e1, AddrShift e2, MachineRep rep) const; - void VisitFloatAdd(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitFloatSub(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitFloatMul(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitFloatDiv(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitIntSub(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitIntMul(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitIntOr(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitIntAnd(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitIntXor(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitIntLsr(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitIntLsl(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitInt32LessThanOrEqual(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitIntOrUintCmp(AddrShift gate, AddrShift e1, AddrShift e2, LLVMIntPredicate opcode) const; - void VisitFloatOrDoubleCmp(AddrShift gate, AddrShift e1, AddrShift e2, LLVMRealPredicate opcode) const; - void VisitBranch(AddrShift gate, AddrShift cmp, AddrShift btrue, AddrShift bfalse); - void VisitSwitch(AddrShift gate, AddrShift input, const std::vector &outList); - void VisitSwitchCase(AddrShift gate, AddrShift switchBranch, AddrShift out); - void VisitPhi(AddrShift gate, const std::vector &srcGates, MachineRep rep); - void VisitReturn(AddrShift gate, AddrShift popCount, const std::vector &operands) const; - void VisitCastIntXToIntY(AddrShift gate, AddrShift e1, MachineRep rep) const; - void VisitCastInt32ToDouble(AddrShift gate, AddrShift e1) const; - void VisitCastInt64ToDouble(AddrShift gate, AddrShift e1) const; - void VisitCastDoubleToInt(AddrShift gate, AddrShift e1) const; - void VisitCastInt64ToPointer(AddrShift gate, AddrShift e1) const; - void VisitIntMod(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitFloatMod(AddrShift gate, AddrShift e1, AddrShift e2) const; + #define DECLAREVISITOPCODE(name, signature) void Visit##name signature; + OPCODES(DECLAREVISITOPCODE) + #undef DECLAREVISITOPCODE + #define DECLAREHANDLEOPCODE(name, ignore) void Handle##name(AddrShift gate); + OPCODES(DECLAREHANDLEOPCODE) + #undef DECLAREHANDLEOPCODE BasicBlock *EnsurBasicBlock(int id); LLVMValueRef LLVMCallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder); @@ -203,6 +214,7 @@ private: void End(); void ProcessPhiWorkList(); + void AssignHandleMap(); private: const std::vector> *schedule_ {nullptr}; @@ -219,6 +231,8 @@ private: std::vector phiRebuildWorklist_; LLVMStubModule *stubModule_ {nullptr}; + std::unordered_map opCodeHandleMap_; + std::set opCodeHandleIgnore; }; } // namespace kungfu #endif // PANDA_RUNTIME_ECMASCRIPT_COMPILER_LLVM_IR_BUILDER_H \ No newline at end of file diff --git a/ecmascript/compiler/tests/BUILD.gn b/ecmascript/compiler/tests/BUILD.gn index 5268dae914..7adb64d514 100644 --- a/ecmascript/compiler/tests/BUILD.gn +++ b/ecmascript/compiler/tests/BUILD.gn @@ -113,7 +113,8 @@ host_unittest_action("StubTest") { deps = [ "$ark_root/libpandabase:libarkbase", - "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer_test", + "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer_test(${host_toolchain})", + "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser", sdk_libc_secshared_dep, ] } diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index c684a94da8..6a2f63c03e 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -20,7 +20,7 @@ #include "ecmascript/compiler/fast_stub.h" #include "ecmascript/compiler/llvm_ir_builder.h" #include "ecmascript/compiler/llvm_mcjit_engine.h" -#include "ecmascript/compiler/llvm_stackmap_parse.h" +#include "ecmascript/compiler/llvm/llvm_stackmap_parser.h" #include "ecmascript/compiler/scheduler.h" #include "ecmascript/compiler/stub_descriptor.h" #include "ecmascript/compiler/verifier.h" @@ -720,6 +720,27 @@ int RuntimeFunc2(struct ThreadTy *fpInfo) for (int i = 0; i < 40; i++) { // print 40 ptr value for debug std::cout << std::hex << &(rbp[i]) << " :" << rbp[i] << std::endl; } + /* walk back + stack frame: 0 pre rbp <-- rbp + -8 type + -16 pre frame thread fp + */ + int64_t *frameType = nullptr; + int64_t *gcFp = nullptr; + std::cout << "-----------------walkback----------------" << std::endl; + do { + frameType = rbp - 1; + if (*frameType == 1) { + gcFp = rbp - 2; // 2: 2 stack slot + } else { + gcFp = rbp; + } + rbp = reinterpret_cast(*gcFp); + std::cout << std::hex << "frameType :" << *frameType << " gcFp:" << *gcFp << std::endl; + } while (*gcFp != 0); + std::cout << "+++++++++++++++++walkback++++++++++++++++" << std::endl; + std::cout << "call RuntimeFunc2 func ThreadTy fp: " << fpInfo->fp << " magic:" << fpInfo->magic << std::endl; + std::cout << "RuntimeFunc2 +" << std::endl; return 0; } } @@ -770,7 +791,7 @@ LLVMValueRef LLVMCallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder) return frameAddr; } -#ifdef LLVM_SUPPORT_GC +#ifdef ARK_GC_SUPPORT HWTEST_F_L0(StubTest, JSEntryTest) { std::cout << " ---------- JSEntryTest ------------- " << std::endl; @@ -1062,7 +1083,7 @@ HWTEST_F_L0(StubTest, LoadGCIRTest) { std::cout << "--------------LoadGCIRTest--------------------" << std::endl; char *path = get_current_dir_name(); - std::string filePath = std::string(path) + "/../../ark/js_runtime/ecmascript/compiler/tests/satepoint_GC_0.ll"; + std::string filePath = std::string(path) + "/ark/js_runtime/ecmascript/compiler/tests/satepoint_GC_0.ll"; char resolvedPath[PATH_MAX]; char *res = realpath(filePath.c_str(), resolvedPath); @@ -1089,8 +1110,8 @@ HWTEST_F_L0(StubTest, LoadGCIRTest) auto *mainPtr = reinterpret_cast(LLVMGetPointerToGlobal(engine, function)); uint8_t *ptr = assembler.GetStackMapsSection(); - LLVMStackMapParse::GetInstance().CalculateStackMap(ptr); - LLVMStackMapParse::GetInstance().Print(); + LLVMStackMapParser::GetInstance().CalculateStackMap(ptr); + LLVMStackMapParser::GetInstance().Print(); assembler.Disassemble(); LLVMDumpModule(module); @@ -1108,19 +1129,21 @@ void DoSafepoint() uintptr_t returnAddr = *(rbp + 1); uintptr_t *rsp = rbp + 2; // move 2 steps from rbp to get rsp rbp = reinterpret_cast(*rbp); - DwarfRegAndOffsetType info; - bool found = LLVMStackMapParse::GetInstance().StackMapByAddr(returnAddr, info); + DwarfRegAndOffsetTypeVector infos; + bool found = LLVMStackMapParser::GetInstance().StackMapByAddr(returnAddr, infos); if (found) { - uintptr_t **address = nullptr; - if (info.first == 7) { // 7: x86_64 dwarf register num, representing rsp - address = reinterpret_cast(reinterpret_cast(rsp) + info.second); - // rbp - } else if (info.first == 6) { // 6: x86_64 dwarf register num, representing rbp - address = reinterpret_cast(reinterpret_cast(rbp) + info.second); + for (auto &info : infos) { + uintptr_t **address = nullptr; + if (info.first == 7) { // 7: x86_64 dwarf register num, representing rsp + address = reinterpret_cast(reinterpret_cast(rsp) + info.second); + // rbp + } else if (info.first == 6) { // 6: x86_64 dwarf register num, representing rbp + address = reinterpret_cast(reinterpret_cast(rbp) + info.second); + } + std::cout << std::hex << "ref addr:" << address; + std::cout << " value:" << *address; + std::cout << " *value :" << **address << std::endl; } - std::cout << std::hex << "ref addr:" << address; - std::cout << " value:" << *address; - std::cout << " *value :" << **address << std::endl; } std::cout << std::endl << std::endl; std::cout << std::hex << "+++++++++++++++++++ returnAddr : 0x" << returnAddr << " rbp:" << rbp diff --git a/ecmascript/frames.h b/ecmascript/frames.h index dc5c002286..0012242179 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -13,11 +13,206 @@ * limitations under the License. */ +// in aot project, three Frame: Interpreter Frame、Runtime Frame、Optimized Frame. Optimized Frame split +// Optimized Entry Frame(interpreter call stub) and Optimized Frame(stub call stub) by call scenario. +// ​we gc trigger, we skip Runtime Frame, thus define OPTIMIZED_FRAME、OPTIMIZED_ENTRY_FRAME、 +// INTERPRETER_FRAME respectively +// represent optimized frame、optimized entry frame、interpreter frame. + +// Frame Layout +// Interpreter Frame(alias **iframe** ) Layout as follow: +// ``` +// +---------------------------------+--------------------+ +// | argv[n-1] | ^ +// |----------------------------------| | +// | ........ | | +// | argv[0] | | +// |----------------------------------| | +// | thisArg | | +// |----------------------------------| | +// | newTarget | | +// |----------------------------------| | +// | callTarget | | +// +----------------------------------+--------+ | +// | FrameType | ^ interpreter frame +// |----------------------------------| | | +// | pre(pre stack pointer) | | | +// |----------------------------------| | | +// | numActualArgs | | | +// |----------------------------------| | | +// | env | | | +// |----------------------------------| | | +// | acc | FrameState | +// |----------------------------------| | | +// | constantpool | | | +// |----------------------------------| | | +// | method | | | +// |----------------------------------| | | +// | sp(current stack point) | | | +// |----------------------------------| | | +// | pc(bytecode addr) | v v +// +----------------------------------+--------+----------+ +// ``` +// address space grow from high address to low address.we add new field **FrameType** , +// the field's value is INTERPRETER_FRAME(represent interpreter frame). +// **currentsp** is pointer to callTarget field address, sp field 's value is **currentsp** , +// pre field pointer pre stack frame point. fill JSthread's sp field with iframe sp field +// by calling JSThread->SetCurrentSPFrame and save pre Frame address to iframe pre field. + +// Runtime Frame: comply with C-ABI without custom modify, function generat frame. +// ​ +// Optimized Frame and Optimized Entry Frame, we also comply with C-ABI, +// the difference from Runtime Frame is that prologue and epilogue is customed. + +// Optimized Entry Frame layout as follow, we reserve two stack slot for saving eparately new field **FrameType** +// which's value is OPTIMIZED_ENTRY_FRAME and +// new field pre that's value is iframe.sp by calling JSThread->GetCurrentSPFrame. +// fp field point to pre frame, **currentfp** is pointer to fp field address. +// save JSthread's sp to pre field and fill JSthread's sp field with **currentfp** . + + +// ``` +// +---------------------------------------------------+ +// | parameter i | ^ +// |- - - - - - - - - -- | | +// | parameter n-2 | Caller frame +// | ... | comply c-abi +// | parameter n-1 | paramters push to stack from left to right +// |- - - - - - - - - | i-n th prameter spill to slot +// | parameter n | v +// +--------------------------+------------------------+ +// | return addr | ^ ^ +// |- - - - - - - - - | | | +// | fp | Fixed | +// |- - - - - - - - - | Header <-- frame ptr | +// | FrameType | | callee frame Header +// |- - - - - - - - - | | | +// | pre | v | +// +--------------------------+------------------------+ +// ``` + +// ​ Optimized Frame layout as follow, we reserve one stack slot for saving FrameType field, +// which's value is OPTIMIZED_FRAME. + +// ``` +// +---------------------------------------------------+ +// | parameter n | ^ +// |- - - - - - - - - -- | | +// | parameter n-1 | Caller frame +// | ... | comply c-abi +// | parameter n-2 | paramters push to stack from left to right +// |- - - - - - - - - | i-n th prameter spill to slot +// | parameter i | v +// +--------------------------+------------------------+ +// | return addr | ^ ^ +// |- - - - - - - - - | | | +// | fp | Fixed | +// |- - - - - - - - - | Header <-- frame ptr callee frame Header +// | FrameType | V | +// +--------------------------+------------------------+ +// ``` + +// ​ JSthread's sp will be updated dynamic, the scenarios is as follows by different Frames: +// **SAVE** is to save JSthread's sp to current Frame pre field, +// **UPDATE** is to fill JSthread's sp with currentsp or currentfp when current frame is iframe +// or Optimized EntryFrame/Optimized Frame. +// **nop** represent don't call SAVE or UPDATE, **illegal** represent this secnarios don't existed. + +// ``` +// iframe OptimizedEntry Optimized RunTime +// iframe SAVE/UPATE SAVE illegal SAVE/UPATE +// OptimizedEntry UPATE illegal nop UPATE +// Optimized UPATE illegal nop UPATE +// RunTime nop illegal illegal nop +// ``` + +// ​ Iterator Frame from Runtime Frame, the process is as flollows: + +// 1 calling JSThread->GetCurrentSPFrame get Current Frame, then get FrameType field + +// 2 Iterator previous Frame: + +// ​ accessing fp field when the current frame is Optimized Frame; + +// ​ accessing pre field when the current frame is Optimized Entry Frame or Interpreter Frame + +// 3 repeat process 2 until Current Frame is nullptr + +// For Example: +// ``` +// call call call +// foo -----------------> bar --------------->baz---------------------> rtfunc +// (interpret frame) (Optimized Entry Frame) (Optimized Frame) (Runtime Frame) +// ``` + +// Frame Layout as follow: +// ``` +// +---------------------------------+--------------------+ +// | argv[n-1] | ^ +// |----------------------------------| | +// | ........ | | +// | argv[0] | | +// |----------------------------------| | +// | thisArg | | +// |----------------------------------| | +// | newTarget | | +// |----------------------------------| | +// | callTarget | | +// +----------------------------------+--------+ | +// | FrameType | ^ foo's frame +// |----------------------------------| | | +// | pre(pre stack pointer) | | | +// |----------------------------------| | | +// | numActualArgs | | | +// |----------------------------------| | | +// | env | | | +// |----------------------------------| | | +// | acc | FrameState | +// |----------------------------------| | | +// | constantpool | | | +// |----------------------------------| | | +// | method | | | +// |----------------------------------| | | +// | sp(current stack point) | | | +// |----------------------------------| | | +// | pc(bytecode addr) | v v +// +----------------------------------+--------+----------+ +// | ............. | +// +--------------------------+---------------------------+ +// | return addr | ^ ^ +// |- - - - - - - - - | | | +// | fp | Fixed | +// |- - - - - - - - - | Header <-- frame ptr | +// | FrameType | | bar's frame Header +// |- - - - - - - - - | | | +// | pre | v | +// +--------------------------+---------------------------+ +// | ............. | +// +--------------------------+---------------------------+ +// | return addr | ^ ^ +// |- - - - - - - - - | | | +// | fp | Fixed | +// |- - - - - - - - - | Header <-- frame ptr | +// | FrameType | v baz's frame Header +// | ............. | +// +--------------------------+---------------------------+ +// | | +// | rtfunc's Frame | +// | | +// +------------------------------------------------------+ +// ``` +// Iterator: +// rtfunc get baz's Frame **currentfp** by calling GetCurrentSPFrame. +// baz'Frame fp field point to bar's Frame **currentfp**, then get bar's Frame pre field. +// bar's Frame pre field point to foo's Frame **currentsp**. +// finally we can iterator foo's Frame. + #ifndef ECMASCRIPT_FRAMES_H #define ECMASCRIPT_FRAMES_H namespace panda::ecmascript { -enum class FrameType: unsigned int { +class JSThread; +enum class FrameType: uint64_t { OPTIMIZED_FRAME = 0, OPTIMIZED_ENTRY_FRAME = 1, INTERPRETER_FRAME = 2, @@ -30,16 +225,22 @@ auto as_integer(Enumeration const value) return static_cast::type>(value); } -class FrameStateBase { +class OptFrameStateBase { public: FrameType frameType; uint64_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc }; -class LLVMBoundaryFrameState { +class InterPretFrameStateBase { +public: + uint64_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc + FrameType frameType; +}; + +class LLVMOptimizedEntryFrameState { public: uint64_t *threadFp; // for gc - FrameStateBase base; + OptFrameStateBase base; }; constexpr int kSystemPointerSize = sizeof(void*); @@ -47,8 +248,7 @@ class FrameConst { public: uint64_t *prev; FrameType frameType; - static constexpr int kPreOffset = -kSystemPointerSize; - static constexpr int kFrameType = -2 * kSystemPointerSize; + static constexpr int kFrameType = -kSystemPointerSize; }; } // namespace panda::ecmascript #endif // ECMASCRIPT_FRAMES_H \ No newline at end of file diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index c0ac197d1e..f50b97c14a 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -15,9 +15,12 @@ #include "ecmascript/interpreter/frame_handler.h" +#include + #include "ecmascript/interpreter/interpreter.h" #include "ecmascript/js_thread.h" #include "libpandafile/bytecode_instruction-inl.h" +#include "ecmascript/compiler/llvm/llvm_stackmap_parser.h" namespace panda::ecmascript { EcmaFrameHandler::EcmaFrameHandler(const JSThread *thread) @@ -44,7 +47,7 @@ void EcmaFrameHandler::PrevFrame() ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) FrameState *state = reinterpret_cast(sp_) - 1; - sp_ = state->prev; + sp_ = state->base.prev; } EcmaFrameHandler EcmaFrameHandler::GetPrevFrame() const @@ -52,7 +55,7 @@ EcmaFrameHandler EcmaFrameHandler::GetPrevFrame() const ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) FrameState *state = reinterpret_cast(sp_) - 1; - return EcmaFrameHandler(state->prev); + return EcmaFrameHandler(state->base.prev); } JSTaggedValue EcmaFrameHandler::GetVRegValue(size_t index) const @@ -82,7 +85,7 @@ uint32_t EcmaFrameHandler::GetSize() const ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) FrameState *state = reinterpret_cast(sp_) - 1; - JSTaggedType *prevSp = state->prev; + JSTaggedType *prevSp = state->base.prev; ASSERT(prevSp != nullptr); auto size = (prevSp - sp_) - FRAME_STATE_SIZE; return static_cast(size); @@ -152,14 +155,14 @@ JSTaggedValue EcmaFrameHandler::GetEnv() const void EcmaFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) { JSTaggedType *current = sp_; - while (current != nullptr) { + if (current != nullptr) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) FrameState *state = reinterpret_cast(current) - 1; if (state->sp != nullptr) { uintptr_t start = ToUintPtr(current); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - FrameState *prev_state = reinterpret_cast(state->prev) - 1; + FrameState *prev_state = reinterpret_cast(state->base.prev) - 1; uintptr_t end = ToUintPtr(prev_state); v1(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end)); if (state->pc != nullptr) { @@ -170,7 +173,6 @@ void EcmaFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1 v0(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&state->profileTypeInfo))); } } - current = state->prev; } } @@ -194,4 +196,80 @@ void EcmaFrameHandler::DumpPC(std::ostream &os, const uint8_t *pc) const int offset = pc - JSMethod::Cast(frameHandler.GetMethod())->GetBytecodeArray(); os << "offset: " << offset << "\n"; } + +void OptimizedFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const +{ +#ifdef PANDA_TARGET_AMD64 + JSTaggedType *current = fp_; + if (current != nullptr) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + std::vector slotAddrs; + auto returnAddr = reinterpret_cast(*(current + 1)); + bool ret = kungfu::LLVMStackMapParser::GetInstance().StackMapByFuncAddrFp( + returnAddr, + reinterpret_cast(fp_), + slotAddrs); + if (ret == false) { + return; + } + for (auto &address: slotAddrs) { + v0(Root::ROOT_FRAME, ObjectSlot(address)); + } + } +#else + (void)v0; + (void)v1; +#endif +} + +void OptimizedEntryFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const +{ +#ifdef PANDA_TARGET_AMD64 + JSTaggedType *current = fp_; + if (current != nullptr) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + std::vector slotAddrs; + auto returnAddr = *(current + 1); + bool ret = kungfu::LLVMStackMapParser::GetInstance().StackMapByFuncAddrFp( + reinterpret_cast(returnAddr), + reinterpret_cast(fp_), + slotAddrs); + if (ret == false) { + return; + } + for (auto &address: slotAddrs) { + v0(Root::ROOT_FRAME, ObjectSlot(address)); + } + } +#else + (void)v0; + (void)v1; +#endif +} + +void FrameIterator::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const +{ + JSTaggedType *current = fp_; + while (current) { + FrameType type = *(reinterpret_cast( + reinterpret_cast(current) + FrameConst::kFrameType)); + if (type == FrameType::INTERPRETER_FRAME) { + FrameState *state = reinterpret_cast(current) - 1; + EcmaFrameHandler(current).Iterate(v0, v1); + current = state->base.prev; + } else if (type == FrameType::OPTIMIZED_FRAME) { + OptFrameStateBase *state = reinterpret_cast( + reinterpret_cast(current) - + MEMBER_OFFSET(OptFrameStateBase, prev)); + OptimizedFrameHandler(current).Iterate(v0, v1); + current = reinterpret_cast(state->prev); + } else { + LLVMOptimizedEntryFrameState *state = reinterpret_cast( + reinterpret_cast(current) - + MEMBER_OFFSET(LLVMOptimizedEntryFrameState, base.prev)); + OptimizedEntryFrameHandler(current).Iterate(v0, v1); + current = reinterpret_cast(state->threadFp); + } + } +} } // namespace panda::ecmascript diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index ad82f37236..25b3e53638 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -68,6 +68,34 @@ public: private: JSTaggedType *sp_{nullptr}; }; -} // namespace ecmascript + +class OptimizedFrameHandler { +public: + explicit OptimizedFrameHandler(JSTaggedType *fp) : fp_(fp) {} + explicit OptimizedFrameHandler(const JSThread *thread); + ~OptimizedFrameHandler() = default; + void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; +private: + JSTaggedType *fp_ {nullptr}; +}; + +class OptimizedEntryFrameHandler { +public: + explicit OptimizedEntryFrameHandler(JSTaggedType *fp) : fp_(fp) {} + explicit OptimizedEntryFrameHandler(const JSThread *thread); + ~OptimizedEntryFrameHandler() = default; + void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; +private: + JSTaggedType *fp_ {nullptr}; +}; + +class FrameIterator { +public: + explicit FrameIterator(JSTaggedType *fp) : fp_(fp) {} + void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; +private: + JSTaggedType *fp_ {nullptr}; +}; +} // namespace ecmascript } // namespace panda #endif // ECMASCRIPT_INTERPRETER_FRAME_HANDLER_H diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index a9232e5d88..596acfa3d3 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -228,7 +228,8 @@ JSTaggedValue EcmaInterpreter::ExecuteNative(JSThread *thread, const CallParams& } FrameState *state = GET_FRAME(newSp); - state->prev = sp; + state->base.prev = sp; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; state->pc = nullptr; state->sp = newSp; state->method = methodToCall; @@ -261,7 +262,8 @@ JSTaggedValue EcmaInterpreter::Execute(JSThread *thread, const CallParams& param FrameState *breakState = GET_FRAME(newSp); breakState->pc = nullptr; breakState->sp = nullptr; - breakState->prev = originalPrevSp; + breakState->base.prev = originalPrevSp; + breakState->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; breakState->numActualArgs = 0; JSTaggedType *prevSp = newSp; @@ -300,7 +302,8 @@ JSTaggedValue EcmaInterpreter::Execute(JSThread *thread, const CallParams& param ConstantPool *constpool = ConstantPool::Cast(thisFunc->GetConstantPool().GetTaggedObject()); state->constpool = constpool; state->profileTypeInfo = thisFunc->GetProfileTypeInfo(); - state->prev = prevSp; + state->base.prev = prevSp; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; state->numActualArgs = numActualArgs; JSTaggedValue env = thisFunc->GetLexicalEnv(); @@ -338,7 +341,8 @@ JSTaggedValue EcmaInterpreter::GeneratorReEnterInterpreter(JSThread *thread, JSH FrameState *breakState = GET_FRAME(breakSp); breakState->pc = nullptr; breakState->sp = nullptr; - breakState->prev = currentSp; + breakState->base.prev = currentSp; + breakState->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; breakState->numActualArgs = 0; // create new frame and resume sp and pc @@ -368,7 +372,8 @@ JSTaggedValue EcmaInterpreter::GeneratorReEnterInterpreter(JSThread *thread, JSH state->profileTypeInfo = func->GetProfileTypeInfo(); state->acc = context->GetAcc(); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - state->prev = breakSp; + state->base.prev = breakSp; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; JSTaggedValue env = context->GetLexicalEnv(); state->env = env; // execute interpreter @@ -399,7 +404,8 @@ void EcmaInterpreter::ChangeGenContext(JSThread *thread, JSHandlepc = nullptr; breakState->sp = nullptr; - breakState->prev = currentSp; + breakState->base.prev = currentSp; + breakState->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; // create new frame and resume sp and pc uint32_t nregs = context->GetNRegs().GetInt(); @@ -428,7 +434,8 @@ void EcmaInterpreter::ChangeGenContext(JSThread *thread, JSHandleprofileTypeInfo = func->GetProfileTypeInfo(); state->acc = context->GetAcc(); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - state->prev = breakSp; + state->base.prev = breakSp; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; state->env = context->GetLexicalEnv(); thread->SetCurrentSPFrame(newSp); @@ -438,7 +445,7 @@ void EcmaInterpreter::ResumeContext(JSThread *thread) { JSTaggedType *sp = const_cast(thread->GetCurrentSPFrame()); FrameState *state = GET_FRAME(sp); - thread->SetCurrentSPFrame(state->prev); + thread->SetCurrentSPFrame(state->base.prev); } void EcmaInterpreter::NotifyBytecodePcChanged(JSThread *thread) @@ -771,7 +778,8 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool } FrameState *state = GET_FRAME(newSp); - state->prev = sp; + state->base.prev = sp; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; state->pc = nullptr; state->sp = newSp; state->method = methodToCall; @@ -854,7 +862,8 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool InterpreterFrameCopyArgs(newSp, numVregs, actualNumArgs, numDeclaredArgs); FrameState *state = GET_FRAME(newSp); - state->prev = sp; + state->base.prev = sp; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; state->pc = pc = JSMethod::Cast(methodToCall)->GetBytecodeArray(); state->sp = sp = newSp; state->method = methodToCall; @@ -880,7 +889,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool << std::hex << reinterpret_cast(state->pc); [[maybe_unused]] auto fistPC = state->method->GetInstructions(); UPDATE_HOTNESS_COUNTER(-(pc - fistPC)); - sp = state->prev; + sp = state->base.prev; ASSERT(sp != nullptr); FrameState *prevState = GET_FRAME(sp); pc = prevState->pc; @@ -904,7 +913,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool << std::hex << reinterpret_cast(state->pc); [[maybe_unused]] auto fistPC = state->method->GetInstructions(); UPDATE_HOTNESS_COUNTER_NON_ACC(-(pc - fistPC)); - sp = state->prev; + sp = state->base.prev; ASSERT(sp != nullptr); FrameState *prevState = GET_FRAME(sp); pc = prevState->pc; @@ -2003,7 +2012,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool UPDATE_HOTNESS_COUNTER(-(pc - fistPC)); LOG(DEBUG, INTERPRETER) << "Exit: SuspendGenerator " << std::hex << reinterpret_cast(sp) << " " << std::hex << reinterpret_cast(state->pc); - sp = state->prev; + sp = state->base.prev; ASSERT(sp != nullptr); FrameState *prevState = GET_FRAME(sp); pc = prevState->pc; @@ -3215,7 +3224,8 @@ void EcmaInterpreter::InitStackFrame(JSThread *thread) state->acc = JSTaggedValue::Hole(); state->constpool = nullptr; state->profileTypeInfo = JSTaggedValue::Undefined(); - state->prev = nullptr; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; + state->base.prev = nullptr; state->numActualArgs = 0; } diff --git a/ecmascript/interpreter/interpreter.h b/ecmascript/interpreter/interpreter.h index cb988f3701..0c1a504d99 100644 --- a/ecmascript/interpreter/interpreter.h +++ b/ecmascript/interpreter/interpreter.h @@ -20,6 +20,7 @@ #include "ecmascript/js_tagged_value.h" #include "ecmascript/js_handle.h" #include "ecmascript/js_thread.h" +#include "ecmascript/frames.h" namespace panda::ecmascript { class ConstantPool; @@ -32,7 +33,6 @@ using TaggedType = coretypes::TaggedType; struct FrameState { const uint8_t *pc; JSTaggedType *sp; - uint64_t *prev; JSMethod *method; // aligned with 8 bits alignas(sizeof(uint64_t)) ConstantPool *constpool; @@ -40,6 +40,7 @@ struct FrameState { JSTaggedValue acc; JSTaggedValue env; uint64_t numActualArgs; + InterPretFrameStateBase base; }; // NOLINTNEXTLINE(bugprone-sizeof-expression) diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index 5ed583444c..6338196739 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -86,14 +86,13 @@ void JSThread::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) if (!exception_.IsHole()) { v0(Root::ROOT_VM, ObjectSlot(ToUintPtr(&exception_))); } - // visit global Constant globalConst_.VisitRangeSlot(v1); // visit stack roots - EcmaFrameHandler(currentFrame_).Iterate(v0, v1); + FrameIterator iterator(currentFrame_); + iterator.Iterate(v0, v1); // visit internal call params internalCallParams_->Iterate(v1); - // visit tagged handle storage roots if (currentHandleStorageIndex_ != -1) { int32_t nid = currentHandleStorageIndex_; diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 7f597de23a..9edc94579a 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -22,6 +22,7 @@ #include "ecmascript/interpreter/frame_handler.h" #include "ecmascript/mem/heap_roots.h" #include "include/thread.h" +#include "ecmascript/frames.h" namespace panda::ecmascript { class EcmaVM; diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index 839459d5e0..efb4b20274 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -18,6 +18,7 @@ #include "ecmascript/ecma_macros.h" #include "ecmascript/js_object.h" #include "ecmascript/js_proxy.h" +#include "ecmascript/frames.h" #include "ecmascript/layout_info.h" #include "ecmascript/message_string.h" #include "ecmascript/object_factory.h" @@ -26,7 +27,12 @@ namespace panda::ecmascript { bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argReceiver, uint32_t argIndex, uint64_t argValue, uint32_t argAttr) { + JSTaggedType *fp = nullptr; +#ifdef PANDA_TARGET_AMD64 + asm("mov %%rbp, %0" : "=rm" (fp)); +#endif auto thread = reinterpret_cast(argThread); + StubCallRunTimeThreadFpLock(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle receiver(thread, reinterpret_cast(argReceiver)); JSHandle value(thread, JSTaggedValue(reinterpret_cast(argValue))); @@ -37,7 +43,12 @@ bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argRece bool RuntimeTrampolines::CallSetter(uint64_t argThread, uint64_t argSetter, uint64_t argReceiver, uint64_t argValue, bool argMayThrow) { + JSTaggedType *fp = nullptr; +#ifdef PANDA_TARGET_AMD64 + asm("mov %%rbp, %0" : "=rm" (fp)); +#endif auto thread = reinterpret_cast(argThread); + StubCallRunTimeThreadFpLock(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle receiver(thread, JSTaggedValue(reinterpret_cast(argReceiver))); JSHandle value(thread, JSTaggedValue(reinterpret_cast(argValue))); @@ -47,7 +58,12 @@ bool RuntimeTrampolines::CallSetter(uint64_t argThread, uint64_t argSetter, uint void RuntimeTrampolines::ThrowTypeError(uint64_t argThread, int argMessageStringId) { + JSTaggedType *fp = nullptr; +#ifdef PANDA_TARGET_AMD64 + asm("mov %%rbp, %0" : "=rm" (fp)); +#endif auto thread = reinterpret_cast(argThread); + StubCallRunTimeThreadFpLock(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); std::string message = MessageString::GetMessageString(argMessageStringId); ObjectFactory *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); @@ -58,7 +74,12 @@ void RuntimeTrampolines::ThrowTypeError(uint64_t argThread, int argMessageString bool RuntimeTrampolines::JSProxySetProperty(uint64_t argThread, uint64_t argProxy, uint64_t argKey, uint64_t argValue, uint64_t argReceiver, bool argMayThrow) { + JSTaggedType *fp = nullptr; +#ifdef PANDA_TARGET_AMD64 + asm("mov %%rbp, %0" : "=rm" (fp)); +#endif auto thread = reinterpret_cast(argThread); + StubCallRunTimeThreadFpLock(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle proxy(thread, JSTaggedValue(reinterpret_cast(argProxy))); JSHandle index(thread, JSTaggedValue(reinterpret_cast(argKey))); @@ -76,7 +97,12 @@ uint32_t RuntimeTrampolines::GetHash32(uint64_t key, uint64_t len) uint64_t RuntimeTrampolines::CallGetter(uint64_t argThread, uint64_t argGetter, uint64_t argReceiver) { + JSTaggedType *fp = nullptr; +#ifdef PANDA_TARGET_AMD64 + asm("mov %%rbp, %0" : "=rm" (fp)); +#endif auto thread = reinterpret_cast(argThread); + StubCallRunTimeThreadFpLock(thread, fp); auto accessor = AccessorData::Cast(reinterpret_cast(argGetter)); JSHandle objHandle(thread, JSTaggedValue(reinterpret_cast(argReceiver))); return JSObject::CallGetter(thread, accessor, objHandle).GetRawData(); @@ -84,7 +110,12 @@ uint64_t RuntimeTrampolines::CallGetter(uint64_t argThread, uint64_t argGetter, uint64_t RuntimeTrampolines::AccessorGetter(uint64_t argThread, uint64_t argGetter, uint64_t argReceiver) { + JSTaggedType *fp = nullptr; +#ifdef PANDA_TARGET_AMD64 + asm("mov %%rbp, %0" : "=rm" (fp)); +#endif auto thread = reinterpret_cast(argThread); + StubCallRunTimeThreadFpLock(thread, fp); auto accessor = AccessorData::Cast(reinterpret_cast(argGetter)); JSHandle objHandle(thread, JSTaggedValue(reinterpret_cast(argReceiver))); return accessor->CallInternalGet(thread, objHandle).GetRawData(); diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index 678ea521ee..88a83ced24 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -49,5 +49,33 @@ public: static int32_t FindElementWithCache(uint64_t argThread, uint64_t hClass, uint64_t key, int32_t num); static uint32_t StringGetHashCode(uint64_t ecmaString); }; + +class StubCallRunTimeThreadFpLock { +public: + StubCallRunTimeThreadFpLock(JSThread *thread, JSTaggedType *newFp) + :oldRbp_(const_cast(thread->GetCurrentSPFrame())), + thread_(thread) + { + thread_->SetCurrentSPFrame(newFp); + + std::cout << "StubCallRunTimeThreadFpLock newFp: " << newFp << " oldRbp_ : " << oldRbp_ + << " thread_->fp:" << thread_->GetCurrentSPFrame() <( + reinterpret_cast(newFp) + FrameConst::kFrameType)); + std::cout << "type = " << as_integer(type) << std::endl; + } + ~StubCallRunTimeThreadFpLock() + { + std::cout << "~StubCallRunTimeThreadFpLock oldRbp_: " << oldRbp_ << + " thread_->fp:" << thread_->GetCurrentSPFrame() << std::endl; + FrameType type = *(reinterpret_cast( + reinterpret_cast(oldRbp_) + FrameConst::kFrameType)); + std::cout << "type = " << as_integer(type) << std::endl; + thread_->SetCurrentSPFrame(oldRbp_); + } +private: + JSTaggedType *oldRbp_; + JSThread *thread_; +}; } // namespace panda::ecmascript #endif \ No newline at end of file diff --git a/ecmascript/tests/test_helper.h b/ecmascript/tests/test_helper.h index 4a5a202f9e..fd21b70234 100644 --- a/ecmascript/tests/test_helper.h +++ b/ecmascript/tests/test_helper.h @@ -64,7 +64,8 @@ public: JSTaggedType *newSp = sp - frameSize; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) FrameState *state = reinterpret_cast(newSp) - 1; - state->prev = sp; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; + state->base.prev = sp; state->pc = nullptr; state->sp = newSp; state->method = thread->GetEcmaVM()->GetMethodForNativeFunction(nullptr); diff --git a/ecmascript/tooling/BUILD.gn b/ecmascript/tooling/BUILD.gn index e789c1b086..4466c7ed0f 100644 --- a/ecmascript/tooling/BUILD.gn +++ b/ecmascript/tooling/BUILD.gn @@ -94,6 +94,7 @@ ohos_shared_library("libark_ecma_debugger_test") { deps = [ ":libark_ecma_debugger_test_static", "//ark/js_runtime:libark_jsruntime_test_static", + "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser", ] configs = [ diff --git a/llvm.patch b/llvm.patch new file mode 100644 index 0000000000..86f6381f71 --- /dev/null +++ b/llvm.patch @@ -0,0 +1,121 @@ +diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt +index 0e85afa82c7..f56219422d2 100644 +--- a/llvm/CMakeLists.txt ++++ b/llvm/CMakeLists.txt +@@ -507,6 +507,12 @@ option(LLVM_BUILD_EXAMPLES + "Build the LLVM example programs. If OFF, just generate build targets." OFF) + option(LLVM_INCLUDE_EXAMPLES "Generate build targets for the LLVM examples" ON) + ++option(BUILD_ARK_GC_SUPPORT ++ "ARK support GC. If ON, support GC." OFF) ++if(BUILD_ARK_GC_SUPPORT) ++ add_definitions(-DARK_GC_SUPPORT) ++endif(ARK_SUPPORT_GC) ++ + if(LLVM_BUILD_EXAMPLES) + add_definitions(-DBUILD_EXAMPLES) + endif(LLVM_BUILD_EXAMPLES) +diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp +index 1da20371caf..875184f32b2 100644 +--- a/llvm/lib/Target/X86/X86FrameLowering.cpp ++++ b/llvm/lib/Target/X86/X86FrameLowering.cpp +@@ -31,6 +31,7 @@ + #include "llvm/Support/Debug.h" + #include "llvm/Target/TargetOptions.h" + #include ++#include + + using namespace llvm; + +@@ -1169,6 +1170,29 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, + MFI.setOffsetAdjustment(-StackSize); + } + ++#ifdef ARK_GC_SUPPORT ++ // push marker ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) ++ { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ std::cout << __LINE__ << " marker:" << std::dec << marker << std::endl; ++ ++ BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH64i32)) ++ .addImm(marker) ++ .setMIFlag(MachineInstr::FrameSetup); ++ /*reserve thread.fp */ ++ if (marker == 1) { ++ BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH64i32)) ++ .addImm(marker) ++ .setMIFlag(MachineInstr::FrameSetup); ++ } ++ } ++#endif ++ + // For EH funclets, only allocate enough space for outgoing calls. Save the + // NumBytes value that we would've used for the parent frame. + unsigned ParentFrameNumBytes = NumBytes; +@@ -1635,6 +1659,27 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, + uint64_t SEHStackAllocAmt = NumBytes; + + if (HasFP) { ++#ifdef ARK_GC_SUPPORT ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) ++ { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ ++ // pop marker ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), ++ MachineFramePtr) ++ .setMIFlag(MachineInstr::FrameDestroy); ++ if (marker == 1) { ++ // pop thread.fp ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), ++ MachineFramePtr) ++ .setMIFlag(MachineInstr::FrameDestroy); ++ } ++ } ++#endif + // Pop EBP. + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), + MachineFramePtr) +@@ -1993,8 +2038,33 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( + + if (hasFP(MF)) { + // emitPrologue always spills frame register the first thing. ++#ifdef ARK_GC_SUPPORT ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ if (marker == 1) { ++ SpillSlotOffset -= 3 * SlotSize; // add type and thread.fp ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ CalleeSavedFrameSize += 16; ++ } else { ++ SpillSlotOffset -= 2 * SlotSize; // add type ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ CalleeSavedFrameSize += 8; ++ } ++ } else { ++ SpillSlotOffset -= SlotSize; // add type and thread.fp ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ } ++#else + SpillSlotOffset -= SlotSize; + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++#endif + + // Since emitPrologue and emitEpilogue will handle spilling and restoring of + // the frame register, we can delete it from CSI list and not have to worry -- Gitee From bd912a47b69170a1007b5df4b3866d509723b3e1 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Mon, 11 Oct 2021 10:41:32 +0800 Subject: [PATCH 2/6] add mul gc tests Signed-off-by: surpassgoodchao --- ecmascript/compiler/circuit_builder.cpp | 2 + ecmascript/compiler/fast_stub.cpp | 43 ++++++++++++- ecmascript/compiler/fast_stub.h | 2 +- ecmascript/compiler/fast_stub_define.h | 6 +- ecmascript/compiler/gate.cpp | 3 + ecmascript/compiler/gate.h | 2 + ecmascript/compiler/llvm_codegen.cpp | 14 +++++ ecmascript/compiler/llvm_ir_builder.cpp | 3 + ecmascript/compiler/machine_type.h | 1 + ecmascript/compiler/stub_aot_compiler.cpp | 12 ++++ ecmascript/compiler/stub_descriptor.cpp | 31 ++++++++- ecmascript/interpreter/interpreter-inl.h | 12 ++++ ecmascript/runtime_trampolines.cpp | 76 ++++++++++++++++++++++- ecmascript/runtime_trampolines.h | 2 + js_runtime_config.gni | 2 +- 15 files changed, 200 insertions(+), 11 deletions(-) diff --git a/ecmascript/compiler/circuit_builder.cpp b/ecmascript/compiler/circuit_builder.cpp index 541311d2f5..bb8b6ae459 100644 --- a/ecmascript/compiler/circuit_builder.cpp +++ b/ecmascript/compiler/circuit_builder.cpp @@ -329,6 +329,8 @@ OpCode CircuitBuilder::GetCallOpCodeFromMachineType(MachineType type) return OpCode(OpCode::FLOAT32_CALL); case FLOAT64_TYPE: return OpCode(OpCode::FLOAT64_CALL); + case TAGVALUE_TYPE: + return OpCode(OpCode::TAGVALUE_CALL); default: UNREACHABLE(); } diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index ac005e5b53..56aa55a05d 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -19,6 +19,7 @@ #include "ecmascript/message_string.h" #include "ecmascript/tagged_hash_table-inl.h" #include "llvm_ir_builder.h" +#include "ecmascript/frames.h" namespace kungfu { using namespace panda::ecmascript; @@ -187,10 +188,16 @@ void FastSubStub::GenerateCircuit() void FastMulStub::GenerateCircuit() { auto env = GetEnvironment(); - AddrShift x = Int64Argument(0); - AddrShift y = Int64Argument(1); + env->GetCircuit()->SetFrameType(FrameType::OPTIMIZED_ENTRY_FRAME); + AddrShift thread = PtrArgument(0); + (void)thread; + AddrShift x = Int64Argument(1); + AddrShift y = Int64Argument(2); + DEFVARIABLE(intX, MachineType::INT32_TYPE, 0); DEFVARIABLE(intY, MachineType::INT32_TYPE, 0); + DEFVARIABLE(intZ, MachineType::INT32_TYPE, 0); + DEFVARIABLE(valuePtr, MachineType::INT64_TYPE, 0); DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); Label xIsNumber(env); @@ -242,6 +249,38 @@ void FastMulStub::GenerateCircuit() } Bind(&xIsDoubleAndyIsDouble); doubleX = DoubleMul(*doubleX, *doubleY); +//#define TEST_FRAME_TYPE +#ifdef TEST_FRAME_TYPE + StubDescriptor *getStringLen = GET_STUBDESCRIPTOR(GetStringLen); + AddrShift double1 = CallRuntime(getStringLen, thread, GetWord64Constant(FAST_STUB_ID(GetStringLen)), + {thread}); + AddrShift double2 = CallRuntime(getStringLen, thread, GetWord64Constant(FAST_STUB_ID(GetStringLen)), + {thread}); + doubleX = DoubleMul(*doubleX, double1); + doubleX = DoubleMul(*doubleX, double2); +#endif + +#if 1 + StubDescriptor *getStringPtr = GET_STUBDESCRIPTOR(GetStringPtr); + AddrShift ptr1 = CallRuntime(getStringPtr, thread, GetWord64Constant(FAST_STUB_ID(GetStringPtr)), + {thread}); + AddrShift ptr2 = CallRuntime(getStringPtr, thread, GetWord64Constant(FAST_STUB_ID(GetStringPtr)), + {thread}); + (void)ptr2; + + + StubDescriptor *getStringLen = GET_STUBDESCRIPTOR(GetStringLen); + AddrShift double1 = CallRuntime(getStringLen, thread, GetWord64Constant(FAST_STUB_ID(GetStringLen)), + {thread}); + doubleX = DoubleMul(*doubleX, double1); + + valuePtr = Load(INT64_TYPE, ptr1); + + AddrShift value = CastInt64ToFloat64(*valuePtr); + doubleX = DoubleMul(*doubleX, value); + //doubleX = DoubleMul(*doubleX, ptr2); +#endif + Return(DoubleBuildTagged(*doubleX)); } diff --git a/ecmascript/compiler/fast_stub.h b/ecmascript/compiler/fast_stub.h index 6814fa37c7..5ed775366a 100644 --- a/ecmascript/compiler/fast_stub.h +++ b/ecmascript/compiler/fast_stub.h @@ -53,7 +53,7 @@ public: class FastMulStub : public Stub { public: // 2 : 2 means argument counts - explicit FastMulStub(Circuit *circuit) : Stub("FastMul", 2, circuit) {} + explicit FastMulStub(Circuit *circuit) : Stub("FastMul", 3, circuit) {} ~FastMulStub() = default; NO_MOVE_SEMANTIC(FastMulStub); NO_COPY_SEMANTIC(FastMulStub); diff --git a/ecmascript/compiler/fast_stub_define.h b/ecmascript/compiler/fast_stub_define.h index ccf3bf3c31..510ab5bca3 100644 --- a/ecmascript/compiler/fast_stub_define.h +++ b/ecmascript/compiler/fast_stub_define.h @@ -27,13 +27,15 @@ namespace kungfu { V(JSProxySetProperty, 6) \ V(GetHash32, 2) \ V(FindElementWithCache, 4) \ - V(StringGetHashCode, 1) + V(StringGetHashCode, 1) \ + V(GetStringLen, 1) \ + V(GetStringPtr, 1) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define FAST_RUNTIME_STUB_LIST(V) \ V(FastAdd, 2) \ V(FastSub, 2) \ - V(FastMul, 2) \ + V(FastMul, 3) \ V(FastDiv, 2) \ V(FastMod, 2) \ V(FastEqual, 2) \ diff --git a/ecmascript/compiler/gate.cpp b/ecmascript/compiler/gate.cpp index f2e09834fd..72d2b64cca 100644 --- a/ecmascript/compiler/gate.cpp +++ b/ecmascript/compiler/gate.cpp @@ -148,6 +148,8 @@ Properties OpCode::GetProperties() const return {FLOAT32, NO_STATE, ONE_DEPEND, MANY_VALUE(PtrValueCode(), ANYVALUE), NO_ROOT}; case FLOAT64_CALL: return {FLOAT64, NO_STATE, ONE_DEPEND, MANY_VALUE(PtrValueCode(), ANYVALUE), NO_ROOT}; + case TAGVALUE_CALL: + return {TAGVALUE, NO_STATE, ONE_DEPEND, MANY_VALUE(PtrValueCode(), ANYVALUE), NO_ROOT}; case ALLOCA: return {PtrValueCode(), NO_STATE, NO_DEPEND, NO_VALUE, OpCode(ALLOCA_LIST)}; case INT1_ARG: @@ -381,6 +383,7 @@ std::string OpCode::Str() const {INT64_CALL, "INT64_CALL"}, {FLOAT32_CALL, "FLOAT32_CALL"}, {FLOAT64_CALL, "FLOAT64_CALL"}, + {TAGVALUE_CALL, "TAGVALUE_CALL"}, {ALLOCA, "ALLOCA"}, {INT1_ARG, "INT1_ARG"}, {INT8_ARG, "INT8_ARG"}, diff --git a/ecmascript/compiler/gate.h b/ecmascript/compiler/gate.h index a112479593..1dd1c51799 100644 --- a/ecmascript/compiler/gate.h +++ b/ecmascript/compiler/gate.h @@ -49,6 +49,7 @@ enum ValueCode { INT64, FLOAT32, FLOAT64, + TAGVALUE, }; std::string ValueCodeToStr(ValueCode valueCode); @@ -128,6 +129,7 @@ public: INT64_CALL, FLOAT32_CALL, FLOAT64_CALL, + TAGVALUE_CALL, ALLOCA, INT1_ARG, INT8_ARG, diff --git a/ecmascript/compiler/llvm_codegen.cpp b/ecmascript/compiler/llvm_codegen.cpp index f58bef33ab..77faaaa7d0 100644 --- a/ecmascript/compiler/llvm_codegen.cpp +++ b/ecmascript/compiler/llvm_codegen.cpp @@ -14,8 +14,12 @@ */ #include "llvm_codegen.h" +#include +#include +#include #include "ecmascript/object_factory.h" #include "stub_descriptor.h" +#include "ecmascript/compiler/llvm/llvm_stackmap_parser.h" using namespace panda::ecmascript; namespace kungfu { @@ -30,19 +34,29 @@ void LLVMCodeGeneratorImpl::GenerateCodeForStub(Circuit *circuit, const ControlF void LLVMModuleAssembler::AssembleModule() { assembler_.Run(); + uint8_t *ptr = assembler_.GetStackMapsSection(); + std::cout << " AssembleModule " << __LINE__ << std::endl; + LLVMStackMapParser::GetInstance().CalculateStackMap(ptr); + LLVMStackMapParser::GetInstance().Print(); } void LLVMModuleAssembler::CopyAssembleCodeToModule(StubModule *module) { auto codeBuff = reinterpret_cast
(assembler_.GetCodeBuffer()); auto engine = assembler_.GetEngine(); + std::map addr2name; for (int i = 0; i < FAST_STUB_MAXCOUNT; i++) { + std::cout << "i :" << i << std::endl; auto stubfunction = stubmodule_->GetStubFunction(i); if (stubfunction != nullptr) { Address stubEntry = reinterpret_cast
(LLVMGetPointerToGlobal(engine, stubfunction)); module->SetStubEntry(i, stubEntry - codeBuff); + std::string str = FastStubDescriptors::GetInstance().GetStubDescriptor(i)->GetName(); + uint64_t key = stubEntry; + addr2name[key] = str; } } + assembler_.Disassemble(addr2name); auto codeSize = assembler_.GetCodeSize(); diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 36ea4d96f4..59c195ecb5 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -157,6 +157,7 @@ void LLVMIRBuilder::AssignHandleMap() {OpCode::INT64_LSL, &LLVMIRBuilder::HandleIntLsl}, {OpCode::FLOAT64_SMOD, &LLVMIRBuilder::HandleFloatMod}, {OpCode::INT32_SMOD, &LLVMIRBuilder::HandleIntMod}, + {OpCode::TAGVALUE_CALL, &LLVMIRBuilder::HandleCall}, }; opCodeHandleIgnore= {OpCode::NOP, OpCode::CIRCUIT_ROOT, OpCode::DEPEND_ENTRY, @@ -386,6 +387,7 @@ void LLVMIRBuilder::HandleCall(AddrShift gate) case OpCode::INT1_CALL: case OpCode::INT32_CALL: case OpCode::FLOAT64_CALL: + case OpCode::TAGVALUE_CALL: case OpCode::INT64_CALL: { VisitCall(gate, ins); break; @@ -1380,6 +1382,7 @@ LLVMTypeRef LLVMStubModule::ConvertLLVMTypeFromMachineType(MachineType type) {MachineType::UINT64_TYPE, LLVMInt64Type()}, {MachineType::FLOAT32_TYPE, LLVMFloatType()}, {MachineType::FLOAT64_TYPE, LLVMDoubleType()}, + {MachineType::TAGVALUE_TYPE, LLVMPointerType(LLVMInt64Type(), 1)}, }; return machineTypeMap[type]; } diff --git a/ecmascript/compiler/machine_type.h b/ecmascript/compiler/machine_type.h index 3530cd14dd..f7caed1ce4 100644 --- a/ecmascript/compiler/machine_type.h +++ b/ecmascript/compiler/machine_type.h @@ -33,6 +33,7 @@ enum MachineType { TAGGED_POINTER_TYPE, FLOAT32_TYPE, FLOAT64_TYPE, + TAGVALUE_TYPE, }; } // namespace kungfu #endif // ECMASCRIPT_COMPILER_MACHINE_TYPE_H \ No newline at end of file diff --git a/ecmascript/compiler/stub_aot_compiler.cpp b/ecmascript/compiler/stub_aot_compiler.cpp index 530c67699d..a455c53e24 100644 --- a/ecmascript/compiler/stub_aot_compiler.cpp +++ b/ecmascript/compiler/stub_aot_compiler.cpp @@ -177,6 +177,18 @@ int main(int argc, char *argv[]) kungfu::FastSetElementStub fastSetElementStub(&fastSetElementCircuit); mouldeBuilder.SetStub(FAST_STUB_ID(SetElement), &fastSetElementStub); + kungfu::Circuit fastGetPropertyByNameCircuit; + kungfu::FastGetPropertyByNameStub fastGetPropertyByNameStub(&fastGetPropertyByNameCircuit); + mouldeBuilder.SetStub(FAST_STUB_ID(GetPropertyByName), &fastGetPropertyByNameStub); + + kungfu::Circuit fastGetPropertyByIndexCircuit; + kungfu::FastGetPropertyByIndexStub fastGetPropertyByIndexStub(&fastGetPropertyByIndexCircuit); + mouldeBuilder.SetStub(FAST_STUB_ID(GetPropertyByIndex), &fastGetPropertyByIndexStub); + + kungfu::Circuit fastSetPropertyByIndexCircuit; + kungfu::FastSetPropertyByIndexStub fastSetPropertyByIndexStub(&fastSetPropertyByIndexCircuit); + mouldeBuilder.SetStub(FAST_STUB_ID(SetPropertyByIndex), &fastSetPropertyByIndexStub); + mouldeBuilder.BuildStubModule(&stubModule); stubModule.Save(moduleFilename); exit(0); diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index 31cc658a5a..ec34b32331 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -56,10 +56,11 @@ CALL_STUB_INIT_DESCRIPTOR(FastSub) CALL_STUB_INIT_DESCRIPTOR(FastMul) { // 2 : 2 input parameters - static StubDescriptor fastMul("FastMul", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + static StubDescriptor fastMul("FastMul", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); *descriptor = fastMul; // 2 : 2 input parameters - std::array params = { + std::array params = { + MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, }; @@ -222,6 +223,32 @@ CALL_STUB_INIT_DESCRIPTOR(AddElementInternal) descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); } +CALL_STUB_INIT_DESCRIPTOR(GetStringLen) +{ + // 2 : 2 input parameters + static StubDescriptor GetStringLen("GetStringLen", 0, 1, ArgumentsOrder::DEFAULT_ORDER, FLOAT64_TYPE); + *descriptor = GetStringLen; + // 2 : 2 input parameters + std::array params = { + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); +} + +CALL_STUB_INIT_DESCRIPTOR(GetStringPtr) +{ + // 2 : 2 input parameters + static StubDescriptor GetStringPtr("GetStringPtr", 0, 1, ArgumentsOrder::DEFAULT_ORDER, TAGVALUE_TYPE); + *descriptor = GetStringPtr; + // 2 : 2 input parameters + std::array params = { + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); +} + CALL_STUB_INIT_DESCRIPTOR(CallSetter) { // 5 : 5 input parameters diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index 596acfa3d3..d1d78fc030 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -1280,7 +1280,19 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool << " v" << v0; JSTaggedValue left = GET_VREG_VALUE(v0); JSTaggedValue right = acc; + std::cout << "szc mul " << std::endl; + auto current = thread->GetCurrentSPFrame(); + FrameType type = *(reinterpret_cast( + reinterpret_cast(current) + FrameConst::kFrameType)); + std::cout << "type = " << as_integer(type) << std::endl; + std::cout << "type = " << as_integer(type) << " frame: " << thread->GetCurrentSPFrame() << std::endl; + #if 0 JSTaggedValue value = FastRuntimeStub::FastMul(left, right); + #else + auto fastMulFn = + reinterpret_cast(thread->GetFastStubEntry(FAST_STUB_ID(FastMul))); + auto value = fastMulFn(reinterpret_cast(thread), left.GetRawData(), right.GetRawData()); + #endif if (!value.IsHole()) { SET_ACC(value); } else { diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index efb4b20274..1a28b10b33 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -22,6 +22,9 @@ #include "ecmascript/layout_info.h" #include "ecmascript/message_string.h" #include "ecmascript/object_factory.h" +#include "ecmascript/ecma_vm.h" +#include "ecmascript/js_handle.h" +#include "ecmascript/ecma_string-inl.h" namespace panda::ecmascript { bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argReceiver, uint32_t argIndex, @@ -40,15 +43,82 @@ bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argRece return JSObject::AddElementInternal(thread, receiver, argIndex, value, attr); } -bool RuntimeTrampolines::CallSetter(uint64_t argThread, uint64_t argSetter, uint64_t argReceiver, uint64_t argValue, - bool argMayThrow) +double RuntimeTrampolines::GetStringLen(uint64_t argThread) { JSTaggedType *fp = nullptr; #ifdef PANDA_TARGET_AMD64 asm("mov %%rbp, %0" : "=rm" (fp)); #endif + auto rbp = reinterpret_cast(fp); + fp = reinterpret_cast(*rbp); + + std::cout << " RuntimeFunc2 rbp:" << rbp << " fp: "<< fp << std::endl; + for (int i = 0; i < 40; i++) { + std::cout << std::hex << &(rbp[i]) << " :" << rbp[i] << std::endl; + } + auto thread = reinterpret_cast(argThread); + auto current = thread->GetCurrentSPFrame(); + FrameType type = *(reinterpret_cast( + reinterpret_cast(current) + FrameConst::kFrameType)); + std::cout << "type = " << as_integer(type) << std::endl; + + StubCallRunTimeThreadFpLock lock(thread, fp); + + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle str = factory->NewFromCanBeCompressString("szc"); + // trigger GC + thread->GetEcmaVM()->CollectGarbage(TriggerGCType::COMPRESS_FULL_GC); + thread->GetEcmaVM()->CollectGarbage(TriggerGCType::SEMI_GC); // Trigger GC. + thread->GetEcmaVM()->CollectGarbage(TriggerGCType::HUGE_GC); // Trigger GC. + return static_cast(str->GetLength()); +} + +TaggedObject* RuntimeTrampolines::GetStringPtr(uint64_t argThread) +{ + JSTaggedType *fp = nullptr; +#ifdef PANDA_TARGET_AMD64 + asm("mov %%rbp, %0" : "=rm" (fp)); +#endif + auto rbp = reinterpret_cast(fp); + fp = reinterpret_cast(*rbp); + + std::cout << " RuntimeFunc2 rbp:" << rbp << " fp: "<< fp << std::endl; + for (int i = 0; i < 40; i++) { + std::cout << std::hex << &(rbp[i]) << " :" << rbp[i] << std::endl; + } + auto thread = reinterpret_cast(argThread); + auto current = thread->GetCurrentSPFrame(); + FrameType type = *(reinterpret_cast( + reinterpret_cast(current) + FrameConst::kFrameType)); + std::cout << "type = " << as_integer(type) << std::endl; + + StubCallRunTimeThreadFpLock lock(thread, fp); + + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + static int i = 0; + JSHandle str; + if (i == 0) { + str = factory->NewFromCanBeCompressString("szc"); + } else { + str = factory->NewFromCanBeCompressString("1234567890"); + } + i++; + JSHandle value = JSHandle::Cast(str); + // trigger GC + if (i != 1) { + thread->GetEcmaVM()->CollectGarbage(TriggerGCType::COMPRESS_FULL_GC); + thread->GetEcmaVM()->CollectGarbage(TriggerGCType::SEMI_GC); // Trigger GC. + thread->GetEcmaVM()->CollectGarbage(TriggerGCType::HUGE_GC); // Trigger GC. + } + auto ret = value.GetTaggedValue().GetTaggedObject(); + std::cout << "szc tagged object : " << ret << std::endl; + return ret; +} + +bool RuntimeTrampolines::CallSetter(uint64_t argThread, uint64_t argSetter, uint64_t argReceiver, uint64_t argValue, + bool argMayThrow) +{ auto thread = reinterpret_cast(argThread); - StubCallRunTimeThreadFpLock(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle receiver(thread, JSTaggedValue(reinterpret_cast(argReceiver))); JSHandle value(thread, JSTaggedValue(reinterpret_cast(argValue))); diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index 88a83ced24..0439f4392c 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -38,6 +38,8 @@ public: } static bool AddElementInternal(uint64_t argThread, uint64_t argReceiver, uint32_t argIndex, uint64_t argValue, uint32_t argAttr); + static double GetStringLen(uint64_t argThread); + static TaggedObject* GetStringPtr(uint64_t argThread); static bool CallSetter(uint64_t argThread, uint64_t argSetter, uint64_t argReceiver, uint64_t argValue, bool argMayThrow); static uint64_t CallGetter(uint64_t argThread, uint64_t argGetter, uint64_t argReceiver); diff --git a/js_runtime_config.gni b/js_runtime_config.gni index ea4700b461..55f7a3e9ff 100644 --- a/js_runtime_config.gni +++ b/js_runtime_config.gni @@ -13,7 +13,7 @@ ark_root = "//ark/runtime_core" js_root = "//ark/js_runtime" -compile_llvm_online = false +compile_llvm_online = true # For OpenHarmony build, always link with the static lib: sdk_libc_secshared_dep = "//utils/native/base:utilsecurec" -- Gitee From 82a0fc5547a0cf479443e22b6b4b29e9e70cf875 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Mon, 11 Oct 2021 16:04:12 +0800 Subject: [PATCH 3/6] TEST_MUL_GC FastMulStub host print stackMap Signed-off-by: surpassgoodchao --- ecmascript/compiler/fast_stub.cpp | 110 +++++++++++++++++++++- ecmascript/compiler/fast_stub.h | 14 +++ ecmascript/compiler/fast_stub_define.h | 6 ++ ecmascript/compiler/llvm_codegen.cpp | 10 +- ecmascript/compiler/llvm_codegen.h | 1 - ecmascript/compiler/llvm_ir_builder.cpp | 3 + ecmascript/compiler/llvm_mcjit_engine.cpp | 3 + ecmascript/compiler/llvm_mcjit_engine.h | 2 +- ecmascript/compiler/stub_aot_compiler.cpp | 8 +- ecmascript/compiler/stub_descriptor.cpp | 19 ++++ ecmascript/compiler/tests/stub_tests.cpp | 9 ++ 11 files changed, 176 insertions(+), 9 deletions(-) diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index 56aa55a05d..f6f45a6df5 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -23,6 +23,111 @@ namespace kungfu { using namespace panda::ecmascript; + +#define TEST_MUL_GC 1 +#if TEST_MUL_GC +void FastMulStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + env->GetCircuit()->SetFrameType(FrameType::OPTIMIZED_ENTRY_FRAME); + AddrShift thread = PtrArgument(0); + (void)thread; + AddrShift x = Int64Argument(1); + AddrShift y = Int64Argument(2); + + DEFVARIABLE(intX, MachineType::INT32_TYPE, 0); + DEFVARIABLE(intY, MachineType::INT32_TYPE, 0); + DEFVARIABLE(intZ, MachineType::INT32_TYPE, 0); + DEFVARIABLE(valuePtr, MachineType::INT64_TYPE, 0); + DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); + DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); + Label xIsNumber(env); + Label xNotNumberOryNotNumber(env); + Label xIsNumberAndyIsNumber(env); + Label xIsDoubleAndyIsDouble(env); + Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber); + Bind(&xIsNumber); + { + Label yIsNumber(env); + // if right.IsNumber() + Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber); + Bind(&yIsNumber); + { + Label xIsInt(env); + Label xNotInt(env); + Branch(TaggedIsInt(x), &xIsInt, &xNotInt); + Bind(&xIsInt); + { + intX = TaggedCastToInt32(x); + doubleX = CastInt32ToFloat64(*intX); + Jump(&xIsNumberAndyIsNumber); + } + Bind(&xNotInt); + { + doubleX = TaggedCastToDouble(x); + Jump(&xIsNumberAndyIsNumber); + } + } + } + Bind(&xNotNumberOryNotNumber); + Return(GetHoleConstant()); + Label yIsInt(env); + Label yNotInt(env); + Bind(&xIsNumberAndyIsNumber); + { + Branch(TaggedIsInt(y), &yIsInt, &yNotInt); + Bind(&yIsInt); + { + intY = TaggedCastToInt32(y); + doubleY = CastInt32ToFloat64(*intY); + Jump(&xIsDoubleAndyIsDouble); + } + Bind(&yNotInt); + { + doubleY = TaggedCastToDouble(y); + Jump(&xIsDoubleAndyIsDouble); + } + } + Bind(&xIsDoubleAndyIsDouble); + doubleX = DoubleMul(*doubleX, *doubleY); +//#define TEST_FRAME_TYPE +#ifdef TEST_FRAME_TYPE + StubDescriptor *getStringLen = GET_STUBDESCRIPTOR(GetStringLen); + AddrShift double1 = CallRuntime(getStringLen, thread, GetWord64Constant(FAST_STUB_ID(GetStringLen)), + {thread}); + AddrShift double2 = CallRuntime(getStringLen, thread, GetWord64Constant(FAST_STUB_ID(GetStringLen)), + {thread}); + doubleX = DoubleMul(*doubleX, double1); + doubleX = DoubleMul(*doubleX, double2); +#endif + +#if 1 + StubDescriptor *getStringPtr = GET_STUBDESCRIPTOR(GetStringPtr); + AddrShift ptr1 = CallRuntime(getStringPtr, thread, GetWord64Constant(FAST_STUB_ID(GetStringPtr)), + {thread}); + AddrShift ptr2 = CallRuntime(getStringPtr, thread, GetWord64Constant(FAST_STUB_ID(GetStringPtr)), + {thread}); + (void)ptr2; + + + StubDescriptor *getStringLen = GET_STUBDESCRIPTOR(GetStringLen); + AddrShift double1 = CallRuntime(getStringLen, thread, GetWord64Constant(FAST_STUB_ID(GetStringLen)), + {thread}); + doubleX = DoubleMul(*doubleX, double1); + + valuePtr = Load(INT64_TYPE, ptr1); + + AddrShift value = CastInt64ToFloat64(*valuePtr); + doubleX = DoubleMul(*doubleX, value); + //doubleX = DoubleMul(*doubleX, ptr2); +#endif + + Return(DoubleBuildTagged(*doubleX)); +} + +#else + + void FastArrayLoadElementStub::GenerateCircuit() { auto env = GetEnvironment(); @@ -249,7 +354,7 @@ void FastMulStub::GenerateCircuit() } Bind(&xIsDoubleAndyIsDouble); doubleX = DoubleMul(*doubleX, *doubleY); -//#define TEST_FRAME_TYPE +#define TEST_FRAME_TYPE #ifdef TEST_FRAME_TYPE StubDescriptor *getStringLen = GET_STUBDESCRIPTOR(GetStringLen); AddrShift double1 = CallRuntime(getStringLen, thread, GetWord64Constant(FAST_STUB_ID(GetStringLen)), @@ -260,7 +365,7 @@ void FastMulStub::GenerateCircuit() doubleX = DoubleMul(*doubleX, double2); #endif -#if 1 +#if 0 StubDescriptor *getStringPtr = GET_STUBDESCRIPTOR(GetStringPtr); AddrShift ptr1 = CallRuntime(getStringPtr, thread, GetWord64Constant(FAST_STUB_ID(GetStringPtr)), {thread}); @@ -1197,4 +1302,5 @@ void FastModStub::GenerateCircuit() } } } +#endif } // namespace kungfu \ No newline at end of file diff --git a/ecmascript/compiler/fast_stub.h b/ecmascript/compiler/fast_stub.h index 5ed775366a..362ddd41c4 100644 --- a/ecmascript/compiler/fast_stub.h +++ b/ecmascript/compiler/fast_stub.h @@ -20,6 +20,19 @@ #include "ecmascript/compiler/stub.h" namespace kungfu { +#define TEST_MUL_GC 1 +#if TEST_MUL_GC +class FastMulStub : public Stub { +public: + // 2 : 2 means argument counts + explicit FastMulStub(Circuit *circuit) : Stub("FastMul", 3, circuit) {} + ~FastMulStub() = default; + NO_MOVE_SEMANTIC(FastMulStub); + NO_COPY_SEMANTIC(FastMulStub); + void GenerateCircuit() override; +}; + +#else class FastArrayLoadElementStub : public Stub { public: // 2 : 2 means argument counts @@ -149,5 +162,6 @@ public: NO_COPY_SEMANTIC(FastModStub); void GenerateCircuit() override; }; +#endif } // namespace kungfu #endif // ECMASCRIPT_COMPILER_FASTPATH_STUB_H \ No newline at end of file diff --git a/ecmascript/compiler/fast_stub_define.h b/ecmascript/compiler/fast_stub_define.h index 510ab5bca3..7f774e9846 100644 --- a/ecmascript/compiler/fast_stub_define.h +++ b/ecmascript/compiler/fast_stub_define.h @@ -32,6 +32,11 @@ namespace kungfu { V(GetStringPtr, 1) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define TEST_MUL_GC 1 +#if TEST_MUL_GC +#define FAST_RUNTIME_STUB_LIST(V) \ + V(FastMul, 3) +#else #define FAST_RUNTIME_STUB_LIST(V) \ V(FastAdd, 2) \ V(FastSub, 2) \ @@ -60,6 +65,7 @@ namespace kungfu { V(FindOwnElement2, 6) \ V(GetPropertyByIndex, 3) \ V(SetPropertyByIndex, 4) +#endif #define CALL_STUB_LIST(V) \ FAST_RUNTIME_STUB_LIST(V) \ diff --git a/ecmascript/compiler/llvm_codegen.cpp b/ecmascript/compiler/llvm_codegen.cpp index 77faaaa7d0..9f2c6df1f1 100644 --- a/ecmascript/compiler/llvm_codegen.cpp +++ b/ecmascript/compiler/llvm_codegen.cpp @@ -34,10 +34,6 @@ void LLVMCodeGeneratorImpl::GenerateCodeForStub(Circuit *circuit, const ControlF void LLVMModuleAssembler::AssembleModule() { assembler_.Run(); - uint8_t *ptr = assembler_.GetStackMapsSection(); - std::cout << " AssembleModule " << __LINE__ << std::endl; - LLVMStackMapParser::GetInstance().CalculateStackMap(ptr); - LLVMStackMapParser::GetInstance().Print(); } void LLVMModuleAssembler::CopyAssembleCodeToModule(StubModule *module) @@ -56,8 +52,14 @@ void LLVMModuleAssembler::CopyAssembleCodeToModule(StubModule *module) addr2name[key] = str; } } + LLVMDumpModule(stubmodule_->GetModule()); assembler_.Disassemble(addr2name); + uint8_t *ptr = assembler_.GetStackMapsSection(); + std::cout << " AssembleModule " << __LINE__ << std::endl; + LLVMStackMapParser::GetInstance().CalculateStackMap(ptr); + LLVMStackMapParser::GetInstance().Print(); + auto codeSize = assembler_.GetCodeSize(); MachineCode *code = reinterpret_cast(new char(sizeof(MachineCode) + codeSize)); diff --git a/ecmascript/compiler/llvm_codegen.h b/ecmascript/compiler/llvm_codegen.h index f55463005b..4b056526e4 100644 --- a/ecmascript/compiler/llvm_codegen.h +++ b/ecmascript/compiler/llvm_codegen.h @@ -41,7 +41,6 @@ public: explicit LLVMModuleAssembler(LLVMStubModule *module) : stubmodule_(module), assembler_(module->GetModule()) {} void AssembleModule(); void CopyAssembleCodeToModule(panda::ecmascript::StubModule *module); - private: LLVMStubModule *stubmodule_; LLVMAssembler assembler_; diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 59c195ecb5..323254bf2b 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -45,6 +45,7 @@ LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule }; function_ = LLVMAddFunction(module_, "foo", LLVMFunctionType(LLVMInt32Type(), paramTys, 1, 0)); bbIdMapBb_.clear(); + LLVMSetGC(function_, "statepoint-example"); } LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, @@ -55,6 +56,7 @@ LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule builder_ = LLVMCreateBuilder(); context_ = LLVMGetGlobalContext(); bbIdMapBb_.clear(); + LLVMSetGC(function_, "statepoint-example"); } LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, @@ -66,6 +68,7 @@ LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule builder_ = LLVMCreateBuilder(); context_ = LLVMGetGlobalContext(); bbIdMapBb_.clear(); + LLVMSetGC(function_, "statepoint-example"); } int LLVMIRBuilder::FindBasicBlock(AddrShift gate) const diff --git a/ecmascript/compiler/llvm_mcjit_engine.cpp b/ecmascript/compiler/llvm_mcjit_engine.cpp index 7d00ed89f9..e2cc1f57bb 100644 --- a/ecmascript/compiler/llvm_mcjit_engine.cpp +++ b/ecmascript/compiler/llvm_mcjit_engine.cpp @@ -108,8 +108,11 @@ void LLVMAssembler::BuildAndRunPasses() const LLVMAddConstantPropagationPass(pass); LLVMAddInstructionCombiningPass(pass); llvm::unwrap(pass)->add(llvm::createRewriteStatepointsForGCLegacyPass()); + + LOG_ECMA(INFO) << "Current Module: " << LLVMPrintModuleToString(module_); LLVMRunPassManager(pass, module_); + //LLVMDumpModule(module_); LLVMDisposePassManager(pass); std::cout << "BuildAndRunPasses + " << std::endl; } diff --git a/ecmascript/compiler/llvm_mcjit_engine.h b/ecmascript/compiler/llvm_mcjit_engine.h index 3eaafb206b..2a88503fc0 100644 --- a/ecmascript/compiler/llvm_mcjit_engine.h +++ b/ecmascript/compiler/llvm_mcjit_engine.h @@ -49,7 +49,7 @@ struct CodeInfo { ~CodeInfo() { Reset(); - munmap(machineCode, MAX_MACHINE_CODE_SIZE); + //munmap(machineCode, MAX_MACHINE_CODE_SIZE); } uint8_t *AllocaCodeSection(uintptr_t size, const char *sectionName) { diff --git a/ecmascript/compiler/stub_aot_compiler.cpp b/ecmascript/compiler/stub_aot_compiler.cpp index a455c53e24..2c75243053 100644 --- a/ecmascript/compiler/stub_aot_compiler.cpp +++ b/ecmascript/compiler/stub_aot_compiler.cpp @@ -144,6 +144,12 @@ int main(int argc, char *argv[]) kungfu::StubAotCompiler mouldeBuilder; panda::ecmascript::StubModule stubModule; +#define TEST_MUL_GC 1 +#if TEST_MUL_GC + kungfu::Circuit fastmulCircuit; + kungfu::FastMulStub fastmulStub(&fastmulCircuit); + mouldeBuilder.SetStub(FAST_STUB_ID(FastMul), &fastmulStub); +#else /* Set Stub into module */ kungfu::Circuit fastaddCircuit; kungfu::FastAddStub fastaddStub(&fastaddCircuit); @@ -188,7 +194,7 @@ int main(int argc, char *argv[]) kungfu::Circuit fastSetPropertyByIndexCircuit; kungfu::FastSetPropertyByIndexStub fastSetPropertyByIndexStub(&fastSetPropertyByIndexCircuit); mouldeBuilder.SetStub(FAST_STUB_ID(SetPropertyByIndex), &fastSetPropertyByIndexStub); - +#endif mouldeBuilder.BuildStubModule(&stubModule); stubModule.Save(moduleFilename); exit(0); diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index ec34b32331..49482e4b69 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -27,6 +27,23 @@ namespace kungfu { }; \ void Stub##name##InterfaceDescriptor::Initialize(StubDescriptor *descriptor) +#define TEST_MUL_GC 1 +#if TEST_MUL_GC +CALL_STUB_INIT_DESCRIPTOR(FastMul) +{ + // 2 : 2 input parameters + static StubDescriptor fastMul("FastMul", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + *descriptor = fastMul; + // 2 : 2 input parameters + std::array params = { + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); +} + +#else CALL_STUB_INIT_DESCRIPTOR(FastAdd) { // 2 : 2 input parameters @@ -208,6 +225,7 @@ CALL_STUB_INIT_DESCRIPTOR(SetPropertyByIndex) }; descriptor->SetParameters(params.data()); } +#endif CALL_STUB_INIT_DESCRIPTOR(AddElementInternal) { @@ -361,6 +379,7 @@ CALL_STUB_INIT_DESCRIPTOR(StringGetHashCode) descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); } + void FastStubDescriptors::InitializeStubDescriptors() { // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 6a2f63c03e..92ee4d680c 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -66,6 +66,7 @@ public: LLVMStubModule stubModule{"fast_stub"}; }; +#if 0 HWTEST_F_L0(StubTest, FastLoadElement) { auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); @@ -422,6 +423,7 @@ HWTEST_F_L0(StubTest, FastSubTest) std::cout << "res for FastSub(11, 11) = " << std::dec << resC.GetNumber() << std::endl; } +#if 0 HWTEST_F_L0(StubTest, FastMulTest) { LLVMModuleRef module = LLVMModuleCreateWithName("fast_mul_module"); @@ -478,6 +480,7 @@ HWTEST_F_L0(StubTest, FastMulTest) auto expectedG = FastRuntimeStub::FastMul(JSTaggedValue(x1), JSTaggedValue(y1)); EXPECT_EQ(resG, expectedG); } +#endif HWTEST_F_L0(StubTest, FastDivTest) { @@ -656,6 +659,8 @@ HWTEST_F_L0(StubTest, SetElementStub) assembler.Run(); } +#endif + struct ThreadTy { intptr_t magic; // 0x11223344 intptr_t fp; @@ -791,6 +796,7 @@ LLVMValueRef LLVMCallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder) return frameAddr; } +#define ARK_GC_SUPPORT #ifdef ARK_GC_SUPPORT HWTEST_F_L0(StubTest, JSEntryTest) { @@ -1153,6 +1159,7 @@ void DoSafepoint() } } +#if 0 HWTEST_F_L0(StubTest, FastGetPropertyByIndexStub) { auto module = stubModule.GetModule(); @@ -1270,6 +1277,7 @@ HWTEST_F_L0(StubTest, FastGetPropertyByNameStub) EXPECT_EQ(resVal.GetNumber(), y); } + HWTEST_F_L0(StubTest, FastModTest) { LLVMModuleRef module = LLVMModuleCreateWithName("fast_mod_module"); @@ -1341,4 +1349,5 @@ HWTEST_F_L0(StubTest, FastModTest) std::cout << "result1 for FastMod(7, 'helloworld') = " << result5.GetRawData() << std::endl; EXPECT_EQ(result5, expectRes5); } +#endif } // namespace panda::test -- Gitee From a475520ef8450480c85803cdc1b39b4d32acbde3 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Tue, 12 Oct 2021 10:35:12 +0800 Subject: [PATCH 4/6] use out/ohos-arm-release/clang_x64/tests/unittest/ark/js_runtime/StubTest crash use new llvm --- ecmascript/compiler/llvm_ir_builder.cpp | 17 +++++++++++++++-- ecmascript/compiler/tests/stub_tests.cpp | 1 + js_runtime_config.gni | 2 +- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 36ea4d96f4..e42bb81a97 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -55,6 +55,7 @@ LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule builder_ = LLVMCreateBuilder(); context_ = LLVMGetGlobalContext(); bbIdMapBb_.clear(); + } LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, @@ -838,13 +839,24 @@ void LLVMIRBuilder::VisitLoad(AddrShift gate, MachineRep rep, AddrShift base) co void LLVMIRBuilder::VisitStore(AddrShift gate, MachineRep rep, AddrShift base, AddrShift dataToStore) const { - LOG_ECMA(INFO) << "store base gate:" << base; + //LOG_ECMA(INFO) << "store base gate:" << base; + std::cout << "store base gate: " << std::endl; LLVMValueRef baseAddr = g_values[base]; if (LLVMGetTypeKind(LLVMTypeOf(baseAddr)) == LLVMIntegerTypeKind) { baseAddr = LLVMBuildIntToPtr(builder_, baseAddr, LLVMPointerType(GetMachineRepType(rep), 0), ""); } + LLVMValueRef data = g_values[dataToStore]; + // bug fix + if (LLVMGetTypeKind(LLVMTypeOf(g_values[dataToStore])) == LLVMIntegerTypeKind) { + data = LLVMBuildIntCast(builder_, data, GetMachineRepType(rep), ""); + } baseAddr = LLVMBuildPointerCast(builder_, baseAddr, LLVMPointerType(GetMachineRepType(rep), 0), ""); - LLVMValueRef value = LLVMBuildStore(builder_, g_values[dataToStore], baseAddr); + LLVMDumpValue(baseAddr); + std::cout << std::endl; + LLVMDumpValue(g_values[dataToStore]); + std::cout << std::endl; + + LLVMValueRef value = LLVMBuildStore(builder_, data, baseAddr); g_values[gate] = value; LOG_ECMA(INFO) << "store value:" << value << " " << "value type" << LLVMTypeOf(value); @@ -1079,6 +1091,7 @@ void LLVMIRBuilder::HandleStore(AddrShift gate) std::vector outs = circuit_->GetOutVector(gate); switch (circuit_->GetOpCode(gate)) { case OpCode::INT32_STORE: { + VisitStore(gate, MachineRep::K_WORD32, ins[2], ins[1]); // 2:baseAddr gate, 1:data gate break; } diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 6a2f63c03e..a67e1cf19c 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -48,6 +48,7 @@ public: { TestHelper::CreateEcmaVMWithScope(instance, thread, scope); stubModule.Initialize(); + panda::Logger::SetLevel(panda::Logger::Level::INFO); } void TearDown() override diff --git a/js_runtime_config.gni b/js_runtime_config.gni index ea4700b461..55f7a3e9ff 100644 --- a/js_runtime_config.gni +++ b/js_runtime_config.gni @@ -13,7 +13,7 @@ ark_root = "//ark/runtime_core" js_root = "//ark/js_runtime" -compile_llvm_online = false +compile_llvm_online = true # For OpenHarmony build, always link with the static lib: sdk_libc_secshared_dep = "//utils/native/base:utilsecurec" -- Gitee From 24b850038ba2c04b47a03f79ac27f786dbb507b9 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Tue, 12 Oct 2021 20:30:35 +0800 Subject: [PATCH 5/6] add tests Signed-off-by: surpassgoodchao --- ecmascript/compiler/tests/stub_tests.cpp | 5 +- ecmascript/runtime_trampolines.cpp | 66 ++++++++++++++++++++++++ ecmascript/runtime_trampolines.h | 2 + 3 files changed, 70 insertions(+), 3 deletions(-) diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 2d7f7bf995..884708ceb2 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -66,7 +66,7 @@ public: LLVMStubModule stubModule {"fast_stub", "x86_64-unknown-linux-gnu"}; }; -#if 0 + HWTEST_F_L0(StubTest, FastLoadElement) { auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); @@ -659,7 +659,7 @@ HWTEST_F_L0(StubTest, SetElementStub) assembler.Run(); } -#endif + struct ThreadTy { intptr_t magic; // 0x11223344 @@ -1348,5 +1348,4 @@ HWTEST_F_L0(StubTest, FastModTest) std::cout << "result1 for FastMod(7, 'helloworld') = " << result5.GetRawData() << std::endl; EXPECT_EQ(result5, expectRes5); } -#endif } // namespace panda::test diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index e9592ee8ac..db637abad3 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -38,6 +38,72 @@ bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argRece return JSObject::AddElementInternal(thread, receiver, argIndex, value, attr); } +double RuntimeTrampolines::GetStringLen(uint64_t argThread) +{ + JSTaggedType *fp = nullptr; + GET_CURRETN_FP(fp); + auto thread = reinterpret_cast(argThread); + CallRuntimeTrampolinesScope scope(thread, fp); + auto rbp = reinterpret_cast(fp); + fp = reinterpret_cast(*rbp); + + std::cout << " RuntimeFunc2 rbp:" << rbp << " fp: "<< fp << std::endl; + for (int i = 0; i < 40; i++) { + std::cout << std::hex << &(rbp[i]) << " :" << rbp[i] << std::endl; + } + auto current = thread->GetCurrentSPFrame(); + FrameType type = *(reinterpret_cast( + reinterpret_cast(current) + FrameConst::kFrameType)); + std::cout << "type = " << as_integer(type) << std::endl; + + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle str = factory->NewFromCanBeCompressString("szc"); + // trigger GC + thread->GetEcmaVM()->CollectGarbage(TriggerGCType::COMPRESS_FULL_GC); + thread->GetEcmaVM()->CollectGarbage(TriggerGCType::SEMI_GC); // Trigger GC. + thread->GetEcmaVM()->CollectGarbage(TriggerGCType::HUGE_GC); // Trigger GC. + return static_cast(str->GetLength()); +} + +TaggedObject* RuntimeTrampolines::GetStringPtr(uint64_t argThread) +{ + JSTaggedType *fp = nullptr; + GET_CURRETN_FP(fp); + auto thread = reinterpret_cast(argThread); + CallRuntimeTrampolinesScope scope(thread, fp); + auto rbp = reinterpret_cast(fp); + fp = reinterpret_cast(*rbp); + + std::cout << " RuntimeFunc2 rbp:" << rbp << " fp: "<< fp << std::endl; + for (int i = 0; i < 40; i++) { + std::cout << std::hex << &(rbp[i]) << " :" << rbp[i] << std::endl; + } + auto current = thread->GetCurrentSPFrame(); + FrameType type = *(reinterpret_cast( + reinterpret_cast(current) + FrameConst::kFrameType)); + std::cout << "type = " << as_integer(type) << std::endl; + + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + static int i = 0; + JSHandle str; + if (i == 0) { + str = factory->NewFromCanBeCompressString("szc"); + } else { + str = factory->NewFromCanBeCompressString("1234567890"); + } + i++; + JSHandle value = JSHandle::Cast(str); + // trigger GC + if (i != 1) { + thread->GetEcmaVM()->CollectGarbage(TriggerGCType::COMPRESS_FULL_GC); + thread->GetEcmaVM()->CollectGarbage(TriggerGCType::SEMI_GC); // Trigger GC. + thread->GetEcmaVM()->CollectGarbage(TriggerGCType::HUGE_GC); // Trigger GC. + } + auto ret = value.GetTaggedValue().GetTaggedObject(); + std::cout << "szc tagged object : " << ret << std::endl; + return ret; +} + bool RuntimeTrampolines::CallSetter(uint64_t argThread, uint64_t argSetter, uint64_t argReceiver, uint64_t argValue, bool argMayThrow) { diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index 7d7c286760..ddf7ab83a0 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -48,6 +48,8 @@ public: static uint32_t GetHash32(uint64_t key, uint64_t len); static int32_t FindElementWithCache(uint64_t argThread, uint64_t hClass, uint64_t key, int32_t num); static uint32_t StringGetHashCode(uint64_t ecmaString); + static double GetStringLen(uint64_t argThread); + static TaggedObject* GetStringPtr(uint64_t argThread); }; class CallRuntimeTrampolinesScope { -- Gitee From 9f66dc5b3419c26a8d1a390f453a3eea79ee2137 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Tue, 12 Oct 2021 20:36:40 +0800 Subject: [PATCH 6/6] add test Signed-off-by: surpassgoodchao --- ecmascript/compiler/fast_stub.cpp | 2 +- ecmascript/compiler/fast_stub.h | 2 +- ecmascript/compiler/fast_stub_define.h | 2 +- ecmascript/compiler/stub_aot_compiler.cpp | 2 +- ecmascript/compiler/stub_descriptor.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index 4e2b22617f..7a21138ac3 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -24,7 +24,7 @@ namespace kungfu { using namespace panda::ecmascript; -#define TEST_MUL_GC 1 +#define TEST_MUL_GC 0 #if TEST_MUL_GC void FastMulStub::GenerateCircuit() { diff --git a/ecmascript/compiler/fast_stub.h b/ecmascript/compiler/fast_stub.h index 614b778fd0..7773bfe915 100644 --- a/ecmascript/compiler/fast_stub.h +++ b/ecmascript/compiler/fast_stub.h @@ -20,7 +20,7 @@ #include "ecmascript/compiler/stub.h" namespace kungfu { -#define TEST_MUL_GC 1 +#define TEST_MUL_GC 0 #if TEST_MUL_GC class FastMulStub : public Stub { public: diff --git a/ecmascript/compiler/fast_stub_define.h b/ecmascript/compiler/fast_stub_define.h index 7f774e9846..04f027a33b 100644 --- a/ecmascript/compiler/fast_stub_define.h +++ b/ecmascript/compiler/fast_stub_define.h @@ -32,7 +32,7 @@ namespace kungfu { V(GetStringPtr, 1) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define TEST_MUL_GC 1 +#define TEST_MUL_GC 0 #if TEST_MUL_GC #define FAST_RUNTIME_STUB_LIST(V) \ V(FastMul, 3) diff --git a/ecmascript/compiler/stub_aot_compiler.cpp b/ecmascript/compiler/stub_aot_compiler.cpp index 7216647b80..d7ab7e4825 100644 --- a/ecmascript/compiler/stub_aot_compiler.cpp +++ b/ecmascript/compiler/stub_aot_compiler.cpp @@ -177,7 +177,7 @@ int main(const int argc, const char **argv) SET_ALL_STUB_TO_MODEULE(mouldeBuilder); panda::ecmascript::StubModule stubModule; -#define TEST_MUL_GC 1 +#define TEST_MUL_GC 0 #if TEST_MUL_GC kungfu::Circuit fastmulCircuit; kungfu::FastMulStub fastmulStub(&fastmulCircuit); diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index 49482e4b69..b4b0bb5d4a 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -27,7 +27,7 @@ namespace kungfu { }; \ void Stub##name##InterfaceDescriptor::Initialize(StubDescriptor *descriptor) -#define TEST_MUL_GC 1 +#define TEST_MUL_GC 0 #if TEST_MUL_GC CALL_STUB_INIT_DESCRIPTOR(FastMul) { -- Gitee