diff --git a/BUILD.gn b/BUILD.gn index 0f8e7fe84d7bd8d9216411a4bd284f2846d65196..19c96042b6c3afbb83d4797620dc3ba338f9cc0e 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -34,9 +34,6 @@ group("ark_js_host_linux_tools_packages") { #"//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer(${host_toolchain})", ] - if (current_cpu == "x86_64" || current_cpu == "x64") { - deps += [ "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer(${host_toolchain})" ] - } } } @@ -69,10 +66,8 @@ group("ark_js_host_unittest") { "//ark/js_runtime/ecmascript/snapshot/tests:host_unittest", "//ark/js_runtime/ecmascript/tests:host_unittest", "//ark/js_runtime/ecmascript/tooling/test:host_unittest", + "//ark/js_runtime/ecmascript/compiler/tests:host_unittest", ] - if (current_cpu == "x86_64" || current_cpu == "x64") { - deps += [ "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer(${host_toolchain})" ] - } # js bytecode test deps += [ "//ark/js_runtime/test/moduletest:ark_js_moduletest" ] diff --git a/ecmascript/compiler/llvm/BUILD.gn b/ecmascript/compiler/llvm/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..19e90e0383a8174b11d5db49e22a741ca753d20c --- /dev/null +++ b/ecmascript/compiler/llvm/BUILD.gn @@ -0,0 +1,25 @@ +# 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" +} \ No newline at end of file diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b8327747df2cdbcb4b05e257a3842470f46cf7d3 --- /dev/null +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp @@ -0,0 +1,159 @@ +/* + * 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. + */ + +#include "ecmascript/compiler/llvm_stackmap_parser.h" +#include +#include +#include + +namespace kungfu { +std::string LocationTy::TypeToString(Kind location) const +{ + switch (location) { + case Kind::REGISTER: + return "Register Reg Value in a register"; + case Kind::DIRECT: + return "Direct Reg + Offset Frame index value"; + case Kind::INDIRECT: + return "Indirect [Reg + Offset] Spilled value"; + case Kind::CONSTANT: + return "Constant Offset Small constant"; + case Kind::CONSTANTNDEX: + return "ConstIndex constants[Offset] Large constant"; + default: + return "no know location"; + } +} + +bool LLVMStackMapParser::StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetTypeVector &infos) +{ + bool found = false; + for (auto it: callSiteInfos_) { + if (it.first == funcAddr) { + DwarfRegAndOffsetType info = it.second; + infos.push_back(info); + found true; + } + } + return found; +} + +bool StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t frameFp, + std::vector &slotAddrs) +{ + DwarfRegAndOffsetTypeVector infos; + if (StackMapByAddr(funcAddr, infos) == false) { + return false; + } +#ifdef PANDA_TARGET_AMD64 + uintptr_t *rbp = reinterpret_cast(frameFp); + uintptr_t returnAddr = *(rbp + 1); + uintptr_t *rsp = rbp + 2; + 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)); + } +#endif + return true; +} + +void LLVMStackMapParser::CalcCallSite() +{ + uint64_t recordNum = 0; + for (size_t i = 0; i < llvmStackMap_.StkSizeRecords.size(); i++) { + uintptr_t address = llvmStackMap_.StkSizeRecords[i].functionAddress; + std::cout << std::hex << "address " << address << std::endl; + uint64_t recordCount = llvmStackMap_.StkSizeRecords[i].recordCount; + std::cout << std::hex << "recordCount " << recordCount << std::endl; + recordNum += recordCount; + std::cout << std::hex << "recordNum " << recordNum << std::endl; + struct StkMapRecordHeadTy recordHead = llvmStackMap_.StkMapRecord[recordNum - 1].head; + uint32_t instructionOffset = recordHead.InstructionOffset; + std::cout << std::hex << "instructionOffset " << instructionOffset << std::endl; + uintptr_t callsite = address + instructionOffset; + + for (int j = 0; j < recordHead.NumLocations; j++) { + struct LocationTy loc = llvmStackMap_.StkMapRecord[recordNum - 1].Locations[j]; + if (loc.location == LocationTy::Kind::INDIRECT) { + DwarfRegAndOffsetType info(loc.DwarfRegNum, loc.OffsetOrSmallConstant); + Fun2InfoType callSiteInfo {callsite, info}; + callSiteInfos_.push_back(callSiteInfo); + } + } + } +} + +bool LLVMStackMapParser::CalculateStackMap(const uint8_t *stackMapAddr) +{ + stackMapAddr_ = stackMapAddr; + if (!stackMapAddr_) { + std::cerr << "stackMapAddr_ nullptr error ! " << std::endl; + return false; + } + dataInfo_ = std::make_unique(stackMapAddr_); + llvmStackMap_.head = dataInfo_->Read(); + uint32_t numFunctions, numConstants, numRecords; + numFunctions = dataInfo_->Read(); + numConstants = dataInfo_->Read(); + numRecords = dataInfo_->Read(); + for (uint32_t i = 0; i < numFunctions; i++) { + auto stkRecord = dataInfo_->Read(); + llvmStackMap_.StkSizeRecords.push_back(stkRecord); + } + for (uint32_t i = 0; i < numConstants; i++) { + auto val = dataInfo_->Read(); + llvmStackMap_.Constants.push_back(val); + } + for (uint32_t i = 0; i < numRecords; i++) { + struct StkMapRecordTy stkSizeRecord; + auto head = dataInfo_->Read(); + stkSizeRecord.head = head; + for (uint16_t j = 0; j < head.NumLocations; j++) { + auto location = dataInfo_->Read(); + stkSizeRecord.Locations.push_back(location); + } + uint16_t padding; + while (dataInfo_->GetOffset() & 7) { // 7: 8 byte align + padding = dataInfo_->Read(); + } + uint32_t numLiveOuts = dataInfo_->Read(); + if (numLiveOuts > 0) { + for (uint32_t j = 0; j < numLiveOuts; j++) { + auto liveOut = dataInfo_->Read(); + stkSizeRecord.LiveOuts.push_back(liveOut); + } + } + while (dataInfo_->GetOffset() & 7) { // 7: 8 byte align + padding = dataInfo_->Read(); + } + llvmStackMap_.StkMapRecord.push_back(stkSizeRecord); + } + CalcCallSite(); + return true; +} +} // namespace kungfu \ No newline at end of file diff --git a/ecmascript/compiler/llvm_stackmap_parse.h b/ecmascript/compiler/llvm/llvm_stackmap_parser.h similarity index 90% rename from ecmascript/compiler/llvm_stackmap_parse.h rename to ecmascript/compiler/llvm/llvm_stackmap_parser.h index 17204129db3881cacc565a950921b9b7ab5b632f..a38b69a42a4bcd1f6aaa2240e9c1b52e818c4f1c 100644 --- a/ecmascript/compiler/llvm_stackmap_parse.h +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.h @@ -23,6 +23,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 { @@ -175,11 +176,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); @@ -187,15 +188,17 @@ public: { llvmStackMap_.Print(); } - bool StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetType &info); + bool StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetTypeVector &info); + 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 22fa5a9adb66fb4d6652e2aeaae98271d045fca6..08f9b254c28a47ef7a6e2190b4504ff76874874d 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -15,6 +15,8 @@ #include "ecmascript/compiler/llvm_ir_builder.h" +#include +#include #include #include "ecmascript/compiler/circuit.h" @@ -23,8 +25,6 @@ #include "ecmascript/compiler/stub_interface.h" #include "ecmascript/js_array.h" #include "ecmascript/js_thread.h" -#include "llvm/IR/Instructions.h" -#include "llvm/Support/Host.h" #include "llvm_mcjit_compiler.h" #include "securec.h" #include "utils/logger.h" diff --git a/ecmascript/compiler/llvm_ir_builder.h b/ecmascript/compiler/llvm_ir_builder.h index ca6f1dd0850a2d3d987952b4526fe0dc7edb4ff9..35bc899714c27772c83f674c9a25089a4c824928 100644 --- a/ecmascript/compiler/llvm_ir_builder.h +++ b/ecmascript/compiler/llvm_ir_builder.h @@ -145,7 +145,7 @@ private: void VisitCastIntToDouble(AddrShift gate, AddrShift e1) const; void VisitCastDoubleToInt(AddrShift gate, AddrShift e1) const; void VisitCastInt64ToPointer(AddrShift gate, AddrShift e1) const; - +ssss BasicBlock *EnsurBasicBlock(int id); LLVMValueRef LLVMCallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder); void PrologueHandle(LLVMModuleRef &module, LLVMBuilderRef &builder); diff --git a/ecmascript/compiler/llvm_stackmap_parse.cpp b/ecmascript/compiler/llvm_stackmap_parse.cpp index e49ed47e66b5370bfebfda2ef42d32b6d604c164..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/ecmascript/compiler/llvm_stackmap_parse.cpp +++ b/ecmascript/compiler/llvm_stackmap_parse.cpp @@ -1,125 +0,0 @@ -/* - * 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. - */ - -#include "ecmascript/compiler/llvm_stackmap_parse.h" -#include -#include -#include - -namespace kungfu { -std::string LocationTy::TypeToString(Kind location) const -{ - switch (location) { - case Kind::REGISTER: - return "Register Reg Value in a register"; - case Kind::DIRECT: - return "Direct Reg + Offset Frame index value"; - case Kind::INDIRECT: - return "Indirect [Reg + Offset] Spilled value"; - case Kind::CONSTANT: - return "Constant Offset Small constant"; - case Kind::CONSTANTNDEX: - return "ConstIndex constants[Offset] Large constant"; - default: - return "no know location"; - } -} - -bool LLVMStackMapParse::StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetType &info) -{ - for (auto it: callSiteInfos_) { - if (it.first == funcAddr) { - info = it.second; - return true; - } - } - return false; -} - -void LLVMStackMapParse::CalcCallSite() -{ - uint64_t recordNum = 0; - for (size_t i = 0; i < llvmStackMap_.StkSizeRecords.size(); i++) { - uintptr_t address = llvmStackMap_.StkSizeRecords[i].functionAddress; - std::cout << std::hex << "address " << address << std::endl; - uint64_t recordCount = llvmStackMap_.StkSizeRecords[i].recordCount; - std::cout << std::hex << "recordCount " << recordCount << std::endl; - recordNum += recordCount; - std::cout << std::hex << "recordNum " << recordNum << std::endl; - struct StkMapRecordHeadTy recordHead = llvmStackMap_.StkMapRecord[recordNum - 1].head; - uint32_t instructionOffset = recordHead.InstructionOffset; - std::cout << std::hex << "instructionOffset " << instructionOffset << std::endl; - uintptr_t callsite = address + instructionOffset; - - for (int j = 0; j < recordHead.NumLocations; j++) { - struct LocationTy loc = llvmStackMap_.StkMapRecord[recordNum - 1].Locations[j]; - if (loc.location == LocationTy::Kind::INDIRECT) { - DwarfRegAndOffsetType info(loc.DwarfRegNum, loc.OffsetOrSmallConstant); - Fun2InfoType callSiteInfo {callsite, info}; - callSiteInfos_.push_back(callSiteInfo); - } - } - } -} - -bool LLVMStackMapParse::CalculateStackMap(const uint8_t *stackMapAddr) -{ - stackMapAddr_ = stackMapAddr; - if (!stackMapAddr_) { - std::cerr << "stackMapAddr_ nullptr error ! " << std::endl; - return false; - } - dataInfo_ = std::make_unique(stackMapAddr_); - llvmStackMap_.head = dataInfo_->Read(); - uint32_t numFunctions, numConstants, numRecords; - numFunctions = dataInfo_->Read(); - numConstants = dataInfo_->Read(); - numRecords = dataInfo_->Read(); - for (uint32_t i = 0; i < numFunctions; i++) { - auto stkRecord = dataInfo_->Read(); - llvmStackMap_.StkSizeRecords.push_back(stkRecord); - } - for (uint32_t i = 0; i < numConstants; i++) { - auto val = dataInfo_->Read(); - llvmStackMap_.Constants.push_back(val); - } - for (uint32_t i = 0; i < numRecords; i++) { - struct StkMapRecordTy stkSizeRecord; - auto head = dataInfo_->Read(); - stkSizeRecord.head = head; - for (uint16_t j = 0; j < head.NumLocations; j++) { - auto location = dataInfo_->Read(); - stkSizeRecord.Locations.push_back(location); - } - uint16_t padding; - while (dataInfo_->GetOffset() & 7) { // 7: 8 byte align - padding = dataInfo_->Read(); - } - uint32_t numLiveOuts = dataInfo_->Read(); - if (numLiveOuts > 0) { - for (uint32_t j = 0; j < numLiveOuts; j++) { - auto liveOut = dataInfo_->Read(); - stkSizeRecord.LiveOuts.push_back(liveOut); - } - } - while (dataInfo_->GetOffset() & 7) { // 7: 8 byte align - padding = dataInfo_->Read(); - } - llvmStackMap_.StkMapRecord.push_back(stkSizeRecord); - } - CalcCallSite(); - return true; -} -} // namespace kungfu \ No newline at end of file diff --git a/ecmascript/compiler/tests/BUILD.gn b/ecmascript/compiler/tests/BUILD.gn index 4c5845aa3025328a6219ff332c785aca740ed35e..57ba5cd6578d5ff9e5782c97f45ed5632fd584b2 100644 --- a/ecmascript/compiler/tests/BUILD.gn +++ b/ecmascript/compiler/tests/BUILD.gn @@ -164,7 +164,9 @@ host_unittest_action("StubOptimizerTest") { "$ark_root/libpandabase:libarkbase", "$ark_root/runtime:libarkruntime", "//ark/js_runtime:libark_jsruntime_test", - "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer(${host_toolchain})", + #"//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer(${host_toolchain})", + "//ark/js_runtime/ecmascript/compiler:libark_jsoptimize", + "//third_party/googletest:gtest_main", sdk_libc_secshared_dep, ] } diff --git a/ecmascript/compiler/tests/stub_optimizer_tests.cpp b/ecmascript/compiler/tests/stub_optimizer_tests.cpp index 165e90c9a1b77a86d70770f786f1da9590f776e5..85dae60836f7f038e0a06d8c36165044f29665a5 100644 --- a/ecmascript/compiler/tests/stub_optimizer_tests.cpp +++ b/ecmascript/compiler/tests/stub_optimizer_tests.cpp @@ -1849,8 +1849,8 @@ HWTEST_F_L0(StubOptimizerTest, LoadGCIRTest) auto *mainPtr = reinterpret_cast(LLVMGetPointerToGlobal(engine, function)); uint8_t *ptr = compiler.GetStackMapsSection(); - LLVMStackMapParse::GetInstance().CalculateStackMap(ptr); - LLVMStackMapParse::GetInstance().Print(); + LLVMStackMapParser::GetInstance().CalculateStackMap(ptr); + LLVMStackMapParser::GetInstance().Print(); compiler.Disassemble(); LLVMDumpModule(module); @@ -1861,24 +1861,28 @@ extern "C" { void DoSafepoint() { uintptr_t *rbp; +#ifdef PANDA_TARGET_AMD64 asm("mov %%rbp, %0" : "=rm" (rbp)); +#endif for (int i = 0; i < 3; i++) { uintptr_t returnAddr = *(rbp + 1); uintptr_t *rsp = rbp + 2; rbp = reinterpret_cast(*rbp); - DwarfRegAndOffsetType info; - bool found = LLVMStackMapParse::GetInstance().StackMapByAddr(returnAddr, info); + DwarfRegAndOffsetTypeVector infos; + bool found = LLVMStackMapParser::GetInstance().StackMapByAddr(returnAddr, info); if (found) { - uintptr_t **address = nullptr; - if (info.first == 7) { - address = reinterpret_cast(reinterpret_cast(rsp) + info.second); - // rbp - } else if (info.first == 6) { - address = reinterpret_cast(reinterpret_cast(rbp) + info.second); + for (auto &info: infos) { + uintptr_t **address = nullptr; + if (info.first == 7) { + address = reinterpret_cast(reinterpret_cast(rsp) + info.second); + // rbp + } else if (info.first == 6) { + 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 dc5c0022865afcd0c0ac708b802e7959a959027a..63818d8c829d73e35655f1e34da819e67f58d771 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -16,6 +16,8 @@ #ifndef ECMASCRIPT_FRAMES_H #define ECMASCRIPT_FRAMES_H +#include "ecmascript/js_thread.h" + namespace panda::ecmascript { enum class FrameType: unsigned int { OPTIMIZED_FRAME = 0, @@ -36,7 +38,7 @@ public: uint64_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc }; -class LLVMBoundaryFrameState { +class LLVMOptimizedEntryFrameState { public: uint64_t *threadFp; // for gc FrameStateBase base; @@ -50,5 +52,27 @@ public: static constexpr int kPreOffset = -kSystemPointerSize; static constexpr int kFrameType = -2 * kSystemPointerSize; }; + +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() <fp:" << thread_->GetCurrentSPFrame() << std::endl; + thread_->SetCurrentSPFrame(oldRbp_); + } +private: + JSTaggedType *oldRbp_; + JSThread *thread_; +}; + } // 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 e321181c29b25910e4fcaec2e4a55f7475ca0b53..fee741c7564e06fe9ff803279ce96a301d9dbdfb 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -18,6 +18,7 @@ #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) @@ -48,7 +49,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 @@ -56,7 +57,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 @@ -86,7 +87,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); @@ -156,14 +157,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) { @@ -174,7 +175,6 @@ void EcmaFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1 v0(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&state->profileTypeInfo))); } } - current = state->prev; } } @@ -198,4 +198,46 @@ void EcmaFrameHandler::DumpPC(std::ostream &os, const uint8_t *pc) const int offset = pc - JSMethod::Cast(frameHandler.GetMethod())->GetBytecodeArray(); os << "offset: " << offset << "\n"; } + +void LLVMOptimizedFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const +{ + 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 false; + } + for (auto &address: slotAddrs) { + v0(Root::ROOT_FRAME, ObjectSlot(address)); + } + } +} + +void LLVMOptimizedEntryFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const +{ + 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 false; + } + for (auto &address: slotAddrs) { + v0(Root::ROOT_FRAME, ObjectSlot(address)); + } + } +} + + } // namespace panda::ecmascript diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index ad82f3723649049c2155188d8baf6354f9aeff11..4b11c118370e8a4b85501aa7bd047f6588a92c65 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -68,6 +68,27 @@ public: private: JSTaggedType *sp_{nullptr}; }; -} // namespace ecmascript + +class LLVMOptimizedFrameHandler { +public: + explicit LLVMOptimizedFrameHandler(JSTaggedType *fp) : fp_(fp) {} + explicit LLVMOptimizedFrameHandler(const JSThread *thread); + ~LLVMOptimizedFrameHandler() = default; + void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; +private: + JSTaggedType *fp_{nullptr}; +}; + +class LLVMOptimizedEntryFrameHandler { +public: + explicit LLVMOptimizedEntryFrameHandler(JSTaggedType *fp) : fp_(fp) {} + explicit LLVMOptimizedEntryFrameHandler(const JSThread *thread); + ~LLVMOptimizedEntryFrameHandler() = default; + 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 e0200af99896c07bd0241fa827e58966764f943e..064ae30d52c600adbae767cd603c7aea08e088ca 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -227,7 +227,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; @@ -259,7 +260,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; @@ -298,7 +300,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(); @@ -336,7 +339,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 @@ -366,7 +370,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 @@ -397,7 +402,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(); @@ -426,7 +432,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); @@ -436,7 +443,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) @@ -766,7 +773,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; @@ -845,7 +853,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; @@ -871,7 +880,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; @@ -895,7 +904,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; @@ -1994,7 +2003,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; @@ -3086,7 +3095,8 @@ void EcmaInterpreter::InitStackFrame(JSThread *thread) state->acc = JSTaggedValue::Hole(); state->constpool = nullptr; state->profileTypeInfo = JSTaggedValue::Undefined(); - state->prev = nullptr; + state->base.prev = nullptr; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; state->numActualArgs = 0; } diff --git a/ecmascript/interpreter/interpreter.h b/ecmascript/interpreter/interpreter.h index ab6ecb8f6d96ec9dacd035d1a4a9e8e8af1aeb46..f7a4985e0dab7a94736a5164db5aaf14a233ecd7 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; + FrameStateBase base; }; // NOLINTNEXTLINE(bugprone-sizeof-expression) diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index f2352867b9ef8d99579a91b8946df96b78b13597..99d09930a740524349b65a4af3452b2048551eae 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -91,6 +91,27 @@ void JSThread::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) globalConst_.Visitor(v1); // visit stack roots EcmaFrameHandler(currentFrame_).Iterate(v0, v1); + JSTaggedType *current = currentFrame_; + while (current) { + FrameType type = *(reinterpret_cast(current) + FrameConst::kFrameType); + std::cout << "szc type:" << as_integer(type) << std::endl; + if (type == FrameTpe::INTERPRETER_FRAME) { + FrameState *state = reinterpret_cast(current) - 1; + EcmaFrameHandler(current).Iterate(v0, v1); + current = state->prev; + } else if (type == FrameTpe::OPTIMIZED_FRAME) { + FrameStateBase *state = reinterpret_cast(current); + LVMOptimizedFrameHandler(current).Iterate(v0, v1); + current = state->prev; + abort(); + } else { + LLVMOptimizedEntryFrameState *state = reinterpret_cast(current); + LVMOptimizedFrameHandler(current).Iterate(v0, v1); + current = state->prev; + abort(); + } + } + // visit internal call params internalCallParams_->Iterate(v1); diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index 1df5a198186c68b9a6e5f7a2ce098d74a0067d78..64eff77eeade3892a7aa16ef560c75fb667373b7 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/message_string.h" #include "ecmascript/object_factory.h" @@ -25,7 +26,12 @@ namespace panda::ecmascript { bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argReceiver, uint32_t argIndex, uint64_t argValue, uint32_t argAttr) { + JSTaggedType *fp; +#ifdef PANDA_TARGET_AMD64 + asm("mov %%fp, %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))); diff --git a/ecmascript/tests/test_helper.h b/ecmascript/tests/test_helper.h index 4a5a202f9e68100756d2e562ddf55cec6a6bdd4c..9414bef3ee162e9dfc431067e09f38b11f9ee7fe 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; + breakState->base.prev = currentSp; + breakState->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; state->pc = nullptr; state->sp = newSp; state->method = thread->GetEcmaVM()->GetMethodForNativeFunction(nullptr);