mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-27 04:00:37 +00:00
Implement __llvm_deoptimize to void relocate deopt hander
1.implement __llvm_deoptimize in Aot module, __llvm_deoptimize funciton is to call runtime function 2.add asm bridge frame to avoid unnecessary fpdelta calculation Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I6NSFQ?from=project-issue Signed-off-by: zhangyukun8 <zhangyukun8@huawei.com> Change-Id: Ibb559ae877633c63fd8cc7efee5770ba88597f9c
This commit is contained in:
parent
26bdac03bf
commit
ff796ce366
1
BUILD.gn
1
BUILD.gn
@ -525,7 +525,6 @@ ecma_source = [
|
||||
"ecmascript/date_parse.cpp",
|
||||
"ecmascript/deoptimizer/calleeReg.cpp",
|
||||
"ecmascript/deoptimizer/deoptimizer.cpp",
|
||||
"ecmascript/deoptimizer/relocator.cpp",
|
||||
"ecmascript/dfx/stackinfo/js_stackinfo.cpp",
|
||||
"ecmascript/dfx/vmstat/caller_stat.cpp",
|
||||
"ecmascript/dfx/vmstat/opt_code_profiler.cpp",
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "ecmascript/compiler/common_stubs.h"
|
||||
#include "ecmascript/compiler/compiler_log.h"
|
||||
#include "ecmascript/deoptimizer/deoptimizer.h"
|
||||
#include "ecmascript/deoptimizer/relocator.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/message_string.h"
|
||||
#include "ecmascript/jspandafile/constpool_value.h"
|
||||
@ -277,41 +276,6 @@ void AnFileInfo::Save(const std::string &filename, kungfu::Triple triple)
|
||||
file.close();
|
||||
}
|
||||
|
||||
|
||||
void AnFileInfo::RewriteRelcateDeoptHandler([[maybe_unused]] EcmaVM *vm)
|
||||
{
|
||||
#if !WIN_OR_MAC_OR_IOS_PLATFORM
|
||||
JSThread *thread = vm->GetJSThread();
|
||||
uintptr_t patchAddr = thread->GetRTInterface(RTSTUB_ID(DeoptHandlerAsm));
|
||||
RewriteRelcateTextSection(LLVM_DEOPT_RELOCATE_SYMBOL, patchAddr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AnFileInfo::RewriteRelcateTextSection([[maybe_unused]] const char* symbol,
|
||||
[[maybe_unused]] uintptr_t patchAddr)
|
||||
{
|
||||
#if !WIN_OR_MAC_OR_IOS_PLATFORM
|
||||
for (auto &des: des_) {
|
||||
uint32_t relaTextSize = des.GetSecSize(ElfSecName::RELATEXT);
|
||||
if (relaTextSize != 0) {
|
||||
uint64_t relatextAddr = des.GetSecAddr(ElfSecName::RELATEXT);
|
||||
uint64_t textAddr = des.GetSecAddr(ElfSecName::TEXT);
|
||||
uint64_t symTabAddr = des.GetSecAddr(ElfSecName::SYMTAB);
|
||||
uint32_t symTabSize = des.GetSecSize(ElfSecName::SYMTAB);
|
||||
uint32_t strTabSize = des.GetSecSize(ElfSecName::STRTAB);
|
||||
uint64_t strTabAddr = des.GetSecAddr(ElfSecName::STRTAB);
|
||||
RelocateTextInfo relaText = {textAddr, relatextAddr, relaTextSize};
|
||||
SymAndStrTabInfo symAndStrTabInfo = {symTabAddr, symTabSize, strTabAddr, strTabSize};
|
||||
Relocator relocate(relaText, symAndStrTabInfo);
|
||||
#ifndef NDEBUG
|
||||
relocate.DumpRelocateText();
|
||||
#endif
|
||||
relocate.RelocateBySymbol(symbol, patchAddr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool AnFileInfo::Load(const std::string &filename)
|
||||
{
|
||||
std::string realPath;
|
||||
@ -432,7 +396,7 @@ void AOTFileManager::LoadStubFile(const std::string &fileName)
|
||||
void AOTFileManager::LoadAnFile(const std::string &fileName)
|
||||
{
|
||||
AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
|
||||
if (!anFileDataManager->SafeLoad(fileName, AnFileDataManager::Type::AOT, vm_)) {
|
||||
if (!anFileDataManager->SafeLoad(fileName, AnFileDataManager::Type::AOT)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -867,7 +831,7 @@ void AnFileDataManager::SafeDestoryAllData()
|
||||
loadedAn_.clear();
|
||||
}
|
||||
|
||||
bool AnFileDataManager::SafeLoad(const std::string &fileName, Type type, EcmaVM* vm)
|
||||
bool AnFileDataManager::SafeLoad(const std::string &fileName, Type type)
|
||||
{
|
||||
os::memory::WriteLockHolder lock(lock_);
|
||||
if (type == Type::STUB) {
|
||||
@ -880,7 +844,7 @@ bool AnFileDataManager::SafeLoad(const std::string &fileName, Type type, EcmaVM*
|
||||
if (aotFileInfo != nullptr) {
|
||||
return true;
|
||||
}
|
||||
return UnsafeLoadFromAOT(fileName, vm);
|
||||
return UnsafeLoadFromAOT(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -915,7 +879,7 @@ void AnFileDataManager::Dump() const
|
||||
}
|
||||
}
|
||||
|
||||
bool AnFileDataManager::UnsafeLoadFromAOT(const std::string &fileName, EcmaVM *vm)
|
||||
bool AnFileDataManager::UnsafeLoadFromAOT(const std::string &fileName)
|
||||
{
|
||||
// note: This method is not thread-safe
|
||||
// need to ensure that the instance of AnFileDataManager has been locked before use
|
||||
@ -923,7 +887,6 @@ bool AnFileDataManager::UnsafeLoadFromAOT(const std::string &fileName, EcmaVM *v
|
||||
if (!info->Load(fileName)) {
|
||||
return false;
|
||||
}
|
||||
info->RewriteRelcateDeoptHandler(vm);
|
||||
std::string anBasename = JSFilePath::GetBaseName(fileName);
|
||||
anFileNameToIndexMap_.insert({anBasename, loadedAn_.size()});
|
||||
loadedAn_.emplace_back(info);
|
||||
|
@ -378,8 +378,6 @@ public:
|
||||
|
||||
void Dump() const;
|
||||
|
||||
void RewriteRelcateDeoptHandler(EcmaVM *vm);
|
||||
|
||||
private:
|
||||
bool Load(const std::string &filename);
|
||||
void RewriteRelcateTextSection(const char* symbol, uintptr_t patchAddr);
|
||||
@ -473,7 +471,7 @@ public:
|
||||
static AnFileDataManager *GetInstance();
|
||||
~AnFileDataManager();
|
||||
|
||||
bool SafeLoad(const std::string &fileName, Type type, EcmaVM *vm = nullptr);
|
||||
bool SafeLoad(const std::string &fileName, Type type);
|
||||
uint32_t SafeGetFileInfoIndex(const std::string &fileName);
|
||||
std::shared_ptr<AnFileInfo> SafeGetAnFileInfo(uint32_t index);
|
||||
std::shared_ptr<StubFileInfo> SafeGetStubFileInfo();
|
||||
@ -509,7 +507,7 @@ public:
|
||||
public:
|
||||
AnFileDataManager() = default;
|
||||
std::shared_ptr<AnFileInfo> UnsafeFind(const std::string &fileName) const;
|
||||
bool UnsafeLoadFromAOT(const std::string &fileName, EcmaVM *vm);
|
||||
bool UnsafeLoadFromAOT(const std::string &fileName);
|
||||
bool UnsafeLoadFromStub();
|
||||
|
||||
os::memory::RWLock lock_;
|
||||
@ -562,12 +560,6 @@ public:
|
||||
void DumpAOTInfo() const DUMP_API_ATTR;
|
||||
|
||||
private:
|
||||
|
||||
void RewriteRelcateDeoptHandler(EcmaVM *vm, AnFileInfo AOTFileInfo)
|
||||
{
|
||||
AOTFileInfo.RewriteRelcateDeoptHandler(vm);
|
||||
}
|
||||
|
||||
void PrintAOTEntry(const JSPandaFile *file, const Method *method, uintptr_t entry);
|
||||
void InitializeStubEntries(const std::vector<AnFileInfo::FuncEntryDes>& stubs);
|
||||
void AdjustBCStubAndDebuggerStubEntries(JSThread *thread, const std::vector<AOTFileInfo::FuncEntryDes> &stubs,
|
||||
|
@ -1702,11 +1702,12 @@ DEF_CALL_SIGNATURE(CreateArrayFromList)
|
||||
DEF_CALL_SIGNATURE(DeoptHandlerAsm)
|
||||
{
|
||||
// 1 : 1 input parameters
|
||||
CallSignature deoptHandlerAsm("DeoptHandlerAsm", 0, 1,
|
||||
CallSignature deoptHandlerAsm("DeoptHandlerAsm", 0, 2,
|
||||
ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
|
||||
*callSign = deoptHandlerAsm;
|
||||
std::array<VariableType, 1> params = { // 1 : 1 input parameters
|
||||
std::array<VariableType, 2> params = { // 2 : 2 input parameters
|
||||
VariableType::NATIVE_POINTER(), // glue
|
||||
VariableType::NATIVE_POINTER(), // deoptType
|
||||
};
|
||||
callSign->SetVariadicArgs(false);
|
||||
callSign->SetParameters(params.data());
|
||||
|
@ -310,7 +310,8 @@ GateRef CircuitBuilder::TypedCallOperator(GateRef hirGate, MachineType type, con
|
||||
{
|
||||
ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
|
||||
auto numValueIn = args.size() - 2; // 2: state & depend
|
||||
uint64_t pcOffset = acc_.GetPcOffset(hirGate);
|
||||
uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
|
||||
ASSERT(pcOffset != 0);
|
||||
return GetCircuit()->NewGate(circuit_->TypedCall(numValueIn, pcOffset), type, args, GateType::AnyType());
|
||||
}
|
||||
|
||||
@ -556,7 +557,7 @@ GateRef CircuitBuilder::Call(const CallSignature* cs, GateRef glue, GateRef targ
|
||||
inputs.insert(inputs.end(), args.begin(), args.end());
|
||||
auto numValuesIn = args.size() + 2; // 2: target & glue
|
||||
if (GetCircuit()->IsOptimizedJSFunctionFrame() && hirGate != Circuit::NullGate()) {
|
||||
GateRef pcOffset = Int64(acc_.GetPcOffset(hirGate));
|
||||
GateRef pcOffset = Int64(acc_.TryGetPcOffset(hirGate));
|
||||
inputs.emplace_back(pcOffset);
|
||||
numValuesIn += 1;
|
||||
}
|
||||
@ -680,7 +681,8 @@ GateRef CircuitBuilder::Construct(GateRef hirGate, std::vector<GateRef> args)
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
uint64_t bitfield = args.size();
|
||||
uint64_t pcOffset = acc_.GetPcOffset(hirGate);
|
||||
uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
|
||||
ASSERT(pcOffset != 0);
|
||||
args.insert(args.begin(), currentDepend);
|
||||
args.insert(args.begin(), currentControl);
|
||||
auto callGate = GetCircuit()->NewGate(circuit_->Construct(bitfield, pcOffset), MachineType::I64,
|
||||
@ -697,7 +699,8 @@ GateRef CircuitBuilder::TypedAotCall(GateRef hirGate, std::vector<GateRef> args)
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
uint64_t bitfield = args.size();
|
||||
uint64_t pcOffset = acc_.GetPcOffset(hirGate);
|
||||
uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
|
||||
ASSERT(pcOffset != 0);
|
||||
args.insert(args.begin(), currentDepend);
|
||||
args.insert(args.begin(), currentControl);
|
||||
auto callGate = GetCircuit()->NewGate(circuit_->TypedAotCall(bitfield, pcOffset), MachineType::I64,
|
||||
@ -710,7 +713,8 @@ GateRef CircuitBuilder::TypedAotCall(GateRef hirGate, std::vector<GateRef> args)
|
||||
GateRef CircuitBuilder::CallGetter(GateRef hirGate, GateRef receiver, GateRef propertyLookupResult)
|
||||
{
|
||||
ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
|
||||
uint64_t pcOffset = acc_.GetPcOffset(hirGate);
|
||||
uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
|
||||
ASSERT(pcOffset != 0);
|
||||
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
@ -726,7 +730,8 @@ GateRef CircuitBuilder::CallGetter(GateRef hirGate, GateRef receiver, GateRef pr
|
||||
GateRef CircuitBuilder::CallSetter(GateRef hirGate, GateRef receiver, GateRef propertyLookupResult, GateRef value)
|
||||
{
|
||||
ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
|
||||
uint64_t pcOffset = acc_.GetPcOffset(hirGate);
|
||||
uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
|
||||
ASSERT(pcOffset != 0);
|
||||
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
|
@ -176,7 +176,7 @@ const ChunkVector<char>& GateAccessor::GetConstantString(GateRef gate) const
|
||||
return gatePtr->GetStringMetaData()->GetString();
|
||||
}
|
||||
|
||||
uint32_t GateAccessor::GetPcOffset(GateRef gate) const
|
||||
uint32_t GateAccessor::TryGetPcOffset(GateRef gate) const
|
||||
{
|
||||
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
||||
OpCode op = GetOpCode(gate);
|
||||
|
@ -380,7 +380,7 @@ public:
|
||||
TypedUnaryAccessor GetTypedUnOp(GateRef gate) const;
|
||||
uint64_t GetConstantValue(GateRef gate) const;
|
||||
const ChunkVector<char>& GetConstantString(GateRef gate) const;
|
||||
uint32_t GetPcOffset(GateRef gate) const;
|
||||
uint32_t TryGetPcOffset(GateRef gate) const;
|
||||
EcmaOpcode GetByteCodeOpcode(GateRef gate) const;
|
||||
void Print(GateRef gate) const;
|
||||
void ShortPrint(GateRef gate) const;
|
||||
|
@ -332,7 +332,7 @@ void LLVMIRBuilder::GenPrologue()
|
||||
reservedSlotsSize = OptimizedFrame::ComputeReservedSize(slotSize_);
|
||||
LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots",
|
||||
std::to_string(reservedSlotsSize).c_str());
|
||||
SaveFrameTypeOnFrame(frameType);
|
||||
SaveFrameTypeOnFrame(frameType, builder_);
|
||||
} else if (frameType == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) {
|
||||
reservedSlotsSize = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_);
|
||||
LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots",
|
||||
@ -344,7 +344,7 @@ void LLVMIRBuilder::GenPrologue()
|
||||
LLVMValueRef value = LLVMGetParam(function_, argth);
|
||||
if (argth == static_cast<int>(CommonArgIdx::FUNC)) {
|
||||
SaveJSFuncOnOptJSFuncFrame(value);
|
||||
SaveFrameTypeOnFrame(frameType);
|
||||
SaveFrameTypeOnFrame(frameType, builder_);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -353,15 +353,15 @@ void LLVMIRBuilder::GenPrologue()
|
||||
}
|
||||
}
|
||||
|
||||
void LLVMIRBuilder::SaveFrameTypeOnFrame(FrameType frameType)
|
||||
void LLVMIRBuilder::SaveFrameTypeOnFrame(FrameType frameType, LLVMBuilderRef builder)
|
||||
{
|
||||
LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false);
|
||||
LLVMValueRef llvmFpAddr = CallingFp(module_, builder, false);
|
||||
|
||||
LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder_, llvmFpAddr, slotType_, "cast_int_t");
|
||||
LLVMValueRef frameTypeSlotAddr = LLVMBuildSub(builder_, frameAddr, LLVMConstInt(slotType_, slotSize_, false), "");
|
||||
LLVMValueRef addr = LLVMBuildIntToPtr(builder_, frameTypeSlotAddr, LLVMPointerType(slotType_, 0), "frameType.Addr");
|
||||
LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder, llvmFpAddr, slotType_, "cast_int_t");
|
||||
LLVMValueRef frameTypeSlotAddr = LLVMBuildSub(builder, frameAddr, LLVMConstInt(slotType_, slotSize_, false), "");
|
||||
LLVMValueRef addr = LLVMBuildIntToPtr(builder, frameTypeSlotAddr, LLVMPointerType(slotType_, 0), "frameType.Addr");
|
||||
LLVMValueRef llvmFrameType = LLVMConstInt(slotType_, static_cast<uintptr_t>(frameType), 0);
|
||||
LLVMBuildStore(builder_, llvmFrameType, addr);
|
||||
LLVMBuildStore(builder, llvmFrameType, addr);
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMIRBuilder::CallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder, bool isCaller)
|
||||
@ -1969,6 +1969,44 @@ LLVMTypeRef LLVMIRBuilder::GetExperimentalDeoptTy()
|
||||
return fnTy;
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMModule::GetDeoptFunction()
|
||||
{
|
||||
auto fn = LLVMGetNamedFunction(module_, Deoptimizier::GetLLVMDeoptRelocateSymbol());
|
||||
return fn;
|
||||
}
|
||||
|
||||
void LLVMIRBuilder::GenDeoptEntry(LLVMModuleRef &module)
|
||||
{
|
||||
std::vector<LLVMTypeRef> paramTys = {LLVMInt64Type(), LLVMInt64Type()}; // glue type
|
||||
auto funcType = LLVMFunctionType(LLVMInt64Type(), paramTys.data(), paramTys.size(), 0);
|
||||
auto function = LLVMAddFunction(module, Deoptimizier::GetLLVMDeoptRelocateSymbol(), funcType);
|
||||
LLVMSetFunctionCallConv(function, LLVMCCallConv);
|
||||
llvmModule_->SetFunction(LLVMModule::kDeoptEntryOffset, function);
|
||||
|
||||
LLVMBasicBlockRef entry = LLVMAppendBasicBlock(function, "entry");
|
||||
LLVMBuilderRef builder = LLVMCreateBuilder();
|
||||
LLVMPositionBuilderAtEnd(builder, entry);
|
||||
|
||||
auto reservedSlotsSize = OptimizedFrame::ComputeReservedSize(slotSize_);
|
||||
LLVMAddTargetDependentFunctionAttr(function, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str());
|
||||
SaveFrameTypeOnFrame(FrameType::OPTIMIZED_FRAME, builder);
|
||||
|
||||
LLVMValueRef glue = LLVMGetParam(function, 0);
|
||||
LLVMValueRef check = LLVMGetParam(function, 1);
|
||||
|
||||
StubIdType stubId = RTSTUB_ID(DeoptHandlerAsm);
|
||||
int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId));
|
||||
LLVMValueRef rtoffset = LLVMBuildAdd(builder, glue, GetRTStubOffset(glue, stubIndex), "");
|
||||
LLVMValueRef patchAddr = LLVMBuildIntToPtr(builder, rtoffset, LLVMPointerType(LLVMInt64Type(), 0), "");
|
||||
LLVMValueRef llvmAddr = LLVMBuildLoad(builder, patchAddr, "");
|
||||
LLVMTypeRef rtfuncTypePtr = LLVMPointerType(funcType, 0);
|
||||
LLVMValueRef callee = LLVMBuildIntToPtr(builder, llvmAddr, rtfuncTypePtr, "");
|
||||
std::vector<LLVMValueRef> params = {glue, check};
|
||||
LLVMValueRef runtimeCall = LLVMBuildCall2(builder, funcType, callee, params.data(), params.size(), "");
|
||||
LLVMBuildRet(builder, runtimeCall);
|
||||
LLVMPositionBuilderAtEnd(builder, entry);
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMIRBuilder::GetExperimentalDeopt(LLVMModuleRef &module)
|
||||
{
|
||||
/* 0:calling 1:its caller */
|
||||
@ -1976,6 +2014,7 @@ LLVMValueRef LLVMIRBuilder::GetExperimentalDeopt(LLVMModuleRef &module)
|
||||
if (!fn) {
|
||||
auto fnTy = GetExperimentalDeoptTy();
|
||||
fn = LLVMAddFunction(module, "llvm.experimental.deoptimize.p1i64", fnTy);
|
||||
GenDeoptEntry(module);
|
||||
}
|
||||
return fn;
|
||||
}
|
||||
@ -2151,6 +2190,7 @@ LLVMValueRef LLVMModule::AddFunc(const panda::ecmascript::MethodLiteral *methodL
|
||||
name += std::string("@") + std::to_string(offsetInPandaFile) + std::string("@") + fileName;
|
||||
|
||||
auto function = LLVMAddFunction(module_, name.c_str(), funcType);
|
||||
ASSERT(offsetInPandaFile != LLVMModule::kDeoptEntryOffset);
|
||||
SetFunction(offsetInPandaFile, function);
|
||||
return function;
|
||||
}
|
||||
|
@ -169,6 +169,9 @@ public:
|
||||
{
|
||||
return callSigns_;
|
||||
}
|
||||
LLVMValueRef GetDeoptFunction();
|
||||
|
||||
static constexpr int kDeoptEntryOffset = 0;
|
||||
private:
|
||||
LLVMValueRef AddAndGetFunc(const CallSignature *stubDescriptor);
|
||||
void InitialLLVMFuncTypeAndFuncByModuleCSigns();
|
||||
@ -336,10 +339,11 @@ private:
|
||||
CallExceptionKind kind);
|
||||
void SaveLexicalEnvOnOptJSFuncFrame(LLVMValueRef value);
|
||||
void SaveJSFuncOnOptJSFuncFrame(LLVMValueRef value);
|
||||
void SaveFrameTypeOnFrame(FrameType frameType);
|
||||
void SaveFrameTypeOnFrame(FrameType frameType, LLVMBuilderRef builder);
|
||||
void UpdateLeaveFrame(LLVMValueRef glue);
|
||||
LLVMTypeRef GetExperimentalDeoptTy();
|
||||
LLVMValueRef GetExperimentalDeopt(LLVMModuleRef &module);
|
||||
void GenDeoptEntry(LLVMModuleRef &module);
|
||||
const CompilationConfig *compCfg_ {nullptr};
|
||||
const std::vector<std::vector<GateRef>> *scheduledGates_ {nullptr};
|
||||
const Circuit *circuit_ {nullptr};
|
||||
|
@ -116,7 +116,7 @@ private:
|
||||
static void IncreaseStackForArguments(ExtendedAssembler *assembler, Register argC, Register fp);
|
||||
static void PushOptimizedArgsConfigFrame(ExtendedAssembler *assembler);
|
||||
static void PopOptimizedArgsConfigFrame(ExtendedAssembler *assembler);
|
||||
static void PushOptimizedFrame(ExtendedAssembler *assembler);
|
||||
static void PushAsmBridgeFrame(ExtendedAssembler *assembler);
|
||||
static void PopOptimizedFrame(ExtendedAssembler *assembler);
|
||||
static void JSCallInternal(ExtendedAssembler *assembler, Register jsfunc, bool isNew = false);
|
||||
static void ConstructorJSCallInternal(ExtendedAssembler *assembler, Register jsfunc);
|
||||
|
@ -450,7 +450,7 @@ void OptimizedCall::JSCallInternal(ExtendedAssembler *assembler, Register jsfunc
|
||||
__ Ldp(Register(X6), Register(X7), MemoryOperand(sp, QUINTUPLE_SLOT_SIZE)); // get arg0 arg1
|
||||
__ Cmp(Register(X5), Immediate(3)); // 3: callarg3
|
||||
__ B(Condition::NE, &lTailCall);
|
||||
PushOptimizedFrame(assembler);
|
||||
PushAsmBridgeFrame(assembler);
|
||||
{
|
||||
// push arg3 and call
|
||||
TempRegister2Scope scope2(assembler);
|
||||
@ -931,14 +931,14 @@ void OptimizedCall::PopOptimizedArgsConfigFrame(ExtendedAssembler *assembler)
|
||||
__ RestoreFpAndLr();
|
||||
}
|
||||
|
||||
void OptimizedCall::PushOptimizedFrame(ExtendedAssembler *assembler)
|
||||
void OptimizedCall::PushAsmBridgeFrame(ExtendedAssembler *assembler)
|
||||
{
|
||||
Register sp(SP);
|
||||
TempRegister2Scope temp2Scope(assembler);
|
||||
Register frameType = __ TempRegister2();
|
||||
__ PushFpAndLr();
|
||||
// construct frame
|
||||
__ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::OPTIMIZED_FRAME)));
|
||||
__ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::ASM_BRIDGE_FRAME)));
|
||||
// 2 : 2 means pairs. X19 means calleesave and 16bytes align
|
||||
__ Stp(Register(X19), frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
|
||||
__ Add(Register(FP), sp, Immediate(FRAME_SLOT_SIZE));
|
||||
@ -1190,7 +1190,7 @@ void OptimizedCall::DeoptHandlerAsm(ExtendedAssembler *assembler)
|
||||
Register frameType(X2);
|
||||
Register glueReg(X0);
|
||||
|
||||
__ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::OPTIMIZED_FRAME)));
|
||||
__ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::ASM_BRIDGE_FRAME)));
|
||||
__ Stp(glueReg, frameType, MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
|
||||
__ Add(fp, sp, Immediate(DOUBLE_SLOT_SIZE));
|
||||
__ CalleeSave();
|
||||
|
@ -693,7 +693,7 @@ void OptimizedCall::GenJSCall(ExtendedAssembler *assembler, bool isNew)
|
||||
__ Movq(rsp, argV);
|
||||
__ Addq(SEXTUPLE_SLOT_SIZE, argV);
|
||||
__ Pushq(rbp);
|
||||
__ Pushq(static_cast<int32_t>(FrameType::OPTIMIZED_FRAME));
|
||||
__ Pushq(static_cast<int32_t>(FrameType::ASM_BRIDGE_FRAME));
|
||||
__ Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp);
|
||||
|
||||
if (!isNew) {
|
||||
@ -1451,7 +1451,7 @@ void OptimizedCall::DeoptHandlerAsm(ExtendedAssembler *assembler)
|
||||
|
||||
Register glueReg = rdi;
|
||||
__ Pushq(rbp);
|
||||
__ Pushq(static_cast<int32_t>(FrameType::OPTIMIZED_FRAME));
|
||||
__ Pushq(static_cast<int32_t>(FrameType::ASM_BRIDGE_FRAME));
|
||||
__ Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp);
|
||||
__ Push(glueReg);
|
||||
__ PushCppCalleeSaveRegisters();
|
||||
|
@ -109,10 +109,57 @@ void Deoptimizier::CollectVregs(const std::vector<kungfu::ARKDeopt>& deoptBundle
|
||||
}
|
||||
}
|
||||
|
||||
// when AOT trigger deopt, frame layout as the following
|
||||
// * OptimizedJSFunctionFrame layout description as the following:
|
||||
// +--------------------------+ ---------------
|
||||
// | ...... | ^
|
||||
// | ...... | callerFunction
|
||||
// | ...... | |
|
||||
// |--------------------------| |
|
||||
// | args | v
|
||||
// +--------------------------+ ---------------
|
||||
// | returnAddr | ^
|
||||
// |--------------------------| |
|
||||
// | callsiteFp | |
|
||||
// |--------------------------| OptimizedJSFunction FrameType:OPTIMIZED_JS_FUNCTION_FRAME
|
||||
// | frameType | |
|
||||
// |--------------------------| |
|
||||
// | call-target | |
|
||||
// |--------------------------| |
|
||||
// | lexEnv | |
|
||||
// |--------------------------| |
|
||||
// | ........... | v
|
||||
// +--------------------------+ ---------------
|
||||
// | returnAddr | ^
|
||||
// |--------------------------| |
|
||||
// | callsiteFp | |
|
||||
// |--------------------------| __llvm_deoptimize FrameType:OPTIMIZED_FRAME
|
||||
// | frameType | |
|
||||
// |--------------------------| |
|
||||
// | No CalleeSave | |
|
||||
// | Registers | v
|
||||
// +--------------------------+ ---------------
|
||||
// | returnAddr | ^
|
||||
// |--------------------------| |
|
||||
// | callsiteFp | |
|
||||
// |--------------------------| DeoptHandlerAsm FrameType:ASM_BRIDGE_FRAME
|
||||
// | frameType | |
|
||||
// |--------------------------| |
|
||||
// | glue | |
|
||||
// |--------------------------| |
|
||||
// | CalleeSave Registers | v
|
||||
// +--------------------------+ ---------------
|
||||
// | ......... | ^
|
||||
// | ......... | CallRuntime FrameType:LEAVE_FRAME
|
||||
// | ......... | |
|
||||
// | ......... | v
|
||||
// |--------------------------| ---------------
|
||||
|
||||
void Deoptimizier::CollectDeoptBundleVec(std::vector<kungfu::ARKDeopt>& deoptBundle)
|
||||
{
|
||||
JSTaggedType *lastLeave = const_cast<JSTaggedType *>(thread_->GetLastLeaveFrame());
|
||||
FrameIterator it(lastLeave, thread_);
|
||||
// note: last deopt bridge frame is generated by DeoptHandlerAsm, callee Regs is grow from this frame
|
||||
for (; !it.Done() && deoptBundle.empty(); it.Advance<GCVisitedFlag::VISITED>()) {
|
||||
FrameType type = it.GetFrameType();
|
||||
switch (type) {
|
||||
@ -132,12 +179,14 @@ void Deoptimizier::CollectDeoptBundleVec(std::vector<kungfu::ARKDeopt>& deoptBun
|
||||
stackContext_.callerFp_ = reinterpret_cast<uintptr_t>(frame->GetPrevFrameFp());
|
||||
break;
|
||||
}
|
||||
case FrameType::OPTIMIZED_FRAME: {
|
||||
case FrameType::ASM_BRIDGE_FRAME: {
|
||||
auto sp = reinterpret_cast<uintptr_t*>(it.GetSp());
|
||||
sp -= 2; // 2: skip type & glue
|
||||
static constexpr size_t TYPE_GLUE_SLOT = 2; // 2: skip type & glue
|
||||
sp -= TYPE_GLUE_SLOT;
|
||||
calleeRegAddr_ = sp - numCalleeRegs_;
|
||||
break;
|
||||
}
|
||||
case FrameType::OPTIMIZED_FRAME:
|
||||
case FrameType::LEAVE_FRAME:
|
||||
break;
|
||||
default: {
|
||||
|
@ -23,8 +23,6 @@
|
||||
#include "ecmascript/js_tagged_value.h"
|
||||
#include "ecmascript/stackmap/llvm_stackmap_type.h"
|
||||
|
||||
// todo:place to Deoptimizier class
|
||||
#define LLVM_DEOPT_RELOCATE_SYMBOL "__llvm_deoptimize"
|
||||
namespace panda::ecmascript {
|
||||
class JSThread;
|
||||
enum class SpecVregIndex: int {
|
||||
@ -106,6 +104,11 @@ public:
|
||||
return thread_;
|
||||
}
|
||||
|
||||
static const char *GetLLVMDeoptRelocateSymbol()
|
||||
{
|
||||
return "__llvm_deoptimize";
|
||||
}
|
||||
|
||||
private:
|
||||
size_t GetFrameIndex(kungfu::CommonArgIdx index)
|
||||
{
|
||||
|
@ -1,175 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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/deoptimizer/relocator.h"
|
||||
#include <climits>
|
||||
#include <iomanip>
|
||||
#include "ecmascript/compiler/assembler/aarch64/assembler_aarch64_constants.h"
|
||||
#include "ecmascript/message_string.h"
|
||||
#if !WIN_OR_MAC_OR_IOS_PLATFORM
|
||||
|
||||
namespace panda::ecmascript {
|
||||
std::optional<Elf64_Word> Relocator::GetSymbol(const char* symbol) const
|
||||
{
|
||||
ASSERT(symAndStrTabInfo_.symSize_ % sizeof(Elf64_Sym) == 0);
|
||||
int n = symAndStrTabInfo_.symSize_ / sizeof(Elf64_Sym);
|
||||
ASSERT(symAndStrTabInfo_.symAddr_ > 0 && symAndStrTabInfo_.symSize_ > 0);
|
||||
Elf64_Sym *ptr = reinterpret_cast<Elf64_Sym *>(symAndStrTabInfo_.symAddr_);
|
||||
for (int i = 0; i < n; i++) {
|
||||
Elf64_Sym *cur = ptr + i;
|
||||
const char *name = reinterpret_cast<char *>(symAndStrTabInfo_.strAddr_) + cur->st_name;
|
||||
if (std::strcmp(symbol, name) == 0) {
|
||||
return static_cast<Elf64_Word>(i);
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool Relocator::Relocate(Elf64_Rela *sec, uintptr_t symbolAddr, uintptr_t patchAddr)
|
||||
{
|
||||
bool ret = false;
|
||||
ASSERT(reinterpret_cast<intptr_t>(sec) > 0);
|
||||
Elf64_Word type = GetType(sec);
|
||||
Elf64_Sxword addend = sec->r_addend;
|
||||
|
||||
switch (type) {
|
||||
case R_AARCH64_CALL26: {
|
||||
/* S + A - P
|
||||
S: (when used on its own) is the address of the symbol
|
||||
A: is the addend for the relocation
|
||||
P: is the address of the place beging relocated(derived from r_offset)
|
||||
*/
|
||||
intptr_t imm = patchAddr + addend - symbolAddr;
|
||||
ASSERT(-(1 << 27) <= imm && imm < (1 << 27)); // 27: "Check that -2^27 <= result < 2^27".
|
||||
imm = (imm & 0x0FFFFFFC) >> 2; // 0x0FFFFFFC: get immediate file to bits [27:2]
|
||||
*(reinterpret_cast<uint32_t *>(symbolAddr)) = imm | panda::ecmascript::aarch64::CallOpCode::BL;
|
||||
break;
|
||||
}
|
||||
case R_X86_64_PLT32: {
|
||||
/* S + A - P
|
||||
S: (when used on its own) is the address of the symbol
|
||||
A: is the addend for the relocation
|
||||
P: is the address of the place beging relocated(derived from r_offset)
|
||||
*/
|
||||
intptr_t v = patchAddr + addend - symbolAddr;
|
||||
ASSERT((v >= INT_MIN) && (v <= INT_MAX));
|
||||
*(reinterpret_cast<uint32_t *>(symbolAddr)) = v;
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG_COMPILER(FATAL) << " unsupported type:" << type;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Relocator::HasSymStrTable() const
|
||||
{
|
||||
return (symAndStrTabInfo_.symAddr_ >= 0) && (symAndStrTabInfo_.symSize_ >= 0) &&
|
||||
(symAndStrTabInfo_.strAddr_ >= 0) && (symAndStrTabInfo_.strSize_ >= 0);
|
||||
}
|
||||
|
||||
bool Relocator::HasRelocateText() const
|
||||
{
|
||||
return (relocateTextInfo_.relaTextAddr_ > 0) && (relocateTextInfo_.relaTextSize_ > 0);
|
||||
}
|
||||
|
||||
bool Relocator::RelocateBySymbolId(Elf64_Word symbolId, uintptr_t patchAddr)
|
||||
{
|
||||
bool ret = false;
|
||||
ASSERT(relocateTextInfo_.relaTextSize_ % sizeof(Elf64_Rela) == 0);
|
||||
ASSERT(relocateTextInfo_.relaTextAddr_ > 0 && relocateTextInfo_.relaTextSize_ > 0);
|
||||
size_t n = relocateTextInfo_.relaTextSize_ / sizeof(Elf64_Rela);
|
||||
Elf64_Rela *ptr = reinterpret_cast<Elf64_Rela *>(relocateTextInfo_.relaTextAddr_);
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
Elf64_Rela *cur = ptr + i;
|
||||
Elf64_Word id = GetSymbol(cur);
|
||||
intptr_t symbolAddr = relocateTextInfo_.textAddr_ + static_cast<uintptr_t>(cur->r_offset);
|
||||
if (id == symbolId) {
|
||||
ret = Relocate(cur, symbolAddr, patchAddr);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Relocator::RelocateBySymbol(const char* symbol, uintptr_t patchAddr)
|
||||
{
|
||||
if (!HasSymStrTable()) {
|
||||
return false;
|
||||
}
|
||||
auto symId = GetSymbol(symbol);
|
||||
if (!symId.has_value()) {
|
||||
LOG_COMPILER(DEBUG) << " don't find symbol:" << symbol << " in symbol table.";
|
||||
return false;
|
||||
}
|
||||
bool ret = RelocateBySymbolId(symId.value(), patchAddr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Relocator::DumpRelocateText()
|
||||
{
|
||||
if (!HasRelocateText()) {
|
||||
LOG_COMPILER(ERROR) << " input valid relocateText addr & size:";
|
||||
return;
|
||||
}
|
||||
ASSERT(relocateTextInfo_.relaTextSize_ % sizeof(Elf64_Rela) == 0);
|
||||
ASSERT(relocateTextInfo_.relaTextAddr_ > 0 && relocateTextInfo_.relaTextSize_ > 0);
|
||||
size_t n = relocateTextInfo_.relaTextSize_ / sizeof(Elf64_Rela);
|
||||
Elf64_Rela *ptr = reinterpret_cast<Elf64_Rela *>(relocateTextInfo_.relaTextAddr_);
|
||||
static constexpr int leftAdjustment = 12;
|
||||
LOG_COMPILER(DEBUG) << std::left << std::setw(leftAdjustment) << "symbolId "
|
||||
<< std::left << std::setw(leftAdjustment) << "Info(0x): "
|
||||
<< std::left << std::setw(leftAdjustment) << "Type: "
|
||||
<< std::left << std::setw(leftAdjustment) << "r_offset(0x): "
|
||||
<< std::left << std::setw(leftAdjustment) << "addend: ";
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
Elf64_Rela *cur = ptr + i;
|
||||
Elf64_Word id = GetSymbol(cur);
|
||||
Elf64_Word type = GetType(cur);
|
||||
Elf64_Sxword addend = ptr->r_addend;
|
||||
LOG_COMPILER(DEBUG) << std::left << std::setw(leftAdjustment) << id
|
||||
<< std::left << std::setw(leftAdjustment) << std::hex << cur->r_info
|
||||
<< std::left << std::setw(leftAdjustment) << std::dec << type
|
||||
<< std::left << std::setw(leftAdjustment) << std::hex << static_cast<intptr_t>(cur->r_offset)
|
||||
<< std::left << std::setw(leftAdjustment) << std::dec << static_cast<intptr_t>(addend);
|
||||
}
|
||||
if (!HasSymStrTable()) {
|
||||
return;
|
||||
}
|
||||
ASSERT(symAndStrTabInfo_.symSize_ % sizeof(Elf64_Sym) == 0);
|
||||
n = symAndStrTabInfo_.symSize_ / sizeof(Elf64_Sym);
|
||||
ASSERT(symAndStrTabInfo_.symAddr_ > 0 && symAndStrTabInfo_.symSize_ > 0);
|
||||
Elf64_Sym *symPtr = reinterpret_cast<Elf64_Sym *>(symAndStrTabInfo_.symAddr_);
|
||||
LOG_COMPILER(DEBUG) << std::left << std::setw(leftAdjustment) << "symbolId "
|
||||
<< std::left << std::setw(leftAdjustment) << "binding: "
|
||||
<< std::left << std::setw(leftAdjustment) << "Type: "
|
||||
<< std::left << std::setw(leftAdjustment) << "st_name: "
|
||||
<< std::left << std::setw(leftAdjustment) << "name: ";
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
Elf64_Sym *cur = symPtr + i;
|
||||
const char *name = reinterpret_cast<char *>(symAndStrTabInfo_.strAddr_) + cur->st_name;
|
||||
unsigned char binding = GetBinding(cur);
|
||||
unsigned char type = GetType(cur);
|
||||
LOG_COMPILER(DEBUG) << std::left << std::setw(leftAdjustment) << i
|
||||
<< std::left << std::setw(leftAdjustment) << std::dec << static_cast<int>(binding)
|
||||
<< std::left << std::setw(leftAdjustment) << std::dec << static_cast<int>(type)
|
||||
<< std::left << std::setw(leftAdjustment) << std::dec << cur->st_name
|
||||
<< std::left << std::setw(leftAdjustment) << name;
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
#endif
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_DEOPTIMIZER_RELCATOR_H
|
||||
#define ECMASCRIPT_DEOPTIMIZER_RELCATOR_H
|
||||
|
||||
#include "ecmascript/common.h"
|
||||
#if !WIN_OR_MAC_OR_IOS_PLATFORM
|
||||
|
||||
#include <elf.h>
|
||||
#include <optional>
|
||||
#include "ecmascript/ecma_macros.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
struct RelocateTextInfo {
|
||||
uintptr_t textAddr_ {0};
|
||||
uintptr_t relaTextAddr_ {0};
|
||||
uintptr_t relaTextSize_ {0};
|
||||
};
|
||||
|
||||
struct SymAndStrTabInfo {
|
||||
uintptr_t symAddr_ {0};
|
||||
uintptr_t symSize_ {0};
|
||||
uintptr_t strAddr_ {0};
|
||||
uintptr_t strSize_ {0};
|
||||
};
|
||||
|
||||
class Relocator {
|
||||
public:
|
||||
PUBLIC_API Relocator(RelocateTextInfo relaText, SymAndStrTabInfo symAndStrTabInfo)
|
||||
:relocateTextInfo_(relaText), symAndStrTabInfo_(symAndStrTabInfo) {};
|
||||
|
||||
PUBLIC_API bool RelocateBySymbolId(Elf64_Word symbolId, uintptr_t patchAddr);
|
||||
PUBLIC_API bool RelocateBySymbol(const char* symbol, uintptr_t patchAddr);
|
||||
PUBLIC_API void DumpRelocateText();
|
||||
~Relocator() = default;
|
||||
private:
|
||||
bool HasSymStrTable() const;
|
||||
bool HasRelocateText() const;
|
||||
std::optional<Elf64_Word> GetSymbol(const char* symbol) const;
|
||||
bool Relocate(Elf64_Rela *sec, uintptr_t symbolAddr, uintptr_t patchAddr);
|
||||
|
||||
Elf64_Word GetSymbol(Elf64_Rela *cur) const
|
||||
{
|
||||
Elf64_Word id = (cur->r_info >> 32); // 32: get high 32 bits
|
||||
return id;
|
||||
}
|
||||
|
||||
Elf64_Word GetType(Elf64_Rela *cur) const
|
||||
{
|
||||
return (cur->r_info & 0xffffffffL); // 0xffffffff :get lower 32 bits
|
||||
}
|
||||
|
||||
// These accessors and mutators are identical to those defined for ELF32
|
||||
// symbol table entries.
|
||||
unsigned char GetBinding(Elf64_Sym *cur) const
|
||||
{
|
||||
return cur->st_info >> 4; // 4: offset
|
||||
}
|
||||
|
||||
unsigned char GetType(Elf64_Sym *cur) const
|
||||
{
|
||||
return cur->st_info & 0x0f; // f: get lowest 4 bits
|
||||
}
|
||||
|
||||
RelocateTextInfo relocateTextInfo_ {0};
|
||||
SymAndStrTabInfo symAndStrTabInfo_ {0};
|
||||
};
|
||||
} // panda::ecmascript
|
||||
#endif
|
||||
#endif // ECMASCRIPT_DEOPTIMIZER_RELCATOR_H
|
||||
|
@ -91,6 +91,7 @@ JSTaggedValue FrameIterator::GetFunction() const
|
||||
}
|
||||
case FrameType::OPTIMIZED_FRAME:
|
||||
case FrameType::OPTIMIZED_ENTRY_FRAME:
|
||||
case FrameType::ASM_BRIDGE_FRAME:
|
||||
case FrameType::LEAVE_FRAME:
|
||||
case FrameType::LEAVE_FRAME_WITH_ARGV:
|
||||
case FrameType::INTERPRETER_ENTRY_FRAME:
|
||||
@ -139,6 +140,16 @@ void FrameIterator::Advance()
|
||||
current_ = frame->GetPrevFrameFp();
|
||||
break;
|
||||
}
|
||||
case FrameType::ASM_BRIDGE_FRAME : {
|
||||
auto frame = GetFrame<AsmBridgeFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED) {
|
||||
optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
|
||||
optimizedReturnAddr_ = frame->GetReturnAddr();
|
||||
needCalCallSiteInfo = true;
|
||||
}
|
||||
current_ = frame->GetPrevFrameFp();
|
||||
break;
|
||||
}
|
||||
case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
|
||||
auto frame = GetFrame<OptimizedJSFunctionUnfoldArgVFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED) {
|
||||
@ -290,10 +301,6 @@ void FrameIterator::Advance()
|
||||
std::tie(textStart, stackMapAddr_, fpDeltaPrevFrameSp_, calleeRegInfo_) = CalCallSiteInfo(optimizedReturnAddr_);
|
||||
ASSERT(optimizedReturnAddr_ >= textStart);
|
||||
optimizedReturnAddr_ = optimizedReturnAddr_ - textStart;
|
||||
if (t == FrameType::LEAVE_FRAME && fpDeltaPrevFrameSp_ == 0) {
|
||||
// it may be asm code stub's leave frame.
|
||||
fpDeltaPrevFrameSp_ = 2 * sizeof(uintptr_t); // 2: skip prev and return addr
|
||||
}
|
||||
}
|
||||
}
|
||||
template void FrameIterator::Advance<GCVisitedFlag::VISITED>();
|
||||
@ -336,6 +343,10 @@ uintptr_t FrameIterator::GetPrevFrameCallSiteSp() const
|
||||
auto callSiteSp = reinterpret_cast<uintptr_t>(current_) + fpDeltaPrevFrameSp_;
|
||||
return callSiteSp;
|
||||
}
|
||||
case FrameType::ASM_BRIDGE_FRAME: {
|
||||
auto frame = GetFrame<AsmBridgeFrame>();
|
||||
return frame->GetCallSiteSp();
|
||||
}
|
||||
case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
|
||||
auto frame = GetFrame<OptimizedJSFunctionUnfoldArgVFrame>();
|
||||
return frame->GetPrevFrameSp();
|
||||
@ -712,6 +723,10 @@ bool GetTypeOffsetAndPrevOffsetFromFrameType(uintptr_t frameType, uintptr_t &typ
|
||||
typeOffset = OptimizedEntryFrame::GetTypeOffset();
|
||||
prevOffset = OptimizedEntryFrame::GetLeaveFrameFpOffset();
|
||||
break;
|
||||
case FrameType::ASM_BRIDGE_FRAME:
|
||||
typeOffset = AsmBridgeFrame::GetTypeOffset();
|
||||
prevOffset = AsmBridgeFrame::GetPrevOffset();
|
||||
break;
|
||||
case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME:
|
||||
typeOffset = OptimizedJSFunctionUnfoldArgVFrame::GetTypeOffset();
|
||||
prevOffset = OptimizedJSFunctionUnfoldArgVFrame::GetPrevOffset();
|
||||
|
@ -114,6 +114,7 @@ enum class FrameType: uintptr_t {
|
||||
OPTIMIZED_FRAME = 0,
|
||||
OPTIMIZED_ENTRY_FRAME,
|
||||
OPTIMIZED_JS_FUNCTION_FRAME,
|
||||
ASM_BRIDGE_FRAME,
|
||||
LEAVE_FRAME,
|
||||
LEAVE_FRAME_WITH_ARGV,
|
||||
BUILTIN_CALL_LEAVE_FRAME,
|
||||
@ -222,6 +223,60 @@ private:
|
||||
};
|
||||
STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64);
|
||||
|
||||
struct AsmBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
|
||||
base::AlignedPointer,
|
||||
base::AlignedPointer,
|
||||
base::AlignedPointer> {
|
||||
public:
|
||||
static size_t GetTypeOffset()
|
||||
{
|
||||
return MEMBER_OFFSET(AsmBridgeFrame, type);
|
||||
}
|
||||
|
||||
static size_t GetPrevOffset()
|
||||
{
|
||||
return MEMBER_OFFSET(AsmBridgeFrame, prevFp);
|
||||
}
|
||||
|
||||
uintptr_t GetCallSiteSp() const
|
||||
{
|
||||
return ToUintPtr(this) + sizeof(AsmBridgeFrame);
|
||||
}
|
||||
|
||||
FrameType GetType() const
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
private:
|
||||
enum class Index : size_t {
|
||||
TypeIndex = 0,
|
||||
PrevFpIndex,
|
||||
ReturnAddrIndex,
|
||||
NumOfMembers
|
||||
};
|
||||
static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
|
||||
|
||||
static AsmBridgeFrame* GetFrameFromSp(const JSTaggedType *sp)
|
||||
{
|
||||
return reinterpret_cast<AsmBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) -
|
||||
MEMBER_OFFSET(AsmBridgeFrame, prevFp));
|
||||
}
|
||||
inline JSTaggedType* GetPrevFrameFp()
|
||||
{
|
||||
return prevFp;
|
||||
}
|
||||
uintptr_t GetReturnAddr() const
|
||||
{
|
||||
return returnAddr;
|
||||
}
|
||||
alignas(EAS) FrameType type {0};
|
||||
alignas(EAS) JSTaggedType *prevFp {nullptr};
|
||||
alignas(EAS) uintptr_t returnAddr {0};
|
||||
friend class FrameIterator;
|
||||
};
|
||||
STATIC_ASSERT_EQ_ARCH(sizeof(AsmBridgeFrame), AsmBridgeFrame::SizeArch32, AsmBridgeFrame::SizeArch64);
|
||||
|
||||
// * OptimizedUnfoldArgVFrame layout description as the following:
|
||||
// sp ----> |--------------------------| ---------------
|
||||
// | returnAddr | ^
|
||||
@ -286,7 +341,8 @@ private:
|
||||
alignas(EAS) uintptr_t returnAddr {0};
|
||||
friend class FrameIterator;
|
||||
};
|
||||
STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64);
|
||||
STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionUnfoldArgVFrame),
|
||||
OptimizedJSFunctionUnfoldArgVFrame::SizeArch32, OptimizedJSFunctionUnfoldArgVFrame::SizeArch64);
|
||||
|
||||
// * The OptimizedJSFunctionArgsConfig Frame's structure is illustrated as the following:
|
||||
// +--------------------------+
|
||||
|
@ -194,6 +194,7 @@ JSTaggedValue FrameHandler::GetFunction() const
|
||||
case FrameType::ASM_INTERPRETER_BRIDGE_FRAME:
|
||||
case FrameType::INTERPRETER_BUILTIN_FRAME:
|
||||
case FrameType::OPTIMIZED_FRAME:
|
||||
case FrameType::ASM_BRIDGE_FRAME:
|
||||
case FrameType::LEAVE_FRAME:
|
||||
case FrameType::LEAVE_FRAME_WITH_ARGV:
|
||||
case FrameType::BUILTIN_CALL_LEAVE_FRAME:
|
||||
@ -301,6 +302,7 @@ ARK_INLINE uintptr_t FrameHandler::GetInterpretedFrameEnd(JSTaggedType *prevSp)
|
||||
case FrameType::BUILTIN_ENTRY_FRAME:
|
||||
case FrameType::BUILTIN_FRAME:
|
||||
case FrameType::OPTIMIZED_FRAME:
|
||||
case FrameType::ASM_BRIDGE_FRAME:
|
||||
case FrameType::LEAVE_FRAME:
|
||||
case FrameType::LEAVE_FRAME_WITH_ARGV:
|
||||
case FrameType::BUILTIN_CALL_LEAVE_FRAME:
|
||||
@ -427,6 +429,7 @@ void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &vis
|
||||
case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME:
|
||||
case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME:
|
||||
case FrameType::OPTIMIZED_ENTRY_FRAME:
|
||||
case FrameType::ASM_BRIDGE_FRAME:
|
||||
case FrameType::ASM_INTERPRETER_ENTRY_FRAME:
|
||||
case FrameType::ASM_INTERPRETER_BRIDGE_FRAME: {
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user