mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 10:09:54 +00:00
[JIT] Support jit re-compile when deopt
Re-compile func if func deopt reach max cnt, and reset jit hotness cnt Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IADV02?from=project-issue Change-Id: I1c6810d9c1cd6fbce86094ecc200f2acada7e6ab Signed-off-by: xiaoweidong <xiaoweidong@huawei.com>
This commit is contained in:
parent
63774d563e
commit
4d8c1d1b25
@ -535,6 +535,25 @@ JSTaggedType Deoptimizier::ConstructAsmInterpretFrame()
|
||||
return reinterpret_cast<JSTaggedType>(frameWriter.GetTop());
|
||||
}
|
||||
|
||||
void Deoptimizier::ResetJitHotness(JSFunction *jsFunc) const
|
||||
{
|
||||
if (jsFunc->GetMachineCode().IsMachineCodeObject()) {
|
||||
JSTaggedValue profileTypeInfoVal = jsFunc->GetProfileTypeInfo();
|
||||
if (!profileTypeInfoVal.IsUndefined()) {
|
||||
ProfileTypeInfo *profileTypeInfo = ProfileTypeInfo::Cast(profileTypeInfoVal.GetTaggedObject());
|
||||
profileTypeInfo->SetJitHotnessCnt(0);
|
||||
constexpr uint16_t thresholdStep = 4;
|
||||
constexpr uint16_t thresholdLimit = ProfileTypeInfo::JIT_DISABLE_FLAG / thresholdStep;
|
||||
uint16_t threshold = profileTypeInfo->GetJitHotnessThreshold();
|
||||
threshold = threshold >= thresholdLimit ? ProfileTypeInfo::JIT_DISABLE_FLAG : threshold * thresholdStep;
|
||||
profileTypeInfo->SetJitHotnessThreshold(threshold);
|
||||
ProfileTypeInfoCell::Cast(jsFunc->GetRawProfileTypeInfo())->SetMachineCode(thread_, JSTaggedValue::Hole());
|
||||
Method *method = Method::Cast(jsFunc->GetMethod().GetTaggedObject());
|
||||
LOG_JIT(DEBUG) << "reset jit hotness for func: " << method->GetMethodName() << ", threshold:" << threshold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Deoptimizier::ClearCompiledCodeStatusWhenDeopt(JSFunction *func, Method *method)
|
||||
{
|
||||
if (func->GetMachineCode().IsMachineCodeObject()) {
|
||||
@ -548,6 +567,7 @@ void Deoptimizier::ClearCompiledCodeStatusWhenDeopt(JSFunction *func, Method *me
|
||||
func->SetCodeEntry(entry);
|
||||
method->ClearAOTStatusWhenDeopt(entry);
|
||||
func->ClearCompiledCodeFlags();
|
||||
ResetJitHotness(func);
|
||||
} // Do not change the func code entry if the method is not aot or deopt has happened already
|
||||
}
|
||||
|
||||
|
@ -180,6 +180,7 @@ private:
|
||||
void Dump(JSTaggedValue callTarget, kungfu::DeoptType type, size_t depth);
|
||||
size_t GetCallSize(size_t curDepth, const uint8_t *resumePc);
|
||||
void ClearCompiledCodeStatusWhenDeopt(JSFunction *fun, Method *method);
|
||||
void ResetJitHotness(JSFunction *jsFunc) const;
|
||||
JSThread *thread_ {nullptr};
|
||||
uintptr_t *calleeRegAddr_ {nullptr};
|
||||
size_t numCalleeRegs_ {0};
|
||||
|
@ -117,40 +117,15 @@ JSTaggedValue FrameIterator::GetFunction() const
|
||||
|
||||
AOTFileInfo::CallSiteInfo FrameIterator::TryCalCallSiteInfoFromMachineCode(uintptr_t retAddr) const
|
||||
{
|
||||
// get CallSiteInfo with jsfunction for jit compiled function
|
||||
FrameType type = GetFrameType();
|
||||
if (type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME ||
|
||||
type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) {
|
||||
auto frame = GetFrame<OptimizedJSFunctionFrame>();
|
||||
JSTaggedValue func = frame->GetFunction();
|
||||
if (!func.IsHeapObject()) {
|
||||
return {};
|
||||
}
|
||||
// cast to jsfunction directly. JSFunction::Cast may fail,
|
||||
// as jsfunction class may set forwardingAddress in Evacuate, but forwarding obj not init.
|
||||
JSFunction *jsfunc = reinterpret_cast<JSFunction*>(func.GetTaggedObject());
|
||||
// machineCode non move
|
||||
JSTaggedValue machineCode = jsfunc->GetMachineCode();
|
||||
if (machineCode.IsMachineCodeObject() &&
|
||||
MachineCode::Cast(machineCode.GetTaggedObject())->IsInText(retAddr)) {
|
||||
return MachineCode::Cast(machineCode.GetTaggedObject())->CalCallSiteInfo(retAddr);
|
||||
}
|
||||
} else if (type == FrameType::FASTJIT_FUNCTION_FRAME ||
|
||||
type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME ||
|
||||
type == FrameType::FASTJIT_FUNCTION_FRAME ||
|
||||
type == FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME) {
|
||||
auto frame = GetFrame<FASTJITFunctionFrame>();
|
||||
JSTaggedValue func = frame->GetFunction();
|
||||
if (!func.IsHeapObject()) {
|
||||
return {};
|
||||
}
|
||||
// cast to jsfunction directly. JSFunction::Cast may fail,
|
||||
// as jsfunction class may set forwardingAddress in Evacuate, but forwarding obj not init.
|
||||
JSFunction *jsfunc = reinterpret_cast<JSFunction*>(func.GetTaggedObject());
|
||||
// machineCode non move
|
||||
JSTaggedValue machineCode = jsfunc->GetMachineCode();
|
||||
if (machineCode.IsMachineCodeObject() &&
|
||||
MachineCode::Cast(machineCode.GetTaggedObject())->IsInText(retAddr)) {
|
||||
return MachineCode::Cast(machineCode.GetTaggedObject())->CalCallSiteInfo(retAddr);
|
||||
}
|
||||
auto machineCode = thread_->GetEcmaVM()->GetHeap()->GetMachineCodeObject(retAddr);
|
||||
ASSERT(machineCode != nullptr);
|
||||
const_cast<FrameIterator*>(this)->machineCode_ = reinterpret_cast<JSTaggedType>(machineCode);
|
||||
return reinterpret_cast<MachineCode*>(machineCode_)->CalCallSiteInfo(retAddr);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@ -664,6 +639,11 @@ ARK_INLINE void OptimizedJSFunctionFrame::GCIterate(const FrameIterator &it,
|
||||
}
|
||||
}
|
||||
|
||||
auto machineCodeSlot = ObjectSlot(ToUintPtr(it.GetMachineCodeSlot()));
|
||||
if (machineCodeSlot.GetTaggedType() != JSTaggedValue::VALUE_UNDEFINED) {
|
||||
visitor(Root::ROOT_FRAME, machineCodeSlot);
|
||||
}
|
||||
|
||||
bool ret = it.IteratorStackMap(visitor, derivedVisitor);
|
||||
if (!ret) {
|
||||
#ifndef NDEBUG
|
||||
@ -722,6 +702,11 @@ ARK_INLINE void FASTJITFunctionFrame::GCIterate(const FrameIterator &it,
|
||||
}
|
||||
}
|
||||
|
||||
auto machineCodeSlot = ObjectSlot(ToUintPtr(it.GetMachineCodeSlot()));
|
||||
if (machineCodeSlot.GetTaggedType() != JSTaggedValue::VALUE_UNDEFINED) {
|
||||
visitor(Root::ROOT_FRAME, machineCodeSlot);
|
||||
}
|
||||
|
||||
bool ret = it.IteratorStackMap(visitor, derivedVisitor);
|
||||
if (!ret) {
|
||||
#ifndef NDEBUG
|
||||
|
@ -2042,6 +2042,11 @@ public:
|
||||
return IsOptimizedJSFunctionFrame() || IsFastJitFunctionFrame();
|
||||
}
|
||||
|
||||
JSTaggedType *GetMachineCodeSlot() const
|
||||
{
|
||||
return const_cast<JSTaggedType*>(&machineCode_);
|
||||
}
|
||||
|
||||
private:
|
||||
JSTaggedType *current_ {nullptr};
|
||||
const JSThread *thread_ {nullptr};
|
||||
@ -2051,6 +2056,9 @@ private:
|
||||
uint8_t *stackMapAddr_ {nullptr};
|
||||
int fpDeltaPrevFrameSp_ {0};
|
||||
kungfu::CalleeRegAndOffsetVec calleeRegInfo_;
|
||||
|
||||
// cache current machine code, it's nonmovable
|
||||
JSTaggedType machineCode_ {JSTaggedValue::VALUE_UNDEFINED};
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_FRAMES_H
|
||||
|
@ -230,17 +230,21 @@ void Jit::ReuseCompiledFunc(JSThread *thread, JSHandle<JSFunction> &jsFunction)
|
||||
if (machineCode.IsHole()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProfileTypeInfo *profileTypeInfo = ProfileTypeInfo::Cast(profCell->GetValue().GetTaggedObject());
|
||||
if (profileTypeInfo->GetJitHotnessThreshold() == ProfileTypeInfo::JIT_DISABLE_FLAG) {
|
||||
// disable reuse as disable jit in deopt
|
||||
return;
|
||||
}
|
||||
if (machineCode.IsUndefined()) {
|
||||
LOG_JIT(DEBUG) << "reset fuction jit hotness count";
|
||||
// if old gc triggered, jit hotness cnt need to be recounted
|
||||
ProfileTypeInfo::Cast(profCell->GetValue().GetTaggedObject())->SetJitHotnessCnt(0);
|
||||
profileTypeInfo->SetJitHotnessCnt(0);
|
||||
profCell->SetMachineCode(thread, JSTaggedValue::Hole());
|
||||
return;
|
||||
}
|
||||
JSHandle<MachineCode> machineCodeHandle(thread, machineCode.GetTaggedObject());
|
||||
JSHandle<Method> method(thread, Method::Cast(jsFunction->GetMethod().GetTaggedObject()));
|
||||
LOG_JIT(DEBUG) << "reuse fuction machine code : " << method->GetJSPandaFile()->GetJSPandaFileDesc()
|
||||
<< ":" << method->GetRecordNameStr() << "." << CString(method->GetMethodName());
|
||||
uintptr_t codeAddr = machineCodeHandle->GetFuncAddr();
|
||||
FuncEntryDes *funcEntryDes = reinterpret_cast<FuncEntryDes *>(machineCodeHandle->GetFuncEntryDes());
|
||||
jsFunction->SetCompiledFuncEntry(codeAddr, funcEntryDes->isFastCall_);
|
||||
|
@ -2347,6 +2347,17 @@ void Heap::UpdateWorkManager(WorkManager *workManager)
|
||||
partialGC_->workManager_ = workManager;
|
||||
}
|
||||
|
||||
MachineCode *Heap::GetMachineCodeObject(uintptr_t pc) const
|
||||
{
|
||||
MachineCodeSpace *machineCodeSpace = GetMachineCodeSpace();
|
||||
MachineCode *machineCode = reinterpret_cast<MachineCode*>(machineCodeSpace->GetMachineCodeObject(pc));
|
||||
if (machineCode != nullptr) {
|
||||
return machineCode;
|
||||
}
|
||||
HugeMachineCodeSpace *hugeMachineCodeSpace = GetHugeMachineCodeSpace();
|
||||
return reinterpret_cast<MachineCode*>(hugeMachineCodeSpace->GetMachineCodeObject(pc));
|
||||
}
|
||||
|
||||
std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> Heap::CalCallSiteInfo(uintptr_t retAddr) const
|
||||
{
|
||||
MachineCodeSpace *machineCodeSpace = GetMachineCodeSpace();
|
||||
|
@ -1355,6 +1355,7 @@ public:
|
||||
void InstallEdenAllocator();
|
||||
void DumpHeapSnapshotBeforeOOM(bool isFullGC = true);
|
||||
std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr) const;
|
||||
MachineCode *GetMachineCodeObject(uintptr_t pc) const;
|
||||
|
||||
PUBLIC_API GCListenerId AddGCListener(FinishGCListener listener, void *data);
|
||||
PUBLIC_API void RemoveGCListener(GCListenerId listenerId);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "ecmascript/mem/space-inl.h"
|
||||
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/js_tagged_value-inl.h"
|
||||
#include "ecmascript/mem/heap_region_allocator.h"
|
||||
#include "ecmascript/mem/mem_controller.h"
|
||||
#include "ecmascript/mem/region-inl.h"
|
||||
@ -107,6 +108,25 @@ HugeMachineCodeSpace::HugeMachineCodeSpace(Heap *heap, HeapRegionAllocator *heap
|
||||
{
|
||||
}
|
||||
|
||||
uintptr_t HugeMachineCodeSpace::GetMachineCodeObject(uintptr_t pc) const
|
||||
{
|
||||
uintptr_t machineCode = 0;
|
||||
EnumerateRegions([&](Region *region) {
|
||||
if (machineCode != 0) {
|
||||
return;
|
||||
}
|
||||
if (!region->InRange(pc)) {
|
||||
return;
|
||||
}
|
||||
uintptr_t curPtr = region->GetBegin();
|
||||
auto obj = MachineCode::Cast(reinterpret_cast<TaggedObject*>(curPtr));
|
||||
if (obj->IsInText(pc)) {
|
||||
machineCode = curPtr;
|
||||
}
|
||||
});
|
||||
return machineCode;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_JITFORT
|
||||
uintptr_t HugeMachineCodeSpace::Allocate(size_t objectSize, JSThread *thread, size_t instructionsSize,
|
||||
uintptr_t &instructionsAddr, AllocateEventType allocType)
|
||||
|
@ -306,6 +306,7 @@ class HugeMachineCodeSpace : public HugeObjectSpace {
|
||||
public:
|
||||
HugeMachineCodeSpace(Heap *heap, HeapRegionAllocator *regionAllocator, size_t initialCapacity,
|
||||
size_t maximumCapacity);
|
||||
uintptr_t GetMachineCodeObject(uintptr_t pc) const;
|
||||
#ifdef ENABLE_JITFORT
|
||||
uintptr_t Allocate(size_t objectSize, JSThread *thread, size_t instructionsSize, uintptr_t &instructionsAddr,
|
||||
AllocateEventType allocType = AllocateEventType::NORMAL);
|
||||
|
@ -711,4 +711,46 @@ uintptr_t MachineCodeSpace::Allocate(size_t size, MachineCodeDesc &desc, bool al
|
||||
}
|
||||
#endif // ENABLE_JITFORT
|
||||
|
||||
size_t MachineCodeSpace::CheckMachineCodeObject(uintptr_t curPtr, uintptr_t &machineCode, uintptr_t pc)
|
||||
{
|
||||
auto freeObject = FreeObject::Cast(curPtr);
|
||||
size_t objSize = 0;
|
||||
if (!freeObject->IsFreeObject()) {
|
||||
auto obj = MachineCode::Cast(reinterpret_cast<TaggedObject*>(curPtr));
|
||||
if (obj->IsInText(pc)) {
|
||||
machineCode = curPtr;
|
||||
}
|
||||
objSize = obj->GetClass()->SizeFromJSHClass(obj);
|
||||
} else {
|
||||
objSize = freeObject->Available();
|
||||
}
|
||||
return objSize;
|
||||
}
|
||||
|
||||
uintptr_t MachineCodeSpace::GetMachineCodeObject(uintptr_t pc)
|
||||
{
|
||||
uintptr_t machineCode = 0;
|
||||
allocator_->FillBumpPointer();
|
||||
|
||||
EnumerateRegions([&](Region *region) {
|
||||
if (machineCode != 0) {
|
||||
return;
|
||||
}
|
||||
if (region->InCollectSet() || !region->InRange(pc)) {
|
||||
return;
|
||||
}
|
||||
uintptr_t curPtr = region->GetBegin();
|
||||
uintptr_t endPtr = region->GetEnd();
|
||||
while (curPtr < endPtr) {
|
||||
size_t objSize = CheckMachineCodeObject(curPtr, machineCode, pc);
|
||||
if (machineCode != 0) {
|
||||
return;
|
||||
}
|
||||
curPtr += objSize;
|
||||
CHECK_OBJECT_SIZE(objSize);
|
||||
}
|
||||
CHECK_REGION_END(curPtr, endPtr);
|
||||
});
|
||||
return machineCode;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -295,6 +295,9 @@ public:
|
||||
~MachineCodeSpace() override;
|
||||
NO_COPY_SEMANTIC(MachineCodeSpace);
|
||||
NO_MOVE_SEMANTIC(MachineCodeSpace); // Note: Expand() left for define
|
||||
uintptr_t GetMachineCodeObject(uintptr_t pc);
|
||||
size_t CheckMachineCodeObject(uintptr_t curPtr, uintptr_t &machineCode, uintptr_t pc);
|
||||
|
||||
#ifdef ENABLE_JITFORT
|
||||
void FreeRegion(Region *current, bool isMain = true) override;
|
||||
uintptr_t Allocate(size_t size, MachineCodeDesc &desc, bool allowGC = true);
|
||||
|
Loading…
Reference in New Issue
Block a user