diff --git a/common_components/common_runtime/base_runtime.cpp b/common_components/common_runtime/base_runtime.cpp index 0b75a938596e2556c4abed32ab01ea2f8fef165f..d2d428bde23ba3c37c6076fc9a113e64684b9139 100755 --- a/common_components/common_runtime/base_runtime.cpp +++ b/common_components/common_runtime/base_runtime.cpp @@ -174,17 +174,35 @@ void BaseRuntime::WriteBarrier(void* obj, void* field, void* ref) *reinterpret_cast*>(field), reinterpret_cast(ref)); } +void* BaseRuntime::ReadBarrier(ThreadHolder* holder, void* obj, void* field) +{ + return reinterpret_cast(Heap::GetBarrier().ReadRefField(holder, reinterpret_cast(obj), + *reinterpret_cast*>(field))); +} + void* BaseRuntime::ReadBarrier(void* obj, void* field) { return reinterpret_cast(Heap::GetBarrier().ReadRefField(reinterpret_cast(obj), *reinterpret_cast*>(field))); } +void* BaseRuntime::ReadBarrier(ThreadHolder* holder, void* field) +{ + return reinterpret_cast(Heap::GetBarrier().ReadStaticRef(holder, + *reinterpret_cast*>(field))); +} + void* BaseRuntime::ReadBarrier(void* field) { return reinterpret_cast(Heap::GetBarrier().ReadStaticRef(*reinterpret_cast*>(field))); } +void* BaseRuntime::AtomicReadBarrier(ThreadHolder* holder, void* obj, void* field, std::memory_order order) +{ + return reinterpret_cast(Heap::GetBarrier().AtomicReadRefField(holder, reinterpret_cast(obj), + *reinterpret_cast*>(field), order)); +} + void* BaseRuntime::AtomicReadBarrier(void* obj, void* field, std::memory_order order) { return reinterpret_cast(Heap::GetBarrier().AtomicReadRefField(reinterpret_cast(obj), diff --git a/common_components/heap/allocator/region_space.h b/common_components/heap/allocator/region_space.h index 21e8f95120f8832b1100d0cc76747ca243868e9f..298fc08086e772f98c2446251285d445a6fdbe06 100755 --- a/common_components/heap/allocator/region_space.h +++ b/common_components/heap/allocator/region_space.h @@ -209,9 +209,14 @@ public: fromSpace_.ExemptFromRegions(); } - BaseObject* RouteObject(BaseObject* fromObj, size_t size) + BaseObject* RouteObject(ThreadHolder* holder, BaseObject* fromObj, size_t size) { - AllocationBuffer* buffer = AllocationBuffer::GetOrCreateAllocBuffer(); + AllocationBuffer* buffer; + if (holder != nullptr) { + buffer = reinterpret_cast(holder->GetAllocBuffer()); + } else { + buffer = AllocationBuffer::GetOrCreateAllocBuffer(); + } uintptr_t toAddr = buffer->ToSpaceAllocate(size); return reinterpret_cast(toAddr); } diff --git a/common_components/heap/barrier/barrier.cpp b/common_components/heap/barrier/barrier.cpp index 64dbf856385da26d254985eadace264246b401f9..25160010f816b9c5299b9af747f59747f7eb0a20 100755 --- a/common_components/heap/barrier/barrier.cpp +++ b/common_components/heap/barrier/barrier.cpp @@ -64,18 +64,34 @@ BaseObject* Barrier::ReadRefField(BaseObject* obj, RefField& field) const return reinterpret_cast(target); } +BaseObject* Barrier::ReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field) const +{ + return ReadRefField(obj, field); +} + BaseObject* Barrier::ReadStaticRef(RefField& field) const { HeapAddress target = field.GetFieldValue(); return reinterpret_cast(target); } +BaseObject* Barrier::ReadStaticRef(ThreadHolder* holder, RefField& field) const +{ + return ReadStaticRef(field); +} + BaseObject* Barrier::ReadStringTableStaticRef(RefField& field) const { HeapAddress target = field.GetFieldValue(); return reinterpret_cast(target); } +BaseObject* Barrier::ReadStringTableStaticRef(ThreadHolder* holder, RefField& field) const +{ + HeapAddress target = field.GetFieldValue(); + return reinterpret_cast(target); +} + // barrier for atomic operation. void Barrier::AtomicWriteRefField(BaseObject* obj, RefField& field, BaseObject* ref, MemoryOrder order) const { @@ -108,6 +124,12 @@ BaseObject* Barrier::AtomicReadRefField(BaseObject* obj, RefField& field, return (BaseObject*)target; } +BaseObject* Barrier::AtomicReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field, + MemoryOrder order) const +{ + return AtomicReadRefField(obj, field, order); +} + bool Barrier::CompareAndSwapRefField(BaseObject* obj, RefField& field, BaseObject* oldRef, BaseObject* newRef, MemoryOrder succOrder, MemoryOrder failOrder) const { diff --git a/common_components/heap/barrier/barrier.h b/common_components/heap/barrier/barrier.h index db753a32cf248828b0fa95d7396bf33a85b2a6b0..5e36b55772072d1a63c24909ba2945b84dbeeb4c 100755 --- a/common_components/heap/barrier/barrier.h +++ b/common_components/heap/barrier/barrier.h @@ -18,6 +18,7 @@ #include "common_components/common/base_object.h" #include "common_components/common/type_def.h" +#include "thread/thread_holder.h" #include namespace common { @@ -30,8 +31,11 @@ public: virtual ~Barrier() {} virtual BaseObject* ReadRefField(BaseObject* obj, RefField& field) const; + virtual BaseObject* ReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field) const; virtual BaseObject* ReadStaticRef(RefField& field) const; + virtual BaseObject* ReadStaticRef(ThreadHolder* holder, RefField& field) const; virtual BaseObject* ReadStringTableStaticRef(RefField &field) const; + virtual BaseObject* ReadStringTableStaticRef(ThreadHolder* holder, RefField &field) const; virtual void ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const; @@ -48,6 +52,9 @@ public: virtual BaseObject* AtomicReadRefField(BaseObject* obj, RefField& field, MemoryOrder order) const; + virtual BaseObject* AtomicReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field, + MemoryOrder order) const; + virtual void AtomicWriteRefField(BaseObject* obj, RefField& field, BaseObject* ref, MemoryOrder order) const; virtual BaseObject* AtomicSwapRefField(BaseObject* obj, RefField& field, BaseObject* ref, MemoryOrder order) const; diff --git a/common_components/heap/barrier/tests/barrier_test.cpp b/common_components/heap/barrier/tests/barrier_test.cpp index f5f361144535d0724322d91bcb465f7180c6dc9f..f74a854e6dabb560058174d3a025de3a64edf61f 100644 --- a/common_components/heap/barrier/tests/barrier_test.cpp +++ b/common_components/heap/barrier/tests/barrier_test.cpp @@ -46,6 +46,10 @@ public: { return nullptr; } + BaseObject* ForwardObject(ThreadHolder*, BaseObject*) override + { + return nullptr; + } bool ShouldIgnoreRequest(GCRequest&) override { return false; @@ -69,10 +73,19 @@ public: return true; } + bool TryUpdateRefField(ThreadHolder* holder, BaseObject* Obj, RefField<>& field, BaseObject*& toVersion) const override + { + return TryUpdateRefField(Obj, field, toVersion); + } + bool TryForwardRefField(BaseObject*, RefField<>&, BaseObject*&) const override { return false; } + bool TryForwardRefField(ThreadHolder*, BaseObject*, RefField<>&, BaseObject*&) const override + { + return false; + } bool TryUntagRefField(BaseObject*, RefField<>&, BaseObject*&) const override { return false; diff --git a/common_components/heap/collector/collector.h b/common_components/heap/collector/collector.h index fe65398193a5b0ac6cfbb3aab5ecf5f4cba4cafb..69f0f4a883fb67742de342ac95fd791d1f03aab8 100755 --- a/common_components/heap/collector/collector.h +++ b/common_components/heap/collector/collector.h @@ -72,6 +72,7 @@ public: } virtual BaseObject* ForwardObject(BaseObject*) = 0; + virtual BaseObject* ForwardObject(ThreadHolder*, BaseObject*) = 0; virtual bool ShouldIgnoreRequest(GCRequest& quest) = 0; virtual bool IsFromObject(BaseObject*) const = 0; @@ -79,7 +80,9 @@ public: virtual BaseObject* FindToVersion(BaseObject* obj) const = 0; virtual bool TryUpdateRefField(BaseObject*, RefField<>&, BaseObject*&) const = 0; + virtual bool TryUpdateRefField(ThreadHolder*, BaseObject*, RefField<>&, BaseObject*&) const = 0; virtual bool TryForwardRefField(BaseObject*, RefField<>&, BaseObject*&) const = 0; + virtual bool TryForwardRefField(ThreadHolder* holder, BaseObject*, RefField<>&, BaseObject*&) const = 0; virtual bool TryUntagRefField(BaseObject*, RefField<>&, BaseObject*&) const = 0; virtual RefField<> GetAndTryTagRefField(BaseObject*) const = 0; diff --git a/common_components/heap/collector/collector_proxy.h b/common_components/heap/collector/collector_proxy.h index d65c16846219061307dff33cdb538fcaf2925c18..739943dc320b6a5d819ae64ec9b69f5303a74a52 100755 --- a/common_components/heap/collector/collector_proxy.h +++ b/common_components/heap/collector/collector_proxy.h @@ -65,16 +65,32 @@ public: BaseObject* ForwardObject(BaseObject* obj) override { return currentCollector_->ForwardObject(obj); } + BaseObject* ForwardObject(ThreadHolder* holder, BaseObject* obj) override + { + return currentCollector_->ForwardObject(holder, obj); + } + bool TryUpdateRefField(BaseObject* obj, RefField<>& field, BaseObject*& toVersion) const override { return currentCollector_->TryUpdateRefField(obj, field, toVersion); } + bool TryUpdateRefField(ThreadHolder* holder, BaseObject* obj, RefField<>& field, BaseObject*& toVersion) const override + { + return currentCollector_->TryUpdateRefField(holder, obj, field, toVersion); + } + bool TryForwardRefField(BaseObject* obj, RefField<>& field, BaseObject*& toVersion) const override { return currentCollector_->TryForwardRefField(obj, field, toVersion); } + bool TryForwardRefField(ThreadHolder* holder, BaseObject* obj, RefField<>& field, + BaseObject*& toVersion) const override + { + return currentCollector_->TryForwardRefField(holder, obj, field, toVersion); + } + bool TryUntagRefField(BaseObject* obj, RefField<>& field, BaseObject*& target) const override { return currentCollector_->TryUntagRefField(obj, field, target); diff --git a/common_components/heap/collector/trace_collector.h b/common_components/heap/collector/trace_collector.h index 3f41128961cc611cf55ae837e6a0dcf7feb0ee77..310db1d03de2505baeea82d54c7f47dd1072eb84 100755 --- a/common_components/heap/collector/trace_collector.h +++ b/common_components/heap/collector/trace_collector.h @@ -242,7 +242,7 @@ public: void CopyObject(const BaseObject& fromObj, BaseObject& toObj, size_t size) const; protected: - virtual BaseObject* CopyObjectAfterExclusive(BaseObject* obj) = 0; + virtual BaseObject* CopyObjectAfterExclusive(ThreadHolder* holder, BaseObject* obj) = 0; virtual void CopyFromSpace(); virtual void ExemptFromSpace(); diff --git a/common_components/heap/w_collector/copy_barrier.cpp b/common_components/heap/w_collector/copy_barrier.cpp index ee3405bca6be514adff29c28283e4a5f2aa76f8b..2d1d777252dbbd2f2c718320f69cd88963c004a1 100755 --- a/common_components/heap/w_collector/copy_barrier.cpp +++ b/common_components/heap/w_collector/copy_barrier.cpp @@ -43,8 +43,36 @@ BaseObject* CopyBarrier::ReadRefField(BaseObject* obj, RefField& field) c return nullptr; } +BaseObject* CopyBarrier::ReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field) const +{ + do { + RefField<> tmpField(field); + bool isWeak = tmpField.IsWeak(); + BaseObject* oldRef = tmpField.GetTargetObject(); + if (LIKELY_CC(!theCollector.IsFromObject(oldRef))) { + return isWeak ? (BaseObject*)((uintptr_t)oldRef | TAG_WEAK) : oldRef; + } + + BaseObject* toObj = nullptr; + if (UNLIKELY(theCollector.IsUnmovableFromObject(oldRef))) { + return isWeak ? (BaseObject*)((uintptr_t)oldRef | TAG_WEAK) : oldRef; + } + if (UNLIKELY(!theCollector.TryForwardRefField(holder, obj, field, toObj))) { + continue; + } + return isWeak ? (BaseObject*)((uintptr_t)toObj | TAG_WEAK) : toObj; + } while (true); + // unreachable path. + return nullptr; +} + BaseObject* CopyBarrier::ReadStaticRef(RefField& field) const { return ReadRefField(nullptr, field); } +BaseObject* CopyBarrier::ReadStaticRef(ThreadHolder* holder, RefField& field) const +{ + return ReadRefField(holder, nullptr, field); +} + // If the object is still alive, return its toSpace object; if not, return nullptr BaseObject* CopyBarrier::ReadStringTableStaticRef(RefField& field) const { @@ -69,6 +97,27 @@ BaseObject* CopyBarrier::ReadStringTableStaticRef(RefField& field) const } } +BaseObject* CopyBarrier::ReadStringTableStaticRef(ThreadHolder* holder, RefField& field) const +{ + if (Heap::GetHeap().GetGCReason() == GC_REASON_YOUNG) { + return reinterpret_cast(field.GetFieldValue()); + } + + auto isSurvivor = [](BaseObject* obj) { + RegionDesc *regionInfo = + RegionDesc::GetRegionDescAt(reinterpret_cast(obj)); + return (regionInfo->IsNewObjectSinceTrace(obj) || regionInfo->IsToRegion() || regionInfo->IsMarkedObject(obj)); + }; + + RefField<> tmpField(field); + BaseObject* obj = tmpField.GetTargetObject(); + if (obj != nullptr && isSurvivor(obj)) { + return ReadRefField(holder, nullptr, field); + } else { + return nullptr; + } +} + void CopyBarrier::ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const { CHECK_CC(!Heap::IsHeapAddress(dst)); @@ -91,6 +140,15 @@ BaseObject* CopyBarrier::AtomicReadRefField(BaseObject* obj, RefField& fie return target; } +BaseObject* CopyBarrier::AtomicReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field, + MemoryOrder order) const +{ + RefField tmpField(field.GetFieldValue(order)); + BaseObject* target = ReadRefField(holder, nullptr, tmpField); + DLOG(FBARRIER, "atomic read obj %p ref-field@%p: %#zx -> %p", obj, &field, tmpField.GetFieldValue(), target); + return target; +} + void CopyBarrier::AtomicWriteRefField(BaseObject* obj, RefField& field, BaseObject* newRef, MemoryOrder order) const { diff --git a/common_components/heap/w_collector/copy_barrier.h b/common_components/heap/w_collector/copy_barrier.h index 85c8cc0b2c7727d7a242398e6934f368d12865ad..89b10950d5c5b15f33277bb7dd97332ba211f999 100755 --- a/common_components/heap/w_collector/copy_barrier.h +++ b/common_components/heap/w_collector/copy_barrier.h @@ -25,12 +25,17 @@ public: explicit CopyBarrier(Collector& collector) : IdleBarrier(collector) {} BaseObject* ReadRefField(BaseObject* obj, RefField& field) const override; + BaseObject* ReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field) const override; BaseObject* ReadStaticRef(RefField& field) const override; + BaseObject* ReadStaticRef(ThreadHolder* holder, RefField& field) const override; BaseObject* ReadStringTableStaticRef(RefField& field) const override; + BaseObject* ReadStringTableStaticRef(ThreadHolder* holder, RefField& field) const override; void ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const override; BaseObject* AtomicReadRefField(BaseObject* obj, RefField& field, MemoryOrder order) const override; + BaseObject* AtomicReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field, + MemoryOrder order) const override; void AtomicWriteRefField(BaseObject* obj, RefField& field, BaseObject* ref, MemoryOrder order) const override; diff --git a/common_components/heap/w_collector/enum_barrier.cpp b/common_components/heap/w_collector/enum_barrier.cpp index d26670c13c0b9aaac76954cedf0dbbafdfdc3cf7..cbc6e9aa14d60a7bd03a8effd86dfbbb72e4cb4b 100755 --- a/common_components/heap/w_collector/enum_barrier.cpp +++ b/common_components/heap/w_collector/enum_barrier.cpp @@ -28,8 +28,18 @@ BaseObject* EnumBarrier::ReadRefField(BaseObject* obj, RefField& field) c return (BaseObject*)tmpField.GetFieldValue(); } +BaseObject* EnumBarrier::ReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field) const +{ + return ReadRefField(obj, field); +} + BaseObject* EnumBarrier::ReadStaticRef(RefField& field) const { return ReadRefField(nullptr, field); } +BaseObject* EnumBarrier::ReadStaticRef(ThreadHolder* holder, RefField& field) const +{ + return ReadStaticRef(field); +} + void EnumBarrier::ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const { CHECK_CC(memcpy_s(reinterpret_cast(dst), size, reinterpret_cast(src), size) == EOK); @@ -137,6 +147,12 @@ BaseObject* EnumBarrier::AtomicReadRefField(BaseObject* obj, RefField& fie return target; } +BaseObject* EnumBarrier::AtomicReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field, + MemoryOrder order) const +{ + return AtomicReadRefField(obj, field, order); +} + BaseObject* EnumBarrier::AtomicSwapRefField(BaseObject* obj, RefField& field, BaseObject* newRef, MemoryOrder order) const { diff --git a/common_components/heap/w_collector/enum_barrier.h b/common_components/heap/w_collector/enum_barrier.h index 40017f4e03263886119e71de4434979f3ab380bf..68160c431560f34b0f2d1baa789bebbd73e940bf 100755 --- a/common_components/heap/w_collector/enum_barrier.h +++ b/common_components/heap/w_collector/enum_barrier.h @@ -25,7 +25,9 @@ public: explicit EnumBarrier(Collector& collector) : IdleBarrier(collector) {} BaseObject* ReadRefField(BaseObject* obj, RefField& field) const override; + BaseObject* ReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field) const override; BaseObject* ReadStaticRef(RefField& field) const override; + BaseObject* ReadStaticRef(ThreadHolder* holder, RefField& field) const override; void ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const override; void WriteRoot(BaseObject *obj) const override; @@ -36,6 +38,8 @@ public: void WriteStaticRef(RefField& field, BaseObject* ref) const override; BaseObject* AtomicReadRefField(BaseObject* obj, RefField& field, MemoryOrder order) const override; + BaseObject* AtomicReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field, + MemoryOrder order) const override; void AtomicWriteRefField(BaseObject* obj, RefField& field, BaseObject* ref, MemoryOrder order) const override; diff --git a/common_components/heap/w_collector/idle_barrier.cpp b/common_components/heap/w_collector/idle_barrier.cpp index 79a4649bcdec5b3e6c2cbc3d1bb4155bba72b65c..850529e05b24f80161da86d9519acb03a9967d5b 100755 --- a/common_components/heap/w_collector/idle_barrier.cpp +++ b/common_components/heap/w_collector/idle_barrier.cpp @@ -27,8 +27,17 @@ BaseObject* IdleBarrier::ReadRefField(BaseObject* obj, RefField& field) c return (BaseObject*)(oldField.GetFieldValue()); } +BaseObject* IdleBarrier::ReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field) const +{ + return ReadRefField(obj, field); +} + BaseObject* IdleBarrier::ReadStaticRef(RefField& field) const { return ReadRefField(nullptr, field); } +BaseObject* IdleBarrier::ReadStaticRef(ThreadHolder* holder, RefField& field) const +{ + return ReadStaticRef(field); +} BaseObject* IdleBarrier::AtomicReadRefField(BaseObject* obj, RefField& field, MemoryOrder order) const { RefField oldField(field.GetFieldValue(order)); @@ -37,6 +46,12 @@ BaseObject* IdleBarrier::AtomicReadRefField(BaseObject* obj, RefField& fie return target; } +BaseObject* IdleBarrier::AtomicReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field, + MemoryOrder order) const +{ + return AtomicReadRefField(obj, field, order); +} + void IdleBarrier::ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const { LOGF_CHECK(memcpy_s(reinterpret_cast(dst), size, reinterpret_cast(src), size) == EOK) << diff --git a/common_components/heap/w_collector/idle_barrier.h b/common_components/heap/w_collector/idle_barrier.h index 0014562a89e4b8096ec7e041e56354d371b99531..4d6d4c7315cf749f33dbedf471d24817e785398a 100755 --- a/common_components/heap/w_collector/idle_barrier.h +++ b/common_components/heap/w_collector/idle_barrier.h @@ -25,7 +25,9 @@ public: explicit IdleBarrier(Collector& collector) : Barrier(collector) {} BaseObject* ReadRefField(BaseObject* obj, RefField& field) const override; + BaseObject* ReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field) const override; BaseObject* ReadStaticRef(RefField& field) const override; + BaseObject* ReadStaticRef(ThreadHolder* holder, RefField& field) const override; void ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const override; void WriteRoot(BaseObject *obj) const override; @@ -36,6 +38,8 @@ public: void WriteStruct(BaseObject* obj, HeapAddress dst, size_t dstLen, HeapAddress src, size_t srcLen) const override; BaseObject* AtomicReadRefField(BaseObject* obj, RefField& field, MemoryOrder order) const override; + BaseObject* AtomicReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field, + MemoryOrder order) const override; void AtomicWriteRefField(BaseObject* obj, RefField& field, BaseObject* ref, MemoryOrder order) const override; diff --git a/common_components/heap/w_collector/post_trace_barrier.cpp b/common_components/heap/w_collector/post_trace_barrier.cpp index 6288c1d30810ece916035a2efd7c00aac9ef7751..7eab0efc96b189bb097081e3b9fa5705953f69b1 100755 --- a/common_components/heap/w_collector/post_trace_barrier.cpp +++ b/common_components/heap/w_collector/post_trace_barrier.cpp @@ -28,8 +28,18 @@ BaseObject* PostTraceBarrier::ReadRefField(BaseObject* obj, RefField& fie return (BaseObject*)tmpField.GetFieldValue(); } +BaseObject* PostTraceBarrier::ReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field) const +{ + return ReadRefField(obj, field); +} + BaseObject* PostTraceBarrier::ReadStaticRef(RefField& field) const { return ReadRefField(nullptr, field); } +BaseObject* PostTraceBarrier::ReadStaticRef(ThreadHolder* holder, RefField& field) const +{ + return ReadStaticRef(field); +} + // If the object is still alive, return it; if not, return nullptr BaseObject* PostTraceBarrier::ReadStringTableStaticRef(RefField &field) const { @@ -53,6 +63,11 @@ BaseObject* PostTraceBarrier::ReadStringTableStaticRef(RefField &field) c } } +BaseObject* PostTraceBarrier::ReadStringTableStaticRef(ThreadHolder* holder, RefField &field) const +{ + return ReadStringTableStaticRef(field); +} + void PostTraceBarrier::ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const { CHECK_CC(memcpy_s(reinterpret_cast(dst), size, reinterpret_cast(src), size) == EOK); @@ -100,6 +115,12 @@ BaseObject* PostTraceBarrier::AtomicReadRefField(BaseObject* obj, RefField return target; } +BaseObject* PostTraceBarrier::AtomicReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field, + MemoryOrder order) const +{ + return AtomicReadRefField(obj, field, order); +} + void PostTraceBarrier::AtomicWriteRefField(BaseObject* obj, RefField& field, BaseObject* newRef, MemoryOrder order) const { diff --git a/common_components/heap/w_collector/post_trace_barrier.h b/common_components/heap/w_collector/post_trace_barrier.h index 924d18afedad0bd73396562312a293d84aad396d..0858a2d50c4aa41a635c8addc5e8a1f77b679da6 100755 --- a/common_components/heap/w_collector/post_trace_barrier.h +++ b/common_components/heap/w_collector/post_trace_barrier.h @@ -26,8 +26,11 @@ public: explicit PostTraceBarrier(Collector& collector) : IdleBarrier(collector) {} BaseObject* ReadRefField(BaseObject* obj, RefField& field) const override; + BaseObject* ReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field) const override; BaseObject* ReadStaticRef(RefField& field) const override; + BaseObject* ReadStaticRef(ThreadHolder* holder, RefField& field) const override; BaseObject* ReadStringTableStaticRef(RefField& field) const override; + BaseObject* ReadStringTableStaticRef(ThreadHolder* holder, RefField& field) const override; void ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const override; @@ -37,6 +40,8 @@ public: void WriteStaticRef(RefField& field, BaseObject* ref) const override; BaseObject* AtomicReadRefField(BaseObject* obj, RefField& field, MemoryOrder order) const override; + BaseObject* AtomicReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field, + MemoryOrder order) const override; void AtomicWriteRefField(BaseObject* obj, RefField& field, BaseObject* ref, MemoryOrder order) const override; BaseObject* AtomicSwapRefField(BaseObject* obj, RefField& field, BaseObject* ref, diff --git a/common_components/heap/w_collector/preforward_barrier.cpp b/common_components/heap/w_collector/preforward_barrier.cpp index 47af6eddb2bca5e8d9caf4a144fe7f90d934aefb..1a41e7efb3aae895d6b840d178b247fdefbacd39 100755 --- a/common_components/heap/w_collector/preforward_barrier.cpp +++ b/common_components/heap/w_collector/preforward_barrier.cpp @@ -44,8 +44,33 @@ BaseObject* PreforwardBarrier::ReadRefField(BaseObject* obj, RefField& fi return nullptr; } +BaseObject* PreforwardBarrier::ReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field) const +{ + do { + RefField<> tmpField(field); + BaseObject* oldRef = reinterpret_cast(tmpField.GetAddress()); + if (LIKELY_CC(!static_cast(&theCollector)->IsFromObject(oldRef))) { + return oldRef; + } + + auto weakMask = reinterpret_cast(oldRef) & TAG_WEAK; + oldRef = reinterpret_cast(reinterpret_cast(oldRef) & (~TAG_WEAK)); + BaseObject* toObj = nullptr; + if (static_cast(&theCollector)->TryForwardRefField(holder, obj, field, toObj)) { + return (BaseObject*)((uintptr_t)toObj | weakMask); + } + } while (true); + // unreachable path. + return nullptr; +} + BaseObject* PreforwardBarrier::ReadStaticRef(RefField& field) const { return ReadRefField(nullptr, field); } +BaseObject* PreforwardBarrier::ReadStaticRef(ThreadHolder* holder, RefField& field) const +{ + return ReadRefField(holder, nullptr, field); +} + // If the object is still alive, return its toSpace object; if not, return nullptr BaseObject* PreforwardBarrier::ReadStringTableStaticRef(RefField& field) const { @@ -71,6 +96,28 @@ BaseObject* PreforwardBarrier::ReadStringTableStaticRef(RefField& field) } } +BaseObject* PreforwardBarrier::ReadStringTableStaticRef(ThreadHolder* holder, RefField& field) const +{ + if (Heap::GetHeap().GetGCReason() == GC_REASON_YOUNG) { + return reinterpret_cast(field.GetFieldValue()); + } + + auto isSurvivor = [](BaseObject* obj) { + auto gcReason = Heap::GetHeap().GetGCReason(); + RegionDesc *regionInfo = + RegionDesc::GetRegionDescAt(reinterpret_cast(obj)); + return (regionInfo->IsNewObjectSinceTrace(obj) || regionInfo->IsToRegion() || regionInfo->IsMarkedObject(obj)); + }; + + RefField<> tmpField(field); + BaseObject* obj = tmpField.GetTargetObject(); + if (obj != nullptr && isSurvivor(obj)) { + return ReadRefField(holder, nullptr, field); + } else { + return nullptr; + } +} + void PreforwardBarrier::ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const { @@ -97,6 +144,15 @@ BaseObject* PreforwardBarrier::AtomicReadRefField(BaseObject* obj, RefField& field, + MemoryOrder order) const +{ + RefField tmpField(field.GetFieldValue(order)); + BaseObject* target = ReadRefField(holder, nullptr, tmpField); + DLOG(PBARRIER, "atomic read obj %p ref@%p: %#zx -> %p", obj, &field, tmpField.GetFieldValue(), target); + return target; +} + void PreforwardBarrier::AtomicWriteRefField(BaseObject* obj, RefField& field, BaseObject* newRef, MemoryOrder order) const { diff --git a/common_components/heap/w_collector/preforward_barrier.h b/common_components/heap/w_collector/preforward_barrier.h index 6abd8d8854e46cfc330965bd9f90469c66a52c77..1065d7b13203928e070a93196ea5ef0694dbf0b9 100755 --- a/common_components/heap/w_collector/preforward_barrier.h +++ b/common_components/heap/w_collector/preforward_barrier.h @@ -26,12 +26,17 @@ public: explicit PreforwardBarrier(Collector& collector) : IdleBarrier(collector) {} BaseObject* ReadRefField(BaseObject* obj, RefField& field) const override; + BaseObject* ReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field) const override; BaseObject* ReadStaticRef(RefField& field) const override; + BaseObject* ReadStaticRef(ThreadHolder* holder, RefField& field) const override; BaseObject* ReadStringTableStaticRef(RefField& field) const override; + BaseObject* ReadStringTableStaticRef(ThreadHolder* holder, RefField& field) const override; void ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const override; BaseObject* AtomicReadRefField(BaseObject* obj, RefField& field, MemoryOrder order) const override; + BaseObject* AtomicReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field, + MemoryOrder order) const override; void AtomicWriteRefField(BaseObject* obj, RefField& field, BaseObject* ref, MemoryOrder order) const override; diff --git a/common_components/heap/w_collector/remark_barrier.cpp b/common_components/heap/w_collector/remark_barrier.cpp index ea7a063bd56d94ad2fe77c86117aadc2f4cae84a..ec781d64b221724047b0db0f590ac96065f01cc6 100644 --- a/common_components/heap/w_collector/remark_barrier.cpp +++ b/common_components/heap/w_collector/remark_barrier.cpp @@ -28,8 +28,17 @@ BaseObject* RemarkBarrier::ReadRefField(BaseObject* obj, RefField& field) return reinterpret_cast(tmpField.GetFieldValue()); } +BaseObject* RemarkBarrier::ReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field) const +{ + return ReadRefField(obj, field); +} + BaseObject* RemarkBarrier::ReadStaticRef(RefField& field) const { return ReadRefField(nullptr, field); } +BaseObject* RemarkBarrier::ReadStaticRef(ThreadHolder* holder, RefField& field) const +{ + return ReadStaticRef(field); +} // If the object is still alive, return it; if not, return nullptr BaseObject* RemarkBarrier::ReadStringTableStaticRef(RefField &field) const @@ -54,6 +63,11 @@ BaseObject* RemarkBarrier::ReadStringTableStaticRef(RefField &field) cons } } +BaseObject* RemarkBarrier::ReadStringTableStaticRef(ThreadHolder* holder, RefField &field) const +{ + return ReadStringTableStaticRef(field); +} + void RemarkBarrier::ReadStruct(HeapAddress dst, BaseObject *obj, HeapAddress src, size_t size) const { CHECK_CC(memcpy_s(reinterpret_cast(dst), size, reinterpret_cast(src), size) == EOK); @@ -160,6 +174,12 @@ BaseObject* RemarkBarrier::AtomicReadRefField(BaseObject* obj, RefField& f return target; } +BaseObject* RemarkBarrier::AtomicReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field, + MemoryOrder order) const +{ + return AtomicReadRefField(obj, field, order); +} + void RemarkBarrier::AtomicWriteRefField(BaseObject *obj, RefField &field, BaseObject *newRef, MemoryOrder order) const diff --git a/common_components/heap/w_collector/remark_barrier.h b/common_components/heap/w_collector/remark_barrier.h index 0cda0539c1db069c5adabe00504765dd455a28e2..86105833fc9f983ab60d684bf63a4ff0e0dbeec6 100644 --- a/common_components/heap/w_collector/remark_barrier.h +++ b/common_components/heap/w_collector/remark_barrier.h @@ -25,9 +25,12 @@ public: explicit RemarkBarrier(Collector& collector) : IdleBarrier(collector) {} BaseObject* ReadRefField(BaseObject* obj, RefField& field) const override; + BaseObject* ReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field) const override; BaseObject* ReadStaticRef(RefField& field) const override; + BaseObject* ReadStaticRef(ThreadHolder* holder, RefField& field) const override; void ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const override; BaseObject* ReadStringTableStaticRef(RefField &field) const override; + BaseObject* ReadStringTableStaticRef(ThreadHolder* holder, RefField &field) const override; void WriteRoot(BaseObject *obj) const override; void WriteRefField(BaseObject* obj, RefField& field, BaseObject* ref) const override; @@ -36,6 +39,8 @@ public: void WriteStaticRef(RefField& field, BaseObject* ref) const override; BaseObject* AtomicReadRefField(BaseObject* obj, RefField& field, MemoryOrder order) const override; + BaseObject* AtomicReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field, + MemoryOrder order) const override; void AtomicWriteRefField(BaseObject* obj, RefField& field, BaseObject* ref, MemoryOrder order) const override; BaseObject* AtomicSwapRefField(BaseObject* obj, RefField& field, BaseObject* ref, diff --git a/common_components/heap/w_collector/tests/mock_barrier_collector.h b/common_components/heap/w_collector/tests/mock_barrier_collector.h index 1465518624739194a3071e32bdb6c5b3a1b4b801..d7759c68643e2785df5aac3b80c34bce4791244c 100755 --- a/common_components/heap/w_collector/tests/mock_barrier_collector.h +++ b/common_components/heap/w_collector/tests/mock_barrier_collector.h @@ -27,6 +27,10 @@ public: { return nullptr; } + BaseObject* ForwardObject(ThreadHolder*, BaseObject*) override + { + return nullptr; + } bool ShouldIgnoreRequest(GCRequest&) override { return false; @@ -50,10 +54,19 @@ public: return true; } + bool TryUpdateRefField(ThreadHolder* holder, BaseObject* obj, RefField<>& field, BaseObject*& toVersion) const override + { + return TryUpdateRefField(obj, field, toVersion); + } + bool TryForwardRefField(BaseObject*, RefField<>&, BaseObject*&) const override { return false; } + bool TryForwardRefField(ThreadHolder*, BaseObject*, RefField<>&, BaseObject*&) const override + { + return false; + } bool TryUntagRefField(BaseObject*, RefField<>&, BaseObject*&) const override { return false; @@ -90,6 +103,10 @@ public: return true; } + bool TryForwardRefField(ThreadHolder*, BaseObject*, RefField<>&, BaseObject*&) const override + { + return true; + } }; } // namespace common diff --git a/common_components/heap/w_collector/tests/w_collector_test.cpp b/common_components/heap/w_collector/tests/w_collector_test.cpp index 9d3b2f59f57f01cbc86e88c34200fd1d24bd5329..05d98468e77c8ef70188f39f52cebc9fb801d9ec 100644 --- a/common_components/heap/w_collector/tests/w_collector_test.cpp +++ b/common_components/heap/w_collector/tests/w_collector_test.cpp @@ -218,10 +218,12 @@ public: explicit TestCreateTraceWCollector(Allocator& allocator, CollectorResources& resources) : TraceCollector(allocator, resources) {} BaseObject* ForwardObject(BaseObject*) override { return nullptr; } + BaseObject* ForwardObject(ThreadHolder*, BaseObject*) override { return nullptr; } bool IsFromObject(BaseObject*) const override { return false; } bool IsUnmovableFromObject(BaseObject*) const override { return false; } BaseObject* FindToVersion(BaseObject* obj) const override { return nullptr; } bool TryUpdateRefField(BaseObject*, RefField<>&, BaseObject*&) const override { return false; } + bool TryUpdateRefField(ThreadHolder*, BaseObject*, RefField<>&, BaseObject*&) const override { return false; } bool TryForwardRefField(BaseObject*, RefField<>&, BaseObject*&) const override { return false; } bool TryUntagRefField(BaseObject*, RefField<>&, BaseObject*&) const override { return false; } RefField<> GetAndTryTagRefField(BaseObject*) const override { return RefField<>(nullptr); } @@ -230,7 +232,7 @@ public: void RemoveRawPointerObject(BaseObject*) override {} bool MarkObject(BaseObject* obj) const override { return false; } void TraceObjectRefFields(BaseObject *obj, TraceRefFieldVisitor *data) override {} - BaseObject* CopyObjectAfterExclusive(BaseObject* obj) override { return nullptr; } + BaseObject* CopyObjectAfterExclusive(ThreadHolder* holder, BaseObject* obj) override { return nullptr; } void DoGarbageCollection() override {} bool IsCurrentPointer(RefField<>&) const override { return false; } TraceRefFieldVisitor CreateTraceObjectRefFieldsVisitor(WorkStack *workStack, WeakStack *weakStack) override @@ -298,7 +300,7 @@ HWTEST_F_L0(WCollectorTest, ForwardUpdateRawRef_TEST1) ObjectRef root; root.object = obj; - auto ret = wcollector->ForwardUpdateRawRef(root); + auto ret = wcollector->ForwardUpdateRawRef(Mutator::GetMutator()->GetThreadHolder(), root); EXPECT_TRUE(wcollector->IsFromObject(obj)); EXPECT_EQ(ret, obj); } @@ -325,7 +327,7 @@ HWTEST_F_L0(WCollectorTest, ForwardObject_TEST1) TestForwardNullObject staticObject; obj->RegisterStatic(&staticObject); - auto ret = wcollector->ForwardObject(obj); + auto ret = wcollector->ForwardObject(Mutator::GetMutator()->GetThreadHolder(), obj); EXPECT_EQ(ret, obj); } @@ -346,7 +348,7 @@ HWTEST_F_L0(WCollectorTest, CopyObjectImpl_TEST1) TestForwardNullObject staticObject; obj->RegisterStatic(&staticObject); - auto ret = wcollector->CopyObjectImpl(obj); + auto ret = wcollector->CopyObjectImpl(Mutator::GetMutator()->GetThreadHolder(), obj); EXPECT_TRUE(ret == nullptr); } @@ -357,7 +359,7 @@ HWTEST_F_L0(WCollectorTest, TryUpdateRefFieldImpl_TEST1) RefField<> field(nullptr); BaseObject* obj = nullptr; - bool ret = wcollector->TryUpdateRefField(nullptr, field, obj); + bool ret = wcollector->TryUpdateRefField(Mutator::GetMutator()->GetThreadHolder(), nullptr, field, obj); EXPECT_FALSE(ret); } @@ -371,7 +373,7 @@ HWTEST_F_L0(WCollectorTest, TryUpdateRefFieldImpl_TEST2) region->SetRegionType(RegionDesc::RegionType::FROM_REGION); BaseObject* obj = reinterpret_cast(addr); RefField field(obj); - bool ret = wcollector->TryUpdateRefField(nullptr, field, obj); + bool ret = wcollector->TryUpdateRefField(Mutator::GetMutator()->GetThreadHolder(), nullptr, field, obj); EXPECT_FALSE(ret); } @@ -393,7 +395,7 @@ HWTEST_F_L0(WCollectorTest, TryUpdateRefFieldImpl_TEST3) obj->RegisterStatic(&staticObject); RefField field(obj); - bool ret = wcollector->TryForwardRefField(nullptr, field, obj); + bool ret = wcollector->TryForwardRefField(Mutator::GetMutator()->GetThreadHolder(), nullptr, field, obj); EXPECT_FALSE(ret); } @@ -415,7 +417,7 @@ HWTEST_F_L0(WCollectorTest, TryUpdateRefFieldImpl_TEST4) obj->RegisterStatic(&staticObject); RefField field(obj); - bool ret = wcollector->TryForwardRefField(nullptr, field, obj); + bool ret = wcollector->TryForwardRefField(Mutator::GetMutator()->GetThreadHolder(), nullptr, field, obj); EXPECT_TRUE(ret); } } // namespace common::test diff --git a/common_components/heap/w_collector/trace_barrier.cpp b/common_components/heap/w_collector/trace_barrier.cpp index da286f75beb96b334678075451004478d3b08b31..07a5ef66d93dbbe2d8787d5595cab0689034b4c7 100755 --- a/common_components/heap/w_collector/trace_barrier.cpp +++ b/common_components/heap/w_collector/trace_barrier.cpp @@ -28,8 +28,18 @@ BaseObject* TraceBarrier::ReadRefField(BaseObject* obj, RefField& field) return (BaseObject*)tmpField.GetFieldValue(); } +BaseObject* TraceBarrier::ReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field) const +{ + return ReadRefField(obj, field); +} + BaseObject* TraceBarrier::ReadStaticRef(RefField& field) const { return ReadRefField(nullptr, field); } +BaseObject* TraceBarrier::ReadStaticRef(ThreadHolder* holder, RefField& field) const +{ + return ReadStaticRef(field); +} + void TraceBarrier::ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const { CHECK_CC(memcpy_s(reinterpret_cast(dst), size, reinterpret_cast(src), size) == EOK); @@ -137,6 +147,12 @@ BaseObject* TraceBarrier::AtomicReadRefField(BaseObject* obj, RefField& fi return target; } +BaseObject* TraceBarrier::AtomicReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field, + MemoryOrder order) const +{ + return AtomicReadRefField(obj, field, order); +} + void TraceBarrier::AtomicWriteRefField(BaseObject* obj, RefField& field, BaseObject* newRef, MemoryOrder order) const { diff --git a/common_components/heap/w_collector/trace_barrier.h b/common_components/heap/w_collector/trace_barrier.h index aaacd4ed17dba876b4cfc7604b7363b418e28bd9..5fc6b476604072c2f2ff9e9635f8be6306ae39ec 100755 --- a/common_components/heap/w_collector/trace_barrier.h +++ b/common_components/heap/w_collector/trace_barrier.h @@ -26,7 +26,9 @@ public: explicit TraceBarrier(Collector& collector) : IdleBarrier(collector) {} BaseObject* ReadRefField(BaseObject* obj, RefField& field) const override; + BaseObject* ReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field) const override; BaseObject* ReadStaticRef(RefField& field) const override; + BaseObject* ReadStaticRef(ThreadHolder* holder, RefField& field) const override; void ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const override; void WriteRoot(BaseObject *obj) const override; @@ -36,6 +38,8 @@ public: void WriteStaticRef(RefField& field, BaseObject* ref) const override; BaseObject* AtomicReadRefField(BaseObject* obj, RefField& field, MemoryOrder order) const override; + BaseObject* AtomicReadRefField(ThreadHolder* holder, BaseObject* obj, RefField& field, + MemoryOrder order) const override; void AtomicWriteRefField(BaseObject* obj, RefField& field, BaseObject* ref, MemoryOrder order) const override; BaseObject* AtomicSwapRefField(BaseObject* obj, RefField& field, BaseObject* ref, diff --git a/common_components/heap/w_collector/w_collector.cpp b/common_components/heap/w_collector/w_collector.cpp index 5fbff3e5a212e90ec656d183960ab159eadfdb82..956d545be3b8d15711be16f353c368083d37482a 100755 --- a/common_components/heap/w_collector/w_collector.cpp +++ b/common_components/heap/w_collector/w_collector.cpp @@ -54,63 +54,82 @@ bool WCollector::MarkObject(BaseObject* obj) const } // this api updates current pointer as well as old pointer, caller should take care of this. -template -bool WCollector::TryUpdateRefFieldImpl(BaseObject* obj, RefField<>& field, BaseObject*& fromObj, +template +bool WCollector::TryUpdateRefFieldImpl(ThreadHolder* holder, BaseObject* obj, RefField<>& field, BaseObject*& fromObj, BaseObject*& toObj) const { RefField<> oldRef(field); fromObj = oldRef.GetTargetObject(); - if (IsFromObject(fromObj)) { //LCOV_EXCL_BR_LINE - if (copy) { //LCOV_EXCL_BR_LINE + if (!IsFromObject(fromObj)) { //LCOV_EXCL_BR_LINE + return false; + } + if (copy) { //LCOV_EXCL_BR_LINE + if constexpr (thread == ThreadMode::GC_THREAD) { toObj = const_cast(this)->TryForwardObject(fromObj); - if (toObj != nullptr) { //LCOV_EXCL_BR_LINE - HeapProfilerListener::GetInstance().OnMoveEvent(reinterpret_cast(fromObj), - reinterpret_cast(toObj), - toObj->GetSize()); - } - } else { //LCOV_EXCL_BR_LINE - toObj = FindToVersion(fromObj); + } else { + toObj = const_cast(this)->TryForwardObject(holder, fromObj); } - if (toObj == nullptr) { //LCOV_EXCL_BR_LINE - return false; + if (toObj != nullptr) { //LCOV_EXCL_BR_LINE + HeapProfilerListener::GetInstance().OnMoveEvent(reinterpret_cast(fromObj), + reinterpret_cast(toObj), + toObj->GetSize()); } - RefField<> tmpField(toObj, oldRef.IsWeak()); - if (field.CompareExchange(oldRef.GetFieldValue(), tmpField.GetFieldValue())) { //LCOV_EXCL_BR_LINE - if (obj != nullptr) { //LCOV_EXCL_BR_LINE - DLOG(TRACE, "update obj %p<%p>(%zu)+%zu ref-field@%p: %#zx -> %#zx", obj, obj->GetTypeInfo(), - obj->GetSize(), BaseObject::FieldOffset(obj, &field), &field, oldRef.GetFieldValue(), - tmpField.GetFieldValue()); - } else { //LCOV_EXCL_BR_LINE - DLOG(TRACE, "update ref@%p: 0x%zx -> %p", &field, oldRef.GetFieldValue(), toObj); - } - return true; + } else { //LCOV_EXCL_BR_LINE + toObj = FindToVersion(fromObj); + } + if (toObj == nullptr) { //LCOV_EXCL_BR_LINE + return false; + } + RefField<> tmpField(toObj, oldRef.IsWeak()); + if (field.CompareExchange(oldRef.GetFieldValue(), tmpField.GetFieldValue())) { //LCOV_EXCL_BR_LINE + if (obj != nullptr) { //LCOV_EXCL_BR_LINE + DLOG(TRACE, "update obj %p<%p>(%zu)+%zu ref-field@%p: %#zx -> %#zx", obj, obj->GetTypeInfo(), + obj->GetSize(), BaseObject::FieldOffset(obj, &field), &field, oldRef.GetFieldValue(), + tmpField.GetFieldValue()); } else { //LCOV_EXCL_BR_LINE - if (obj != nullptr) { //LCOV_EXCL_BR_LINE - DLOG(TRACE, - "update obj %p<%p>(%zu)+%zu but cas failed ref-field@%p: %#zx(%#zx) -> %#zx but cas failed ", - obj, obj->GetTypeInfo(), obj->GetSize(), BaseObject::FieldOffset(obj, &field), &field, - oldRef.GetFieldValue(), field.GetFieldValue(), tmpField.GetFieldValue()); - } else { //LCOV_EXCL_BR_LINE - DLOG(TRACE, "update but cas failed ref@%p: 0x%zx(%zx) -> %p", &field, oldRef.GetFieldValue(), - field.GetFieldValue(), toObj); - } - return true; + DLOG(TRACE, "update ref@%p: 0x%zx -> %p", &field, oldRef.GetFieldValue(), toObj); + } + return true; + } else { //LCOV_EXCL_BR_LINE + if (obj != nullptr) { //LCOV_EXCL_BR_LINE + DLOG(TRACE, + "update obj %p<%p>(%zu)+%zu but cas failed ref-field@%p: %#zx(%#zx) -> %#zx but cas failed ", + obj, obj->GetTypeInfo(), obj->GetSize(), BaseObject::FieldOffset(obj, &field), &field, + oldRef.GetFieldValue(), field.GetFieldValue(), tmpField.GetFieldValue()); + } else { //LCOV_EXCL_BR_LINE + DLOG(TRACE, "update but cas failed ref@%p: 0x%zx(%zx) -> %p", &field, oldRef.GetFieldValue(), + field.GetFieldValue(), toObj); } + return true; } - - return false; } bool WCollector::TryUpdateRefField(BaseObject* obj, RefField<>& field, BaseObject*& newRef) const { BaseObject* oldRef = nullptr; - return TryUpdateRefFieldImpl(obj, field, oldRef, newRef); + ASSERT(IsGcThread()); + return TryUpdateRefFieldImpl( + nullptr, obj, field, oldRef, newRef); +} + +bool WCollector::TryUpdateRefField(ThreadHolder* holder, BaseObject* obj, RefField<>& field, BaseObject*& newRef) const +{ + BaseObject* oldRef = nullptr; + return TryUpdateRefFieldImpl( + holder, obj, field, oldRef, newRef); } bool WCollector::TryForwardRefField(BaseObject* obj, RefField<>& field, BaseObject*& newRef) const { BaseObject* oldRef = nullptr; - return TryUpdateRefFieldImpl(obj, field, oldRef, newRef); + ASSERT(IsGcThread()); + return TryUpdateRefFieldImpl(nullptr, obj, field, oldRef, newRef); +} + +bool WCollector::TryForwardRefField(ThreadHolder* holder, BaseObject* obj, RefField<>& field, BaseObject*& newRef) const +{ + BaseObject* oldRef = nullptr; + return TryUpdateRefFieldImpl(holder, obj, field, oldRef, newRef); } // this api untags current pointer as well as old pointer, caller should take care of this. @@ -281,6 +300,29 @@ BaseObject* WCollector::ForwardUpdateRawRef(ObjectRef& root) return oldObj; } +BaseObject* WCollector::ForwardUpdateRawRef(ThreadHolder* holder, ObjectRef& root) +{ + auto& refField = reinterpret_cast&>(root); + RefField<> oldField(refField); + BaseObject* oldObj = oldField.GetTargetObject(); + DLOG(FIX, "try fix raw-ref @%p: %p", &root, oldObj); + if (IsFromObject(oldObj)) { + BaseObject* toVersion = TryForwardObject(holder, oldObj); + CHECK_CC(toVersion != nullptr); + HeapProfilerListener::GetInstance().OnMoveEvent(reinterpret_cast(oldObj), + reinterpret_cast(toVersion), + toVersion->GetSize()); + RefField<> newField(toVersion); + // CAS failure means some mutator or gc thread writes a new ref (must be a to-object), no need to retry. + if (refField.CompareExchange(oldField.GetFieldValue(), newField.GetFieldValue())) { + DLOG(FIX, "fix raw-ref @%p: %p -> %p", &root, oldObj, toVersion); + return toVersion; + } + } + + return oldObj; +} + class RemarkAndPreforwardVisitor { public: RemarkAndPreforwardVisitor(WorkStack &localStack, WCollector *collector) @@ -959,20 +1001,39 @@ BaseObject* WCollector::ForwardObject(BaseObject* obj) return (to != nullptr) ? to : obj; } +BaseObject* WCollector::ForwardObject(ThreadHolder* holder, BaseObject* obj) +{ + BaseObject* to = TryForwardObject(holder, obj); + if (to != nullptr) { + HeapProfilerListener::GetInstance().OnMoveEvent(reinterpret_cast(obj), + reinterpret_cast(to), + to->GetSize()); + } + return (to != nullptr) ? to : obj; +} + BaseObject* WCollector::TryForwardObject(BaseObject* obj) { - return CopyObjectImpl(obj); + return CopyObjectImpl(nullptr, obj); +} + +BaseObject* WCollector::TryForwardObject(ThreadHolder* holder, BaseObject* obj) +{ + // must not be gc thread + return CopyObjectImpl(holder, obj); } // ConcurrentGC -BaseObject* WCollector::CopyObjectImpl(BaseObject* obj) +template +BaseObject* WCollector::CopyObjectImpl(ThreadHolder* holder, BaseObject* obj) { // reconsider phase difference between mutator and GC thread during transition. - if (IsGcThread()) { + if constexpr (thread == ThreadMode::GC_THREAD) { CHECK_CC(GetGCPhase() == GCPhase::GC_PHASE_PRECOPY || GetGCPhase() == GCPhase::GC_PHASE_COPY || GetGCPhase() == GCPhase::GC_PHASE_FIX || GetGCPhase() == GCPhase::GC_PHASE_FINAL_MARK); } else { - auto phase = Mutator::GetMutator()->GetMutatorPhase(); + ASSERT(holder != nullptr); + auto phase = holder->GetMutatorPhase(); CHECK_CC(phase == GCPhase::GC_PHASE_PRECOPY || phase == GCPhase::GC_PHASE_COPY || phase == GCPhase::GC_PHASE_FIX); } @@ -996,7 +1057,7 @@ BaseObject* WCollector::CopyObjectImpl(BaseObject* obj) // 3. hope we can copy this object if (obj->TryLockExclusive(oldWord)) { - return CopyObjectAfterExclusive(obj); + return CopyObjectAfterExclusive(holder, obj); } } while (true); LOG_COMMON(FATAL) << "forwardObject exit in wrong path"; @@ -1004,7 +1065,7 @@ BaseObject* WCollector::CopyObjectImpl(BaseObject* obj) return nullptr; } -BaseObject* WCollector::CopyObjectAfterExclusive(BaseObject* obj) +BaseObject* WCollector::CopyObjectAfterExclusive(ThreadHolder* holder, BaseObject* obj) { size_t size = RegionSpace::GetAllocSize(*obj); // 8: size of free object, but free object can not be copied. @@ -1012,7 +1073,7 @@ BaseObject* WCollector::CopyObjectAfterExclusive(BaseObject* obj) LOG_COMMON(FATAL) << "forward free obj: " << obj << "is survived: " << (IsSurvivedObject(obj) ? "true" : "false"); } - BaseObject* toObj = fwdTable_.RouteObject(obj, size); + BaseObject* toObj = fwdTable_.RouteObject(holder, obj, size); if (toObj == nullptr) { //LCOV_EXCL_BR_LINE Heap::throwOOM(); // ConcurrentGC diff --git a/common_components/heap/w_collector/w_collector.h b/common_components/heap/w_collector/w_collector.h index 9613a4eb3a7c8e58584e16835d17efff5764b0ec..d1b8b13bfb8a4f530d8cc3ce1f27441df8bc01c1 100755 --- a/common_components/heap/w_collector/w_collector.h +++ b/common_components/heap/w_collector/w_collector.h @@ -29,9 +29,9 @@ public: explicit CopyTable(RegionSpace& space) : theSpace(space) {} // if object is not relocated (forwarded or compacted), return nullptr. - BaseObject* RouteObject(BaseObject* old, size_t size) + BaseObject* RouteObject(ThreadHolder* holder, BaseObject* old, size_t size) { - BaseObject* toAddress = theSpace.RouteObject(old, size); + BaseObject* toAddress = theSpace.RouteObject(holder, old, size); return toAddress; } @@ -49,6 +49,11 @@ enum class GCMode: uint8_t { STW = 2 }; +enum class ThreadMode: bool { + GC_THREAD, + MUTATOR_THREAD +}; + class WCollector : public TraceCollector { public: explicit WCollector(Allocator& allocator, CollectorResources& resources) @@ -92,6 +97,8 @@ public: BaseObject* ForwardObject(BaseObject* fromVersion) override; + BaseObject* ForwardObject(ThreadHolder* holder, BaseObject* fromVersion) override; + bool IsOldPointer(RefField<>& ref) const override { return false; } bool IsCurrentPointer(RefField<>& ref) const override { return false; } @@ -110,6 +117,8 @@ public: BaseObject* ForwardUpdateRawRef(ObjectRef& ref); + BaseObject* ForwardUpdateRawRef(ThreadHolder* holder, ObjectRef& ref); + bool IsFromObject(BaseObject* obj) const override { // filter const string object. @@ -134,14 +143,19 @@ public: void SetGCThreadQosPriority(common::PriorityMode mode); - BaseObject* CopyObjectImpl(BaseObject* obj); - BaseObject* CopyObjectAfterExclusive(BaseObject* obj) override; + template + BaseObject* CopyObjectImpl(ThreadHolder* holder, BaseObject* obj); + BaseObject* CopyObjectAfterExclusive(ThreadHolder* holder, BaseObject* obj) override; BaseObject* TryForwardObject(BaseObject* fromVersion); + BaseObject* TryForwardObject(ThreadHolder* holder, BaseObject* fromVersion); bool TryUntagRefField(BaseObject* obj, RefField<>& field, BaseObject*& target) const override; bool TryUpdateRefField(BaseObject* obj, RefField<>& field, BaseObject*& newRef) const override; + bool TryUpdateRefField(ThreadHolder* holder, BaseObject* obj, RefField<>& field, BaseObject*& newRef) const override; bool TryForwardRefField(BaseObject* obj, RefField<>& field, BaseObject*& newRef) const override; + bool TryForwardRefField(ThreadHolder* holder, BaseObject* obj, RefField<>& field, + BaseObject*& newRef) const override; RefField<> GetAndTryTagRefField(BaseObject* target) const override { @@ -181,8 +195,9 @@ protected: private: friend class RemarkAndPreforwardVisitor; - template - bool TryUpdateRefFieldImpl(BaseObject* obj, RefField<>& ref, BaseObject*& oldRef, BaseObject*& newRef) const; + template + bool TryUpdateRefFieldImpl(ThreadHolder* holder, BaseObject* obj, RefField<>& ref, BaseObject*& oldRef, + BaseObject*& newRef) const; enum class EnumRootsPolicy { NO_STW_AND_NO_FLIP_MUTATOR, diff --git a/common_components/objects/base_string_table.cpp b/common_components/objects/base_string_table.cpp index d8d3cc807341c5128fd7543f05bd4b95e3e42bf1..afe64fb8bdd6ee7c66fed6bc914ff8806305c3c5 100644 --- a/common_components/objects/base_string_table.cpp +++ b/common_components/objects/base_string_table.cpp @@ -48,14 +48,14 @@ BaseString* BaseStringTableInternal::GetOrInternFlattenString( if (string->IsInternString()) { return string; } - auto readBarrier = [](void* obj, size_t offset)-> BaseObject* { + auto readBarrier = [holder](void* obj, size_t offset)-> BaseObject* { return BaseObject::Cast( reinterpret_cast(BaseRuntime::ReadBarrier( - obj, reinterpret_cast(reinterpret_cast(obj) + offset)))); + holder, obj, reinterpret_cast(reinterpret_cast(obj) + offset)))); }; uint32_t hashcode = string->GetHashcode(readBarrier); // Strings in string table should not be in the young space. - auto loadResult = stringTable_.template Load(readBarrier, hashcode, string); + auto loadResult = stringTable_.template Load(holder, readBarrier, hashcode, string); if (loadResult.value != nullptr) { return loadResult.value; } @@ -74,12 +74,12 @@ BaseString* BaseStringTableInternal::GetOrInternStringFromCompr { const uint8_t* utf8Data = string->GetDataUtf8() + offset; uint32_t hashcode = BaseString::ComputeHashcodeUtf8(utf8Data, utf8Len, true); - auto readBarrier = [](void* obj, size_t offset)-> BaseObject* { + auto readBarrier = [holder](void* obj, size_t offset)-> BaseObject* { return BaseObject::Cast( reinterpret_cast(BaseRuntime::ReadBarrier( - obj, reinterpret_cast(reinterpret_cast(obj) + offset)))); + holder, obj, reinterpret_cast(reinterpret_cast(obj) + offset)))); }; - auto loadResult = stringTable_.template Load(readBarrier, hashcode, string, offset, utf8Len); + auto loadResult = stringTable_.template Load(holder, readBarrier, hashcode, string, offset, utf8Len); if (loadResult.value != nullptr) { return loadResult.value; } @@ -99,12 +99,12 @@ BaseString* BaseStringTableInternal::GetOrInternStringFromCompr ReadOnlyHandle strHandle = handleCreator(holder, str); return strHandle; }, - [utf8Len, string, offset](const BaseString* foundString) { + [holder, utf8Len, string, offset](const BaseString* foundString) { const uint8_t* utf8Data = string->GetDataUtf8() + offset; - auto readBarrier = [](void* obj, size_t offset)-> BaseObject* { + auto readBarrier = [holder](void* obj, size_t offset)-> BaseObject* { return BaseObject::Cast( reinterpret_cast(BaseRuntime::ReadBarrier( - obj, reinterpret_cast(reinterpret_cast(obj) + offset)))); + holder, obj, reinterpret_cast(reinterpret_cast(obj) + offset)))); }; return BaseString::StringIsEqualUint8Data(readBarrier, foundString, utf8Data, utf8Len, true); }); @@ -134,11 +134,11 @@ BaseString* BaseStringTableInternal::GetOrInternString(ThreadHo ReadOnlyHandle stringHandle = handleCreator(holder, value); return stringHandle; }, - [utf8Data, utf8Len, canBeCompress](BaseString* foundString) { - auto readBarrier = [](void* obj, size_t offset)-> BaseObject* { + [holder, utf8Data, utf8Len, canBeCompress](BaseString* foundString) { + auto readBarrier = [holder](void* obj, size_t offset)-> BaseObject* { return BaseObject::Cast( reinterpret_cast(BaseRuntime::ReadBarrier( - obj, reinterpret_cast(reinterpret_cast(obj) + offset)))); + holder, obj, reinterpret_cast(reinterpret_cast(obj) + offset)))); }; return BaseString::StringIsEqualUint8Data(readBarrier, foundString, utf8Data, utf8Len, canBeCompress); @@ -170,11 +170,11 @@ BaseString* BaseStringTableInternal::GetOrInternString( ReadOnlyHandle stringHandle = handleCreator(holder, value); return stringHandle; }, - [utf16Data, utf16Len](BaseString* foundString) { - auto readBarrier = [](void* obj, size_t offset)-> BaseObject* { + [holder, utf16Data, utf16Len](BaseString* foundString) { + auto readBarrier = [holder](void* obj, size_t offset)-> BaseObject* { return BaseObject::Cast( reinterpret_cast(BaseRuntime::ReadBarrier( - obj, reinterpret_cast(reinterpret_cast(obj) + offset)))); + holder, obj, reinterpret_cast(reinterpret_cast(obj) + offset)))); }; return BaseString::StringsAreEqualUtf16(readBarrier, foundString, utf16Data, utf16Len); }); @@ -191,7 +191,7 @@ BaseString* BaseStringTableInternal::TryGetInternString(const R obj, reinterpret_cast(reinterpret_cast(obj) + offset)))); }; uint32_t hashcode = string->GetHashcode(readBarrier); - return stringTable_.template Load(readBarrier, hashcode, *string); + return stringTable_.template Load(nullptr, readBarrier, hashcode, *string); } template diff --git a/common_components/objects/string_table/hashtriemap-inl.h b/common_components/objects/string_table/hashtriemap-inl.h index 5c2e301411cb748170c0a24d5310726745b1e1db..8651c3c6abcd5401dca0bfde4c706a5749043561 100644 --- a/common_components/objects/string_table/hashtriemap-inl.h +++ b/common_components/objects/string_table/hashtriemap-inl.h @@ -73,7 +73,8 @@ typename HashTrieMap::Node* HashTrieMap template -BaseString* HashTrieMap::Load(ReadBarrier&& readBarrier, const uint32_t key, +BaseString* HashTrieMap::Load(ThreadHolder* holder, + ReadBarrier&& readBarrier, const uint32_t key, BaseString* value) { uint32_t hash = key; @@ -94,7 +95,7 @@ BaseString* HashTrieMap::Load(ReadBarrier&& re } for (Entry* currentEntry = node->AsEntry(); currentEntry != nullptr; currentEntry = currentEntry->Overflow().load(std::memory_order_acquire)) { - auto oldValue = currentEntry->Value(); + auto oldValue = currentEntry->Value(holder); bool valuesEqual = false; if (!IsNull(oldValue) && BaseString::StringsAreEqual(std::forward(readBarrier), oldValue, value)) { @@ -155,7 +156,7 @@ BaseString* HashTrieMap::LoadOrStore(ThreadHol } for (Entry* currentEntry = node->AsEntry(); currentEntry != nullptr; currentEntry = currentEntry->Overflow().load(std::memory_order_acquire)) { - auto oldValue = currentEntry->Value(); + auto oldValue = currentEntry->Value(holder); if (IsNull(oldValue)) { continue; } @@ -207,7 +208,7 @@ BaseString* HashTrieMap::LoadOrStore(ThreadHol oldEntry = node->AsEntry(); for (Entry* currentEntry = oldEntry; currentEntry; currentEntry = currentEntry->Overflow().load(std::memory_order_acquire)) { - auto oldValue = currentEntry->Value(); + auto oldValue = currentEntry->Value(holder); if (IsNull(oldValue)) { continue; } @@ -283,7 +284,7 @@ BaseString* HashTrieMap::LoadOrStoreForJit(Thr } for (Entry* currentEntry = node->AsEntry(); currentEntry != nullptr; currentEntry = currentEntry->Overflow().load(std::memory_order_acquire)) { - auto oldValue = currentEntry->Value(); + auto oldValue = currentEntry->Value(holder); if (IsNull(oldValue)) { continue; } @@ -322,7 +323,7 @@ BaseString* HashTrieMap::LoadOrStoreForJit(Thr oldEntry = node->AsEntry(); for (Entry* currentEntry = oldEntry; currentEntry; currentEntry = currentEntry->Overflow().load(std::memory_order_acquire)) { - auto oldValue = currentEntry->Value(); + auto oldValue = currentEntry->Value(holder); if (IsNull(oldValue)) { continue; } @@ -396,7 +397,7 @@ BaseString* HashTrieMap::StoreOrLoad(ThreadHol if (node->IsEntry()) { for (Entry* currentEntry = node->AsEntry(); currentEntry != nullptr; currentEntry = currentEntry->Overflow().load(std::memory_order_acquire)) { - auto oldValue = currentEntry->Value(); + auto oldValue = currentEntry->Value(holder); if (!IsNull(oldValue) && std::invoke(std::forward(equalsCallback), oldValue)) { return oldValue; @@ -432,7 +433,7 @@ BaseString* HashTrieMap::StoreOrLoad(ThreadHol oldEntry = node->AsEntry(); for (Entry* currentEntry = oldEntry; currentEntry != nullptr; currentEntry = currentEntry->Overflow().load(std::memory_order_acquire)) { - auto oldValue = currentEntry->Value(); + auto oldValue = currentEntry->Value(holder); if (IsNull(oldValue)) { continue; } @@ -471,7 +472,7 @@ BaseString* HashTrieMap::StoreOrLoad(ThreadHol // Load returns the value of the key stored in the mapping, or HashTrieMapLoadResult for StoreOrLoad template template -HashTrieMapLoadResult HashTrieMap::Load(ReadBarrier&& readBarrier, +HashTrieMapLoadResult HashTrieMap::Load(ThreadHolder* holder, ReadBarrier&& readBarrier, const uint32_t key, BaseString* value) { uint32_t hash = key; @@ -488,7 +489,7 @@ HashTrieMapLoadResult HashTrieMap::Load(ReadBa if (node->IsEntry()) { for (Entry* currentEntry = node->AsEntry(); currentEntry != nullptr; currentEntry = currentEntry->Overflow().load(std::memory_order_acquire)) { - auto oldValue = currentEntry->Value(); + auto oldValue = currentEntry->Value(holder); if (IsNull(oldValue)) { continue; } @@ -508,7 +509,8 @@ HashTrieMapLoadResult HashTrieMap::Load(ReadBa // Load returns the value of the key stored in the mapping, or HashTrieMapLoadResult for StoreOrLoad template template -HashTrieMapLoadResult HashTrieMap::Load(ReadBarrier&& readBarrier, const uint32_t key, +HashTrieMapLoadResult HashTrieMap::Load(ThreadHolder* holder, + ReadBarrier&& readBarrier, const uint32_t key, const ReadOnlyHandle& string, uint32_t offset, uint32_t utf8Len) { @@ -530,7 +532,7 @@ HashTrieMapLoadResult HashTrieMap::Load(ReadBa } for (Entry* currentEntry = node->AsEntry(); currentEntry != nullptr; currentEntry = currentEntry->Overflow().load(std::memory_order_acquire)) { - auto oldValue = currentEntry->Value(); + auto oldValue = currentEntry->Value(holder); if (IsNull(oldValue)) { continue; } @@ -591,7 +593,7 @@ BaseString* HashTrieMap::StoreOrLoad(ThreadHol } for (Entry* currentEntry = node->AsEntry(); currentEntry != nullptr; currentEntry = currentEntry->Overflow().load(std::memory_order_acquire)) { - BaseString* oldValue = currentEntry->Value(); + auto oldValue = currentEntry->Value(holder); if (IsNull(oldValue)) { continue; } @@ -631,7 +633,7 @@ BaseString* HashTrieMap::StoreOrLoad(ThreadHol oldEntry = node->AsEntry(); for (Entry* currentEntry = oldEntry; currentEntry != nullptr; currentEntry = currentEntry->Overflow().load(std::memory_order_acquire)) { - BaseString* oldValue = currentEntry->Value(); + auto oldValue = currentEntry->Value(holder); if (IsNull(oldValue)) { continue; } @@ -693,7 +695,7 @@ bool HashTrieMap::CheckValidity(ReadBarrier&& return false; } uint32_t hashcode = value->GetHashcode(std::forward(readBarrier)); - if (this->template Load(std::forward(readBarrier), hashcode, value) != nullptr) { + if (this->template Load(nullptr, std::forward(readBarrier), hashcode, value) != nullptr) { isValid = false; return false; } diff --git a/common_components/objects/string_table/hashtriemap.h b/common_components/objects/string_table/hashtriemap.h index bfb992d093f9b9fa134d777ee9c2ec54b3dcc989..1d96e6ff55d47fd7369c1b98268d20b9746cc289 100644 --- a/common_components/objects/string_table/hashtriemap.h +++ b/common_components/objects/string_table/hashtriemap.h @@ -95,6 +95,21 @@ public: *reinterpret_cast*>((void*)(&value)))); } + template + BaseString* Value(ThreadHolder* holder) const + { + uint64_t value = Pointer::Decode(bitField_); + if constexpr (SlotBarrier == TrieMapConfig::NoSlotBarrier) { + return reinterpret_cast(static_cast(value)); + } + if constexpr (std::is_same_v) { + return reinterpret_cast(Heap::GetBarrier().ReadStringTableStaticRef(holder, + *reinterpret_cast*>((void*)(&value)))); + } + return reinterpret_cast(Heap::GetBarrier().ReadStringTableStaticRef( + *reinterpret_cast*>((void*)(&value)))); + } + void SetValue(BaseString* v) { // Note: CMC GC assumes string is always a non-young object and tries to optimize it out in young GC @@ -267,20 +282,20 @@ public: } #endif template - LoadResult Load(ReadBarrier&& readBarrier, const uint32_t key, BaseString* value); + LoadResult Load(ThreadHolder* holder, ReadBarrier&& readBarrier, const uint32_t key, BaseString* value); template BaseString* StoreOrLoad(ThreadHolder* holder, ReadBarrier&& readBarrier, const uint32_t key, LoadResult loadResult, HandleType str); template - LoadResult Load(ReadBarrier&& readBarrier, const uint32_t key, const ReadOnlyHandle& string, + LoadResult Load(ThreadHolder* holder, ReadBarrier&& readBarrier, const uint32_t key, const ReadOnlyHandle& string, uint32_t offset, uint32_t utf8Len); template BaseString* StoreOrLoad(ThreadHolder* holder, const uint32_t key, LoadResult loadResult, LoaderCallback loaderCallback, EqualsCallback equalsCallback); template - BaseString* Load(ReadBarrier&& readBarrier, const uint32_t key, BaseString* value); + BaseString* Load(ThreadHolder* holder, ReadBarrier&& readBarrier, const uint32_t key, BaseString* value); template BaseString* LoadOrStore(ThreadHolder* holder, const uint32_t key, LoaderCallback loaderCallback, EqualsCallback equalsCallback); diff --git a/ecmascript/ecma_macros.h b/ecmascript/ecma_macros.h index 68a8cab37b17b368df78c27b920e2cb65e7e9f24..19a64ff5930fe0ba755a5c395b7bd519959a9b2f 100644 --- a/ecmascript/ecma_macros.h +++ b/ecmascript/ecma_macros.h @@ -95,6 +95,13 @@ /* dynamically-typed languages like JavaScript. So we simply skip the read-barrier. */ \ return JSTaggedValue(Barriers::GetTaggedValue(thread, this, offset)); \ } \ + JSTaggedValue Get##name(common::ThreadHolder *holder) const \ + { \ + FIELD_ACCESS_CHECK(needCheck, name, check); \ + /* Note: We can't statically decide the element type is a primitive or heap object, especially for */ \ + /* dynamically-typed languages like JavaScript. So we simply skip the read-barrier. */ \ + return JSTaggedValue(Barriers::GetTaggedValue(holder, this, offset)); \ + } \ template \ void Set##name(const JSThread *thread, JSHandle value) \ { \ @@ -136,6 +143,11 @@ { \ return JSTaggedValue(Barriers::GetTaggedValue(thread, this, offset)); \ } \ + template \ + JSTaggedValue Get##name(common::ThreadHolder* holder) const \ + { \ + return JSTaggedValue(Barriers::GetTaggedValue(holder, this, offset)); \ + } \ #define ACCESSORS_DCHECK(name, offset, endOffset, check) \ ACCESSORS_WITH_DCHECK_BASE(name, offset, endOffset, true, check) @@ -192,7 +204,13 @@ { \ FIELD_ACCESS_CHECK(true, name, check); \ return JSTaggedValue(Barriers::GetTaggedValueAtomic(thread, this, offset)); \ - } + } \ + template \ + JSTaggedValue Get##name(common::ThreadHolder *holder) const \ + { \ + FIELD_ACCESS_CHECK(true, name, check); \ + return JSTaggedValue(Barriers::GetTaggedValueAtomic(holder, this, offset)); \ + } \ // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define DEFINE_ALIGN_SIZE(offset) \ diff --git a/ecmascript/ecma_string_table_optimization.cpp b/ecmascript/ecma_string_table_optimization.cpp index 615cd3d83e087fae99f8de5f8ce59cbafab3cf07..99806ab89983102a04e3569df43d1e00f41fb4b4 100644 --- a/ecmascript/ecma_string_table_optimization.cpp +++ b/ecmascript/ecma_string_table_optimization.cpp @@ -104,7 +104,7 @@ EcmaString* EcmaStringTableImpl::GetOrInternFlattenString(EcmaVM* vm, Ec auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * { return Barriers::GetTaggedObject(thread, obj, offset); }; - auto loadResult = stringTable_.template Load(std::move(readBarrier), hashcode, string->ToBaseString()); + auto loadResult = stringTable_.template Load(GetThreadHolder(thread), std::move(readBarrier), hashcode, string->ToBaseString()); if (loadResult.value != nullptr) { return EcmaString::FromBaseString(loadResult.value); } @@ -137,7 +137,7 @@ EcmaString* EcmaStringTableImpl::GetOrInternFlattenStringNoGC(EcmaVM* vm auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * { return Barriers::GetTaggedObject(thread, obj, offset); }; - auto loadResult = stringTable_.template Load(readBarrier, hashcode, string->ToBaseString()); + auto loadResult = stringTable_.template Load(GetThreadHolder(thread), readBarrier, hashcode, string->ToBaseString()); if (loadResult.value != nullptr) { return EcmaString::FromBaseString(loadResult.value); } @@ -160,7 +160,7 @@ EcmaString* EcmaStringTableImpl::GetOrInternStringFromCompressedSubStrin auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * { return Barriers::GetTaggedObject(thread, obj, offset); }; - auto loadResult = stringTable_.template Load(std::move(readBarrier), hashcode, string, offset, utf8Len); + auto loadResult = stringTable_.template Load(GetThreadHolder(thread), std::move(readBarrier), hashcode, string, offset, utf8Len); if (loadResult.value != nullptr) { return EcmaString::FromBaseString(loadResult.value); } @@ -210,7 +210,7 @@ EcmaString *EcmaStringTableImpl::GetOrInternString(EcmaVM *vm, EcmaStrin auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * { return Barriers::GetTaggedObject(thread, obj, offset); }; - auto loadResult = stringTable_.template Load(readBarrier, hashcode, strFlat->ToBaseString()); + auto loadResult = stringTable_.template Load(GetThreadHolder(thread), readBarrier, hashcode, strFlat->ToBaseString()); if (loadResult.value != nullptr) { return EcmaString::FromBaseString(loadResult.value); } @@ -315,7 +315,7 @@ EcmaString* EcmaStringTableImpl::GetOrInternString(EcmaVM* vm, const uin auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * { return Barriers::GetTaggedObject(thread, obj, offset); }; - auto loadResult = stringTable_.template Load(std::move(readBarrier), hashcode, str->ToBaseString()); + auto loadResult = stringTable_.template Load(GetThreadHolder(thread), std::move(readBarrier), hashcode, str->ToBaseString()); if (loadResult.value != nullptr) { return EcmaString::FromBaseString(loadResult.value); } @@ -370,7 +370,7 @@ EcmaString *EcmaStringTableImpl::TryGetInternString(JSThread *thread, co return Barriers::GetTaggedObject(thread, obj, offset); }; return EcmaString::FromBaseString( - stringTable_.template Load(std::move(readBarrier), hashcode, str->ToBaseString())); + stringTable_.template Load(GetThreadHolder(thread), std::move(readBarrier), hashcode, str->ToBaseString())); } // used in jit thread, which unsupport create jshandle diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 6365f8406c13f7c6cb217bd5625d146bcd046dbf..f5a378e2e802ef540e84b6ab6cf4cabcaaa9f34c 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -463,7 +463,7 @@ EcmaVM::~EcmaVM() DFXJSNApi::StopTracing(this); } #endif - moduleManagers_.DestroyAllNativeObj(); + moduleManagers_.DestroyAllNativeObj(thread_); if (!isBundlePack_) { std::shared_ptr jsPandaFile = JSPandaFileManager::GetInstance()->FindJSPandaFile(assetPath_); @@ -2173,11 +2173,11 @@ void EcmaVM::ModuleManagers::PushBack(T v) moduleManagersVec_.push_back(v); } -void EcmaVM::ModuleManagers::DestroyAllNativeObj() +void EcmaVM::ModuleManagers::DestroyAllNativeObj(JSThread *thread) { LockHolder lock(CMCGCMutex_); for (auto &moduleManager : moduleManagersVec_) { - moduleManager->NativeObjDestory(); + moduleManager->NativeObjDestory(thread); } } diff --git a/ecmascript/ecma_vm.h b/ecmascript/ecma_vm.h index 3e128cf2cf4f50264b291cf0b64daa3d3965550e..7366bfa9629b4c8f1d72830dcdff74ae812964f1 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -1616,6 +1616,7 @@ private: void PushBack(T moduleManager); void DestroyAllNativeObj(); + void DestroyAllNativeObj(JSThread *thread); void Clear(); } moduleManagers_; diff --git a/ecmascript/ic/profile_type_info.h b/ecmascript/ic/profile_type_info.h index 48ded9bf0d21a94fe1b11fa407d5dbec2cbbe76b..e0b32444fa38091547c24aa56429072a07afcb9d 100644 --- a/ecmascript/ic/profile_type_info.h +++ b/ecmascript/ic/profile_type_info.h @@ -247,6 +247,11 @@ public: return JSTaggedValue(Barriers::GetTaggedValue(thread, GetData(), GetExtraInfoMapOffset())); } + JSTaggedValue GetExtraInfoMap(ThreadHolder *holder) const + { + return JSTaggedValue(Barriers::GetTaggedValue(holder, GetData(), GetExtraInfoMapOffset())); + } + void SetExtraInfoMap(const JSThread *thread, JSHandle extraInfoMap) { Barriers::SetObject(thread, reinterpret_cast(this), diff --git a/ecmascript/js_function.cpp b/ecmascript/js_function.cpp index 0e84f8822c5903948982329a2737be1246e5797d..9b6c2d07bdfafc665059f99662cb16fe980fa74c 100644 --- a/ecmascript/js_function.cpp +++ b/ecmascript/js_function.cpp @@ -1296,6 +1296,15 @@ bool JSFunction::IsSendableOrConcurrentFunction(JSThread *thread) const return false; } +bool JSFunction::IsSendableOrConcurrentFunction(ThreadHolder *holder) const +{ + if (this->GetClass()->IsJSSharedFunction() || this->GetClass()->IsJSSharedAsyncFunction() || + this->GetFunctionKind(holder) == ecmascript::FunctionKind::CONCURRENT_FUNCTION) { + return true; + } + return false; +} + bool JSFunction::IsSharedFunction() const { if (this->GetClass()->IsJSSharedFunction() || this->GetClass()->IsJSSharedAsyncFunction()) { diff --git a/ecmascript/js_function.h b/ecmascript/js_function.h index 589958f4f8ae085cac71d0c3d7d9998d95e724b5..f0fa68e29de35ad18d3d06473193fef5eb971465 100644 --- a/ecmascript/js_function.h +++ b/ecmascript/js_function.h @@ -65,6 +65,12 @@ public: return Method::ConstCast(method.GetTaggedObject())->GetFunctionKind(); } + FunctionKind GetFunctionKind(ThreadHolder *holder) const + { + JSTaggedValue method = GetMethod(holder); + return Method::ConstCast(method.GetTaggedObject())->GetFunctionKind(); + } + void SetCompiledFuncEntry(uintptr_t codeEntry, bool isFastCall); void SetIsCompiledFastCall(bool isFastCall) @@ -367,6 +373,13 @@ public: !ProfileTypeInfoCell::Cast(GetRawProfileTypeInfo(thread))->GetValue(thread).IsUndefined(); } + inline bool HasProfileTypeInfo(ThreadHolder *holder) const + { + // TODO + return GetRawProfileTypeInfo(holder).IsProfileTypeInfoCell() && + !ProfileTypeInfoCell::Cast(GetRawProfileTypeInfo(holder))->GetValue(holder).IsUndefined(); + } + static void SetFunctionExtraInfo(JSThread *thread, const JSHandle &func, void *nativeFunc, const NativePointerCallback &deleter, void *data, size_t nativeBindingsize = 0, Concurrent isConcurrent = Concurrent::NO); @@ -387,6 +400,11 @@ public: JSTaggedValue raw = GetRawProfileTypeInfo(thread); return ProfileTypeInfoCell::Cast(raw.GetTaggedObject())->GetValue(thread); } + JSTaggedValue GetProfileTypeInfo(ThreadHolder *holder) const + { + JSTaggedValue raw = GetRawProfileTypeInfo(holder); + return ProfileTypeInfoCell::Cast(raw.GetTaggedObject())->GetValue(holder); + } void SetJitCompiledFuncEntry(JSThread *thread, JSHandle &machineCode, bool isFastCall); void SetJitHotnessCnt(const JSThread *thread, uint16_t cnt); @@ -398,6 +416,7 @@ public: const JSHandle &newFunc); bool IsSendableOrConcurrentFunction(JSThread *thread) const; + bool IsSendableOrConcurrentFunction(ThreadHolder *holder) const; bool IsSharedFunction() const; static uint32_t CalcuExpotedOfProperties(JSThread *thread, const JSHandle &fun, diff --git a/ecmascript/js_hclass-inl.h b/ecmascript/js_hclass-inl.h index ab5584bb2349eb0bc4e5e9db32aa3566b12d2f4f..92e99b2d12af1a583a0b3053222f27e21d7b51b2 100644 --- a/ecmascript/js_hclass-inl.h +++ b/ecmascript/js_hclass-inl.h @@ -298,6 +298,19 @@ inline JSHClass *JSHClass::FindRootHClass(const JSThread *thread, JSHClass *hcla return root; } +inline JSHClass *JSHClass::FindRootHClass(ThreadHolder *holder, JSHClass *hclass) +{ + auto root = hclass; + while (!ProfileType(root->GetProfileType()).IsRootType()) { + auto parent = root->GetParent(holder); + if (!parent.IsJSHClass()) { + break; + } + root = JSHClass::Cast(parent.GetTaggedObject()); + } + return root; +} + inline JSTaggedValue JSHClass::FindProtoHClass(const JSThread *thread, JSHClass *hclass) { auto proto = hclass->GetProto(thread); @@ -308,6 +321,16 @@ inline JSTaggedValue JSHClass::FindProtoHClass(const JSThread *thread, JSHClass return JSTaggedValue::Undefined(); } +inline JSTaggedValue JSHClass::FindProtoHClass(ThreadHolder *holder, JSHClass *hclass) +{ + auto proto = hclass->GetProto(holder); + if (proto.IsJSObject()) { + auto prototypeObj = JSObject::Cast(proto); + return JSTaggedValue(prototypeObj->GetClass()); + } + return JSTaggedValue::Undefined(); +} + inline JSTaggedValue JSHClass::FindProtoRootHClass(const JSThread *thread, JSHClass *hclass) { auto proto = hclass->GetProto(thread); @@ -319,6 +342,17 @@ inline JSTaggedValue JSHClass::FindProtoRootHClass(const JSThread *thread, JSHCl return JSTaggedValue::Undefined(); } +inline JSTaggedValue JSHClass::FindProtoRootHClass(ThreadHolder *holder, JSHClass *hclass) +{ + auto proto = hclass->GetProto(holder); + if (proto.IsJSObject()) { + auto prototypeObj = JSObject::Cast(proto); + auto prototypeHClass = prototypeObj->GetClass(); + return JSTaggedValue(JSHClass::FindRootHClass(holder, prototypeHClass)); + } + return JSTaggedValue::Undefined(); +} + inline void JSHClass::UpdateRootHClass(const JSThread *thread, const JSHandle &parent, const JSHandle &child) { @@ -336,6 +370,15 @@ inline int JSHClass::FindPropertyEntry(const JSThread *thread, JSHClass *hclass, return entry; } +// inline int JSHClass::FindPropertyEntry(ThreadHolder *holder, JSHClass *hclass, JSTaggedValue key) +// { +// DISALLOW_GARBAGE_COLLECTION; +// LayoutInfo *layout = LayoutInfo::Cast(hclass->GetLayout(holder).GetTaggedObject()); +// uint32_t propsNumber = hclass->NumberOfProps(); +// int entry = layout->FindElementWithCache(holder, hclass, key, propsNumber); +// return entry; +// } + inline void JSHClass::CompleteObjSizeTracking(const JSThread *thread) { if (!IsObjSizeTrackingInProgress()) { diff --git a/ecmascript/js_hclass.h b/ecmascript/js_hclass.h index 5b4acbc7f29c14b16251264e7d5143bf51f48187..421a486486afb14bd302d45021411c117b6a789a 100644 --- a/ecmascript/js_hclass.h +++ b/ecmascript/js_hclass.h @@ -2079,12 +2079,16 @@ public: inline void ObjSizeTrackingStep(const JSThread *thread); inline static JSHClass *FindRootHClass(const JSThread *thread, JSHClass *hclass); + inline static JSHClass *FindRootHClass(ThreadHolder *holder, JSHClass *hclass); inline static JSTaggedValue FindProtoHClass(const JSThread *thread, JSHClass *hclass); + inline static JSTaggedValue FindProtoHClass(ThreadHolder *holder, JSHClass *hclass); inline static JSTaggedValue FindProtoRootHClass(const JSThread *thread, JSHClass *hclass); + inline static JSTaggedValue FindProtoRootHClass(ThreadHolder *holder, JSHClass *hclass); inline static void UpdateRootHClass(const JSThread *thread, const JSHandle &parent, const JSHandle &child); inline static int FindPropertyEntry(const JSThread *thread, JSHClass *hclass, JSTaggedValue key); + // inline static int FindPropertyEntry(ThreadHolder *holder, JSHClass *hclass, JSTaggedValue key); static PUBLIC_API PropertyLookupResult LookupPropertyInAotHClass(const JSThread *thread, JSHClass *hclass, JSTaggedValue key); diff --git a/ecmascript/layout_info-inl.h b/ecmascript/layout_info-inl.h index cd16e84b75ea1bc0f2db8c7892a5561b491f384d..f3ac4547e8c4064e4399bef2cc057bdb2b7506c7 100644 --- a/ecmascript/layout_info-inl.h +++ b/ecmascript/layout_info-inl.h @@ -154,6 +154,50 @@ inline int LayoutInfo::FindElementWithCache(const JSThread *thread, JSHClass *cl return index; } +// inline int LayoutInfo::FindElementWithCache(ThreadHolder *holder, JSHClass *cls, JSTaggedValue key, +// int propertiesNumber) +// { +// ASSERT(NumberOfElements() >= propertiesNumber); +// const int MAX_ELEMENTS_LINER_SEARCH = 9; // 9: Builtins Object properties number is nine; +// if (propertiesNumber <= MAX_ELEMENTS_LINER_SEARCH) { +// void *properties = reinterpret_cast(GetProperties()); +// size_t keyOffset = 0; +// if (holder->GetMutatorPhase() >= common::GC_PHASE_PRECOPY) { +// for (int i = 0; i < propertiesNumber; i++) { +// JSTaggedValue propKey(Barriers::GetTaggedValue(holder, +// ToUintPtr(properties) + i * sizeof(Properties) + keyOffset)); +// if (propKey == key) { +// return i; +// } +// } +// } else { +// for (int i = 0; i < propertiesNumber; i++) { +// JSTaggedValue propKey(Barriers::GetTaggedValue(holder, +// ToUintPtr(properties) + i * sizeof(Properties) + keyOffset)); +// if (propKey == key) { +// return i; +// } +// } +// } +// return -1; +// } +// +// // jit compile thread not use cache +// if (thread->IsJitThread()) { +// return BinarySearch(thread, key, propertiesNumber); +// } +// +// PropertiesCache *cache = thread->GetPropertiesCache(); +// int index = cache->Get(thread, cls, key); +// if (index == PropertiesCache::NOT_FOUND) { +// index = BinarySearch(thread, key, propertiesNumber); +// if (index != -1) { +// cache->Set(thread, cls, key, index); +// } +// } +// return index; +// } + inline int LayoutInfo::BinarySearch(const JSThread *thread, JSTaggedValue key, int propertiesNumber) { ASSERT(NumberOfElements() >= propertiesNumber); diff --git a/ecmascript/mem/barriers.h b/ecmascript/mem/barriers.h index 478f9653782b9e90b43d0f17d503b9d1097f1210..78f5034572affefedaa0995fee0cfe244f9632d1 100644 --- a/ecmascript/mem/barriers.h +++ b/ecmascript/mem/barriers.h @@ -92,7 +92,9 @@ public: static TaggedObject* GetTaggedObject(const JSThread *thread, const void* obj, size_t offset); static JSTaggedType GetTaggedValue(const JSThread *thread, const void *obj, size_t offset); + static JSTaggedType GetTaggedValue(common::ThreadHolder *holder, const void *obj, size_t offset); static JSTaggedType GetTaggedValue(const JSThread *thread, uintptr_t slotAddress); + static JSTaggedType GetTaggedValue(common::ThreadHolder *holder, uintptr_t slotAddress); static JSTaggedType GetTaggedValueAtomic(const JSThread *thread, const void *obj, size_t offset); static JSTaggedType UpdateSlot(const JSThread *thread, void *obj, size_t offset); @@ -102,12 +104,21 @@ public: template static JSTaggedType GetTaggedValue(const JSThread *thread, const void *obj, size_t offset); + template + static JSTaggedType GetTaggedValue(common::ThreadHolder *holder, const void *obj, size_t offset); + template static JSTaggedType GetTaggedValue(const JSThread *thread, uintptr_t slotAddress); + template + static JSTaggedType GetTaggedValue(common::ThreadHolder *holder, uintptr_t slotAddress); + template static JSTaggedType GetTaggedValueAtomic(const JSThread *thread, const void *obj, size_t offset); + template + static JSTaggedType GetTaggedValueAtomic(common::ThreadHolder *holder, const void *obj, size_t offset); + static void PUBLIC_API Update(const JSThread *thread, uintptr_t slotAddr, Region *objectRegion, TaggedObject *value, Region *valueRegion, WriteBarrierType writeType = WriteBarrierType::NORMAL); diff --git a/ecmascript/mem/barriers_get-inl.h b/ecmascript/mem/barriers_get-inl.h index b37705972f6c7ce1d72d1ce68da0b7cd6c99d0ba..97492e1f16adb83cd45371862754a3c72513c33a 100644 --- a/ecmascript/mem/barriers_get-inl.h +++ b/ecmascript/mem/barriers_get-inl.h @@ -25,14 +25,32 @@ static ARK_INLINE JSTaggedType ReadBarrier(const JSThread *thread, const void *o const JSTaggedValue &value) { if (value.IsHeapObject()) { + auto holder = thread->GetThreadHolder(); #ifdef ENABLE_CMC_RB_DFX JSTaggedValue valueRB(reinterpret_cast( - common::BaseRuntime::ReadBarrier(const_cast(obj), (void*) (ToUintPtr(obj) + offset)))); + common::BaseRuntime::ReadBarrier(holder, const_cast(obj), (void*) (ToUintPtr(obj) + offset)))); valueRB.RemoveReadBarrierDFXTag(); return valueRB.GetRawData(); #else return reinterpret_cast( - common::BaseRuntime::ReadBarrier(const_cast(obj), (void *)(ToUintPtr(obj) + offset))); + common::BaseRuntime::ReadBarrier(holder, const_cast(obj), (void *)(ToUintPtr(obj) + offset))); +#endif + } + return value.GetRawData(); +} + +static inline ARK_INLINE JSTaggedType ReadBarrier(ThreadHolder *holder, const void *obj, size_t offset, + const JSTaggedValue &value) +{ + if (value.IsHeapObject()) { +#ifdef ENABLE_CMC_RB_DFX + JSTaggedValue valueRB(reinterpret_cast( + common::BaseRuntime::ReadBarrier(holder, const_cast(obj), (void*) (ToUintPtr(obj) + offset)))); + valueRB.RemoveReadBarrierDFXTag(); + return valueRB.GetRawData(); +#else + return reinterpret_cast( + common::BaseRuntime::ReadBarrier(holder, const_cast(obj), (void *)(ToUintPtr(obj) + offset))); #endif } return value.GetRawData(); @@ -41,13 +59,29 @@ static ARK_INLINE JSTaggedType ReadBarrier(const JSThread *thread, const void *o static ARK_INLINE JSTaggedType ReadBarrier(const JSThread *thread, uintptr_t slotAddress, const JSTaggedValue &value) { if (value.IsHeapObject()) { + auto holder = thread->GetThreadHolder(); #ifdef ENABLE_CMC_RB_DFX JSTaggedValue valueRB( - reinterpret_cast(common::BaseRuntime::ReadBarrier((void *)slotAddress))); + reinterpret_cast(common::BaseRuntime::ReadBarrier(holder, (void *)slotAddress))); valueRB.RemoveReadBarrierDFXTag(); return valueRB.GetRawData(); #else - return reinterpret_cast(common::BaseRuntime::ReadBarrier((void*)slotAddress)); + return reinterpret_cast(common::BaseRuntime::ReadBarrier(holder, (void*)slotAddress)); +#endif + } + return value.GetRawData(); +} + +static inline ARK_INLINE JSTaggedType ReadBarrier(ThreadHolder *holder, uintptr_t slotAddress, const JSTaggedValue &value) +{ + if (value.IsHeapObject()) { +#ifdef ENABLE_CMC_RB_DFX + JSTaggedValue valueRB( + reinterpret_cast(common::BaseRuntime::ReadBarrier(holder, (void *)slotAddress))); + valueRB.RemoveReadBarrierDFXTag(); + return valueRB.GetRawData(); +#else + return reinterpret_cast(common::BaseRuntime::ReadBarrier(holder, (void*)slotAddress)); #endif } return value.GetRawData(); @@ -57,14 +91,32 @@ static ARK_INLINE JSTaggedType AtomicReadBarrier(const JSThread *thread, const v const JSTaggedValue &value) { if (value.IsHeapObject()) { + auto holder = thread->GetThreadHolder(); #ifdef ENABLE_CMC_RB_DFX JSTaggedValue value(reinterpret_cast(common::BaseRuntime::AtomicReadBarrier( - const_cast(obj), (void*) (ToUintPtr(obj) + offset), std::memory_order_acquire))); + holder, const_cast(obj), (void*) (ToUintPtr(obj) + offset), std::memory_order_acquire))); value.RemoveReadBarrierDFXTag(); return value.GetRawData(); #else return reinterpret_cast(common::BaseRuntime::AtomicReadBarrier( - const_cast(obj), (void *)(ToUintPtr(obj) + offset), std::memory_order_acquire)); + holder, const_cast(obj), (void *)(ToUintPtr(obj) + offset), std::memory_order_acquire)); +#endif + } + return value.GetRawData(); +} + +static inline ARK_INLINE JSTaggedType AtomicReadBarrier(ThreadHolder *holder, const void *obj, size_t offset, + const JSTaggedValue &value) +{ + if (value.IsHeapObject()) { +#ifdef ENABLE_CMC_RB_DFX + JSTaggedValue value(reinterpret_cast(common::BaseRuntime::AtomicReadBarrier( + holder, const_cast(obj), (void*) (ToUintPtr(obj) + offset), std::memory_order_acquire))); + value.RemoveReadBarrierDFXTag(); + return value.GetRawData(); +#else + return reinterpret_cast(common::BaseRuntime::AtomicReadBarrier( + holder, const_cast(obj), (void *)(ToUintPtr(obj) + offset), std::memory_order_acquire)); #endif } return value.GetRawData(); @@ -72,13 +124,14 @@ static ARK_INLINE JSTaggedType AtomicReadBarrier(const JSThread *thread, const v inline ARK_INLINE JSTaggedType Barriers::ReadBarrierForObject(const JSThread *thread, uintptr_t slotAddress) { + auto holder = thread->GetThreadHolder(); #ifdef ENABLE_CMC_RB_DFX JSTaggedValue valueRB( - reinterpret_cast(common::BaseRuntime::ReadBarrier((void *)slotAddress))); + reinterpret_cast(common::BaseRuntime::ReadBarrier(holder, (void *)slotAddress))); valueRB.RemoveReadBarrierDFXTag(); return valueRB.GetRawData(); #else - return reinterpret_cast(common::BaseRuntime::ReadBarrier((void*)slotAddress)); + return reinterpret_cast(common::BaseRuntime::ReadBarrier(holder, (void*)slotAddress)); #endif } @@ -92,6 +145,16 @@ inline ARK_INLINE JSTaggedType Barriers::GetTaggedValue(const JSThread *thread, return value.GetRawData(); } +inline ARK_INLINE JSTaggedType Barriers::GetTaggedValue(ThreadHolder *holder, const void *obj, size_t offset) +{ + JSTaggedValue value = *reinterpret_cast(ToUintPtr(obj) + offset); + ASSERT(holder != nullptr); + if (UNLIKELY(holder->GetMutatorPhase() >= common::GC_PHASE_PRECOPY)) { + return ReadBarrier(holder, obj, offset, value); + } + return value.GetRawData(); +} + inline ARK_INLINE JSTaggedType Barriers::GetTaggedValue(const JSThread *thread, uintptr_t slotAddress) { JSTaggedValue value = *reinterpret_cast(slotAddress); @@ -102,6 +165,16 @@ inline ARK_INLINE JSTaggedType Barriers::GetTaggedValue(const JSThread *thread, return value.GetRawData(); } +inline ARK_INLINE JSTaggedType Barriers::GetTaggedValue(ThreadHolder *holder, uintptr_t slotAddress) +{ + JSTaggedValue value = *reinterpret_cast(slotAddress); + ASSERT(holder != nullptr); + if (UNLIKELY(holder->GetMutatorPhase() >= common::GC_PHASE_PRECOPY)) { + return ReadBarrier(holder, slotAddress, value); + } + return value.GetRawData(); +} + inline ARK_INLINE JSTaggedType Barriers::GetTaggedValueAtomic(const JSThread *thread, const void *obj, size_t offset) { JSTaggedValue value = reinterpret_cast *>(ToUintPtr(obj) + @@ -129,6 +202,22 @@ inline ARK_INLINE JSTaggedType Barriers::GetTaggedValue(const JSThread *thread, return value.GetRawData(); } +template +inline ARK_INLINE JSTaggedType Barriers::GetTaggedValue(common::ThreadHolder *holder, const void *obj, size_t offset) +{ + JSTaggedValue value = *reinterpret_cast(ToUintPtr(obj) + offset); + if constexpr (mode == RBMode::DEFAULT_RB) { + ASSERT(holder != nullptr); + if (UNLIKELY(holder->GetMutatorPhase() >= common::GC_PHASE_PRECOPY)) { + return ReadBarrier(holder, obj, offset, value); + } + } else if constexpr (mode == RBMode::FAST_CMC_RB) { + return ReadBarrier(holder, obj, offset, value); + } + + return value.GetRawData(); +} + template inline ARK_INLINE JSTaggedType Barriers::GetTaggedValue(const JSThread *thread, uintptr_t slotAddress) { @@ -145,6 +234,22 @@ inline ARK_INLINE JSTaggedType Barriers::GetTaggedValue(const JSThread *thread, return value.GetRawData(); } +template +inline ARK_INLINE JSTaggedType Barriers::GetTaggedValue(common::ThreadHolder *holder, uintptr_t slotAddress) +{ + JSTaggedValue value = *reinterpret_cast(slotAddress); + if constexpr (mode == RBMode::DEFAULT_RB) { + ASSERT(holder != nullptr); + if (UNLIKELY(holder->GetMutatorPhase() >= common::GC_PHASE_PRECOPY)) { + return ReadBarrier(holder, slotAddress, value); + } + } else if constexpr (mode == RBMode::FAST_CMC_RB) { + return ReadBarrier(holder, slotAddress, value); + } + + return value.GetRawData(); +} + template inline ARK_INLINE JSTaggedType Barriers::GetTaggedValueAtomic(const JSThread *thread, const void *obj, size_t offset) { @@ -162,6 +267,23 @@ inline ARK_INLINE JSTaggedType Barriers::GetTaggedValueAtomic(const JSThread *th return value.GetRawData(); } +template +inline ARK_INLINE JSTaggedType Barriers::GetTaggedValueAtomic(ThreadHolder *holder, const void *obj, size_t offset) +{ + JSTaggedValue value = reinterpret_cast *>(ToUintPtr(obj) + + offset)->load(std::memory_order_acquire); + if constexpr (mode == RBMode::DEFAULT_RB) { + ASSERT(holder != nullptr); + if (UNLIKELY(holder->GetMutatorPhase() >= common::GC_PHASE_PRECOPY)) { + return AtomicReadBarrier(holder, obj, offset, value); + } + } else if constexpr (mode == RBMode::FAST_CMC_RB) { + return AtomicReadBarrier(holder, obj, offset, value); + } + + return value.GetRawData(); +} + inline ARK_INLINE TaggedObject* Barriers::GetTaggedObject(const JSThread *thread, const void* obj, size_t offset) { return JSTaggedValue(GetTaggedValue(thread, obj, offset)).GetTaggedObject(); diff --git a/ecmascript/mem/gc_root.h b/ecmascript/mem/gc_root.h index 0860f393e8dd1e610a5fcc8b7c1506dcb14e6de1..3ca7fb64549710f49138af28d798c897cfbc7708 100644 --- a/ecmascript/mem/gc_root.h +++ b/ecmascript/mem/gc_root.h @@ -80,6 +80,16 @@ public: } } + JSTaggedValue Read(common::ThreadHolder* holder) + { + if (g_isEnableCMCGC) { + return JSTaggedValue( + reinterpret_cast(common::BaseRuntime::ReadBarrier(holder, reinterpret_cast(&objPtr_)))); + } else { + return objPtr_; + } + } + /** * Allows GC to visit this root during root scanning phases. * Such as enumeration phase and fowarding phase diff --git a/ecmascript/method.cpp b/ecmascript/method.cpp index b24dbd8ec8748109f61ec9061fd4b11ac1ca8076..5e1213bda43f5b2b1058bf52e27a779a50a39fee 100644 --- a/ecmascript/method.cpp +++ b/ecmascript/method.cpp @@ -36,6 +36,12 @@ const char *Method::GetMethodName(const JSThread *thread) const return MethodLiteral::GetMethodName(jsPandaFile, GetMethodId()); } +const char *Method::GetMethodName(ThreadHolder *holder) const +{ + const JSPandaFile *jsPandaFile = GetJSPandaFile(holder); + return MethodLiteral::GetMethodName(jsPandaFile, GetMethodId()); +} + const char *Method::GetMethodName(const JSPandaFile *file) const { return MethodLiteral::GetMethodName(file, GetMethodId()); @@ -53,6 +59,12 @@ uint32_t Method::GetCodeSize(const JSThread *thread) const return MethodLiteral::GetCodeSize(jsPandaFile, GetMethodId()); } +uint32_t Method::GetCodeSize(ThreadHolder *holder) const +{ + const JSPandaFile *jsPandaFile = GetJSPandaFile(holder); + return MethodLiteral::GetCodeSize(jsPandaFile, GetMethodId()); +} + const JSPandaFile *Method::GetJSPandaFile(const JSThread *thread) const { JSTaggedValue constpool = GetConstantPool(thread); @@ -64,6 +76,17 @@ const JSPandaFile *Method::GetJSPandaFile(const JSThread *thread) const return taggedPool->GetJSPandaFile(); } +const JSPandaFile *Method::GetJSPandaFile(ThreadHolder *holder) const +{ + JSTaggedValue constpool = GetConstantPool(holder); + if (constpool.IsUndefined()) { + return nullptr; + } + + const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); + return taggedPool->GetJSPandaFile(); +} + MethodLiteral *Method::GetMethodLiteral(const JSThread *thread) const { if (IsAotWithCallField() || IsDeoptimized()) { diff --git a/ecmascript/method.h b/ecmascript/method.h index 01a0ddb7f7375dd8d0cc93d834b445791da24f83..474a5b29df469ef0533761eaf879d1f8497940f0 100644 --- a/ecmascript/method.h +++ b/ecmascript/method.h @@ -441,10 +441,13 @@ public: } const JSPandaFile *PUBLIC_API GetJSPandaFile(const JSThread *thread) const; + const JSPandaFile *PUBLIC_API GetJSPandaFile(ThreadHolder *holder) const; uint32_t PUBLIC_API GetCodeSize(const JSThread *thread) const; + uint32_t PUBLIC_API GetCodeSize(ThreadHolder *holder) const; MethodLiteral *PUBLIC_API GetMethodLiteral(const JSThread *thread) const; const char *PUBLIC_API GetMethodName(const JSThread *thread) const; + const char *PUBLIC_API GetMethodName(ThreadHolder *holder) const; const char *PUBLIC_API GetMethodName(const JSPandaFile *file) const; std::string PUBLIC_API ParseFunctionName(const JSThread *thread) const; std::pair PUBLIC_API ParseFunctionNameView(const JSThread *thread) const; diff --git a/ecmascript/module/js_module_manager.cpp b/ecmascript/module/js_module_manager.cpp index fbb25daca0fecd0b762255f09b6f1734e8193938..583ebb0f27c27934c0476ea43b560b86c12f694b 100644 --- a/ecmascript/module/js_module_manager.cpp +++ b/ecmascript/module/js_module_manager.cpp @@ -111,7 +111,8 @@ JSHandle ModuleManager::GetImportedModule(const CString &refer JSHandle ModuleManager::HostGetImportedModule(const CString &referencing) { - auto entry = resolvedModules_.Find(referencing); + auto holder = vm_->GetJSThread()->GetThreadHolder(); + auto entry = resolvedModules_.Find(holder, referencing); if (!entry) { // LCOV_EXCL_BR_LINE LOG_ECMA(FATAL) << "Can not get module: " << referencing; } @@ -123,7 +124,8 @@ JSTaggedValue ModuleManager::HostGetImportedModule(void *src) const char *str = reinterpret_cast(src); CString referencing(str, strlen(str)); LOG_FULL(INFO) << "current str during module deregister process : " << referencing; - auto entry = resolvedModules_.Find(referencing); + auto holder = vm_->GetJSThread()->GetThreadHolder(); + auto entry = resolvedModules_.Find(holder, referencing); if (!entry) { // LCOV_EXCL_BR_LINE LOG_FULL(INFO) << "The module has been unloaded, " << referencing; return JSTaggedValue::Undefined(); @@ -133,7 +135,9 @@ JSTaggedValue ModuleManager::HostGetImportedModule(void *src) bool ModuleManager::IsLocalModuleLoaded(const CString& referencing) { - auto entry = resolvedModules_.Find(referencing); + JSThread *thread = vm_->GetJSThread(); + auto holder = thread->GetThreadHolder(); + auto entry = resolvedModules_.Find(holder, referencing); if (!entry) { return false; } @@ -157,7 +161,8 @@ bool ModuleManager::IsModuleLoaded(const CString &referencing) bool ModuleManager::IsEvaluatedModule(const CString &referencing) { - auto entry = resolvedModules_.Find(referencing); + auto holder = vm_->GetJSThread()->GetThreadHolder(); + auto entry = resolvedModules_.Find(holder, referencing); if (!entry) { return false; } @@ -352,7 +357,8 @@ JSHandle ModuleManager::ExecuteCjsModule(JSThread *thread, const JSHandle ModuleManager::TryGetImportedModule(const CString& referencing) { JSThread *thread = vm_->GetJSThread(); - auto entry = resolvedModules_.Find(referencing); + auto holder = thread->GetThreadHolder(); + auto entry = resolvedModules_.Find(holder, referencing); if (!entry) { return thread->GlobalConstants()->GetHandledUndefined(); } @@ -361,7 +367,8 @@ JSHandle ModuleManager::TryGetImportedModule(const CString& refer void ModuleManager::RemoveModuleFromCache(const CString& recordName) { - auto entry = resolvedModules_.Find(recordName); + auto holder = vm_->GetJSThread()->GetThreadHolder(); + auto entry = resolvedModules_.Find(holder, recordName); if (!entry) { // LCOV_EXCL_BR_LINE LOG_ECMA(FATAL) << "Can not get module: " << recordName << ", when try to remove the module"; diff --git a/ecmascript/module/js_module_manager.h b/ecmascript/module/js_module_manager.h index 8311b783431af0f30184b766473ec32f28193b90..07067e83a435eb9c81db9ad7ead47c27c8eec574 100644 --- a/ecmascript/module/js_module_manager.h +++ b/ecmascript/module/js_module_manager.h @@ -92,13 +92,13 @@ public: resolvedModules_.Insert(recordName, module); } - void NativeObjDestory() + void NativeObjDestory(JSThread *thread) { - resolvedModules_.ForEach([](auto it) { + resolvedModules_.ForEach([thread](auto it) { CString key = it->first; ASSERT(!key.empty()); GCRoot &root = it->second; - JSTaggedValue module = root.Read(); + JSTaggedValue module = root.Read(thread->GetThreadHolder()); SourceTextModule::Cast(module)->DestoryLazyImportArray(); SourceTextModule::Cast(module)->DestoryEcmaModuleFilenameString(); SourceTextModule::Cast(module)->DestoryEcmaModuleRecordNameString(); @@ -113,7 +113,10 @@ public: inline void AddNormalSerializeModule(JSThread *thread, JSHandle serializerArray, uint32_t idx) { resolvedModules_.ForEach( - [thread, &idx, serializerArray](auto it) { serializerArray->Set(thread, idx++, it->second.Read()); }); + [thread, &idx, serializerArray](auto it) + { + serializerArray->Set(thread, idx++, it->second.Read(thread->GetThreadHolder())); + }); } inline bool IsVMBundlePack() diff --git a/ecmascript/module/js_shared_module_manager.cpp b/ecmascript/module/js_shared_module_manager.cpp index 35aa0187392d9489738a5df34ed51f01237485e9..5e0363e80da488374fd59113e086e3193f5d9515 100644 --- a/ecmascript/module/js_shared_module_manager.cpp +++ b/ecmascript/module/js_shared_module_manager.cpp @@ -35,9 +35,10 @@ void SharedModuleManager::Iterate(RootVisitor &v) [&v](auto iter) { iter->second.VisitRoot([&v](ObjectSlot slot) { v.VisitRoot(Root::ROOT_VM, slot); }); }); } -bool SharedModuleManager::SearchInSModuleManagerUnsafe(const CString &recordName) +bool SharedModuleManager::SearchInSModuleManagerUnsafe(JSThread *thread, const CString &recordName) { - auto entry = resolvedSharedModules_.Find(recordName); + auto holder = thread->GetThreadHolder(); + auto entry = resolvedSharedModules_.Find(holder, recordName); if (entry) { return true; } @@ -46,7 +47,8 @@ bool SharedModuleManager::SearchInSModuleManagerUnsafe(const CString &recordName JSHandle SharedModuleManager::GetSModuleUnsafe(JSThread *thread, const CString &recordName) { - auto entry = resolvedSharedModules_.Find(recordName); + auto holder = thread->GetThreadHolder(); + auto entry = resolvedSharedModules_.Find(holder, recordName); if (!entry) { return JSHandle(thread->GlobalConstants()->GetHandledUndefined()); } @@ -63,7 +65,7 @@ JSHandle SharedModuleManager::GetSModule(JSThread *thread, con bool SharedModuleManager::SearchInSModuleManager(JSThread *thread, const CString &recordName) { RuntimeLockHolder locker(thread, mutex_); - return SearchInSModuleManagerUnsafe(recordName); + return SearchInSModuleManagerUnsafe(thread, recordName); } bool SharedModuleManager::TryInsertInSModuleManager(JSThread *thread, const CString &recordName, @@ -144,13 +146,13 @@ JSHandle SharedModuleManager::SModuleNamespaceCreate(JSThread * return JSSharedModule::SModuleNamespaceCreate(thread, module, exports); } -void SharedModuleManager::SharedNativeObjDestory() +void SharedModuleManager::SharedNativeObjDestory(common::ThreadHolder* holder) { - resolvedSharedModules_.ForEach([](auto it) { + resolvedSharedModules_.ForEach([holder](auto it) { CString key = it->first; ASSERT(!key.empty()); GCRoot &root = it->second; - JSTaggedValue module = root.Read(); + JSTaggedValue module = root.Read(holder); SourceTextModule::Cast(module)->DestoryLazyImportArray(); SourceTextModule::Cast(module)->DestoryEcmaModuleFilenameString(); SourceTextModule::Cast(module)->DestoryEcmaModuleRecordNameString(); diff --git a/ecmascript/module/js_shared_module_manager.h b/ecmascript/module/js_shared_module_manager.h index 2520d59eac97033e0463749892ae91eca8153173..97bd0560e69e1ffc285a3c3d694f520af591ceea 100644 --- a/ecmascript/module/js_shared_module_manager.h +++ b/ecmascript/module/js_shared_module_manager.h @@ -73,7 +73,7 @@ public: { resolvedSharedModules_.Insert(recordName, module); } - void SharedNativeObjDestory(); + void SharedNativeObjDestory(common::ThreadHolder* holder); RecursiveMutex& GetSharedMutex() { @@ -88,7 +88,10 @@ public: void AddSharedSerializeModule(JSThread *thread, JSHandle serializerArray, uint32_t idx) { resolvedSharedModules_.ForEach( - [thread, &idx, &serializerArray](auto it) { serializerArray->Set(thread, idx++, it->second.Read()); }); + [thread, &idx, &serializerArray](auto it) + { + serializerArray->Set(thread, idx++, it->second.Read(thread->GetThreadHolder())); + }); } private: @@ -98,7 +101,7 @@ private: NO_COPY_SEMANTIC(SharedModuleManager); NO_MOVE_SEMANTIC(SharedModuleManager); - bool SearchInSModuleManagerUnsafe(const CString &recordName); + bool SearchInSModuleManagerUnsafe(JSThread *thread, const CString &recordName); JSHandle GetSModuleUnsafe(JSThread *thread, const CString &recordName); diff --git a/ecmascript/module/module_manager_map.h b/ecmascript/module/module_manager_map.h index ff7c93c7bc14bfc3e4ba0d26be8fccc4bd6b7cc6..3faa4a76c0492fb9df0b19e521073bed3ef12cb6 100644 --- a/ecmascript/module/module_manager_map.h +++ b/ecmascript/module/module_manager_map.h @@ -73,11 +73,11 @@ public: * returned by copy to avoid dangling references after lock release. */ template - std::optional Find(const K &key) + std::optional Find(common::ThreadHolder* holder, const K &key) { std::lock_guard lock(lock_); auto it = map_.find(key); - return it == map_.end() ? std::nullopt : std::make_optional(it->second.Read()); + return it == map_.end() ? std::nullopt : std::make_optional(it->second.Read(holder)); } /** diff --git a/ecmascript/pgo_profiler/pgo_extra_profiler.h b/ecmascript/pgo_profiler/pgo_extra_profiler.h index 4b961aacca6965aed86171d3170771e25ba94123..ea7b27284242d08ec674c18a28ed0bbeadc3198e 100644 --- a/ecmascript/pgo_profiler/pgo_extra_profiler.h +++ b/ecmascript/pgo_profiler/pgo_extra_profiler.h @@ -41,11 +41,21 @@ public: return GetReceiverObject(thread).GetHeapObject()->GetClass(); } + JSHClass* GetReceiverHClass(ThreadHolder *holder) const + { + return GetReceiverObject(holder).GetHeapObject()->GetClass(); + } + JSHClass* GetHolderHClass(const JSThread *thread) const { return GetHolderObject(thread).GetTaggedObject()->GetClass(); } + JSHClass* GetHolderHClass(ThreadHolder *holder) const + { + return GetHolderObject(holder).GetTaggedObject()->GetClass(); + } + void SetReceiver(const JSThread *thread, JSTaggedValue value) { SetReceiverObject(thread, value); @@ -61,11 +71,21 @@ public: return GetReceiverObject(thread); } + JSTaggedValue GetReceiver(ThreadHolder *holder) const + { + return GetReceiverObject(holder); + } + JSTaggedValue GetHolder(const JSThread *thread) const { return GetHolderObject(thread); } + JSTaggedValue GetHolder(ThreadHolder *holder) const + { + return GetHolderObject(holder); + } + void Clear(const JSThread *thread) { SetReceiverObject(thread, JSTaggedValue::Hole()); @@ -93,6 +113,11 @@ public: return !GetReceiverObject(thread).IsHole() && !GetReceiverObject(thread).IsUndefined(); } + bool IsValid(ThreadHolder *holder) const + { + return !GetReceiverObject(holder).IsHole() && !GetReceiverObject(holder).IsUndefined(); + } + DECL_DUMP() }; diff --git a/ecmascript/pgo_profiler/pgo_profiler.cpp b/ecmascript/pgo_profiler/pgo_profiler.cpp index 24ce2558d9481ae9aa30706d6ba8de31d5c7cb8f..bf609ad295dd07e727afc9d5d37ff24b16201dbf 100644 --- a/ecmascript/pgo_profiler/pgo_profiler.cpp +++ b/ecmascript/pgo_profiler/pgo_profiler.cpp @@ -44,9 +44,8 @@ void PGOProfiler::ProfileDefineClass(JSTaggedType ctor) if (!ctorValue.IsJSFunction()) { return; } - JSThread *thread = vm_->GetJSThread(); auto ctorFunc = JSFunction::Cast(ctorValue.GetTaggedObject()); - auto ctorMethodValue = ctorFunc->GetMethod(thread); + auto ctorMethodValue = ctorFunc->GetMethod(holder_); if (!ctorMethodValue.IsMethod()) { return; } @@ -57,15 +56,15 @@ void PGOProfiler::ProfileDefineClass(JSTaggedType ctor) return; } - auto abcId = GetMethodAbcId(thread, ctorFunc); + auto abcId = GetMethodAbcId(holder_, ctorFunc); auto chc = ctorFunc->GetClass(); SetRootProfileType(chc, abcId, entityId, ProfileType::Kind::ConstructorId); - auto protoOrHClass = ctorFunc->GetProtoOrHClass(thread); + auto protoOrHClass = ctorFunc->GetProtoOrHClass(holder_); if (protoOrHClass.IsJSHClass()) { auto ihc = JSHClass::Cast(protoOrHClass.GetTaggedObject()); SetRootProfileType(ihc, abcId, entityId, ProfileType::Kind::ClassId); - protoOrHClass = ihc->GetProto(thread); + protoOrHClass = ihc->GetProto(holder_); } if (protoOrHClass.IsJSObject()) { auto phc = protoOrHClass.GetTaggedObject()->GetClass(); @@ -83,12 +82,11 @@ void PGOProfiler::ProfileClassRootHClass(JSTaggedType ctor, JSTaggedType rootHcV if (!ctorValue.IsJSFunction()) { return; } - JSThread *thread = vm_->GetJSThread(); auto ctorFunc = JSFunction::Cast(ctorValue.GetTaggedObject()); if (!FunctionKindVerify(ctorFunc)) { return; } - auto ctorMethodValue = ctorFunc->GetMethod(thread); + auto ctorMethodValue = ctorFunc->GetMethod(holder_); if (!ctorMethodValue.IsMethod()) { return; } @@ -99,7 +97,7 @@ void PGOProfiler::ProfileClassRootHClass(JSTaggedType ctor, JSTaggedType rootHcV } auto rootHc = JSHClass::Cast(JSTaggedValue(rootHcValue).GetTaggedObject()); - auto abcId = GetMethodAbcId(thread, ctorFunc); + auto abcId = GetMethodAbcId(holder_, ctorFunc); SetRootProfileType(rootHc, abcId, entityId, kind); } @@ -113,15 +111,14 @@ void PGOProfiler::ProfileNapiRootHClass(JSTaggedType ctor, JSTaggedType rootHcVa if (!ctorValue.IsJSFunction()) { return; } - JSThread *thread = vm_->GetJSThread(); auto ctorFunc = JSFunction::Cast(ctorValue.GetTaggedObject()); - auto ctorMethodValue = ctorFunc->GetMethod(thread); + auto ctorMethodValue = ctorFunc->GetMethod(holder_); if (!ctorMethodValue.IsMethod()) { return; } auto entityId = Method::Cast(ctorMethodValue)->GetMethodId().GetOffset(); auto rootHc = JSHClass::Cast(JSTaggedValue(rootHcValue).GetTaggedObject()); - auto abcId = GetMethodAbcId(thread, ctorFunc); + auto abcId = GetMethodAbcId(holder_, ctorFunc); SetRootProfileType(rootHc, abcId, entityId, kind); } @@ -134,7 +131,7 @@ void PGOProfiler::ProfileProtoTransitionClass(JSHandle func, } auto thread = vm_->GetJSThread(); JSHClass *phc = proto->GetTaggedObject()->GetClass(); - JSHClass *phcRoot = JSHClass::FindRootHClass(thread, phc); + JSHClass *phcRoot = JSHClass::FindRootHClass(holder_, phc); auto* transitionTable = vm_->GetFunctionProtoTransitionTable(); JSTaggedType baseIhc = transitionTable->GetFakeParent(JSTaggedType(phcRoot)); if (baseIhc == 0) { @@ -146,11 +143,12 @@ void PGOProfiler::ProfileProtoTransitionClass(JSHandle func, // In the case of `subclass.prototype = Object.create(superclass)`, the current PGO is // unable to collect the pgotype of Object.create(superclass). As a result, when subclass.prototype is modified, // ts hclass cannot be reconstructed during the AOT phase, leading to deoptimization. - JSHClass *baseRoot = JSHClass::FindRootHClass(thread, JSHClass::Cast(JSTaggedValue(baseIhc).GetTaggedObject())); + JSHClass *baseRoot = JSHClass::FindRootHClass(holder_, JSHClass::Cast(JSTaggedValue(baseIhc).GetTaggedObject())); if (GetProfileType(baseRoot).IsNone()) { return; } + // TODO JSHandle keyHandle(thread, thread->GlobalConstants()->GetGlobalConstantObject( static_cast(ConstantIndex::PROTO_TRANS_ROOT_HCLASS_SYMBOL_INDEX))); PropertyDescriptor desc(thread); @@ -184,7 +182,7 @@ void PGOProfiler::ProfileProtoTransitionPrototype(JSHandle func, } auto thread = vm_->GetJSThread(); - auto method = func->GetMethod(thread); + auto method = func->GetMethod(holder_); if (Method::Cast(method)->IsNativeWithCallField()) { return; } @@ -206,7 +204,7 @@ void PGOProfiler::ProfileProtoTransitionPrototype(JSHandle func, // In the case of `subclass.prototype = Object.create(superclass)`, the current PGO is // unable to collect the pgotype of Object.create(superclass). As a result, when subclass.prototype is modified, // ts hclass cannot be reconstructed during the AOT phase, leading to deoptimization. - JSHClass *baseRoot = JSHClass::FindRootHClass(thread, JSHClass::Cast(baseIhc.GetTaggedValue().GetTaggedObject())); + JSHClass *baseRoot = JSHClass::FindRootHClass(holder_, JSHClass::Cast(baseIhc.GetTaggedValue().GetTaggedObject())); if (GetProfileType(baseRoot).IsNone()) { return; } @@ -222,7 +220,7 @@ void PGOProfiler::ProfileProtoTransitionPrototype(JSHandle func, JSObject::DefineOwnProperty(thread, JSHandle::Cast(func), keyHandle, definePropertyDesc); // record phc type - JSHClass *phc0Root = JSHClass::FindRootHClass(thread, oldPrototype->GetTaggedObject()->GetClass()); + JSHClass *phc0Root = JSHClass::FindRootHClass(holder_, oldPrototype->GetTaggedObject()->GetClass()); ProfileClassRootHClass(func.GetTaggedType(), JSTaggedType(phc0Root), ProfileType::Kind::PrototypeId); ProfileClassRootHClass(func.GetTaggedType(), transPhc.GetTaggedType(), ProfileType::Kind::TransitionPrototypeId); } @@ -240,7 +238,7 @@ void PGOProfiler::ProfileDefineGetterSetter(JSHClass* receiverHClass, return; } JSThread *thread = vm_->GetJSThread(); - auto methodValue = JSFunction::Cast(funcValue)->GetMethod(thread); + auto methodValue = JSFunction::Cast(funcValue)->GetMethod(holder_); if (!methodValue.IsMethod()) { return; } @@ -268,13 +266,13 @@ void PGOProfiler::ProfileDefineGetterSetter(JSHClass* receiverHClass, return; } ExtraProfileTypeInfo *mapInfoObj = - ExtraProfileTypeInfo::Cast(dictJShandle->GetValue(thread, entry).GetTaggedObject()); - if (mapInfoObj->GetReceiver(thread) == receiverHClassHandle.GetTaggedValue().CreateAndGetWeakRef() && - mapInfoObj->GetHolder(thread) == holderHClassHandle.GetTaggedValue()) { + ExtraProfileTypeInfo::Cast(dictJShandle->GetValue(holder_, entry).GetTaggedObject()); + if (mapInfoObj->GetReceiver(holder_) == receiverHClassHandle.GetTaggedValue().CreateAndGetWeakRef() && + mapInfoObj->GetHolder(holder_) == holderHClassHandle.GetTaggedValue()) { return; } - ExtraProfileTypeInfo::Cast(dictJShandle->GetValue(thread, entry).GetTaggedObject())->Clear(thread); + ExtraProfileTypeInfo::Cast(dictJShandle->GetValue(holder_, entry).GetTaggedObject())->Clear(thread); } } @@ -321,7 +319,7 @@ void PGOProfiler::UpdateTrackInfo(JSTaggedValue trackInfoVal) if (trackInfoVal.IsHeapObject()) { auto trackInfo = TrackInfo::Cast(trackInfoVal.GetTaggedObject()); auto thread = vm_->GetJSThread(); - auto func = trackInfo->GetCachedFunc(thread); + auto func = trackInfo->GetCachedFunc(holder_); if (!func.IsWeak()) { return; } @@ -333,7 +331,7 @@ void PGOProfiler::UpdateTrackInfo(JSTaggedValue trackInfoVal) if (!function->HasProfileTypeInfo(thread)) { return; } - auto profileTypeInfoVal = function->GetProfileTypeInfo(thread); + auto profileTypeInfoVal = function->GetProfileTypeInfo(holder_); if (profileTypeInfoVal.IsUndefined() || !profileTypeInfoVal.IsTaggedArray()) { return; } @@ -357,7 +355,7 @@ void PGOProfiler::PGODump(JSTaggedType func) if (!funcValue.IsJSFunction()) { return; } - auto methodValue = JSFunction::Cast(funcValue)->GetMethod(vm_->GetJSThread()); + auto methodValue = JSFunction::Cast(funcValue)->GetMethod(holder_); if (!methodValue.IsMethod()) { return; } @@ -421,7 +419,7 @@ void PGOProfiler::PGOPreDump(JSTaggedType func) if (!funcValue.IsJSFunction()) { return; } - auto methodValue = JSFunction::Cast(funcValue)->GetMethod(vm_->GetJSThread()); + auto methodValue = JSFunction::Cast(funcValue)->GetMethod(holder_); if (!methodValue.IsMethod()) { return; } @@ -456,24 +454,23 @@ void PGOProfiler::UpdateExtraProfileTypeInfo(ApEntityId abcId, if (!func->HasProfileTypeInfo(vm_->GetJSThread())) { return; } - JSThread *thread = vm_->GetJSThread(); - ProfileTypeInfoCell *cell = ProfileTypeInfoCell::Cast(func->GetRawProfileTypeInfo(thread)); - ProfileTypeInfo *info = ProfileTypeInfo::Cast((cell->GetValue(thread)).GetTaggedObject()); - if ((info->GetExtraInfoMap(thread)).IsHole() || (info->GetExtraInfoMap(thread)).IsUndefined()) { + ProfileTypeInfoCell *cell = ProfileTypeInfoCell::Cast(func->GetRawProfileTypeInfo(holder_)); + ProfileTypeInfo *info = ProfileTypeInfo::Cast((cell->GetValue(holder_)).GetTaggedObject()); + if ((info->GetExtraInfoMap(holder_)).IsHole() || (info->GetExtraInfoMap(holder_)).IsUndefined()) { return; } - NumberDictionary *dict = NumberDictionary::Cast(info->GetExtraInfoMap(thread).GetTaggedObject()); + NumberDictionary *dict = NumberDictionary::Cast(info->GetExtraInfoMap(holder_).GetTaggedObject()); int size = dict->Size(); for (int hashIndex = 0; hashIndex < size; hashIndex++) { - JSTaggedValue key(dict->GetKey(thread, hashIndex)); + JSTaggedValue key(dict->GetKey(holder_, hashIndex)); if (!key.IsUndefined() && !key.IsHole()) { - JSTaggedValue val(dict->GetValue(thread, hashIndex)); + JSTaggedValue val(dict->GetValue(holder_, hashIndex)); ExtraProfileTypeInfo *extraInfo = ExtraProfileTypeInfo::Cast(val.GetTaggedObject()); - if (!extraInfo->IsValid(thread)) { + if (!extraInfo->IsValid(holder_)) { continue; } - AddObjectInfo(abcId, recordName, methodId, key.GetInt(), extraInfo->GetReceiverHClass(thread), - extraInfo->GetReceiverHClass(thread), extraInfo->GetHolderHClass(thread)); + AddObjectInfo(abcId, recordName, methodId, key.GetInt(), extraInfo->GetReceiverHClass(holder_), + extraInfo->GetReceiverHClass(holder_), extraInfo->GetHolderHClass(holder_)); } } } @@ -484,9 +481,9 @@ bool PGOProfiler::HasValidExtraProfileTypeInfo(JSFunction *func) if (!func->HasProfileTypeInfo(thread)) { return false; } - ProfileTypeInfoCell *profileCell = ProfileTypeInfoCell::Cast(func->GetRawProfileTypeInfo(thread)); - ProfileTypeInfo *profileInfo = ProfileTypeInfo::Cast((profileCell->GetValue(thread)).GetTaggedObject()); - JSTaggedValue map = profileInfo->GetExtraInfoMap(thread); + ProfileTypeInfoCell *profileCell = ProfileTypeInfoCell::Cast(func->GetRawProfileTypeInfo(holder_)); + ProfileTypeInfo *profileInfo = ProfileTypeInfo::Cast((profileCell->GetValue(holder_)).GetTaggedObject()); + JSTaggedValue map = profileInfo->GetExtraInfoMap(holder_); if (map.IsHole() || map.IsUndefined()) { return false; } @@ -541,25 +538,26 @@ void PGOProfiler::HandlePGOPreDump() return; } auto func = JSFunction::Cast(funcValue); - if (func->IsSendableOrConcurrentFunction(thread)) { + if (func->IsSendableOrConcurrentFunction(holder_)) { return; } - JSTaggedValue methodValue = func->GetMethod(thread); + JSTaggedValue methodValue = func->GetMethod(holder_); if (!methodValue.IsMethod()) { return; } + //TODO CString recordName = func->GetRecordName(thread); if (recordName.empty()) { return; } - auto abcId = GetMethodAbcId(thread, func); + auto abcId = GetMethodAbcId(holder_, func); ProcessExtraProfileTypeInfo(func, abcId, recordName, methodValue, current); ProfileType recordType = GetRecordProfileType(abcId, recordName); - recordInfos_->AddMethod(thread, recordType, Method::Cast(methodValue), SampleMode::HOTNESS_MODE); + recordInfos_->AddMethod(holder_, recordType, Method::Cast(methodValue), SampleMode::HOTNESS_MODE); ProfileBytecode(abcId, recordName, funcValue); if (PGOTrace::GetInstance()->IsEnable()) { - PGOTrace::GetInstance()->TryGetMethodData(thread, methodValue, false); + PGOTrace::GetInstance()->TryGetMethodData(holder_, methodValue, false); } }); } @@ -586,11 +584,11 @@ void PGOProfiler::HandlePGODump() continue; } auto func = JSFunction::Cast(value); - if (func->IsSendableOrConcurrentFunction(thread)) { + if (func->IsSendableOrConcurrentFunction(holder_)) { current = PopFromProfileQueue(); continue; } - JSTaggedValue methodValue = func->GetMethod(thread); + JSTaggedValue methodValue = func->GetMethod(holder_); if (!methodValue.IsMethod()) { current = PopFromProfileQueue(); continue; @@ -600,18 +598,18 @@ void PGOProfiler::HandlePGODump() current = PopFromProfileQueue(); continue; } - auto abcId = GetMethodAbcId(thread, func); + auto abcId = GetMethodAbcId(holder_, func); ProcessExtraProfileTypeInfo(func, abcId, recordName, methodValue, current); ProfileType recordType = GetRecordProfileType(abcId, recordName); - if (recordInfos_->AddMethod(thread, recordType, Method::Cast(methodValue), SampleMode::HOTNESS_MODE)) { + if (recordInfos_->AddMethod(holder_, recordType, Method::Cast(methodValue), SampleMode::HOTNESS_MODE)) { methodCount_++; } ProfileBytecode(abcId, recordName, value); current = PopFromProfileQueue(); if (PGOTrace::GetInstance()->IsEnable()) { - PGOTrace::GetInstance()->TryGetMethodData(thread, methodValue, true); + PGOTrace::GetInstance()->TryGetMethodData(holder_, methodValue, true); } } } @@ -909,8 +907,7 @@ void PGOProfiler::ProfileBytecode(ApEntityId abcId, const CString& recordName, J void PGOProfiler::DumpICByName(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId, ProfileTypeInfo *profileTypeInfo, BCType type) { - const JSThread *thread = vm_->GetJSThread(); - JSTaggedValue firstValue = profileTypeInfo->Get(thread, slotId); + JSTaggedValue firstValue = profileTypeInfo->Get(holder_, slotId); if (!firstValue.IsHeapObject()) { if (firstValue.IsHole()) { // Mega state @@ -921,7 +918,7 @@ void PGOProfiler::DumpICByName(ApEntityId abcId, const CString &recordName, Enti if (firstValue.IsWeak()) { TaggedObject *object = firstValue.GetWeakReferentUnChecked(); if (object->GetClass()->IsHClass()) { - JSTaggedValue secondValue = profileTypeInfo->Get(thread, slotId + 1); + JSTaggedValue secondValue = profileTypeInfo->Get(holder_, slotId + 1); JSHClass *hclass = JSHClass::Cast(object); DumpICByNameWithHandler(abcId, recordName, methodId, bcOffset, hclass, secondValue, type); } @@ -933,8 +930,7 @@ void PGOProfiler::DumpICByName(ApEntityId abcId, const CString &recordName, Enti void PGOProfiler::DumpICByValue(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId, ProfileTypeInfo *profileTypeInfo, BCType type) { - const JSThread *thread = vm_->GetJSThread(); - JSTaggedValue firstValue = profileTypeInfo->Get(thread, slotId); + JSTaggedValue firstValue = profileTypeInfo->Get(holder_, slotId); if (!firstValue.IsHeapObject()) { if (firstValue.IsHole()) { // Mega state @@ -945,7 +941,7 @@ void PGOProfiler::DumpICByValue(ApEntityId abcId, const CString &recordName, Ent if (firstValue.IsWeak()) { TaggedObject *object = firstValue.GetWeakReferentUnChecked(); if (object->GetClass()->IsHClass()) { - JSTaggedValue secondValue = profileTypeInfo->Get(thread, slotId + 1); + JSTaggedValue secondValue = profileTypeInfo->Get(holder_, slotId + 1); JSHClass *hclass = JSHClass::Cast(object); DumpICByValueWithHandler(abcId, recordName, methodId, bcOffset, hclass, secondValue, type); } @@ -953,7 +949,7 @@ void PGOProfiler::DumpICByValue(ApEntityId abcId, const CString &recordName, Ent } // Check key if ((firstValue.IsString() || firstValue.IsSymbol())) { - JSTaggedValue secondValue = profileTypeInfo->Get(thread, slotId + 1); + JSTaggedValue secondValue = profileTypeInfo->Get(holder_, slotId + 1); DumpICByValueWithPoly(abcId, recordName, methodId, bcOffset, secondValue, type); return; } @@ -968,12 +964,11 @@ void PGOProfiler::DumpICByNameWithPoly(ApEntityId abcId, return; } ASSERT(cacheValue.IsTaggedArray()); - const JSThread *thread = vm_->GetJSThread(); auto array = TaggedArray::Cast(cacheValue); uint32_t length = array->GetLength(); for (uint32_t i = 0; i < length; i += 2) { // 2 means one ic, two slot - auto result = array->Get(thread, i); - auto handler = array->Get(thread, i + 1); + auto result = array->Get(holder_, i); + auto handler = array->Get(holder_, i + 1); if (!result.IsHeapObject() || !result.IsWeak()) { continue; } @@ -1000,11 +995,10 @@ void PGOProfiler::DumpICByValueWithPoly(ApEntityId abcId, return; } auto array = TaggedArray::Cast(cacheValue); - const JSThread *thread = vm_->GetJSThread(); uint32_t length = array->GetLength(); for (uint32_t i = 0; i < length; i += 2) { // 2 means one ic, two slot - auto result = array->Get(thread, i); - auto handler = array->Get(thread, i + 1); + auto result = array->Get(holder_, i); + auto handler = array->Get(holder_, i + 1); if (!result.IsHeapObject() || !result.IsWeak()) { continue; } @@ -1029,40 +1023,40 @@ bool PGOProfiler::DumpICByNameWithHandler(ApEntityId abcId, const CString &recor return AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, hclass); } else if (secondValue.IsTransitionHandler()) { auto transitionHandler = TransitionHandler::Cast(secondValue.GetTaggedObject()); - auto transitionHClassVal = transitionHandler->GetTransitionHClass(vm_->GetJSThread()); + auto transitionHClassVal = transitionHandler->GetTransitionHClass(holder_); if (transitionHClassVal.IsJSHClass()) { auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject()); return AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, transitionHClass); } } else if (secondValue.IsTransWithProtoHandler()) { auto transWithProtoHandler = TransWithProtoHandler::Cast(secondValue.GetTaggedObject()); - auto cellValue = transWithProtoHandler->GetProtoCell(vm_->GetJSThread()); + auto cellValue = transWithProtoHandler->GetProtoCell(holder_); if (CheckProtoChangeMarker(cellValue)) { return false; } - auto transitionHClassVal = transWithProtoHandler->GetTransitionHClass(vm_->GetJSThread()); + auto transitionHClassVal = transWithProtoHandler->GetTransitionHClass(holder_); if (transitionHClassVal.IsJSHClass()) { auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject()); return AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, transitionHClass); } } else if (secondValue.IsPrototypeHandler()) { auto prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject()); - auto cellValue = prototypeHandler->GetProtoCell(vm_->GetJSThread()); + auto cellValue = prototypeHandler->GetProtoCell(holder_); if (CheckProtoChangeMarker(cellValue)) { return false; } - auto holder = prototypeHandler->GetHolder(vm_->GetJSThread()); + auto holder = prototypeHandler->GetHolder(holder_); auto holderHClass = holder.GetTaggedObject()->GetClass(); auto accessorMethodId = prototypeHandler->GetAccessorMethodId(); return AddObjectInfo( abcId, recordName, methodId, bcOffset, hclass, holderHClass, holderHClass, accessorMethodId); } else if (secondValue.IsStoreAOTHandler()) { StoreAOTHandler *storeAOTHandler = StoreAOTHandler::Cast(secondValue.GetTaggedObject()); - auto cellValue = storeAOTHandler->GetProtoCell(vm_->GetJSThread()); + auto cellValue = storeAOTHandler->GetProtoCell(holder_); if (CheckProtoChangeMarker(cellValue)) { return false; } - auto holder = storeAOTHandler->GetHolder(vm_->GetJSThread()); + auto holder = storeAOTHandler->GetHolder(holder_); auto holderHClass = holder.GetTaggedObject()->GetClass(); return AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, holderHClass, holderHClass); } @@ -1087,11 +1081,11 @@ bool PGOProfiler::DumpICLoadByNameWithHandler(ApEntityId abcId, const CString &r return AddBuiltinsInfoByNameInInstance(abcId, recordName, methodId, bcOffset, hclass); } else if (secondValue.IsPrototypeHandler()) { auto prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject()); - auto cellValue = prototypeHandler->GetProtoCell(vm_->GetJSThread()); + auto cellValue = prototypeHandler->GetProtoCell(holder_); if (CheckProtoChangeMarker(cellValue)) { return ret; } - JSTaggedValue handlerInfoVal = prototypeHandler->GetHandlerInfo(vm_->GetJSThread()); + JSTaggedValue handlerInfoVal = prototypeHandler->GetHandlerInfo(holder_); if (!handlerInfoVal.IsInt()) { return ret; } @@ -1099,7 +1093,7 @@ bool PGOProfiler::DumpICLoadByNameWithHandler(ApEntityId abcId, const CString &r if (HandlerBase::IsNonExist(handlerInfo)) { return ret; } - auto holder = prototypeHandler->GetHolder(vm_->GetJSThread()); + auto holder = prototypeHandler->GetHolder(holder_); auto holderHClass = holder.GetTaggedObject()->GetClass(); auto accessorMethodId = prototypeHandler->GetAccessorMethodId(); if (!AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, holderHClass, @@ -1155,11 +1149,11 @@ void PGOProfiler::DumpICByValueWithHandler(ApEntityId abcId, const CString &reco AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, hclass); } else if (secondValue.IsTransitionHandler()) { auto transitionHandler = TransitionHandler::Cast(secondValue.GetTaggedObject()); - auto transitionHClassVal = transitionHandler->GetTransitionHClass(vm_->GetJSThread()); + auto transitionHClassVal = transitionHandler->GetTransitionHClass(holder_); if (!transitionHClassVal.IsJSHClass()) { return ; } - auto handlerInfoValue = transitionHandler->GetHandlerInfo(vm_->GetJSThread()); + auto handlerInfoValue = transitionHandler->GetHandlerInfo(holder_); auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject()); if (handlerInfoValue.IsInt()) { auto handlerInfo = static_cast(handlerInfoValue.GetInt()); @@ -1172,11 +1166,11 @@ void PGOProfiler::DumpICByValueWithHandler(ApEntityId abcId, const CString &reco AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, transitionHClass); } else if (secondValue.IsTransWithProtoHandler()) { auto transWithProtoHandler = TransWithProtoHandler::Cast(secondValue.GetTaggedObject()); - auto transitionHClassVal = transWithProtoHandler->GetTransitionHClass(vm_->GetJSThread()); + auto transitionHClassVal = transWithProtoHandler->GetTransitionHClass(holder_); if (!transitionHClassVal.IsJSHClass()) { return ; } - auto handlerInfoValue = transWithProtoHandler->GetHandlerInfo(vm_->GetJSThread()); + auto handlerInfoValue = transWithProtoHandler->GetHandlerInfo(holder_); auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject()); if (handlerInfoValue.IsInt()) { auto handlerInfo = static_cast(handlerInfoValue.GetInt()); @@ -1189,7 +1183,7 @@ void PGOProfiler::DumpICByValueWithHandler(ApEntityId abcId, const CString &reco AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, transitionHClass); } else if (secondValue.IsPrototypeHandler()) { PrototypeHandler *prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject()); - auto cellValue = prototypeHandler->GetProtoCell(vm_->GetJSThread()); + auto cellValue = prototypeHandler->GetProtoCell(holder_); if (!cellValue.IsProtoChangeMarker()) { return; } @@ -1198,7 +1192,7 @@ void PGOProfiler::DumpICByValueWithHandler(ApEntityId abcId, const CString &reco if (cell->GetHasChanged()) { return; } - JSTaggedValue handlerInfoValue = prototypeHandler->GetHandlerInfo(vm_->GetJSThread()); + JSTaggedValue handlerInfoValue = prototypeHandler->GetHandlerInfo(holder_); if (handlerInfoValue.IsInt()) { auto handlerInfo = static_cast(handlerInfoValue.GetInt()); if (HandlerBase::IsElement(handlerInfo)) { @@ -1207,7 +1201,7 @@ void PGOProfiler::DumpICByValueWithHandler(ApEntityId abcId, const CString &reco return; } } - auto holder = prototypeHandler->GetHolder(vm_->GetJSThread()); + auto holder = prototypeHandler->GetHolder(holder_); auto holderHClass = holder.GetTaggedObject()->GetClass(); AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, holderHClass, holderHClass); } @@ -1218,13 +1212,12 @@ void PGOProfiler::TryDumpProtoTransitionType(JSHClass *hclass) if (hclass->IsCompositeHClass()) { return; } - auto thread = vm_->GetJSThread(); - JSHClass *ihc1 = JSHClass::FindRootHClass(thread, hclass); + JSHClass *ihc1 = JSHClass::FindRootHClass(holder_, hclass); auto transitionType = GetProfileType(ihc1, true); if (!transitionType.IsRootType() || !transitionType.IsTransitionClassType()) { return; } - JSTaggedValue phc1Root = JSHClass::FindProtoRootHClass(thread, ihc1); + JSTaggedValue phc1Root = JSHClass::FindProtoRootHClass(holder_, ihc1); if (!phc1Root.IsJSHClass()) { LOG_PGO(DEBUG) << "Phc1Root is not a JSHclass!"; return; @@ -1251,7 +1244,7 @@ void PGOProfiler::TryDumpProtoTransitionType(JSHClass *hclass) auto ihc0RootType = GetProfileType(ihc0Obj); ASSERT(ihc0RootType.IsRootType()); - auto baseRootHClass = JSHClass::FindRootHClass(thread, baseIhcObj); + auto baseRootHClass = JSHClass::FindRootHClass(holder_, baseIhcObj); auto baseRootType = GetProfileType(baseRootHClass, true); if (!baseRootType.IsRootType()) { LOG_PGO(DEBUG) << "Unsupported prototypes which cannot be recorded!"; @@ -1270,7 +1263,7 @@ void PGOProfiler::TryDumpProtoTransitionType(JSHClass *hclass) void PGOProfiler::DumpOpType(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId, ProfileTypeInfo *profileTypeInfo) { - JSTaggedValue slotValue = profileTypeInfo->Get(vm_->GetJSThread(), slotId); + JSTaggedValue slotValue = profileTypeInfo->Get(holder_, slotId); if (slotValue.IsInt()) { auto type = slotValue.GetInt(); ProfileType recordType = GetRecordProfileType(abcId, recordName); @@ -1280,7 +1273,7 @@ void PGOProfiler::DumpOpType(ApEntityId abcId, const CString &recordName, Entity bool PGOProfiler::FunctionKindVerify(const JSFunction *ctorFunction) { - FunctionKind kind = Method::Cast(ctorFunction->GetMethod(vm_->GetJSThread()))->GetFunctionKind(); + FunctionKind kind = Method::Cast(ctorFunction->GetMethod(holder_))->GetFunctionKind(); return kind == FunctionKind::BASE_CONSTRUCTOR || kind == FunctionKind::CLASS_CONSTRUCTOR || kind == FunctionKind::DERIVED_CONSTRUCTOR; @@ -1290,22 +1283,22 @@ void PGOProfiler::DumpDefineClass(ApEntityId abcId, const CString &recordName, E uint32_t slotId, ProfileTypeInfo *profileTypeInfo) { const JSThread *thread = vm_->GetJSThread(); - JSTaggedValue slotValue = profileTypeInfo->Get(thread, slotId); + JSTaggedValue slotValue = profileTypeInfo->Get(holder_, slotId); if (!slotValue.IsProfileTypeInfoCell0()) { return; } - JSTaggedValue handle = ProfileTypeInfoCell::Cast(slotValue)->GetHandle(thread); + JSTaggedValue handle = ProfileTypeInfoCell::Cast(slotValue)->GetHandle(holder_); if (!handle.IsHeapObject() || !handle.IsWeak()) { return; } auto object = handle.GetWeakReferentUnChecked(); if (object->GetClass()->IsJSFunction()) { JSFunction *ctorFunction = JSFunction::Cast(object); - auto ctorMethod = ctorFunction->GetMethod(thread); + auto ctorMethod = ctorFunction->GetMethod(holder_); if (!ctorMethod.IsMethod() || !FunctionKindVerify(ctorFunction)) { return; } - ApEntityId ctorAbcId = GetMethodAbcId(thread, ctorFunction); + ApEntityId ctorAbcId = GetMethodAbcId(holder_, ctorFunction); auto ctorJSMethod = Method::Cast(ctorMethod); auto ctorMethodId = ctorJSMethod->GetMethodId().GetOffset(); @@ -1314,15 +1307,16 @@ void PGOProfiler::DumpDefineClass(ApEntityId abcId, const CString &recordName, E return; } PGODefineOpType objDefType(localType); - auto protoOrHClass = ctorFunction->GetProtoOrHClass(thread); + auto protoOrHClass = ctorFunction->GetProtoOrHClass(holder_); if (protoOrHClass.IsJSHClass()) { auto ihc = JSHClass::Cast(protoOrHClass.GetTaggedObject()); SetRootProfileType(ihc, ctorAbcId, ctorMethodId, ProfileType::Kind::ClassId); + // TODO recordInfos_->AddRootLayout(thread, JSTaggedType(ihc), localType); - protoOrHClass = ihc->GetProto(thread); + protoOrHClass = ihc->GetProto(holder_); } - auto ctorRootHClass = JSHClass::FindRootHClass(thread, ctorFunction->GetJSHClass()); + auto ctorRootHClass = JSHClass::FindRootHClass(holder_, ctorFunction->GetJSHClass()); auto ctorType = GetProfileType(ctorRootHClass); if (!ctorType.IsRootType()) { LOG_PGO(DEBUG) << "The profileType of constructor root hclass was not found."; @@ -1333,7 +1327,7 @@ void PGOProfiler::DumpDefineClass(ApEntityId abcId, const CString &recordName, E if (protoOrHClass.IsJSObject()) { auto prototypeHClass = JSObject::Cast(protoOrHClass)->GetClass(); - auto prototypeRootHClass = JSHClass::FindRootHClass(thread, prototypeHClass); + auto prototypeRootHClass = JSHClass::FindRootHClass(holder_, prototypeHClass); ProfileType prototypeType = GetProfileType(prototypeRootHClass); if (!prototypeType.IsRootType()) { LOG_PGO(DEBUG) << "The profileType of prototype root hclass was not found."; @@ -1352,7 +1346,7 @@ void PGOProfiler::DumpCreateObject(ApEntityId abcId, const CString &recordName, uint32_t slotId, ProfileTypeInfo *profileTypeInfo, int32_t traceId) { const JSThread *thread = vm_->GetJSThread(); - JSTaggedValue slotValue = profileTypeInfo->Get(thread, slotId); + JSTaggedValue slotValue = profileTypeInfo->Get(holder_, slotId); if (!slotValue.IsHeapObject()) { return; } @@ -1361,7 +1355,7 @@ void PGOProfiler::DumpCreateObject(ApEntityId abcId, const CString &recordName, auto object = slotValue.GetWeakReferentUnChecked(); if (object->GetClass()->IsHClass()) { auto newHClass = JSHClass::Cast(object); - auto rootHClass = JSHClass::FindRootHClass(thread, newHClass); + auto rootHClass = JSHClass::FindRootHClass(holder_, newHClass); ProfileType profileType = GetProfileType(rootHClass); if (!profileType.IsRootType()) { return; @@ -1382,7 +1376,7 @@ void PGOProfiler::DumpCreateObject(ApEntityId abcId, const CString &recordName, objDefType.SetElementsLength(trackInfo->GetArrayLength()); objDefType.SetSpaceFlag(trackInfo->GetSpaceFlag()); recordInfos_->AddDefine(recordType, methodId, bcOffset, objDefType); - auto cachedHClass = trackInfo->GetCachedHClass(thread); + auto cachedHClass = trackInfo->GetCachedHClass(holder_); if (cachedHClass.IsJSHClass()) { auto hclass = JSHClass::Cast(cachedHClass.GetTaggedObject()); recordInfos_->AddRootLayout(thread, JSTaggedType(hclass), profileType); @@ -1393,8 +1387,7 @@ void PGOProfiler::DumpCreateObject(ApEntityId abcId, const CString &recordName, void PGOProfiler::DumpCall(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId, ProfileTypeInfo *profileTypeInfo) { - const JSThread *thread = vm_->GetJSThread(); - JSTaggedValue slotValue = profileTypeInfo->Get(thread, slotId); + JSTaggedValue slotValue = profileTypeInfo->Get(holder_, slotId); ProfileType::Kind kind; int calleeMethodId = 0; ApEntityId calleeAbcId = 0; @@ -1409,9 +1402,9 @@ void PGOProfiler::DumpCall(ApEntityId abcId, const CString &recordName, EntityId } } else if (slotValue.IsJSFunction()) { JSFunction *callee = JSFunction::Cast(slotValue); - Method *calleeMethod = Method::Cast(callee->GetMethod(thread)); + Method *calleeMethod = Method::Cast(callee->GetMethod(holder_)); calleeMethodId = static_cast(calleeMethod->GetMethodId().GetOffset()); - calleeAbcId = GetMethodAbcId(thread, callee->GetMethod(thread)); + calleeAbcId = GetMethodAbcId(holder_, callee->GetMethod(holder_)); kind = ProfileType::Kind::MethodId; } else { return; @@ -1428,7 +1421,7 @@ void PGOProfiler::DumpGetIterator(ApEntityId abcId, const CString &recordName, E if (thread->GetEnableLazyBuiltins()) { return; } - JSTaggedValue value = profileTypeInfo->Get(thread, slotId); + JSTaggedValue value = profileTypeInfo->Get(holder_, slotId); if (!value.IsInt()) { return; } @@ -1443,14 +1436,13 @@ void PGOProfiler::DumpGetIterator(ApEntityId abcId, const CString &recordName, E void PGOProfiler::DumpNewObjRange(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId, ProfileTypeInfo *profileTypeInfo) { - const JSThread *thread = vm_->GetJSThread(); - JSTaggedValue slotValue = profileTypeInfo->Get(thread, slotId); + JSTaggedValue slotValue = profileTypeInfo->Get(holder_, slotId); int ctorMethodId = 0; if (slotValue.IsInt()) { ctorMethodId = slotValue.GetInt(); } else if (slotValue.IsJSFunction()) { JSFunction *callee = JSFunction::Cast(slotValue); - Method *calleeMethod = Method::Cast(callee->GetMethod(thread)); + Method *calleeMethod = Method::Cast(callee->GetMethod(holder_)); ctorMethodId = static_cast(calleeMethod->GetMethodId().GetOffset()); } else { return; @@ -1469,8 +1461,7 @@ void PGOProfiler::DumpNewObjRange(ApEntityId abcId, const CString &recordName, E void PGOProfiler::DumpInstanceof(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId, ProfileTypeInfo *profileTypeInfo) { - const JSThread *thread = vm_->GetJSThread(); - JSTaggedValue firstValue = profileTypeInfo->Get(thread, slotId); + JSTaggedValue firstValue = profileTypeInfo->Get(holder_, slotId); if (!firstValue.IsHeapObject()) { if (firstValue.IsHole()) { // Mega state @@ -1501,17 +1492,17 @@ void PGOProfiler::DumpInstanceof(ApEntityId abcId, const CString &recordName, En void PGOProfiler::UpdateLayout(JSHClass *hclass) { JSThread *thread = vm_->GetJSThread(); - auto parentHClass = hclass->GetParent(thread); + auto parentHClass = hclass->GetParent(holder_); if (!GetProfileType(hclass).IsRootType() && parentHClass.IsJSHClass()) { UpdateTransitionLayout(JSHClass::Cast(parentHClass.GetTaggedObject()), hclass); } else { - auto rootHClass = JSHClass::FindRootHClass(thread, hclass); + auto rootHClass = JSHClass::FindRootHClass(holder_, hclass); ProfileType rootType = GetProfileType(rootHClass, true); if (!rootType.IsRootType()) { return; } - auto prototypeHClass = JSHClass::FindProtoRootHClass(thread, rootHClass); + auto prototypeHClass = JSHClass::FindProtoRootHClass(holder_, rootHClass); if (prototypeHClass.IsJSHClass()) { auto prototypeObject = JSHClass::Cast(prototypeHClass.GetTaggedObject()); ProfileType prototypeType = GetProfileType(prototypeObject, true); @@ -1529,7 +1520,7 @@ void PGOProfiler::UpdateLayout(JSHClass *hclass) void PGOProfiler::UpdateTransitionLayout(JSHClass* parent, JSHClass* child) { JSThread *thread = vm_->GetJSThread(); - auto rootHClass = JSHClass::FindRootHClass(thread, parent); + auto rootHClass = JSHClass::FindRootHClass(holder_, parent); auto rootType = GetProfileType(rootHClass, true); if (!rootType.IsRootType()) { return; @@ -1543,7 +1534,7 @@ void PGOProfiler::UpdateTransitionLayout(JSHClass* parent, JSHClass* child) hclassVec.emplace(parent); while (!GetProfileType(parent).IsRootType()) { - auto parentHCValue = parent->GetParent(thread); + auto parentHCValue = parent->GetParent(holder_); if (!parentHCValue.IsJSHClass()) { break; } @@ -1633,7 +1624,7 @@ void PGOProfiler::UpdatePrototypeChainInfo(JSHClass *receiver, JSHClass *holder, } std::vector> protoChain; - JSTaggedValue proto = JSHClass::FindProtoHClass(vm_->GetJSThread(), receiver); + JSTaggedValue proto = JSHClass::FindProtoHClass(holder_, receiver); while (proto.IsJSHClass()) { auto protoHClass = JSHClass::Cast(proto.GetTaggedObject()); if (protoHClass == holder) { @@ -1645,7 +1636,7 @@ void PGOProfiler::UpdatePrototypeChainInfo(JSHClass *receiver, JSHClass *holder, } auto protoType = GetOrInsertProfileType(protoHClass, protoRootType); protoChain.emplace_back(protoRootType, protoType); - proto = JSHClass::FindProtoHClass(vm_->GetJSThread(), protoHClass); + proto = JSHClass::FindProtoHClass(holder_, protoHClass); } if (!protoChain.empty()) { info.AddPrototypePt(protoChain); @@ -1854,7 +1845,7 @@ void PGOProfiler::SetRootProfileType(JSHClass *root, ApEntityId abcId, uint32_t ProfileType PGOProfiler::FindRootProfileType(JSHClass *hclass) { - auto rootHClass = JSHClass::FindRootHClass(vm_->GetJSThread(), hclass); + auto rootHClass = JSHClass::FindRootHClass(holder_, hclass); return GetProfileType(rootHClass, true); } @@ -1987,6 +1978,21 @@ ApEntityId PGOProfiler::GetMethodAbcId(const JSThread *thread, JSTaggedValue jsM } return abcId; } +ApEntityId PGOProfiler::GetMethodAbcId(ThreadHolder *holder, JSTaggedValue jsMethod) +{ + ASSERT(jsMethod.IsMethod()); + CString pfName; + + const auto *pf = Method::Cast(jsMethod)->GetJSPandaFile(holder); + if (pf != nullptr) { + pfName = pf->GetJSPandaFileDesc(); + } + ApEntityId abcId(0); + if (!PGOProfilerManager::GetInstance()->GetPandaFileId(pfName, abcId) && !pfName.empty()) { + LOG_PGO(ERROR) << "Get method abc id failed. abcName: " << pfName; + } + return abcId; +} ApEntityId PGOProfiler::GetMethodAbcId(const JSThread *thread, JSFunction *jsFunction) { CString pfName; @@ -1998,13 +2004,24 @@ ApEntityId PGOProfiler::GetMethodAbcId(const JSThread *thread, JSFunction *jsFun UNREACHABLE(); } +ApEntityId PGOProfiler::GetMethodAbcId(ThreadHolder *holder, JSFunction *jsFunction) +{ + CString pfName; + auto jsMethod = jsFunction->GetMethod(holder); + if (jsMethod.IsMethod()) { + return GetMethodAbcId(holder, jsMethod); + } + LOG_PGO(ERROR) << "Get method abc id failed. Not a method."; + UNREACHABLE(); +} + ProfileType PGOProfiler::GetRecordProfileType(JSFunction *jsFunction, const CString &recordName) { CString pfName; JSThread *thread = vm_->GetJSThread(); - auto jsMethod = jsFunction->GetMethod(thread); + auto jsMethod = jsFunction->GetMethod(holder_); if (jsMethod.IsMethod()) { - const auto *pf = Method::Cast(jsMethod)->GetJSPandaFile(thread); + const auto *pf = Method::Cast(jsMethod)->GetJSPandaFile(holder_); if (pf != nullptr) { pfName = pf->GetJSPandaFileDesc(); } @@ -2015,7 +2032,7 @@ ProfileType PGOProfiler::GetRecordProfileType(JSFunction *jsFunction, const CStr << ", recordName: " << recordName; return ProfileType::PROFILE_TYPE_NONE; } - return GetRecordProfileType(pf, GetMethodAbcId(thread, jsFunction), recordName); + return GetRecordProfileType(pf, GetMethodAbcId(holder_, jsFunction), recordName); } ProfileType PGOProfiler::GetRecordProfileType(ApEntityId abcId, const CString &recordName) @@ -2156,7 +2173,7 @@ JSTaggedValue PGOProfiler::TryFindKeyInPrototypeChain(TaggedObject *currObj, JSH return JSTaggedValue(currHC); } } else { - TaggedArray *array = TaggedArray::Cast(JSObject::Cast(currObj)->GetProperties(thread).GetTaggedObject()); + TaggedArray *array = TaggedArray::Cast(JSObject::Cast(currObj)->GetProperties(holder_).GetTaggedObject()); ASSERT(array->IsDictionaryMode()); NameDictionary *dict = NameDictionary::Cast(array); int entry = dict->FindEntry(thread, key); @@ -2164,7 +2181,7 @@ JSTaggedValue PGOProfiler::TryFindKeyInPrototypeChain(TaggedObject *currObj, JSH return JSTaggedValue(currHC); } } - auto proto = currHC->GetProto(thread); + auto proto = currHC->GetProto(holder_); if (!proto.IsHeapObject()) { return JSTaggedValue::Undefined(); } diff --git a/ecmascript/pgo_profiler/pgo_profiler.h b/ecmascript/pgo_profiler/pgo_profiler.h index c2247f91ce85b39c6d6a38ce8c459be576aa278f..73acd1910f197fded3261e5a53d1bf8db06362ef 100644 --- a/ecmascript/pgo_profiler/pgo_profiler.h +++ b/ecmascript/pgo_profiler/pgo_profiler.h @@ -97,7 +97,9 @@ public: void UpdateTrackInfo(JSTaggedValue trackInfoVal); JSTaggedValue TryFindKeyInPrototypeChain(TaggedObject* currObj, JSHClass* currHC, JSTaggedValue key); static ApEntityId PUBLIC_API GetMethodAbcId(const JSThread *thread, JSFunction* jsFunction); + static ApEntityId PUBLIC_API GetMethodAbcId(ThreadHolder *holder, JSFunction* jsFunction); static ApEntityId PUBLIC_API GetMethodAbcId(const JSThread *thread, JSTaggedValue jsMethod); + static ApEntityId PUBLIC_API GetMethodAbcId(ThreadHolder *holder, JSTaggedValue jsMethod); void Reset(bool isEnable); void InsertSkipCtorMethodIdSafe(EntityId ctorMethodId); void SetSaveTimestamp(std::chrono::system_clock::time_point timestamp); diff --git a/ecmascript/pgo_profiler/pgo_profiler_info.cpp b/ecmascript/pgo_profiler/pgo_profiler_info.cpp index bca2240159d61623f694ff06a35dcb39906b7a44..1f940a13de6e762d22897d9a127103dc7559beba 100644 --- a/ecmascript/pgo_profiler/pgo_profiler_info.cpp +++ b/ecmascript/pgo_profiler/pgo_profiler_info.cpp @@ -217,6 +217,34 @@ bool PGOMethodInfoMap::AddMethod(const JSThread *thread, Chunk *chunk, Method *j } } +bool PGOMethodInfoMap::AddMethod(ThreadHolder *holder, Chunk *chunk, Method *jsMethod, SampleMode mode) +{ + PGOMethodId methodId(jsMethod->GetMethodId()); + auto result = methodInfos_.find(methodId); + if (result != methodInfos_.end()) { + auto info = result->second; + info->IncreaseCount(); + info->SetSampleMode(mode); + return false; + } else { + CString methodName = jsMethod->GetMethodName(holder); + size_t strlen = methodName.size(); + size_t size = static_cast(PGOMethodInfo::Size(strlen)); + void *infoAddr = chunk->Allocate(size); + if (infoAddr == nullptr) { + LOG_ECMA(ERROR) << "infoAddr is null!"; + return false; + } + auto info = new (infoAddr) PGOMethodInfo(methodId, 0, mode, methodName.c_str()); + info->IncreaseCount(); + methodInfos_.emplace(methodId, info); + auto checksum = PGOMethodInfo::CalcChecksum(jsMethod->GetMethodName(holder), jsMethod->GetBytecodeArray(), + jsMethod->GetCodeSize(holder)); + methodsChecksum_.emplace(methodId, checksum); + return true; + } +} + PGOMethodTypeSet *PGOMethodInfoMap::GetOrInsertMethodTypeSet(Chunk *chunk, PGOMethodId methodId) { auto typeInfoSetIter = methodTypeInfos_.find(methodId); @@ -653,6 +681,15 @@ bool PGORecordDetailInfos::AddMethod(const JSThread *thread, ProfileType recordP return curMethodInfos->AddMethod(thread, chunk_.get(), jsMethod, mode); } +bool PGORecordDetailInfos::AddMethod(ThreadHolder *holder, ProfileType recordProfileType, Method *jsMethod, + SampleMode mode) +{ + auto curMethodInfos = GetMethodInfoMap(recordProfileType); + ASSERT(curMethodInfos != nullptr); + ASSERT(jsMethod != nullptr); + return curMethodInfos->AddMethod(holder, chunk_.get(), jsMethod, mode); +} + bool PGORecordDetailInfos::AddType(ProfileType recordProfileType, PGOMethodId methodId, int32_t offset, PGOSampleType type) { diff --git a/ecmascript/pgo_profiler/pgo_profiler_info.h b/ecmascript/pgo_profiler/pgo_profiler_info.h index 836549661042982d5280984a82d6cf8282d90363..f43d4d64d39ed481a8e4d0d713dbd2d8dca50e18 100644 --- a/ecmascript/pgo_profiler/pgo_profiler_info.h +++ b/ecmascript/pgo_profiler/pgo_profiler_info.h @@ -311,6 +311,7 @@ public: } bool AddMethod(const JSThread *thread, Chunk *chunk, Method *jsMethod, SampleMode mode); + bool AddMethod(ThreadHolder *holder, Chunk *chunk, Method *jsMethod, SampleMode mode); bool AddType(Chunk *chunk, PGOMethodId methodId, int32_t offset, PGOSampleType type); bool AddCallTargetType(Chunk *chunk, PGOMethodId methodId, int32_t offset, PGOSampleType type); bool AddObjectInfo(Chunk *chunk, PGOMethodId methodId, int32_t offset, const PGOObjectInfo &info); @@ -502,6 +503,7 @@ public: // If it is a new method, return true. bool AddMethod(const JSThread *thread, ProfileType recordProfileType, Method *jsMethod, SampleMode mode); + bool AddMethod(ThreadHolder *holder, ProfileType recordProfileType, Method *jsMethod, SampleMode mode); bool AddType(ProfileType recordProfileType, PGOMethodId methodId, int32_t offset, PGOSampleType type); bool AddCallTargetType(ProfileType recordProfileType, PGOMethodId methodId, int32_t offset, PGOSampleType type); bool AddObjectInfo(ProfileType recordProfileType, PGOMethodId methodId, int32_t offset, const PGOObjectInfo &info); diff --git a/ecmascript/pgo_profiler/pgo_trace.h b/ecmascript/pgo_profiler/pgo_trace.h index 7845e2a4405434cca17bb31e3706159df3d87c55..4871a68cb843d084c33ce95bb7741da3e09cac3e 100644 --- a/ecmascript/pgo_profiler/pgo_trace.h +++ b/ecmascript/pgo_profiler/pgo_trace.h @@ -75,6 +75,15 @@ public: hotness_ = hotness; } + MethodData(ThreadHolder *holder, JSTaggedValue value, bool hotness) + { + Method* method = Method::Cast(value); + name_ = method->GetMethodName(holder); + id_ = method->GetMethodId(); + codesize_ = method->GetCodeSize(holder); + hotness_ = hotness; + } + EntityId GetId() const { return id_; @@ -139,6 +148,19 @@ public: } } + MethodData* TryGetMethodData(ThreadHolder *holder, JSTaggedValue value, bool hotness = false) + { + MethodData method(holder, value, hotness); + auto data = GetMethodData(method.GetId()); + if (data) { + data->SetHotness(hotness); + return data; + } else { + auto res = methods.emplace(method.GetId(), method); + return &(res.first->second); + } + } + void Print() const { LOG_TRACE(INFO) << "only print methods which (total time > 10 ms || count > 10) on ohos device"; diff --git a/ecmascript/runtime.cpp b/ecmascript/runtime.cpp index db35fbb87ce99d2de11248a4a0e8ed3059e03034..677462ef3e2e2cc518e2569842e2adfda215b41f 100644 --- a/ecmascript/runtime.cpp +++ b/ecmascript/runtime.cpp @@ -192,7 +192,8 @@ void Runtime::DestroyIfLastVm() LockHolder lock(*vmCreationLock_); if (--vmCount_ <= 0) { Jit::GetInstance()->Destroy(); - SharedModuleManager::GetInstance()->SharedNativeObjDestory(); + auto holder = DaemonThread::GetInstance()->GetThreadHolder(); + SharedModuleManager::GetInstance()->SharedNativeObjDestory(holder); SharedHeap::GetInstance()->WaitAllTasksFinishedAfterAllJSThreadEliminated(); DaemonThread::DestroyInstance(); if (g_isEnableCMCGC) { diff --git a/ecmascript/tagged_array.h b/ecmascript/tagged_array.h index 2da29a0c8696605a2ff14436aced2b58b6c306d8..8a6917e0fbf8af07d705a7a605da0050f4f6f588 100644 --- a/ecmascript/tagged_array.h +++ b/ecmascript/tagged_array.h @@ -46,6 +46,16 @@ public: DATA_OFFSET + offset)); } + template + JSTaggedValue Get(ThreadHolder *holder, uint32_t idx) const + { + ASSERT(idx < GetLength()); + size_t offset = JSTaggedValue::TaggedTypeSize() * idx; + + return JSTaggedValue(Barriers::GetTaggedValue(holder, reinterpret_cast(ToUintPtr(this)), + DATA_OFFSET + offset)); + } + JSTaggedValue GetPrimitive(uint32_t idx) const { ASSERT(idx < GetLength()); diff --git a/ecmascript/tagged_hash_table.h b/ecmascript/tagged_hash_table.h index 75d6da7b93ca3387b890d8275c1bacac3ccd7fe1..1a1d5e4079cf1de973a61a894602f804f71954a6 100644 --- a/ecmascript/tagged_hash_table.h +++ b/ecmascript/tagged_hash_table.h @@ -191,6 +191,15 @@ public: return Get(thread, index); } + JSTaggedValue GetKey(ThreadHolder *holder, int entry) const + { + int index = Derived::GetKeyIndex(entry); + if (UNLIKELY((index < 0 || index > static_cast(GetLength())))) { + return JSTaggedValue::Undefined(); + } + return Get(holder, index); + } + JSTaggedValue GetValue(const JSThread *thread, int entry) const { int index = Derived::GetValueIndex(entry); @@ -200,6 +209,15 @@ public: return Get(thread, index); } + JSTaggedValue GetValue(ThreadHolder *holder, int entry) const + { + int index = Derived::GetValueIndex(entry); + if (UNLIKELY((index < 0 || index > static_cast(GetLength())))) { + return JSTaggedValue::Undefined(); + } + return Get(holder, index); + } + inline void GetAllKeys(const JSThread *thread, int offset, TaggedArray *keyArray) const { ASSERT_PRINT(offset + EntriesCount() <= static_cast(keyArray->GetLength()), @@ -251,6 +269,28 @@ public: return -1; } + // inline int FindEntry(JSThread *thread, const JSTaggedValue &key) + // { + // int size = Size(); + // int count = 1; + // JSTaggedValue keyValue; + // int32_t hash = static_cast(Derived::Hash(thread, key)); + // + // for (uint32_t entry = GetFirstPosition(hash, size);; entry = GetNextPosition(entry, count++, size)) { + // keyValue = GetKey(thread, entry); + // if (keyValue.IsHole()) { + // continue; + // } + // if (keyValue.IsUndefined()) { + // return -1; + // } + // if (Derived::IsMatch(thread, key, keyValue)) { + // return entry; + // } + // } + // return -1; + // } + inline int FindEntry(const JSThread *thread, const uint8_t* str, int strSize) { int size = Size(); diff --git a/ecmascript/tests/ecma_string_table_test.cpp b/ecmascript/tests/ecma_string_table_test.cpp index 296e4244619e9a2af8fa5a8af55aef4e8b0ac804..1f290d8ec20154c88379098eb29b99d655332890 100644 --- a/ecmascript/tests/ecma_string_table_test.cpp +++ b/ecmascript/tests/ecma_string_table_test.cpp @@ -252,7 +252,8 @@ void EcmaStringTableTest::TestLoadOrStoreInsertNewKey() auto readBarrier = [vm](const void *obj, size_t offset) -> TaggedObject * { return Barriers::GetTaggedObject(vm->GetAssociatedJSThread(), obj, offset); }; - BaseString* loadResult1 = map->template Load(std::move(readBarrier), key, value->ToBaseString()); + BaseString* loadResult1 = map->template Load(thread, + std::move(readBarrier), key, value->ToBaseString()); EXPECT_EQ(loadResult1, nullptr); // Test insertion BaseString* result = map->template LoadOrStore( @@ -262,7 +263,8 @@ void EcmaStringTableTest::TestLoadOrStoreInsertNewKey() EcmaString::FromBaseString(foudString)); }); EXPECT_EQ(result, value->ToBaseString()); - BaseString* loadResult2 = map->template Load(std::move(readBarrier), key, value->ToBaseString()); + BaseString* loadResult2 = map->template Load(thread, + std::move(readBarrier), key, value->ToBaseString()); EXPECT_STREQ(EcmaStringAccessor(EcmaString::FromBaseString(loadResult2)).ToCString(thread).c_str(), "test_value"); EXPECT_EQ(loadResult2, value->ToBaseString()); delete map; @@ -308,9 +310,9 @@ void EcmaStringTableTest::TestLoadOrStoreStoreExistingKey() auto readBarrier = [vm](const void *obj, size_t offset) -> TaggedObject * { return Barriers::GetTaggedObject(vm->GetAssociatedJSThread(), obj, offset); }; - EXPECT_EQ(map->template Load(std::move(readBarrier), key1, original->ToBaseString()), + EXPECT_EQ(map->template Load(thread, std::move(readBarrier), key1, original->ToBaseString()), original->ToBaseString()); - EXPECT_EQ(map->template Load(std::move(readBarrier), key2, origina2->ToBaseString()), + EXPECT_EQ(map->template Load(thread, std::move(readBarrier), key2, origina2->ToBaseString()), origina2->ToBaseString()); delete map; } diff --git a/ecmascript/tests/module_manager_map_test.cpp b/ecmascript/tests/module_manager_map_test.cpp index 14c0b2a4d78f876c7246fb90ad1abdb46cca65f3..c7bc366f32e7522b520d1327b6d8e01b4912067d 100644 --- a/ecmascript/tests/module_manager_map_test.cpp +++ b/ecmascript/tests/module_manager_map_test.cpp @@ -105,7 +105,8 @@ HWTEST_F_L0(ModuleManagerMapTest, InsertAndFind) map.Insert(1, value); - auto result = map.Find(1); + auto holder = thread->GetThreadHolder(); + auto result = map.Find(holder, 1); ASSERT_TRUE(result.has_value()); ASSERT_EQ(result->GetRawData(), value.GetRawData()); } @@ -116,7 +117,8 @@ HWTEST_F_L0(ModuleManagerMapTest, EmplaceAndFind) map.Emplace(1, value); - auto result = map.Find(1); + auto holder = thread->GetThreadHolder(); + auto result = map.Find(holder, 1); ASSERT_TRUE(result.has_value()); ASSERT_EQ(result->GetRawData(), value.GetRawData()); } @@ -129,7 +131,8 @@ HWTEST_F_L0(ModuleManagerMapTest, EmplaceDoesNotOverwrite) map.Insert(1, value1); map.Emplace(1, value2); // Should not overwrite - auto result = map.Find(1); + auto holder = thread->GetThreadHolder(); + auto result = map.Find(holder, 1); ASSERT_TRUE(result.has_value()); ASSERT_EQ(result->GetRawData(), value1.GetRawData()); // Should still be original value } @@ -142,14 +145,16 @@ HWTEST_F_L0(ModuleManagerMapTest, InsertOverwrites) map.Insert(1, value1); map.Insert(1, value2); // Should overwrite - auto result = map.Find(1); + auto holder = thread->GetThreadHolder(); + auto result = map.Find(holder, 1); ASSERT_TRUE(result.has_value()); ASSERT_EQ(result->GetRawData(), value2.GetRawData()); // Should be new value } HWTEST_F_L0(ModuleManagerMapTest, FindNonExistent) { - auto result = map.Find(999); + auto holder = thread->GetThreadHolder(); + auto result = map.Find(holder, 999); ASSERT_FALSE(result.has_value()); } @@ -180,10 +185,11 @@ HWTEST_F_L0(ModuleManagerMapTest, Erase) JSTaggedValue value(42); map.Insert(1, value); - ASSERT_TRUE(map.Find(1).has_value()); + auto holder = thread->GetThreadHolder(); + ASSERT_TRUE(map.Find(holder, 1).has_value()); map.Erase(1); - ASSERT_FALSE(map.Find(1).has_value()); + ASSERT_FALSE(map.Find(holder, 1).has_value()); ASSERT_EQ(map.Size(), 0U); } @@ -211,8 +217,9 @@ HWTEST_F_L0(ModuleManagerMapTest, Clear) map.Clear(); ASSERT_EQ(map.Size(), 0U); - ASSERT_FALSE(map.Find(1).has_value()); - ASSERT_FALSE(map.Find(2).has_value()); + auto holder = thread->GetThreadHolder(); + ASSERT_FALSE(map.Find(holder, 1).has_value()); + ASSERT_FALSE(map.Find(holder, 2).has_value()); } HWTEST_F_L0(ModuleManagerMapTest, TemplateKeyType) @@ -222,10 +229,11 @@ HWTEST_F_L0(ModuleManagerMapTest, TemplateKeyType) string_map.Insert("test_key", value); - auto result = string_map.Find("test_key"); + auto holder = thread->GetThreadHolder(); + auto result = string_map.Find(holder, "test_key"); ASSERT_TRUE(result.has_value()); ASSERT_EQ(result->GetRawData(), value.GetRawData()); - ASSERT_FALSE(string_map.Find("non_existent").has_value()); + ASSERT_FALSE(string_map.Find(holder, "non_existent").has_value()); } } // namespace panda::test