diff --git a/common_components/common_runtime/base_runtime.cpp b/common_components/common_runtime/base_runtime.cpp index eed63ae50e71df80ad5dcb3c1fc72f96c3d67019..4839135b9e448342b78321719c03f360fc9d66a6 100755 --- a/common_components/common_runtime/base_runtime.cpp +++ b/common_components/common_runtime/base_runtime.cpp @@ -179,10 +179,10 @@ void BaseRuntime::WriteRoot(void *obj) Heap::GetBarrier().WriteRoot(reinterpret_cast(obj)); } -void BaseRuntime::WriteBarrier(void* obj, void* field, void* ref) +void BaseRuntime::WriteBarrier(void* obj, void* field, void* ref, Mutator *mutator) { DCHECK_CC(field != nullptr); - Heap::GetBarrier().WriteBarrier(reinterpret_cast(obj), + Heap::GetBarrier().WriteBarrier(mutator, reinterpret_cast(obj), *reinterpret_cast*>(field), reinterpret_cast(ref)); } diff --git a/common_components/heap/ark_collector/enum_barrier.cpp b/common_components/heap/ark_collector/enum_barrier.cpp index 45dde4bf47605224429fc3fc3cdf32f6516460af..9f566435d5ebe3693838afe9b691ebead56a2127 100755 --- a/common_components/heap/ark_collector/enum_barrier.cpp +++ b/common_components/heap/ark_collector/enum_barrier.cpp @@ -62,7 +62,7 @@ void EnumBarrier::WriteRefField(BaseObject* obj, RefField& field, BaseObj field.SetFieldValue(newField.GetFieldValue()); } #ifdef ARK_USE_SATB_BARRIER -void EnumBarrier::WriteBarrier(BaseObject* obj, RefField& field, BaseObject* ref) const +void EnumBarrier::WriteBarrier(Mutator *mutator, BaseObject* obj, RefField& field, BaseObject* ref) const { RefField<> tmpField(field); BaseObject* remeberedObject = nullptr; @@ -73,7 +73,9 @@ void EnumBarrier::WriteBarrier(BaseObject* obj, RefField& field, BaseObje } UpdateRememberSet(obj, ref); remeberedObject = tmpField.GetTargetObject(); - Mutator* mutator = Mutator::GetMutator(); + if (UNLIKELY(mutator == nullptr)) { + mutator = Mutator::GetMutator(); + } if (remeberedObject != nullptr) { mutator->RememberObjectInSatbBuffer(remeberedObject); } @@ -85,7 +87,7 @@ void EnumBarrier::WriteBarrier(BaseObject* obj, RefField& field, BaseObje DLOG(BARRIER, "write obj %p ref@%p: 0x%zx -> %p", obj, &field, remeberedObject, ref); } #else -void EnumBarrier::WriteBarrier(BaseObject* obj, RefField& field, BaseObject* ref) const +void EnumBarrier::WriteBarrier(Mutator *mutator, BaseObject* obj, RefField& field, BaseObject* ref) const { if (!Heap::IsTaggedObject((HeapAddress)ref)) { return; @@ -94,7 +96,9 @@ void EnumBarrier::WriteBarrier(BaseObject* obj, RefField& field, BaseObje UpdateRememberSet(obj, ref); } ref = (BaseObject*)((uintptr_t)ref & ~(TAG_WEAK)); - Mutator* mutator = Mutator::GetMutator(); + if (UNLIKELY(mutator == nullptr)) { + mutator = Mutator::GetMutator(); + } mutator->RememberObjectInSatbBuffer(ref); DLOG(BARRIER, "write obj %p ref-field@%p: -> %p", obj, &field, ref); } diff --git a/common_components/heap/ark_collector/enum_barrier.h b/common_components/heap/ark_collector/enum_barrier.h index 525f0ff8f320a2e486bb4bea38ad49707badfba4..0169e9cc8941ea9e81710fd0b210922bc128e6de 100755 --- a/common_components/heap/ark_collector/enum_barrier.h +++ b/common_components/heap/ark_collector/enum_barrier.h @@ -30,7 +30,7 @@ public: void WriteRoot(BaseObject *obj) const override; void WriteRefField(BaseObject* obj, RefField& field, BaseObject* ref) const override; - void WriteBarrier(BaseObject* obj, RefField& field, BaseObject* ref) const override; + void WriteBarrier(Mutator *mutator, BaseObject* obj, RefField& field, BaseObject* ref) const override; void WriteStruct(BaseObject* obj, HeapAddress dst, size_t dstLen, HeapAddress src, size_t srcLen) const override; void WriteStaticRef(RefField& field, BaseObject* ref) const override; diff --git a/common_components/heap/ark_collector/idle_barrier.cpp b/common_components/heap/ark_collector/idle_barrier.cpp index b36155a99da04c478acdaef480e8793ce1302605..76abad4c620f67f3e09804bd5525ec36b02131ce 100755 --- a/common_components/heap/ark_collector/idle_barrier.cpp +++ b/common_components/heap/ark_collector/idle_barrier.cpp @@ -116,7 +116,7 @@ void IdleBarrier::WriteRefField(BaseObject* obj, RefField& field, BaseObj field.SetTargetObject(ref); } -void IdleBarrier::WriteBarrier(BaseObject* obj, RefField& field, BaseObject* ref) const +void IdleBarrier::WriteBarrier(Mutator *mutator, BaseObject* obj, RefField& field, BaseObject* ref) const { if (!Heap::IsTaggedObject((HeapAddress)ref)) { return; diff --git a/common_components/heap/ark_collector/idle_barrier.h b/common_components/heap/ark_collector/idle_barrier.h index 292c2601c2e321d7566367726bd12ae723e435fe..53f438af61db7d48fcdea051d34ee04f33541e4f 100755 --- a/common_components/heap/ark_collector/idle_barrier.h +++ b/common_components/heap/ark_collector/idle_barrier.h @@ -30,7 +30,7 @@ public: void WriteRoot(BaseObject *obj) const override; void WriteRefField(BaseObject* obj, RefField& field, BaseObject* ref) const override; - void WriteBarrier(BaseObject* obj, RefField& field, BaseObject* ref) const override; + void WriteBarrier(Mutator *mutator, BaseObject* obj, RefField& field, BaseObject* ref) const override; void WriteStaticRef(RefField& field, BaseObject* ref) const override; void WriteStruct(BaseObject* obj, HeapAddress dst, size_t dstLen, HeapAddress src, size_t srcLen) const override; diff --git a/common_components/heap/ark_collector/marking_barrier.cpp b/common_components/heap/ark_collector/marking_barrier.cpp index 049349b3beed43a72e778d6c9a4bd73780b154d9..18620e5ba7164225e62b5a92625072f7a86feca3 100755 --- a/common_components/heap/ark_collector/marking_barrier.cpp +++ b/common_components/heap/ark_collector/marking_barrier.cpp @@ -59,7 +59,7 @@ void MarkingBarrier::WriteRefField(BaseObject* obj, RefField& field, Base field.SetFieldValue(newField.GetFieldValue()); } #ifdef ARK_USE_SATB_BARRIER -void MarkingBarrier::WriteBarrier(BaseObject* obj, RefField& field, BaseObject* ref) const +void MarkingBarrier::WriteBarrier(Mutator *mutator, BaseObject* obj, RefField& field, BaseObject* ref) const { RefField<> tmpField(field); BaseObject* rememberedObject = nullptr; @@ -68,7 +68,9 @@ void MarkingBarrier::WriteBarrier(BaseObject* obj, RefField& field, BaseO return; } UpdateRememberSet(obj, ref); - Mutator* mutator = Mutator::GetMutator(); + if (UNLIKELY(mutator == nullptr)) { + mutator = Mutator::GetMutator(); + } if (rememberedObject != nullptr) { mutator->RememberObjectInSatbBuffer(rememberedObject); } @@ -83,7 +85,7 @@ void MarkingBarrier::WriteBarrier(BaseObject* obj, RefField& field, BaseO DLOG(BARRIER, "write obj %p ref-field@%p: %#zx -> %p", obj, &field, rememberedObject, ref); } #else -void MarkingBarrier::WriteBarrier(BaseObject* obj, RefField& field, BaseObject* ref) const +void MarkingBarrier::WriteBarrier(Mutator *mutator, BaseObject* obj, RefField& field, BaseObject* ref) const { if (!Heap::IsTaggedObject((HeapAddress)ref)) { return; @@ -92,7 +94,9 @@ void MarkingBarrier::WriteBarrier(BaseObject* obj, RefField& field, BaseO UpdateRememberSet(obj, ref); } ref = (BaseObject*)((uintptr_t)ref & ~(TAG_WEAK)); - Mutator* mutator = Mutator::GetMutator(); + if (UNLIKELY(mutator == nullptr)) { + mutator = Mutator::GetMutator(); + } mutator->RememberObjectInSatbBuffer(ref); DLOG(BARRIER, "write obj %p ref-field@%p: -> %p", obj, &field, ref); } diff --git a/common_components/heap/ark_collector/marking_barrier.h b/common_components/heap/ark_collector/marking_barrier.h index 8af0cc7e5c799e9d2023e29297499e39b549d3bd..d36222b1f6934e779febe62d140f3715ef5b5761 100755 --- a/common_components/heap/ark_collector/marking_barrier.h +++ b/common_components/heap/ark_collector/marking_barrier.h @@ -31,7 +31,7 @@ public: void WriteRoot(BaseObject *obj) const override; void WriteRefField(BaseObject* obj, RefField& field, BaseObject* ref) const override; - void WriteBarrier(BaseObject* obj, RefField& field, BaseObject* ref) const override; + void WriteBarrier(Mutator *mutator, BaseObject* obj, RefField& field, BaseObject* ref) const override; void WriteStruct(BaseObject* obj, HeapAddress dst, size_t dstLen, HeapAddress src, size_t srcLen) const override; void WriteStaticRef(RefField& field, BaseObject* ref) const override; diff --git a/common_components/heap/ark_collector/post_marking_barrier.cpp b/common_components/heap/ark_collector/post_marking_barrier.cpp index 0afa07f836ab4a4ed70e9f8ba8a6616570466749..ee056f90f5ac4b1e472ad9beedca249e89ea3c1c 100755 --- a/common_components/heap/ark_collector/post_marking_barrier.cpp +++ b/common_components/heap/ark_collector/post_marking_barrier.cpp @@ -65,7 +65,7 @@ void PostMarkingBarrier::WriteRefField(BaseObject* obj, RefField& field, field.SetFieldValue(newField.GetFieldValue()); } -void PostMarkingBarrier::WriteBarrier(BaseObject* obj, RefField& field, BaseObject* ref) const +void PostMarkingBarrier::WriteBarrier(Mutator *mutator, BaseObject* obj, RefField& field, BaseObject* ref) const { if (Heap::GetHeap().GetGCReason() == GC_REASON_YOUNG) { UpdateRememberSet(obj, ref); diff --git a/common_components/heap/ark_collector/post_marking_barrier.h b/common_components/heap/ark_collector/post_marking_barrier.h index d141e46fcfc9ae4a0a962d193f77dd4c25e41757..72dc393f49563fec73ba509757463edb0c4e5fa7 100755 --- a/common_components/heap/ark_collector/post_marking_barrier.h +++ b/common_components/heap/ark_collector/post_marking_barrier.h @@ -32,7 +32,7 @@ public: void ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const override; void WriteRefField(BaseObject* obj, RefField& field, BaseObject* ref) const override; - void WriteBarrier(BaseObject* obj, RefField& field, BaseObject* ref) const override; + void WriteBarrier(Mutator *mutator, BaseObject* obj, RefField& field, BaseObject* ref) const override; void WriteStruct(BaseObject* obj, HeapAddress dst, size_t dstLen, HeapAddress src, size_t srcLen) const override; void WriteStaticRef(RefField& field, BaseObject* ref) const override; diff --git a/common_components/heap/ark_collector/remark_barrier.cpp b/common_components/heap/ark_collector/remark_barrier.cpp index 24b19cf7a5fa1c7fd99801c6646c445e91c4d058..8f300cde186c8a836872fa3ac01fb15003682614 100644 --- a/common_components/heap/ark_collector/remark_barrier.cpp +++ b/common_components/heap/ark_collector/remark_barrier.cpp @@ -84,7 +84,7 @@ void RemarkBarrier::WriteRefField(BaseObject *obj, RefField &field, BaseO field.SetFieldValue(newField.GetFieldValue()); } #ifdef ARK_USE_SATB_BARRIER -void RemarkBarrier::WriteBarrier(BaseObject* obj, RefField& field, BaseObject* ref) const +void RemarkBarrier::WriteBarrier(Mutator *mutator, BaseObject* obj, RefField& field, BaseObject* ref) const { RefField<> tmpField(field); BaseObject* rememberedObject = nullptr; @@ -93,7 +93,9 @@ void RemarkBarrier::WriteBarrier(BaseObject* obj, RefField& field, BaseOb return; } UpdateRememberSet(obj, ref); - Mutator* mutator = Mutator::GetMutator(); + if (UNLIKELY(mutator == nullptr)) { + mutator = Mutator::GetMutator(); + } if (rememberedObject != nullptr) { mutator->RememberObjectInSatbBuffer(rememberedObject); } @@ -108,14 +110,16 @@ void RemarkBarrier::WriteBarrier(BaseObject* obj, RefField& field, BaseOb DLOG(BARRIER, "write obj %p ref-field@%p: %#zx -> %p", obj, &field, rememberedObject, ref); } #else -void RemarkBarrier::WriteBarrier(BaseObject* obj, RefField& field, BaseObject* ref) const +void RemarkBarrier::WriteBarrier(Mutator *mutator, BaseObject* obj, RefField& field, BaseObject* ref) const { if (!Heap::IsTaggedObject((HeapAddress)ref)) { return; } UpdateRememberSet(obj, ref); ref = reinterpret_cast(reinterpret_cast(ref) & ~TAG_WEAK); - Mutator* mutator = Mutator::GetMutator(); + if (UNLIKELY(mutator == nullptr)) { + mutator = Mutator::GetMutator(); + } mutator->RememberObjectInSatbBuffer(ref); DLOG(BARRIER, "write obj %p ref-field@%p: -> %p", obj, &field, ref); } diff --git a/common_components/heap/ark_collector/remark_barrier.h b/common_components/heap/ark_collector/remark_barrier.h index 7a7a78a5a946b6501094da822b5e0c241ff14757..541b434694ebe8b87d98add974af40b7a2f05d6d 100644 --- a/common_components/heap/ark_collector/remark_barrier.h +++ b/common_components/heap/ark_collector/remark_barrier.h @@ -31,7 +31,7 @@ public: void WriteRoot(BaseObject *obj) const override; void WriteRefField(BaseObject* obj, RefField& field, BaseObject* ref) const override; - void WriteBarrier(BaseObject* obj, RefField& field, BaseObject* ref) const override; + void WriteBarrier(Mutator *mutator, BaseObject* obj, RefField& field, BaseObject* ref) const override; void WriteStruct(BaseObject* obj, HeapAddress dst, size_t dstLen, HeapAddress src, size_t srcLen) const override; void WriteStaticRef(RefField& field, BaseObject* ref) const override; diff --git a/common_components/heap/ark_collector/tests/enum_barrier_test.cpp b/common_components/heap/ark_collector/tests/enum_barrier_test.cpp index 31fd6b0195c9cf860574de375c5bacfe9aea8b94..0bd15341454b7100aabbd53c22d32f5deea948e1 100755 --- a/common_components/heap/ark_collector/tests/enum_barrier_test.cpp +++ b/common_components/heap/ark_collector/tests/enum_barrier_test.cpp @@ -150,9 +150,9 @@ HWTEST_F_L0(EnumBarrierTest, WriteBarrier_TEST1) constexpr uint64_t TAG_HEAP_OBJECT_MASK = TAG_MARK | TAG_SPECIAL | TAG_BOOLEAN; RefField<> field(MAddress(0)); - enumBarrier->WriteBarrier(nullptr, field, nullptr); + enumBarrier->WriteBarrier(nullptr, nullptr, field, nullptr); BaseObject *obj = reinterpret_cast(TAG_HEAP_OBJECT_MASK); - enumBarrier->WriteBarrier(obj, field, obj); + enumBarrier->WriteBarrier(nullptr, obj, field, obj); EXPECT_TRUE(obj != nullptr); #endif } @@ -167,19 +167,19 @@ HWTEST_F_L0(EnumBarrierTest, WriteBarrier_TEST2) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); RefField normalField(obj); - enumBarrier->WriteBarrier(obj, normalField, obj); + enumBarrier->WriteBarrier(nullptr, obj, normalField, obj); EXPECT_TRUE(obj != nullptr); HeapAddress weakAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* weakObj = reinterpret_cast(weakAddr); RefField weakField(MAddress(0)); - enumBarrier->WriteBarrier(&weakObj, weakField, &weakObj); + enumBarrier->WriteBarrier(nullptr, &weakObj, weakField, &weakObj); EXPECT_TRUE(weakObj != nullptr); HeapAddress nonTaggedAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* nonTaggedObj = reinterpret_cast(nonTaggedAddr); RefField nonTaggedField(&nonTaggedObj); - enumBarrier->WriteBarrier(nullptr, nonTaggedField, &nonTaggedObj); + enumBarrier->WriteBarrier(nullptr, nullptr, nonTaggedField, &nonTaggedObj); EXPECT_TRUE(nonTaggedObj != nullptr); #endif } @@ -201,7 +201,29 @@ HWTEST_F_L0(EnumBarrierTest, WriteBarrier_TEST3) BaseObject* obj = reinterpret_cast(addr); RefField<> field(obj); Heap::GetHeap().SetGCReason(GC_REASON_YOUNG); - enumBarrier->WriteBarrier(obj, field, obj); + enumBarrier->WriteBarrier(nullptr, obj, field, obj); + EXPECT_TRUE(obj != nullptr); +#endif +} + +HWTEST_F_L0(EnumBarrierTest, WriteBarrier_TEST4) +{ + MockCollector collector; + auto enumBarrier = std::make_unique(collector); + ASSERT_TRUE(enumBarrier != nullptr); + +#ifndef ARK_USE_SATB_BARRIER + constexpr uint64_t TAG_BITS_SHIFT = 48; + constexpr uint64_t TAG_MARK = 0xFFFFULL << TAG_BITS_SHIFT; + constexpr uint64_t TAG_SPECIAL = 0x02ULL; + constexpr uint64_t TAG_BOOLEAN = 0x04ULL; + constexpr uint64_t TAG_HEAP_OBJECT_MASK = TAG_MARK | TAG_SPECIAL | TAG_BOOLEAN; + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RefField<> field(obj); + Heap::GetHeap().SetGCReason(GC_REASON_YOUNG); + enumBarrier->WriteBarrier(Mutator::GetMutator(), obj, field, obj); EXPECT_TRUE(obj != nullptr); #endif } diff --git a/common_components/heap/ark_collector/tests/idle_barrier_test.cpp b/common_components/heap/ark_collector/tests/idle_barrier_test.cpp index 7e2f0240d148e534490dbe51c92ced90129825b1..45b96dfa71b3452f6fd19b35fdb6d9995d023caf 100755 --- a/common_components/heap/ark_collector/tests/idle_barrier_test.cpp +++ b/common_components/heap/ark_collector/tests/idle_barrier_test.cpp @@ -249,7 +249,7 @@ HWTEST_F_L0(IdleBarrierTest, WriteBarrier_TEST1) RefField<> field(MAddress(0)); BaseObject *obj = reinterpret_cast(TAG_HEAP_OBJECT_MASK); - idleBarrier->WriteBarrier(obj, field, obj); + idleBarrier->WriteBarrier(nullptr, obj, field, obj); EXPECT_TRUE(obj != nullptr); } @@ -262,7 +262,7 @@ HWTEST_F_L0(IdleBarrierTest, WriteBarrier_TEST2) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); RefField<> field(obj); - idleBarrier->WriteBarrier(obj, field, obj); + idleBarrier->WriteBarrier(nullptr, obj, field, obj); EXPECT_TRUE(obj != nullptr); } diff --git a/common_components/heap/ark_collector/tests/marking_barrier_test.cpp b/common_components/heap/ark_collector/tests/marking_barrier_test.cpp index be88b96801d9001207f183d1bf8dccb473a71e0d..0543a2bbe357843cfd1ed00b3884ce225abb2897 100755 --- a/common_components/heap/ark_collector/tests/marking_barrier_test.cpp +++ b/common_components/heap/ark_collector/tests/marking_barrier_test.cpp @@ -176,9 +176,9 @@ HWTEST_F_L0(MarkingBarrierTest, WriteBarrier_TEST1) constexpr uint64_t TAG_HEAP_OBJECT_MASK = TAG_MARK | TAG_SPECIAL | TAG_BOOLEAN; RefField<> field(MAddress(0)); - markingBarrier->WriteBarrier(nullptr, field, nullptr); + markingBarrier->WriteBarrier(nullptr, nullptr, field, nullptr); BaseObject *obj = reinterpret_cast(TAG_HEAP_OBJECT_MASK); - markingBarrier->WriteBarrier(obj, field, obj); + markingBarrier->WriteBarrier(nullptr, obj, field, obj); EXPECT_TRUE(obj != nullptr); #endif } @@ -193,17 +193,17 @@ HWTEST_F_L0(MarkingBarrierTest, WriteBarrier_TEST2) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); RefField normalField(obj); - markingBarrier->WriteBarrier(obj, normalField, obj); + markingBarrier->WriteBarrier(nullptr, obj, normalField, obj); EXPECT_TRUE(obj != nullptr); BaseObject weakObj; RefField weakField(MAddress(0)); - markingBarrier->WriteBarrier(&weakObj, weakField, &weakObj); + markingBarrier->WriteBarrier(nullptr, &weakObj, weakField, &weakObj); EXPECT_TRUE(weakObj != nullptr); BaseObject nonTaggedObj; RefField nonTaggedField(&nonTaggedObj); - markingBarrier->WriteBarrier(nullptr, nonTaggedField, &nonTaggedObj); + markingBarrier->WriteBarrier(nullptr, nullptr, nonTaggedField, &nonTaggedObj); EXPECT_TRUE(nonTaggedObj != nullptr); #endif } @@ -219,7 +219,23 @@ HWTEST_F_L0(MarkingBarrierTest, WriteBarrier_TEST3) BaseObject* obj = reinterpret_cast(addr); RefField<> field(obj); Heap::GetHeap().SetGCReason(GC_REASON_YOUNG); - markingBarrier->WriteBarrier(obj, field, obj); + markingBarrier->WriteBarrier(nullptr, obj, field, obj); + EXPECT_TRUE(obj != nullptr); +#endif +} + +HWTEST_F_L0(MarkingBarrierTest, WriteBarrier_TEST4) +{ + MockCollector collector; + auto markingBarrier = std::make_unique(collector); + ASSERT_TRUE(markingBarrier != nullptr); + +#ifndef ARK_USE_SATB_BARRIER + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RefField<> field(obj); + Heap::GetHeap().SetGCReason(GC_REASON_YOUNG); + markingBarrier->WriteBarrier(Mutator::GetMutator(), obj, field, obj); EXPECT_TRUE(obj != nullptr); #endif } diff --git a/common_components/heap/ark_collector/tests/post_marking_barrier_test.cpp b/common_components/heap/ark_collector/tests/post_marking_barrier_test.cpp index 140515f1ebbb3a792706cafcdfe88f95d08e89ed..f995ffbf75ceca76003c0121ae7c9053ba12d61e 100755 --- a/common_components/heap/ark_collector/tests/post_marking_barrier_test.cpp +++ b/common_components/heap/ark_collector/tests/post_marking_barrier_test.cpp @@ -177,7 +177,7 @@ HWTEST_F_L0(PostMarkingBarrierTest, WriteBarrier_TEST1) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); RefField<> field(obj); - postMarkingBarrier->WriteBarrier(obj, field, obj); + postMarkingBarrier->WriteBarrier(nullptr, obj, field, obj); EXPECT_TRUE(obj != nullptr); } @@ -191,7 +191,7 @@ HWTEST_F_L0(PostMarkingBarrierTest, WriteBarrier_TEST2) BaseObject* obj = reinterpret_cast(addr); RefField<> field(obj); Heap::GetHeap().SetGCReason(GC_REASON_YOUNG); - postMarkingBarrier->WriteBarrier(obj, field, obj); + postMarkingBarrier->WriteBarrier(nullptr, obj, field, obj); EXPECT_TRUE(obj != nullptr); } diff --git a/common_components/heap/ark_collector/tests/remark_barrier_test.cpp b/common_components/heap/ark_collector/tests/remark_barrier_test.cpp index 0aaea4d50cb0caf9a4ee88ef538f6795ca9603cf..cccc48e689cf3b3029cc5819c833bfde4f042e82 100755 --- a/common_components/heap/ark_collector/tests/remark_barrier_test.cpp +++ b/common_components/heap/ark_collector/tests/remark_barrier_test.cpp @@ -239,7 +239,7 @@ HWTEST_F_L0(RemarkBarrierTest, WriteBarrier_TEST1) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); addr |= TAG_HEAP_OBJECT_MASK; BaseObject* obj = reinterpret_cast(addr); - remarkBarrier->WriteBarrier(obj, field, obj); + remarkBarrier->WriteBarrier(nullptr, obj, field, obj); EXPECT_TRUE(obj != nullptr); #endif } @@ -254,17 +254,17 @@ HWTEST_F_L0(RemarkBarrierTest, WriteBarrier_TEST2) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); RefField normalField(obj); - remarkBarrier->WriteBarrier(obj, normalField, obj); + remarkBarrier->WriteBarrier(nullptr, obj, normalField, obj); EXPECT_TRUE(obj != nullptr); BaseObject weakObj; RefField weakField(MAddress(0)); - remarkBarrier->WriteBarrier(&weakObj, weakField, &weakObj); + remarkBarrier->WriteBarrier(nullptr, &weakObj, weakField, &weakObj); EXPECT_TRUE(weakObj != nullptr); BaseObject nonTaggedObj; RefField nonTaggedField(&nonTaggedObj); - remarkBarrier->WriteBarrier(nullptr, nonTaggedField, &nonTaggedObj); + remarkBarrier->WriteBarrier(nullptr, nullptr, nonTaggedField, &nonTaggedObj); EXPECT_TRUE(nonTaggedObj != nullptr); #endif } @@ -279,7 +279,22 @@ HWTEST_F_L0(RemarkBarrierTest, WriteBarrier_TEST3) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); RefField<> field(obj); - remarkBarrier->WriteBarrier(obj, field, obj); + remarkBarrier->WriteBarrier(nullptr, obj, field, obj); + EXPECT_TRUE(obj != nullptr); +#endif +} + +HWTEST_F_L0(RemarkBarrierTest, WriteBarrier_TEST4) +{ + MockCollector collector; + auto remarkBarrier = std::make_unique(collector); + ASSERT_TRUE(remarkBarrier != nullptr); + +#ifndef ARK_USE_SATB_BARRIER + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RefField<> field(obj); + remarkBarrier->WriteBarrier(Mutator::GetMutator(), obj, field, obj); EXPECT_TRUE(obj != nullptr); #endif } diff --git a/common_components/heap/barrier/barrier.cpp b/common_components/heap/barrier/barrier.cpp index 64dbf856385da26d254985eadace264246b401f9..0663adc9b91d16dcb746a2bff3d413e79fdc7342 100755 --- a/common_components/heap/barrier/barrier.cpp +++ b/common_components/heap/barrier/barrier.cpp @@ -31,7 +31,7 @@ void Barrier::WriteRefField(BaseObject* obj, RefField& field, BaseObject* field.SetTargetObject(ref); } -void Barrier::WriteBarrier(BaseObject* obj, RefField& field, BaseObject* ref) const +void Barrier::WriteBarrier(Mutator *mutator, BaseObject* obj, RefField& field, BaseObject* ref) const { DLOG(BARRIER, "write obj %p ref-field@%p: %p => %p", obj, &field, field.GetTargetObject(), ref); } diff --git a/common_components/heap/barrier/barrier.h b/common_components/heap/barrier/barrier.h index db753a32cf248828b0fa95d7396bf33a85b2a6b0..a552a509643c3a39a1dd76bf741285193959c972 100755 --- a/common_components/heap/barrier/barrier.h +++ b/common_components/heap/barrier/barrier.h @@ -37,7 +37,7 @@ public: virtual void WriteRoot(BaseObject* obj) const; virtual void WriteRefField(BaseObject* obj, RefField& field, BaseObject* ref) const; - virtual void WriteBarrier(BaseObject* obj, RefField& field, BaseObject* ref) const; + virtual void WriteBarrier(Mutator *mutator, BaseObject* obj, RefField& field, BaseObject* ref) const; virtual void WriteStaticRef(RefField& field, BaseObject* ref) const; virtual void WriteStruct(BaseObject* obj, HeapAddress dst, size_t dstLen, HeapAddress src, size_t srcLen) const; diff --git a/common_components/mutator/mutator.h b/common_components/mutator/mutator.h index b9ce1e978095e40b95ded034370dffec967346f2..f534e1afefe27a1b3e5305b339731d249261dcdb 100755 --- a/common_components/mutator/mutator.h +++ b/common_components/mutator/mutator.h @@ -314,7 +314,7 @@ private: void RememberObjectImpl(const BaseObject* obj) { if (LIKELY_CC(Heap::IsHeapAddress(obj))) { - if (SatbBuffer::Instance().ShouldEnqueue(obj)) { + if (SatbBuffer::ShouldEnqueue(obj)) { SatbBuffer::Instance().EnsureGoodNode(satbNode_); satbNode_->Push(obj); } diff --git a/common_components/mutator/satb_buffer.h b/common_components/mutator/satb_buffer.h index 10783b4be9b86f031b3471bb9366529edbd61e6f..2d17230fb86bc78993482c2d257135aca7c816d0 100755 --- a/common_components/mutator/satb_buffer.h +++ b/common_components/mutator/satb_buffer.h @@ -28,6 +28,9 @@ public: static constexpr size_t INITIAL_PAGES = 64; // 64 pages of initial satb buffer static constexpr size_t CACHE_LINE_ALIGN = 64; // for most hardware platfrom, the cache line is 64-byte aigned. static SatbBuffer& Instance() noexcept; + + static bool ShouldEnqueue(const BaseObject* obj); + class TreapNode { friend class SatbBuffer; @@ -208,7 +211,6 @@ public: LOGF_CHECK(node->IsEmpty()) << "get an unempty node from free nodes"; } } - bool ShouldEnqueue(const BaseObject* obj); // must not have thread racing void Init() diff --git a/ecmascript/compiler/barrier_stub_builder.cpp b/ecmascript/compiler/barrier_stub_builder.cpp index 3702fbf4c735e269e3dd9f481439c4fbb3fcee07..8c51d88938022478d0d803007f13fb400fbdb5bb 100644 --- a/ecmascript/compiler/barrier_stub_builder.cpp +++ b/ecmascript/compiler/barrier_stub_builder.cpp @@ -814,7 +814,7 @@ void BarrierStubBuilder::DoReverseBarrier() Bind(&markInBuffer); { ASSERT(RuntimeStubCSigns::Get(RTSTUB_ID(MarkInBuffer))->IsNoTailCall()); - CallNGCRuntime(glue_, RTSTUB_ID(MarkInBuffer), {ref}); + CallNGCRuntime(glue_, RTSTUB_ID(MarkInBuffer), {glue_, ref}); Jump(¬MarkRSetLoopEnd); } diff --git a/ecmascript/compiler/builtins/builtins_number_stub_builder.cpp b/ecmascript/compiler/builtins/builtins_number_stub_builder.cpp index cfb2b8ec40008d3c1c301df9da6bceba567fc823..e96050e8b9a20a2e47cf57d27b9888ed77069466 100644 --- a/ecmascript/compiler/builtins/builtins_number_stub_builder.cpp +++ b/ecmascript/compiler/builtins/builtins_number_stub_builder.cpp @@ -422,7 +422,7 @@ GateRef BuiltinsNumberStubBuilder::NumberToString(GateRef number, GateRef radix) } } Bind(&loopEnd); - LoopEndWithCheckSafePoint(&loopHead, env, glue_); + LoopEnd(&loopHead); Bind(&loopExit); { NewObjectStubBuilder newBuilder(this); diff --git a/ecmascript/compiler/call_signature.cpp b/ecmascript/compiler/call_signature.cpp index faff89b72dbcc7b2d74567d243a7a60e56b143d9..fd7a7259fd442b3d0d69facb19100a6880a09a71 100644 --- a/ecmascript/compiler/call_signature.cpp +++ b/ecmascript/compiler/call_signature.cpp @@ -3503,11 +3503,12 @@ DEF_CALL_SIGNATURE(MarkRSetCardTable) DEF_CALL_SIGNATURE(MarkInBuffer) { - // 3 : 3 input parameters - CallSignature MarkInBuffer("MarkInBuffer", 0, 1, ArgumentsOrder::DEFAULT_ORDER, + // 2 : 2 input parameters + CallSignature MarkInBuffer("MarkInBuffer", 0, 2, ArgumentsOrder::DEFAULT_ORDER, VariableType::BOOL()); *callSign = MarkInBuffer; - std::array params = { // 1 : 1 input parameters + std::array params = { // 2 : 2 input parameters + VariableType::NATIVE_POINTER(), VariableType::JS_POINTER(), }; callSign->SetParameters(params.data()); @@ -3519,10 +3520,11 @@ DEF_CALL_SIGNATURE(MarkInBuffer) DEF_CALL_SIGNATURE(BatchMarkInBuffer) { // 3 : 3 input parameters - CallSignature BatchMarkInBuffer("BatchMarkInBuffer", 0, 2, ArgumentsOrder::DEFAULT_ORDER, + CallSignature BatchMarkInBuffer("BatchMarkInBuffer", 0, 3, ArgumentsOrder::DEFAULT_ORDER, VariableType::BOOL()); *callSign = BatchMarkInBuffer; - std::array params = { // 2 : 2 input parameters + std::array params = { // 3 : 3 input parameters + VariableType::NATIVE_POINTER(), VariableType::NATIVE_POINTER(), VariableType::INT32(), }; diff --git a/ecmascript/compiler/interpreter_stub.cpp b/ecmascript/compiler/interpreter_stub.cpp index b2d6077c34657142bf905065d719f9ac9bcec241..b1b86370db8b365364151399acc73d3130e97e46 100644 --- a/ecmascript/compiler/interpreter_stub.cpp +++ b/ecmascript/compiler/interpreter_stub.cpp @@ -126,7 +126,7 @@ void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef sp, GateRef pc #define UPDATE_HOTNESS(_sp, callback) \ varHotnessCounter = Int32Add(offset, *varHotnessCounter); \ - BRANCH(Int32LessThan(*varHotnessCounter, Int32(0)), &slowPath, &dispatch); \ + BRANCH_UNLIKELY(Int32LessThan(*varHotnessCounter, Int32(0)), &slowPath, &dispatch); \ Bind(&slowPath); \ { \ GateRef func = GetFunctionFromFrame(glue, GetFrame(_sp)); \ @@ -135,9 +135,9 @@ void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef sp, GateRef pc varHotnessCounter = Int32(EcmaInterpreter::METHOD_HOTNESS_THRESHOLD); \ Label initialized(env); \ Label callRuntime(env); \ - BRANCH(BitOr(TaggedIsUndefined(*varProfileTypeInfo), \ - Int8Equal(interruptsFlag, Int8(VmThreadControl::VM_NEED_SUSPENSION))), \ - &callRuntime, &initialized); \ + BRANCH_UNLIKELY(BitOr(TaggedIsUndefined(*varProfileTypeInfo), \ + Int8Equal(interruptsFlag, Int8(VmThreadControl::VM_NEED_SUSPENSION))), \ + &callRuntime, &initialized); \ Bind(&callRuntime); \ if (!(callback).IsEmpty()) { \ varProfileTypeInfo = CallRuntime(glue, RTSTUB_ID(UpdateHotnessCounterWithProf), {func}); \ @@ -146,7 +146,7 @@ void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef sp, GateRef pc } \ Label handleException(env); \ Label noException(env); \ - BRANCH(HasPendingException(glue), &handleException, &noException); \ + BRANCH_UNLIKELY(HasPendingException(glue), &handleException, &noException); \ Bind(&handleException); \ { \ DISPATCH_LAST(); \ @@ -158,9 +158,13 @@ void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef sp, GateRef pc Bind(&initialized); \ Label callCheckSafePoint(env); \ Label afterCheckSafePoint(env); \ + Label enableCMCGC(env); \ BRANCH_UNLIKELY(LoadPrimitive(VariableType::BOOL(), glue, IntPtr( \ JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))), \ - &callCheckSafePoint, &afterCheckSafePoint); \ + &enableCMCGC, &afterCheckSafePoint); \ + Bind(&enableCMCGC); \ + BRANCH_UNLIKELY(Int32Equal(Int32(ThreadFlag::SUSPEND_REQUEST), \ + CheckSuspendForCMCGC(glue)), &callCheckSafePoint, &afterCheckSafePoint); \ Bind(&callCheckSafePoint); \ { \ CallRuntime(glue, RTSTUB_ID(CheckSafePoint), {}); \ @@ -244,8 +248,7 @@ void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef sp, GateRef pc Label executeBCByInterpreter(env); \ GateRef curFrame = GetFrame(sp); \ GateRef curFunction = GetFunctionFromFrame(glue, curFrame); \ - GateRef curMethod = Load(VariableType::JS_ANY(), glue, curFunction, IntPtr(JSFunctionBase::METHOD_OFFSET)); \ - Branch(TaggedIsUndefined(profileTypeInfo), &executeBCByInterpreter, &getOsrCache); \ + BRANCH(TaggedIsUndefined(profileTypeInfo), &executeBCByInterpreter, &getOsrCache); \ Bind(&getOsrCache); \ { \ GateRef profileTypeInfoLength = GetLengthOfTaggedArray(profileTypeInfo); \ @@ -253,7 +256,7 @@ void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef sp, GateRef pc GateRef relativeOffset = PtrMul(ZExtInt32ToPtr(typeInfoNum), IntPtr(JSTaggedValue::TaggedTypeSize())); \ GateRef osrCacheOffset = PtrAdd(relativeOffset, IntPtr(TaggedArray::DATA_OFFSET)); \ varOsrCache = LoadPrimitive(VariableType::NATIVE_POINTER(), profileTypeInfo, osrCacheOffset); \ - Branch(TaggedIsUndefinedOrNull(*varOsrCache), &executeBCByInterpreter, &getMachineCode); \ + BRANCH_LIKELY(TaggedIsUndefinedOrNull(*varOsrCache), &executeBCByInterpreter, &getMachineCode); \ } \ Bind(&getMachineCode); \ { \ @@ -262,6 +265,7 @@ void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef sp, GateRef pc Label compareOffset(env); \ Label addIndex(env); \ Label traverseOsrCacheAgain(env); \ + GateRef curMethod = Load(VariableType::JS_ANY(), glue, curFunction, IntPtr(JSFunctionBase::METHOD_OFFSET)); \ GateRef fistPC = LoadPrimitive(VariableType::NATIVE_POINTER(), curMethod, \ IntPtr(Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET)); \ GateRef jmpOffsetInFunc = TruncPtrToInt32(PtrSub(pc, fistPC)); \ diff --git a/ecmascript/compiler/new_object_stub_builder.cpp b/ecmascript/compiler/new_object_stub_builder.cpp index 62b62f8ab2f5899f61600c54040895a5a7c73301..e3bbb5470253c1b70cd2cb87eadaa20e903c0109 100644 --- a/ecmascript/compiler/new_object_stub_builder.cpp +++ b/ecmascript/compiler/new_object_stub_builder.cpp @@ -281,9 +281,9 @@ GateRef NewObjectStubBuilder::NewAccessorData(GateRef glue) HeapAlloc(&result, &noException, RegionSpaceFlag::IN_YOUNG_SPACE, hclass); Bind(&noException); { - Store(VariableType::JS_POINTER(), glue, result.ReadVariable(), IntPtr(0), hclass); - Store(VariableType::JS_ANY(), glue, *result, IntPtr(AccessorData::GETTER_OFFSET), Undefined()); - Store(VariableType::JS_ANY(), glue, *result, IntPtr(AccessorData::SETTER_OFFSET), Undefined()); + StoreBuiltinHClass(glue, *result, hclass); + StoreWithoutBarrier(VariableType::JS_ANY(), *result, IntPtr(AccessorData::GETTER_OFFSET), Undefined()); + StoreWithoutBarrier(VariableType::JS_ANY(), *result, IntPtr(AccessorData::SETTER_OFFSET), Undefined()); Jump(&exit); } @@ -1649,7 +1649,7 @@ void NewObjectStubBuilder::AllocateInSOldPrologue([[maybe_unused]] Variable *res #ifdef ECMASCRIPT_SUPPORT_HEAPSAMPLING auto isStartHeapSamplingOffset = JSThread::GlueData::GetIsStartHeapSamplingOffset(env->Is32Bit()); auto isStartHeapSampling = LoadPrimitive(VariableType::JS_ANY(), glue_, IntPtr(isStartHeapSamplingOffset)); - BRANCH(TaggedIsTrue(isStartHeapSampling), callRuntime, &next); + BRANCH_UNLIKELY(TaggedIsTrue(isStartHeapSampling), callRuntime, &next); Bind(&next); #endif Label isCMCGC(env); @@ -1794,7 +1794,7 @@ void NewObjectStubBuilder::AllocateInYoungPrologue([[maybe_unused]] Variable *re #ifdef ECMASCRIPT_SUPPORT_HEAPSAMPLING auto isStartHeapSamplingOffset = JSThread::GlueData::GetIsStartHeapSamplingOffset(env->Is32Bit()); auto isStartHeapSampling = LoadPrimitive(VariableType::JS_ANY(), glue_, IntPtr(isStartHeapSamplingOffset)); - BRANCH(TaggedIsTrue(isStartHeapSampling), callRuntime, &next); + BRANCH_UNLIKELY(TaggedIsTrue(isStartHeapSampling), callRuntime, &next); Bind(&next); #endif Label isCMCGC(env); @@ -1857,6 +1857,7 @@ GateRef NewObjectStubBuilder::NewTrackInfo(GateRef glue, GateRef cachedHClass, G SetParameters(glue, size); HeapAlloc(&result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass); Bind(&initialize); + StoreBuiltinHClass(glue, *result, hclass); Store(VariableType::JS_POINTER(), glue_, *result, IntPtr(0), hclass); GateRef cachedHClassOffset = IntPtr(TrackInfo::CACHED_HCLASS_OFFSET); Store(VariableType::JS_POINTER(), glue, *result, cachedHClassOffset, cachedHClass); @@ -1961,7 +1962,7 @@ void NewObjectStubBuilder::AllocLineStringObject(Variable *result, Label *exit, AllocateInSOld(result, &afterAllocate, stringClass); Bind(&afterAllocate); - StoreHClass(glue_, result->ReadVariable(), stringClass); + StoreBuiltinHClass(glue_, result->ReadVariable(), stringClass); InitStringLengthAndFlags(glue_, result->ReadVariable(), length, compressed); SetMixHashcode(glue_, result->ReadVariable(), Int32(0)); Jump(exit); @@ -1979,7 +1980,7 @@ void NewObjectStubBuilder::AllocSlicedStringObject(Variable *result, Label *exit AllocateInSOld(result, &afterAllocate, stringClass); Bind(&afterAllocate); - StoreHClass(glue_, result->ReadVariable(), stringClass); + StoreBuiltinHClass(glue_, result->ReadVariable(), stringClass); GateRef mixLength = LoadPrimitive(VariableType::INT32(), flatString->GetFlatString(), IntPtr(BaseString::LENGTH_AND_FLAGS_OFFSET)); GateRef compressedStatus = TruncInt32ToInt1(Int32And(Int32((1 << BaseString::CompressedStatusBit::SIZE) - 1), @@ -2008,7 +2009,7 @@ void NewObjectStubBuilder::AllocTreeStringObject(Variable *result, Label *exit, AllocateInSOld(result, &afterAllocate, stringClass); Bind(&afterAllocate); - StoreHClass(glue_, result->ReadVariable(), stringClass); + StoreBuiltinHClass(glue_, result->ReadVariable(), stringClass); InitStringLengthAndFlags(glue_, result->ReadVariable(), length, compressed); SetMixHashcode(glue_, result->ReadVariable(), Int32(0)); Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(TreeString::FIRST_OFFSET), first); @@ -2290,7 +2291,7 @@ GateRef NewObjectStubBuilder::CreateEmptyArray(GateRef glue, GateRef jsFunc, Tra { trackInfo = LoadTrackInfo(glue, jsFunc, traceIdInfo, profileTypeInfo, slotId, slotValue, Circuit::NullGate(), callback); - hclass = Load(VariableType::JS_ANY(), glue, *trackInfo, IntPtr(TrackInfo::CACHED_HCLASS_OFFSET)); + hclass = LoadPrimitive(VariableType::JS_ANY(), *trackInfo, IntPtr(TrackInfo::CACHED_HCLASS_OFFSET)); trackInfo = env->GetBuilder()->CreateWeakRef(*trackInfo); Jump(&createArray); } @@ -2334,7 +2335,7 @@ GateRef NewObjectStubBuilder::CreateArrayWithBuffer(GateRef glue, GateRef index, Bind(&mayFastpath); { trackInfo = LoadTrackInfo(glue, jsFunc, traceIdInfo, profileTypeInfo, slotId, slotValue, obj, callback); - hclass = Load(VariableType::JS_ANY(), glue, *trackInfo, IntPtr(TrackInfo::CACHED_HCLASS_OFFSET)); + hclass = LoadPrimitive(VariableType::JS_ANY(), *trackInfo, IntPtr(TrackInfo::CACHED_HCLASS_OFFSET)); trackInfo = env->GetBuilder()->CreateWeakRef(*trackInfo); Jump(&createArray); } @@ -2893,7 +2894,7 @@ GateRef NewObjectStubBuilder::NewEnumCache(GateRef glue) SetParameters(glue, size); HeapAlloc(&result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass); Bind(&initialize); - Store(VariableType::JS_POINTER(), glue, result.ReadVariable(), IntPtr(0), hclass); + StoreBuiltinHClass(glue, *result, hclass); GateRef enumCacheKindOffset = IntPtr(EnumCache::ENUM_CACHE_KIND_OFFSET); Store(VariableType::INT32(), glue, *result, enumCacheKindOffset, Int32(static_cast(EnumCacheKind::NONE))); diff --git a/ecmascript/compiler/stub_builder.cpp b/ecmascript/compiler/stub_builder.cpp index d2559c6c0eb5640c6d9d4fc8c6a53c091dcdbdfd..e057b09874295abd8b71046f204f2a1c403d6299 100644 --- a/ecmascript/compiler/stub_builder.cpp +++ b/ecmascript/compiler/stub_builder.cpp @@ -2061,7 +2061,7 @@ void StubBuilder::CMCSetValueWithBarrier(GateRef glue, GateRef obj, [[maybe_unus BRANCH_UNLIKELY(shouldProcessSATB, &markInBuffer, &exit); Bind(&markInBuffer); { - CallNGCRuntime(glue, RTSTUB_ID(MarkInBuffer), {value}); + CallNGCRuntime(glue, RTSTUB_ID(MarkInBuffer), {glue, value}); Jump(&exit); } Bind(&exit); @@ -2084,6 +2084,9 @@ void StubBuilder::CMCArrayCopyWriteBarrier(GateRef glue, GateRef dstObj, GateRef DEFVARIABLE(i, VariableType::INT32(), Int32(0)); GateRef gcPhase = GetGCPhase(glue); Label checkOldToYoung(env); + Label objInOld(env); + BRANCH(BoolNot(CMCIsInYoungSpace(objRegionType)), &objInOld, ¬MarkRSet); + Bind(&objInOld); BRANCH(ShouldUpdateRememberSet(glue, gcPhase), &checkOldToYoung, ¬MarkRSet); Bind(&checkOldToYoung); Jump(&loopHead); @@ -2095,8 +2098,8 @@ void StubBuilder::CMCArrayCopyWriteBarrier(GateRef glue, GateRef dstObj, GateRef GateRef ref = LoadPrimitive(VariableType::JS_ANY(), src, offset); BRANCH(TaggedIsHeapObject(ref), &isTaggedObject, &loopEnd); Bind(&isTaggedObject); - GateRef isOldToYoung = IsOldToYoung(objRegionType, GetCMCRegionType(ref)); - BRANCH_UNLIKELY(isOldToYoung, &markRSet, &loopEnd); + GateRef refRegionType = GetCMCRegionType(ref); + BRANCH(CMCIsInYoungSpace(refRegionType), &markRSet, &loopEnd); Bind(&markRSet); MarkRSetCardTable(dstObj, ¬MarkRSet); Bind(&loopEnd); @@ -2108,7 +2111,7 @@ void StubBuilder::CMCArrayCopyWriteBarrier(GateRef glue, GateRef dstObj, GateRef GateRef shouldProcessSATB = ShouldProcessSATB(gcPhase); BRANCH_UNLIKELY(shouldProcessSATB, &markInBuffer, &exit); Bind(&markInBuffer); - CallNGCRuntime(glue, RTSTUB_ID(BatchMarkInBuffer), {TaggedCastToIntPtr(src), count}); + CallNGCRuntime(glue, RTSTUB_ID(BatchMarkInBuffer), {glue, TaggedCastToIntPtr(src), count}); Jump(&exit); Bind(&exit); env->SubCfgExit(); @@ -2134,6 +2137,9 @@ void StubBuilder::CMCArrayCopyWriteBarrierSameArray(GateRef glue, GateRef dstObj Bind(¬IdlePhase); { Label checkOldToYoung(env); + Label objInOld(env); + BRANCH(BoolNot(CMCIsInYoungSpace(objRegionType)), &objInOld, ¬MarkRSet); + Bind(&objInOld); BRANCH(ShouldUpdateRememberSet(glue, gcPhase), &checkOldToYoung, ¬MarkRSet); Bind(&checkOldToYoung); Jump(&loopHead); @@ -2145,8 +2151,8 @@ void StubBuilder::CMCArrayCopyWriteBarrierSameArray(GateRef glue, GateRef dstObj GateRef ref = LoadPrimitive(VariableType::JS_ANY(), src, offset); BRANCH(TaggedIsHeapObject(ref), &isTaggedObject, &loopEnd); Bind(&isTaggedObject); - GateRef isOldToYoung = IsOldToYoung(objRegionType, GetCMCRegionType(ref)); - BRANCH_UNLIKELY(isOldToYoung, &markRSet, &loopEnd); + GateRef refRegionType = GetCMCRegionType(ref); + BRANCH(CMCIsInYoungSpace(refRegionType), &markRSet, &loopEnd); Bind(&markRSet); MarkRSetCardTable(dstObj, ¬MarkRSet); Bind(&loopEnd); @@ -2158,7 +2164,7 @@ void StubBuilder::CMCArrayCopyWriteBarrierSameArray(GateRef glue, GateRef dstObj GateRef shouldProcessSATB = ShouldProcessSATB(gcPhase); BRANCH_UNLIKELY(shouldProcessSATB, &markInBuffer, &exit); Bind(&markInBuffer); - CallNGCRuntime(glue, RTSTUB_ID(BatchMarkInBuffer), {TaggedCastToIntPtr(src), count}); + CallNGCRuntime(glue, RTSTUB_ID(BatchMarkInBuffer), {glue, TaggedCastToIntPtr(src), count}); Jump(&exit); } Bind(&exit); diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 6ac6e1e9ee43cba250859ded73466f9661da80d2..408779420d267f1bea71fb12285f2b196129c775 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -119,6 +119,7 @@ using ThreadHolder = common::ThreadHolder; using ThreadFlag = common::ThreadFlag; using ThreadState = common::ThreadState; using ThreadStateAndFlags = common::ThreadStateAndFlags; +using Mutator = common::Mutator; static constexpr uint32_t THREAD_STATE_OFFSET = common::THREAD_STATE_OFFSET; static constexpr uint32_t THREAD_FLAGS_MASK = common::THREAD_FLAGS_MASK; @@ -1728,6 +1729,17 @@ public: return reinterpret_cast(glueData_.threadHolder_); } + void SetMutator(Mutator *mutator) + { + mutator_ = mutator; + } + + Mutator *GetMutator() const + { + ASSERT(mutator_ != nullptr); + return mutator_; + } + // to impl void Visit(common::CommonRootVisitor visitor) { @@ -2035,6 +2047,7 @@ private: GlueData glueData_; std::atomic id_ {0}; EcmaVM *vm_ {nullptr}; + Mutator *mutator_ {nullptr}; void *env_ {nullptr}; Area *regExpCacheArea_ {nullptr}; diff --git a/ecmascript/mem/barriers-inl.h b/ecmascript/mem/barriers-inl.h index 4d9ce2a821493ac7ba08c13526fc81bece2b4886..3c5cc553d81f25fe291e7db485dd485ab5d8e75d 100644 --- a/ecmascript/mem/barriers-inl.h +++ b/ecmascript/mem/barriers-inl.h @@ -33,7 +33,7 @@ static ARK_INLINE void WriteBarrier(const JSThread *thread, void *obj, size_t of { if (UNLIKELY(thread->IsEnableCMCGC())) { common::BaseRuntime::WriteBarrier(obj, reinterpret_cast(ToUintPtr(obj) + offset), - reinterpret_cast(value)); + reinterpret_cast(value), thread->GetMutator()); // Ignore barrier for cmc gc allocation return; } diff --git a/ecmascript/mem/barriers.cpp b/ecmascript/mem/barriers.cpp index d112ebc9a298b68791927fa8ddc6d868daee0b44..861d8880b7ac502955635bf7587a696791dcafa6 100644 --- a/ecmascript/mem/barriers.cpp +++ b/ecmascript/mem/barriers.cpp @@ -176,11 +176,11 @@ void Barriers::CMCArrayCopyWriteBarrier(const JSThread *thread, const TaggedObje JSTaggedType *srcPtr = reinterpret_cast(src); common::GCPhase gcPhase = thread->GetCMCGCPhase(); // 1. update Rememberset - if (ShouldUpdateRememberSet(gcPhase)) { + if (ShouldUpdateRememberSet(gcPhase) && !objMetaRegion->IsInYoungSpaceForWB()) { auto checkReference = [&](BaseObject *ref) { common::RegionDesc::InlinedRegionMetaData *refMetaRegion = common::RegionDesc::InlinedRegionMetaData::GetInlinedRegionMetaData(reinterpret_cast(ref)); - return (!objMetaRegion->IsInYoungSpaceForWB() && refMetaRegion->IsInYoungSpaceForWB()); + return refMetaRegion->IsInYoungSpaceForWB(); }; for (size_t i = 0; i < count; i++) { @@ -198,7 +198,7 @@ void Barriers::CMCArrayCopyWriteBarrier(const JSThread *thread, const TaggedObje // 2. SATB buffer proccess if (ShouldProcessSATB(gcPhase)) { - common::Mutator* mutator = common::Mutator::GetMutator(); + common::Mutator* mutator = thread->GetMutator(); for (size_t i = 0; i < count; i++) { JSTaggedType ref = *reinterpret_cast(ToUintPtr(srcPtr) + i * sizeof(JSTaggedType)); if (!common::Heap::IsTaggedObject(reinterpret_cast(ref))) { diff --git a/ecmascript/runtime.cpp b/ecmascript/runtime.cpp index 9c296c5013b880716b94ae8c950896aca58e7359..18bfb6350103720caa57ffc887ecb6366a551455 100644 --- a/ecmascript/runtime.cpp +++ b/ecmascript/runtime.cpp @@ -224,6 +224,7 @@ void Runtime::RegisterThread(JSThread* newThread) if (g_isEnableCMCGC) { ThreadHolder* threadHolder = newThread->GetThreadHolder(); threadHolder->BindMutator(); + newThread->SetMutator(reinterpret_cast(threadHolder->GetMutator())); newThread->SetAllocBuffer(threadHolder->GetAllocBuffer()); newThread->OnHeapCreated(common::Heap::heapStartAddr_); newThread->OnHeapExtended(common::Heap::heapCurrentEnd_); diff --git a/ecmascript/stubs/runtime_stubs.cpp b/ecmascript/stubs/runtime_stubs.cpp index 4cc4a0055051cf837cafcce7ad17a83c02f33961..a4b7e002afaf4a91ba3ffe6666b8469d6bfe23e2 100644 --- a/ecmascript/stubs/runtime_stubs.cpp +++ b/ecmascript/stubs/runtime_stubs.cpp @@ -5042,17 +5042,19 @@ bool RuntimeStubs::MarkRSetCardTable(BaseObject* obj) return region->MarkRSetCardTable(obj); } -void RuntimeStubs::MarkInBuffer(BaseObject* ref) +void RuntimeStubs::MarkInBuffer(uintptr_t argGlue, BaseObject* ref) { ref = reinterpret_cast(reinterpret_cast(ref) & ~(common::Barrier::TAG_WEAK)); - common::Mutator* mutator = common::Mutator::GetMutator(); + auto thread = JSThread::GlueToJSThread(argGlue); + common::Mutator* mutator = thread->GetMutator(); mutator->RememberObjectInSatbBuffer(ref); } -void RuntimeStubs::BatchMarkInBuffer(void* src, size_t count) +void RuntimeStubs::BatchMarkInBuffer(uintptr_t argGlue, void* src, size_t count) { uintptr *srcPtr = reinterpret_cast(src); - common::Mutator* mutator = common::Mutator::GetMutator(); + auto thread = JSThread::GlueToJSThread(argGlue); + common::Mutator* mutator = thread->GetMutator(); for (size_t i = 0; i < count; i++) { BaseObject* ref = reinterpret_cast(srcPtr[i]); if (!common::Heap::IsTaggedObject(reinterpret_cast(ref))) { diff --git a/ecmascript/stubs/runtime_stubs.h b/ecmascript/stubs/runtime_stubs.h index 9305cb5491a424829fad7c8c4b657fed245ba0b5..f48fa7b3f8d43af4d2b3f21113c6e8e4e9daf25a 100644 --- a/ecmascript/stubs/runtime_stubs.h +++ b/ecmascript/stubs/runtime_stubs.h @@ -183,8 +183,8 @@ public: static void TraceLazyDeoptCommitSuccess(uintptr_t argGlue, JSHandle func); static JSTaggedValue GetExternalModuleVar(uintptr_t argGlue, JSFunction *jsFunc, int32_t index); static bool MarkRSetCardTable(BaseObject* obj); - static void MarkInBuffer(BaseObject* ref); - static void BatchMarkInBuffer(void* src, size_t count); + static void MarkInBuffer(uintptr_t argGlue, BaseObject* ref); + static void BatchMarkInBuffer(uintptr_t argGlue, void* src, size_t count); private: static void DumpToStreamWithHint(std::ostream &out, std::string_view prompt, JSTaggedValue value); diff --git a/ecmascript/tests/BUILD.gn b/ecmascript/tests/BUILD.gn index d24b8504d2a909f14dea50968689bea90070d734..c601aed3d39039d52e8402a2d34f6c8033f7b1d9 100644 --- a/ecmascript/tests/BUILD.gn +++ b/ecmascript/tests/BUILD.gn @@ -2761,6 +2761,29 @@ host_unittest_action("JS_Barrier_Test") { deps += hiviewdfx_deps } +host_unittest_action("CMC_Barrier_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "cmcbarrier_test.cpp", + ] + + configs = [ "../../:ecma_test_config" ] + + deps = [ "../../:libark_jsruntime_test" ] + + # hiviewdfx libraries + external_deps = hiviewdfx_ext_deps + external_deps += [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "runtime_core:libarkassembler_static", + "runtime_core:libarkverifier", + ] + deps += hiviewdfx_deps +} + host_unittest_action("GC_ModuleManagerMap_Test") { module_out_path = module_output_path @@ -3505,6 +3528,7 @@ group("unittest") { ":ECMA_StringTable_Test", ":BASE_String_Test", + ":CMC_Barrier_Test", ":ECMA_VM_Test", ":GC_ModuleManagerMap_Test", ":GC_ConcurrentMarking_Test", diff --git a/ecmascript/tests/cmcbarrier_test.cpp b/ecmascript/tests/cmcbarrier_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26c6028bb6bd58b552645cf96805044f3a61b96a --- /dev/null +++ b/ecmascript/tests/cmcbarrier_test.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecmascript/js_array.h" +#include "ecmascript/global_env.h" +#include "ecmascript/tests/test_helper.h" +#include "common_components/heap/allocator/region_desc.h" +using namespace panda::ecmascript; + +namespace panda::test { +class CMCBarrierTest : public CMCBaseTestWithScope { +}; + +HWTEST_F_L0(CMCBarrierTest, OldToNewBatchCopy) +{ + ObjectFactory* factory = thread->GetEcmaVM()->GetFactory(); + uint32_t arrayLength = 10; + // length 50 will be in old + JSHandle srcArray = factory->NewOldSpaceTaggedArray(arrayLength); + JSHandle dstArray = factory->NewOldSpaceTaggedArray(arrayLength); + + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); + JSHandle newFun = factory->NewJSFunction(env); // in young + for (uint32_t i = 0; i < 10; i++) { + srcArray->Set(thread, i, newFun); + } + + for (uint32_t i = 0; i < arrayLength; i++) { + auto val = srcArray->Get(thread, i).GetTaggedObject(); + common::RegionDesc::InlinedRegionMetaData *objMetaRegion = + common::RegionDesc::InlinedRegionMetaData::GetInlinedRegionMetaData(reinterpret_cast(val)); + EXPECT_TRUE(objMetaRegion->IsInYoungSpaceForWB()); + } + + thread->SetCMCGCPhase(common::GCPhase::GC_PHASE_FINAL_MARK); + JSTaggedValue* to = reinterpret_cast(ToUintPtr(dstArray->GetData())); + JSTaggedValue* from = reinterpret_cast(ToUintPtr(srcArray->GetData())); + Barriers::CopyObject(thread, *dstArray, to, from, arrayLength); + + // young to young, all the bitset should not be changed. + for (uint32_t i = 0; i < arrayLength; i++) { + auto val = dstArray->Get(thread, i).GetTaggedObject(); + common::RegionDesc::InlinedRegionMetaData *objMetaRegion = + common::RegionDesc::InlinedRegionMetaData::GetInlinedRegionMetaData(reinterpret_cast(val)); + EXPECT_TRUE(objMetaRegion->IsInYoungSpaceForWB()); + } + + // check + for (uint32_t i = 0; i < arrayLength; i++) { + EXPECT_EQ(dstArray->Get(thread, i), srcArray->Get(thread, i)); + } +} +} // namespace panda::ecmascript diff --git a/ecmascript/tests/test_helper.h b/ecmascript/tests/test_helper.h index dd3e04d9ce0af34b2d2a3f2330427cd8a2b19130..0b2d8b8af6d350a007b9b6c341565a598f24b192 100644 --- a/ecmascript/tests/test_helper.h +++ b/ecmascript/tests/test_helper.h @@ -216,5 +216,33 @@ public: EcmaHandleScope *scope {nullptr}; JSThread *thread {nullptr}; }; + +class CMCBaseTestWithScope : public BaseTestWithOutScope { +public: + void SetUp() override + { + JSRuntimeOptions options; +#if defined(PANDA_TARGET_LINUX) && defined(ICU_PATH) + // for consistency requirement, use ohos_icu4j/data as icu-data-path + options.SetIcuDataPath(ICU_PATH); +#endif + options.SetEnableCMCGC(true); + instance = JSNApi::CreateEcmaVM(options); + ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM"; + thread = instance->GetJSThread(); + thread->ManagedCodeBegin(); + scope = new EcmaHandleScope(thread); + JSNApi::InitHybridVMEnv(thread->GetEcmaVM()); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(instance, scope); + } + + EcmaVM *instance {nullptr}; + EcmaHandleScope *scope {nullptr}; + JSThread *thread {nullptr}; +}; } // namespace panda::test #endif // ECMASCRIPT_TESTS_TEST_HELPER_H diff --git a/test/resource/js_runtime/ohos_test.xml b/test/resource/js_runtime/ohos_test.xml index b3272d046e00a44e8a41186755b8fd7f340ee6c6..ad76c64e06466495a9bfc05ac597a2c7d5b1ad2a 100755 --- a/test/resource/js_runtime/ohos_test.xml +++ b/test/resource/js_runtime/ohos_test.xml @@ -372,6 +372,11 @@