• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/mem/verification.h"
17 
18 #include "ecmascript/mem/shared_heap/shared_concurrent_sweeper.h"
19 
20 namespace panda::ecmascript {
LogErrorForObjSlot(const BaseHeap * heap,const char * headerInfo,TaggedObject * obj,ObjectSlot slot,TaggedObject * value)21 void LogErrorForObjSlot(const BaseHeap *heap, const char *headerInfo, TaggedObject *obj, ObjectSlot slot,
22                         TaggedObject *value)
23 { // LCOV_EXCL_START
24     TaggedObject *slotValue = slot.GetTaggedObject();
25     Region *region = Region::ObjectAddressToRange(obj);
26     Region *valueRegion = Region::ObjectAddressToRange(value);
27     Region *slotRegion = Region::ObjectAddressToRange(slotValue);
28     LOG_GC(FATAL) << headerInfo
29                   << ": gctype=" << heap->GetGCType()
30                   << ", obj address=" << obj
31                   << ", obj region=" << region
32                   << ", obj space type=" << region->GetSpaceTypeName()
33                   << ", obj type=" << JSHClass::DumpJSType(obj->GetClass()->GetObjectType())
34                   << ", slot address=" << reinterpret_cast<void*>(slot.SlotAddress())
35                   << ", slot value=" << slotValue
36                   << ", slot value region=" << slotRegion
37                   << ", slot value space type=" << slotRegion->GetSpaceTypeName()
38                   << ", slot value type=" << JSHClass::DumpJSType(slotValue->GetClass()->GetObjectType())
39                   << ", value address=" << value
40                   << ", value region=" << valueRegion
41                   << ", value space type=" << valueRegion->GetSpaceTypeName()
42                   << ", value type=" << JSHClass::DumpJSType(value->GetClass()->GetObjectType())
43                   << ", obj mark bit=" << region->Test(obj)
44                   << ", obj slot oldToNew bit=" << region->TestOldToNew(slot.SlotAddress())
45                   << ", obj slot value mark bit=" << slotRegion->Test(slotValue)
46                   << ", value mark bit=" << valueRegion->Test(value);
47     UNREACHABLE();
48 }
49 
LogErrorForObj(const BaseHeap * heap,const char * headerInfo,TaggedObject * obj)50 void LogErrorForObj(const BaseHeap *heap, const char *headerInfo, TaggedObject *obj)
51 {
52     Region *region = Region::ObjectAddressToRange(obj);
53     LOG_GC(FATAL) << headerInfo
54                   << ": gctype=" << heap->GetGCType()
55                   << ", obj address=" << obj
56                   << ", obj value=" << ObjectSlot(ToUintPtr(obj)).GetTaggedObject()
57                   << ", obj region=" << region
58                   << ", obj space type=" << region->GetSpaceTypeName()
59                   << ", obj type=" << JSHClass::DumpJSType(obj->GetClass()->GetObjectType())
60                   << ", obj mark bit=" << region->Test(obj);
61     UNREACHABLE();
62 } // LCOV_EXCL_STOP
63 
64 // Only used for verify InactiveSemiSpace
VerifyInactiveSemiSpaceMarkedObject(const BaseHeap * heap,void * addr)65 void VerifyObjectVisitor::VerifyInactiveSemiSpaceMarkedObject(const BaseHeap *heap, void *addr)
66 {
67     TaggedObject *object = reinterpret_cast<TaggedObject*>(addr);
68     Region *objectRegion = Region::ObjectAddressToRange(object);
69     if (!objectRegion->InInactiveSemiSpace()) { // LCOV_EXCL_START
70         LogErrorForObj(heap, "Verify InactiveSemiSpaceMarkedObject: Object is not in InactiveSemiSpace.", object);
71     } else {
72         MarkWord word(object);
73         if (!word.IsForwardingAddress()) {
74             LogErrorForObj(heap, "Verify InactiveSemiSpaceMarkedObject: not forwarding address.", object);
75         } else {
76             ObjectSlot slot(ToUintPtr(object));
77             TaggedObject *value = word.ToForwardingAddress();
78             Region *valueRegion = Region::ObjectAddressToRange(value);
79             if (valueRegion->InInactiveSemiSpace()) {
80                 LogErrorForObjSlot(heap, "Verify InactiveSemiSpaceMarkedObject: forwarding address, "
81                     "but InactiveSemiSpace(FromSpace) Object.", object, slot, value);
82             }
83         }
84     } // LCOV_EXCL_STOP
85 }
86 
87 // Verify the object body
VisitAllObjects(TaggedObject * obj)88 void VerifyObjectVisitor::VisitAllObjects(TaggedObject *obj)
89 {
90     auto cb = [this] (ObjectSlot slot, TaggedObject *root) {
91         VerifyObjectSlotLegal(slot, root);
92     };
93     VerifyVisitor verifyVisitor(cb);
94     auto jsHclass = obj->GetClass();
95     ObjectXRay::VisitObjectBody<VisitType::OLD_GC_VISIT>(obj, jsHclass, verifyVisitor);
96 }
97 
VerifyObjectSlotLegal(ObjectSlot slot,TaggedObject * object) const98 void VerifyObjectVisitor::VerifyObjectSlotLegal(ObjectSlot slot, TaggedObject *object) const
99 {
100     JSTaggedValue value(slot.GetTaggedType());
101     if (value.IsWeak()) { // LCOV_EXCL_START
102         if (ToUintPtr(value.GetTaggedWeakRef()) < INVALID_THRESHOLD) {
103             LogErrorForObjSlot(heap_, "Heap verify detected an invalid value.",
104                 object, slot, value.GetTaggedWeakRef());
105         }
106         if (!heap_->IsAlive(value.GetTaggedWeakRef()) && failCount_ != nullptr) {
107             LogErrorForObjSlot(heap_, "Heap verify detected a dead weak object.",
108                 object, slot, value.GetTaggedWeakRef());
109             ++(*failCount_);
110         }
111     } else if (value.IsHeapObject()) {
112         VerifyHeapObjectSlotLegal(slot, value, object);
113     } // LCOV_EXCL_STOP
114 }
115 
VerifyHeapObjectSlotLegal(ObjectSlot slot,JSTaggedValue slotValue,TaggedObject * object) const116 void VerifyObjectVisitor::VerifyHeapObjectSlotLegal(ObjectSlot slot,
117                                                     JSTaggedValue slotValue,
118                                                     TaggedObject *object) const
119 {
120     ASSERT(slotValue.IsHeapObject());
121     if (ToUintPtr(slotValue.GetTaggedObject()) < INVALID_THRESHOLD) { // LCOV_EXCL_START
122         LogErrorForObjSlot(heap_, "Heap verify detected an invalid value.",
123             object, slot, slotValue.GetTaggedObject());
124     }
125     if (!heap_->IsAlive(slotValue.GetTaggedObject()) && failCount_ != nullptr) {
126         LogErrorForObjSlot(heap_, "Heap verify detected a dead object.",
127             object, slot, slotValue.GetTaggedObject());
128         ++(*failCount_);
129     } // LCOV_EXCL_STOP
130     switch (verifyKind_) {
131         case VerifyKind::VERIFY_PRE_GC:
132         case VerifyKind::VERIFY_POST_GC:
133             break;
134         case VerifyKind::VERIFY_MARK_YOUNG:
135             VerifyMarkYoung(object, slot, slotValue.GetTaggedObject());
136             break;
137         case VerifyKind::VERIFY_EVACUATE_YOUNG:
138             VerifyEvacuateYoung(object, slot, slotValue.GetTaggedObject());
139             break;
140         case VerifyKind::VERIFY_MARK_FULL:
141             VerifyMarkFull(object, slot, slotValue.GetTaggedObject());
142             break;
143         case VerifyKind::VERIFY_EVACUATE_OLD:
144             VerifyEvacuateOld(object, slot, slotValue.GetTaggedObject());
145             break;
146         case VerifyKind::VERIFY_EVACUATE_FULL:
147             VerifyEvacuateFull(object, slot, slotValue.GetTaggedObject());
148             break;
149         case VerifyKind::VERIFY_SHARED_RSET_POST_FULL_GC:
150             VerifySharedRSetPostFullGC(object, slot, slotValue.GetTaggedObject());
151             break;
152         case VerifyKind::VERIFY_PRE_SHARED_GC:
153         case VerifyKind::VERIFY_POST_SHARED_GC:
154             VerifySharedObjectReference(object, slot, slotValue.GetTaggedObject());
155             break;
156         default: // LCOV_EXCL_START
157             LOG_GC(FATAL) << "unknown verify kind:" << static_cast<size_t>(verifyKind_);
158             UNREACHABLE(); // LCOV_EXCL_STOP
159     }
160 }
161 
VerifyMarkYoung(TaggedObject * object,ObjectSlot slot,TaggedObject * value) const162 void VerifyObjectVisitor::VerifyMarkYoung(TaggedObject *object, ObjectSlot slot, TaggedObject *value) const
163 {
164     Region *objectRegion = Region::ObjectAddressToRange(object);
165     Region *valueRegion = Region::ObjectAddressToRange(value);
166     ASSERT(!objectRegion->InSharedHeap());
167     if (objectRegion->InGeneralOldSpace() && valueRegion->InYoungSpace()) { // LCOV_EXCL_START
168         if (!objectRegion->TestOldToNew(slot.SlotAddress())) {
169             LogErrorForObjSlot(heap_, "Verify MarkYoung: Old object, slot miss old_to_new bit.", object, slot, value);
170         } else if (!valueRegion->Test(value)) {
171             LogErrorForObjSlot(heap_, "Verify MarkYoung: Old object, slot has old_to_new bit, miss gc_mark bit.",
172                 object, slot, value);
173         }
174     }
175     if (!objectRegion->InSharedHeap() && valueRegion->InSharedSweepableSpace()) {
176         if (!objectRegion->TestLocalToShare(slot.SlotAddress())) {
177             LogErrorForObjSlot(heap_, "Verify MarkYoung: Local object, slot local_to_share bit = 0, "
178                 "but SharedHeap object.", object, slot, value);
179         }
180     }
181     if (objectRegion->Test(object)) {
182         if (!objectRegion->InYoungSpace() && !objectRegion->InAppSpawnSpace() &&
183             !objectRegion->InReadOnlySpace()) {
184             LogErrorForObj(heap_, "Verify MarkYoung: Marked object, NOT in Young/AppSpawn/ReadOnly Space", object);
185         }
186         if (valueRegion->InYoungSpace() && !valueRegion->Test(value)) {
187             LogErrorForObjSlot(heap_, "Verify MarkYoung: Marked object, slot in YoungSpace, miss gc_mark bit.",
188                 object, slot, value);
189         }
190         if (valueRegion->Test(value) &&
191             !(valueRegion->InYoungSpace() || valueRegion->InAppSpawnSpace() || valueRegion->InReadOnlySpace() ||
192               valueRegion->InSharedHeap())) {
193             LogErrorForObjSlot(heap_, "Verify MarkYoung: Marked object, slot marked, but NOT in "
194                 "Young/AppSpawn/ReadOnly Space.", object, slot, value);
195         }
196     } // LCOV_EXCL_STOP
197 }
198 
VerifyEvacuateYoung(TaggedObject * object,ObjectSlot slot,TaggedObject * value) const199 void VerifyObjectVisitor::VerifyEvacuateYoung(TaggedObject *object, ObjectSlot slot, TaggedObject *value) const
200 {
201     Region *objectRegion = Region::ObjectAddressToRange(object);
202     Region *valueRegion = Region::ObjectAddressToRange(value);
203 
204     if (objectRegion->InGeneralOldSpace()) { // LCOV_EXCL_START
205         if (objectRegion->TestOldToNew(slot.SlotAddress())) {
206             if (!valueRegion->InActiveSemiSpace()) {
207                 LogErrorForObjSlot(heap_, "Verify EvacuateYoung: Old object, slot old_to_new bit = 1, "
208                     "but NOT ActiveSpace(ToSpace) object.", object, slot, value);
209             }
210         } else {
211             if (valueRegion->InYoungSpace()) {
212                 LogErrorForObjSlot(heap_, "Verify EvacuateYoung: Old object, slot old_to_new bit = 0, "
213                     "but YoungSpace object.", object, slot, value);
214             }
215         }
216     }
217     if (!objectRegion->InSharedHeap() && valueRegion->InSharedSweepableSpace()) {
218         if (!objectRegion->TestLocalToShare(slot.SlotAddress())) {
219             LogErrorForObjSlot(heap_, "Verify EvacuateYoung: Local object, slot local_to_share bit = 0, "
220                 "but SharedHeap object.", object, slot, value);
221         }
222     }
223     if (objectRegion->InActiveSemiSpace()) {
224         if (valueRegion->InInactiveSemiSpace()) {
225             LogErrorForObjSlot(heap_, "Verify EvacuateYoung: ActiveSpace object, slot in InactiveSpace(FromSpace).",
226                 object, slot, value);
227         }
228     } // LCOV_EXCL_STOP
229 }
230 
VerifyMarkFull(TaggedObject * object,ObjectSlot slot,TaggedObject * value) const231 void VerifyObjectVisitor::VerifyMarkFull(TaggedObject *object, ObjectSlot slot, TaggedObject *value) const
232 {
233     Region *objectRegion = Region::ObjectAddressToRange(object);
234     Region *valueRegion = Region::ObjectAddressToRange(value);
235     if (objectRegion->InGeneralOldSpace() && valueRegion->InYoungSpace()) { // LCOV_EXCL_START
236         if (!objectRegion->TestOldToNew(slot.SlotAddress())) {
237             LogErrorForObjSlot(heap_, "Verify MarkFull: Old object, slot miss old_to_new bit.", object, slot, value);
238         }
239     }
240     if (objectRegion->Test(object)) {
241         if (!valueRegion->InSharedHeap() && !valueRegion->Test(value)) {
242             LogErrorForObjSlot(heap_, "Verify MarkFull: Marked object, slot miss gc_mark bit.", object, slot, value);
243         }
244     }
245     if (!objectRegion->InSharedHeap() && valueRegion->InSharedSweepableSpace()) {
246         if (!objectRegion->TestLocalToShare(slot.SlotAddress())) {
247             LogErrorForObjSlot(heap_, "Verify VerifyMarkFull: Local object, slot local_to_share bit = 0, "
248                 "but SharedHeap object.", object, slot, value);
249         }
250     } // LCOV_EXCL_STOP
251 }
252 
VerifyEvacuateOld(TaggedObject * root,ObjectSlot slot,TaggedObject * value) const253 void VerifyObjectVisitor::VerifyEvacuateOld([[maybe_unused]]TaggedObject *root,
254                                             [[maybe_unused]]ObjectSlot slot,
255                                             [[maybe_unused]]TaggedObject *value) const
256 {
257     VerifyEvacuateYoung(root, slot, value);
258 }
259 
VerifyEvacuateFull(TaggedObject * root,ObjectSlot slot,TaggedObject * value) const260 void VerifyObjectVisitor::VerifyEvacuateFull([[maybe_unused]]TaggedObject *root,
261                                              [[maybe_unused]]ObjectSlot slot,
262                                              [[maybe_unused]]TaggedObject *value) const
263 {
264     VerifyEvacuateYoung(root, slot, value);
265 }
266 
VerifySharedObjectReference(TaggedObject * object,ObjectSlot slot,TaggedObject * value) const267 void VerifyObjectVisitor::VerifySharedObjectReference(TaggedObject *object, ObjectSlot slot, TaggedObject *value) const
268 {
269     Region *objectRegion = Region::ObjectAddressToRange(object);
270     Region *valueRegion = Region::ObjectAddressToRange(value);
271     if (objectRegion->InSharedHeap()) { // LCOV_EXCL_START
272         if (!valueRegion->InSharedHeap()) {
273             LogErrorForObjSlot(heap_, "Verify SharedObjectReference: Shared object references a local object",
274                 object, slot, value);
275         }
276     } else if (valueRegion->InSharedSweepableSpace()) {
277         if (!objectRegion->TestLocalToShare(slot.SlotAddress())) {
278             LogErrorForObjSlot(heap_, "Verify SharedObjectReference: Local object, slot local_to_share bit = 0, "
279                 "but SharedHeap object.", object, slot, value);
280         }
281     } // LCOV_EXCL_STOP
282 }
283 
VerifySharedRSetPostFullGC(TaggedObject * object,ObjectSlot slot,TaggedObject * value) const284 void VerifyObjectVisitor::VerifySharedRSetPostFullGC(TaggedObject *object, ObjectSlot slot, TaggedObject *value) const
285 {
286     Region *objectRegion = Region::ObjectAddressToRange(object);
287     Region *valueRegion = Region::ObjectAddressToRange(value);
288     if (!objectRegion->InSharedHeap() && valueRegion->InSharedSweepableSpace()) { // LCOV_EXCL_START
289         if (!objectRegion->TestLocalToShare(slot.SlotAddress())) {
290             LogErrorForObjSlot(heap_, "Verify SharedRSetPostFullGC: Local object, slot local_to_share bit = 0, "
291                 "but SharedHeap object.", object, slot, value);
292         }
293     } // LCOV_EXCL_STOP
294 }
295 
operator ()(TaggedObject * obj,JSTaggedValue value)296 void VerifyObjectVisitor::operator()(TaggedObject *obj, JSTaggedValue value)
297 {
298     ObjectSlot slot(reinterpret_cast<uintptr_t>(obj));
299     if (!value.IsHeapObject()) {
300         LOG_GC(DEBUG) << "Heap object(" << slot.SlotAddress() << ") old to new rset fail: value is "
301                       << slot.GetTaggedType();
302         return;
303     }
304 
305     TaggedObject *object = value.GetRawTaggedObject();
306     auto region = Region::ObjectAddressToRange(object);
307     if (region->InGeneralOldSpace() && failCount_ != nullptr) { // LCOV_EXCL_START
308         LOG_GC(ERROR) << "Heap object(" << slot.GetTaggedType() << ") old to new rset fail: value("
309                       << slot.GetTaggedObject() << "/"
310                       << JSHClass::DumpJSType(slot.GetTaggedObject()->GetClass()->GetObjectType())
311                       << ")" << " in " << region->GetSpaceTypeName();
312         ++(*failCount_);
313     } // LCOV_EXCL_STOP
314 }
315 
VerifyAll() const316 void Verification::VerifyAll() const
317 {
318     [[maybe_unused]] VerifyScope verifyScope(heap_);
319     heap_->GetSweeper()->EnsureAllTaskFinished();
320     size_t result = VerifyRoot();
321     result += VerifyHeap();
322     if (result > 0) { // LCOV_EXCL_START
323         LOG_GC(FATAL) << "Verify (type=" << static_cast<uint8_t>(verifyKind_)
324                       << ") corrupted and " << result << " corruptions";
325     } // LCOV_EXCL_STOP
326 }
327 
VisitRoot(Root type,ObjectSlot slot)328 void Verification::VerificationRootVisitor::VisitRoot([[maybe_unused]] Root type, ObjectSlot slot)
329 {
330     JSTaggedValue value(slot.GetTaggedType());
331     // Skip verifying shared object in local gc verification.
332     if (value.IsInSharedHeap()) {
333         return;
334     }
335     verification_->VerifyObjectSlot(slot, &failCount_);
336 };
337 
VisitRangeRoot(Root type,ObjectSlot start,ObjectSlot end)338 void Verification::VerificationRootVisitor::VisitRangeRoot([[maybe_unused]] Root type, ObjectSlot start,
339                                                            ObjectSlot end)
340 {
341     for (ObjectSlot slot = start; slot < end; slot++) {
342         JSTaggedValue value(slot.GetTaggedType());
343         // Skip verifying shared object in local gc verification.
344         if (value.IsInSharedHeap()) {
345             return;
346         }
347         verification_->VerifyObjectSlot(slot, &failCount_);
348     }
349 };
350 
VisitBaseAndDerivedRoot(Root type,ObjectSlot base,ObjectSlot derived,uintptr_t baseOldObject)351 void Verification::VerificationRootVisitor::VisitBaseAndDerivedRoot([[maybe_unused]] Root type,
352     [[maybe_unused]] ObjectSlot base, [[maybe_unused]] ObjectSlot derived, [[maybe_unused]] uintptr_t baseOldObject)
353 {
354 }
355 
VerifyRoot() const356 size_t Verification::VerifyRoot() const
357 {
358     size_t failCount = 0;
359     VerificationRootVisitor verificationRootVisitor(this, failCount);
360     ObjectXRay::VisitVMRoots(heap_->GetEcmaVM(), verificationRootVisitor, VMRootVisitType::VERIFY);
361     if (failCount > 0) {
362         LOG_GC(ERROR) << "VerifyRoot detects deadObject count is " << failCount;
363     }
364 
365     return failCount;
366 }
367 
VerifyHeap() const368 size_t Verification::VerifyHeap() const
369 {
370     size_t failCount = heap_->VerifyHeapObjects(verifyKind_);
371     if (failCount > 0) {
372         LOG_GC(ERROR) << "VerifyHeap detects deadObject count is " << failCount;
373     }
374     return failCount;
375 }
376 
VerifyOldToNewRSet() const377 size_t Verification::VerifyOldToNewRSet() const
378 {
379     size_t failCount = heap_->VerifyOldToNewRSet(verifyKind_);
380     if (failCount > 0) {
381         LOG_GC(ERROR) << "VerifyOldToNewRSet detects non new space count is " << failCount;
382     }
383     return failCount;
384 }
385 
VerifyObjectSlot(const ObjectSlot & slot,size_t * failCount) const386 void Verification::VerifyObjectSlot(const ObjectSlot &slot, size_t *failCount) const
387 {
388     JSTaggedValue value(slot.GetTaggedType());
389     if (value.IsWeak()) {
390         VerifyObjectVisitor(heap_, failCount, verifyKind_)(value.GetTaggedWeakRef());
391     } else if (value.IsHeapObject()) {
392         VerifyObjectVisitor(heap_, failCount, verifyKind_)(value.GetTaggedObject());
393     }
394 }
395 
VerifyMark(Heap * heap)396 void Verification::VerifyMark(Heap *heap)
397 {
398     LOG_ECMA(DEBUG) << "start verify mark";
399     switch (heap->GetMarkType()) {
400         case MarkType::MARK_YOUNG:
401             Verification(heap, VerifyKind::VERIFY_MARK_YOUNG).VerifyAll();
402             break;
403         case MarkType::MARK_FULL:
404             Verification(heap, VerifyKind::VERIFY_MARK_FULL).VerifyAll();
405             break;
406     }
407 }
408 
VerifyEvacuate(Heap * heap)409 void Verification::VerifyEvacuate(Heap *heap)
410 {
411     LOG_ECMA(DEBUG) << "start verify evacuate and sweep";
412     switch (heap->GetMarkType()) {
413         case MarkType::MARK_YOUNG:
414             Verification(heap, VerifyKind::VERIFY_EVACUATE_YOUNG).VerifyAll();
415             break;
416         case MarkType::MARK_FULL:
417             Verification(heap, VerifyKind::VERIFY_EVACUATE_OLD).VerifyAll();
418             break;
419     }
420 }
421 
VerifyAll() const422 void SharedHeapVerification::VerifyAll() const
423 {
424     [[maybe_unused]] VerifyScope verifyScope(sHeap_);
425     sHeap_->GetSweeper()->EnsureAllTaskFinished();
426     size_t result = VerifyRoot();
427     result += VerifyHeap();
428     if (result > 0) { // LCOV_EXCL_START
429         LOG_GC(FATAL) << "Verify (type=" << static_cast<uint8_t>(verifyKind_)
430                       << ") corrupted and " << result << " corruptions";
431     } // LCOV_EXCL_STOP
432 }
433 
VerifyMark(bool cm) const434 void SharedHeapVerification::VerifyMark(bool cm) const
435 {
436     LOG_GC(DEBUG) << "start verify shared mark";
437     [[maybe_unused]] VerifyScope verifyScope(sHeap_);
438     sHeap_->GetSweeper()->EnsureAllTaskFinished();
439     auto cb1 = [cm] (ObjectSlot slot, TaggedObject *obj) {
440         Region *objectRegion = Region::ObjectAddressToRange(obj);
441         JSTaggedValue value(slot.GetTaggedType());
442         if (value.IsWeak() || !value.IsHeapObject()) {
443             return;
444         }
445         Region *valueRegion = Region::ObjectAddressToRange(value.GetTaggedObject());
446         if (!valueRegion->InSharedSweepableSpace()) {
447             return;
448         }
449         if (!objectRegion->TestLocalToShare(slot.SlotAddress())) { // LCOV_EXCL_START
450             LOG_GC(FATAL) << "verify shared1 " << cm << ':' << slot.SlotAddress()
451                           << ' ' << value.GetTaggedObject();
452             UNREACHABLE();
453         }
454         if (!valueRegion->Test(value.GetTaggedObject())) {
455             LOG_GC(FATAL) << "verify shared2 " << cm << ':' << slot.SlotAddress()
456                           << ' ' << value.GetTaggedObject();
457             UNREACHABLE();
458         }
459         if (value.GetTaggedObject()->GetClass()->IsFreeObject()) {
460             LOG_GC(FATAL) << "verify shared3 " << cm << ':' << slot.SlotAddress()
461                           << ' ' << value.GetTaggedObject();
462             UNREACHABLE();
463         } // LCOV_EXCL_STOP
464     };
465     VerifyVisitor verifyVisitor1(cb1);
466     Runtime::GetInstance()->GCIterateThreadList([cm, &verifyVisitor1](JSThread *thread) {
467         auto vm = thread->GetEcmaVM();
468         auto heap = vm->GetHeap();
469         heap->GetSweeper()->EnsureAllTaskFinished();
470         const_cast<Heap*>(heap)->FillBumpPointerForTlab();
471         auto localBuffer = const_cast<Heap*>(heap)->GetMarkingObjectLocalBuffer();
472         if (localBuffer != nullptr) { // LCOV_EXCL_START
473             LOG_GC(FATAL) << "verify shared node not null " << cm << ':' << thread;
474             UNREACHABLE();
475         } // LCOV_EXCL_STOP
476         heap->IterateOverObjects([&verifyVisitor1](TaggedObject *obj) {
477             auto jsHclass = obj->GetClass();
478             ObjectXRay::VisitObjectBody<VisitType::OLD_GC_VISIT>(obj, jsHclass, verifyVisitor1);
479         });
480     });
481     auto cb2 = [cm] (ObjectSlot slot, TaggedObject *obj) {
482         Region *objectRegion = Region::ObjectAddressToRange(obj);
483         if (!objectRegion->Test(obj)) {
484             return;
485         }
486         JSTaggedValue value(slot.GetTaggedType());
487         if (value.IsWeak() || !value.IsHeapObject()) {
488             return;
489         }
490         [[maybe_unused]] Region *valueRegion = Region::ObjectAddressToRange(value.GetTaggedObject());
491         if (!valueRegion->InSharedHeap()) { // LCOV_EXCL_START
492             LOG_GC(FATAL) << "verify shared4 " << cm << ':' << slot.SlotAddress()
493                           << ' ' << value.GetTaggedObject();
494             UNREACHABLE();
495         }
496         if (!valueRegion->InSharedReadOnlySpace()
497                 && !valueRegion->Test(value.GetTaggedObject())) {
498             LOG_GC(FATAL) << "verify shared5 " << cm << ':' << slot.SlotAddress()
499                           << ' ' << value.GetTaggedObject();
500             UNREACHABLE();
501         }
502         if (value.GetTaggedObject()->GetClass()->IsFreeObject()) {
503             LOG_GC(FATAL) << "verify shared6 " << cm << ':' << slot.SlotAddress()
504                           << ' ' << value.GetTaggedObject();
505             UNREACHABLE();
506         } // LCOV_EXCL_STOP
507     };
508     VerifyVisitor verifyVisitor2(cb2);
509     sHeap_->IterateOverObjects([&verifyVisitor2](TaggedObject *obj) {
510         auto jsHclass = obj->GetClass();
511         ObjectXRay::VisitObjectBody<VisitType::OLD_GC_VISIT>(obj, jsHclass, verifyVisitor2);
512     });
513 }
514 
VerifySweep(bool cm) const515 void SharedHeapVerification::VerifySweep(bool cm) const
516 {
517     LOG_GC(DEBUG) << "start verify shared sweep";
518     [[maybe_unused]] VerifyScope verifyScope(sHeap_);
519     sHeap_->GetSweeper()->EnsureAllTaskFinished();
520     auto cb1 = [cm] (ObjectSlot slot, TaggedObject *obj) {
521         Region *objectRegion = Region::ObjectAddressToRange(obj);
522         JSTaggedValue value(slot.GetTaggedType());
523         if (value.IsWeak() || !value.IsHeapObject()) {
524             return;
525         }
526         Region *valueRegion = Region::ObjectAddressToRange(value.GetTaggedObject());
527         if (!valueRegion->InSharedSweepableSpace()) {
528             return;
529         }
530         if (!objectRegion->TestLocalToShare(slot.SlotAddress())) { // LCOV_EXCL_START
531             LOG_GC(FATAL) << "verify shared7 " << cm << ':' << slot.SlotAddress()
532                           << ' ' << value.GetTaggedObject();
533             UNREACHABLE();
534         }
535         if (valueRegion->InSCollectSet()) {
536             LOG_GC(FATAL) << "verify shared8 " << cm << ':' << slot.SlotAddress()
537                           << ' ' << value.GetTaggedObject();
538             UNREACHABLE();
539         }
540         if (value.GetTaggedObject()->GetClass()->IsFreeObject()) {
541             LOG_GC(FATAL) << "verify shared9 " << cm << ':' << slot.SlotAddress()
542                           << ' ' << value.GetTaggedObject();
543             UNREACHABLE();
544         } // LCOV_EXCL_STOP
545     };
546     VerifyVisitor verifyVisitor1(cb1);
547     Runtime::GetInstance()->GCIterateThreadList([&verifyVisitor1](JSThread *thread) {
548         auto vm = thread->GetEcmaVM();
549         auto heap = vm->GetHeap();
550         heap->GetSweeper()->EnsureAllTaskFinished();
551         const_cast<Heap*>(heap)->FillBumpPointerForTlab();
552         heap->IterateOverObjects([&verifyVisitor1](TaggedObject *obj) {
553             auto jsHclass = obj->GetClass();
554             ObjectXRay::VisitObjectBody<VisitType::OLD_GC_VISIT>(obj, jsHclass, verifyVisitor1);
555         });
556     });
557     auto cb2 = [cm] (ObjectSlot slot, TaggedObject *obj) {
558         [[maybe_unused]] Region *objectRegion = Region::ObjectAddressToRange(obj);
559         if (objectRegion->InSCollectSet()) { // LCOV_EXCL_START
560             LOG_GC(FATAL) << "verify shared10 " << cm << ':' << obj;
561             UNREACHABLE();
562         }
563         JSTaggedValue value(slot.GetTaggedType());
564         if (value.IsWeak() || !value.IsHeapObject()) {
565             return;
566         }
567         [[maybe_unused]] Region *valueRegion = Region::ObjectAddressToRange(value.GetTaggedObject());
568         if (!valueRegion->InSharedHeap()) {
569             LOG_GC(FATAL) << "verify shared11 " << cm << ':' << slot.SlotAddress()
570                           << ' ' << value.GetTaggedObject();
571             UNREACHABLE();
572         }
573         if (!valueRegion->InSharedReadOnlySpace() && valueRegion->InSCollectSet()) {
574             LOG_GC(FATAL) << "verify shared12 " << cm << ':' << slot.SlotAddress()
575                           << ' ' << value.GetTaggedObject();
576             UNREACHABLE();
577         }
578         if (value.GetTaggedObject()->GetClass()->IsFreeObject()) {
579             LOG_GC(FATAL) << "verify shared13 " << cm << ':' << slot.SlotAddress()
580                           << ' ' << value.GetTaggedObject();
581             UNREACHABLE();
582         } // LCOV_EXCL_STOP
583     };
584     VerifyVisitor verifyVisitor2(cb2);
585     sHeap_->IterateOverObjects([&verifyVisitor2](TaggedObject *obj) {
586         auto jsHclass = obj->GetClass();
587 
588         ObjectXRay::VisitObjectBody<VisitType::OLD_GC_VISIT>(obj, jsHclass, verifyVisitor2);
589     });
590 }
591 
VisitRoot(Root type,ObjectSlot slot)592 void SharedHeapVerification::VerificationRootVisitor::VisitRoot([[maybe_unused]] Root type, ObjectSlot slot)
593 {
594     sVerification_->VerifyObjectSlot(slot, &failCount_);
595 };
596 
VisitRangeRoot(Root type,ObjectSlot start,ObjectSlot end)597 void SharedHeapVerification::VerificationRootVisitor::VisitRangeRoot([[maybe_unused]] Root type, ObjectSlot start,
598                                                                      ObjectSlot end)
599 {
600     for (ObjectSlot slot = start; slot < end; slot++) {
601         sVerification_->VerifyObjectSlot(slot, &failCount_);
602     }
603 };
604 
VisitBaseAndDerivedRoot(Root type,ObjectSlot base,ObjectSlot derived,uintptr_t baseOldObject)605 void SharedHeapVerification::VerificationRootVisitor::VisitBaseAndDerivedRoot([[maybe_unused]] Root type,
606     [[maybe_unused]] ObjectSlot base, [[maybe_unused]] ObjectSlot derived, [[maybe_unused]] uintptr_t baseOldObject)
607 {
608 }
609 
VisitRoot(Root type,ObjectSlot slot)610 void SharedHeapVerification::VerificationSerializeRootVisitor::VisitRoot([[maybe_unused]] Root type, ObjectSlot slot)
611 {
612     JSTaggedValue value(slot.GetTaggedType());
613     if (!sHeap_->IsAlive(value.GetTaggedObject())) {
614         LOG_ECMA(ERROR) << "Serialize Heap verify detected a dead object. " << value.GetTaggedObject();
615         ++failCount_;
616     }
617 };
618 
VisitRangeRoot(Root type,ObjectSlot start,ObjectSlot end)619 void SharedHeapVerification::VerificationSerializeRootVisitor::VisitRangeRoot([[maybe_unused]] Root type,
620     [[maybe_unused]] ObjectSlot start, [[maybe_unused]] ObjectSlot end)
621 {
622 }
623 
VisitBaseAndDerivedRoot(Root type,ObjectSlot base,ObjectSlot derived,uintptr_t baseOldObject)624 void SharedHeapVerification::VerificationSerializeRootVisitor::VisitBaseAndDerivedRoot([[maybe_unused]] Root type,
625     [[maybe_unused]] ObjectSlot base, [[maybe_unused]] ObjectSlot derived, [[maybe_unused]] uintptr_t baseOldObject)
626 {
627 }
628 
VerifyRoot() const629 size_t SharedHeapVerification::VerifyRoot() const
630 {
631     size_t failCount = 0;
632     VerificationRootVisitor verificationRootVisitor(this, failCount);
633     VerificationSerializeRootVisitor verificationSerializeRootVisitor(sHeap_, failCount);
634     Runtime::GetInstance()->IterateSerializeRoot(verificationSerializeRootVisitor);
635     Runtime::GetInstance()->GCIterateThreadList([&](JSThread *thread) {
636         ASSERT(!thread->IsInRunningState());
637         auto vm = thread->GetEcmaVM();
638         auto localHeap = const_cast<Heap*>(vm->GetHeap());
639         localHeap->GetSweeper()->EnsureAllTaskFinished();
640         ObjectXRay::VisitVMRoots(vm, verificationRootVisitor, VMRootVisitType::VERIFY);
641         if (failCount > 0) {
642             LOG_GC(ERROR) << "SharedHeap VerifyRoot detects deadObject count is " << failCount;
643         }
644     });
645     return failCount;
646 }
647 
VerifyHeap() const648 size_t SharedHeapVerification::VerifyHeap() const
649 {
650     Runtime::GetInstance()->GCIterateThreadList([&](JSThread *thread) {
651         ASSERT(!thread->IsInRunningState());
652         const_cast<Heap*>(thread->GetEcmaVM()->GetHeap())->FillBumpPointerForTlab();
653     });
654     size_t failCount = sHeap_->VerifyHeapObjects(verifyKind_);
655     if (failCount > 0) {
656         LOG_GC(ERROR) << "SharedHeap VerifyHeap detects deadObject count is " << failCount;
657     }
658     VerifyKind localVerifyKind = VerifyKind::VERIFY_END;
659     if (verifyKind_ == VerifyKind::VERIFY_PRE_SHARED_GC) {
660         localVerifyKind = VerifyKind::VERIFY_PRE_GC;
661     } else if (verifyKind_ == VerifyKind::VERIFY_POST_SHARED_GC) {
662         localVerifyKind = VerifyKind::VERIFY_POST_GC;
663     }
664 
665     Runtime::GetInstance()->GCIterateThreadList([&, localVerifyKind](JSThread *thread) {
666         ASSERT(!thread->IsInRunningState());
667         auto vm = thread->GetEcmaVM();
668         auto localHeap = const_cast<Heap*>(vm->GetHeap());
669         localHeap->GetSweeper()->EnsureAllTaskFinished();
670         if (localVerifyKind != VerifyKind::VERIFY_END) {
671             Verification(localHeap, localVerifyKind).VerifyAll();
672         }
673         if (failCount > 0) {
674             LOG_GC(ERROR) << "SharedHeap VerifyRoot detects deadObject in local heap count is " << failCount;
675         }
676     });
677     return failCount;
678 }
679 
VerifyObjectSlot(const ObjectSlot & slot,size_t * failCount) const680 void SharedHeapVerification::VerifyObjectSlot(const ObjectSlot &slot, size_t *failCount) const
681 {
682     JSTaggedValue value(slot.GetTaggedType());
683     if (value.IsWeak()) {
684         VerifyObjectVisitor(sHeap_, failCount, verifyKind_)(value.GetTaggedWeakRef());
685     } else if (value.IsHeapObject()) {
686         VerifyObjectVisitor(sHeap_, failCount, verifyKind_)(value.GetTaggedObject());
687     }
688 }
689 }  // namespace panda::ecmascript
690