14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/mem/verification.h" 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ci#include "ecmascript/mem/shared_heap/shared_concurrent_sweeper.h" 194514f5e3Sopenharmony_ci#include "ecmascript/runtime.h" 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_cinamespace panda::ecmascript { 224514f5e3Sopenharmony_civoid LogErrorForObjSlot(const BaseHeap *heap, const char *headerInfo, TaggedObject *obj, ObjectSlot slot, 234514f5e3Sopenharmony_ci TaggedObject *value) 244514f5e3Sopenharmony_ci{ // LCOV_EXCL_START 254514f5e3Sopenharmony_ci TaggedObject *slotValue = slot.GetTaggedObject(); 264514f5e3Sopenharmony_ci Region *region = Region::ObjectAddressToRange(obj); 274514f5e3Sopenharmony_ci Region *valueRegion = Region::ObjectAddressToRange(value); 284514f5e3Sopenharmony_ci Region *slotRegion = Region::ObjectAddressToRange(slotValue); 294514f5e3Sopenharmony_ci LOG_GC(FATAL) << headerInfo 304514f5e3Sopenharmony_ci << ": gctype=" << heap->GetGCType() 314514f5e3Sopenharmony_ci << ", obj address=" << obj 324514f5e3Sopenharmony_ci << ", obj region=" << region 334514f5e3Sopenharmony_ci << ", obj space type=" << region->GetSpaceTypeName() 344514f5e3Sopenharmony_ci << ", obj type=" << JSHClass::DumpJSType(obj->GetClass()->GetObjectType()) 354514f5e3Sopenharmony_ci << ", slot address=" << reinterpret_cast<void*>(slot.SlotAddress()) 364514f5e3Sopenharmony_ci << ", slot value=" << slotValue 374514f5e3Sopenharmony_ci << ", slot value region=" << slotRegion 384514f5e3Sopenharmony_ci << ", slot value space type=" << slotRegion->GetSpaceTypeName() 394514f5e3Sopenharmony_ci << ", slot value type=" << JSHClass::DumpJSType(slotValue->GetClass()->GetObjectType()) 404514f5e3Sopenharmony_ci << ", value address=" << value 414514f5e3Sopenharmony_ci << ", value region=" << valueRegion 424514f5e3Sopenharmony_ci << ", value space type=" << valueRegion->GetSpaceTypeName() 434514f5e3Sopenharmony_ci << ", value type=" << JSHClass::DumpJSType(value->GetClass()->GetObjectType()) 444514f5e3Sopenharmony_ci << ", obj mark bit=" << region->Test(obj) 454514f5e3Sopenharmony_ci << ", obj slot oldToNew bit=" << region->TestOldToNew(slot.SlotAddress()) 464514f5e3Sopenharmony_ci << ", obj slot newToEden bit=" << region->TestNewToEden(slot.SlotAddress()) 474514f5e3Sopenharmony_ci << ", obj slot value mark bit=" << slotRegion->Test(slotValue) 484514f5e3Sopenharmony_ci << ", value mark bit=" << valueRegion->Test(value); 494514f5e3Sopenharmony_ci UNREACHABLE(); 504514f5e3Sopenharmony_ci} 514514f5e3Sopenharmony_ci 524514f5e3Sopenharmony_civoid LogErrorForObj(const BaseHeap *heap, const char *headerInfo, TaggedObject *obj) 534514f5e3Sopenharmony_ci{ 544514f5e3Sopenharmony_ci Region *region = Region::ObjectAddressToRange(obj); 554514f5e3Sopenharmony_ci LOG_GC(FATAL) << headerInfo 564514f5e3Sopenharmony_ci << ": gctype=" << heap->GetGCType() 574514f5e3Sopenharmony_ci << ", obj address=" << obj 584514f5e3Sopenharmony_ci << ", obj value=" << ObjectSlot(ToUintPtr(obj)).GetTaggedObject() 594514f5e3Sopenharmony_ci << ", obj region=" << region 604514f5e3Sopenharmony_ci << ", obj space type=" << region->GetSpaceTypeName() 614514f5e3Sopenharmony_ci << ", obj type=" << JSHClass::DumpJSType(obj->GetClass()->GetObjectType()) 624514f5e3Sopenharmony_ci << ", obj mark bit=" << region->Test(obj); 634514f5e3Sopenharmony_ci UNREACHABLE(); 644514f5e3Sopenharmony_ci} // LCOV_EXCL_STOP 654514f5e3Sopenharmony_ci 664514f5e3Sopenharmony_ci// Only used for verify InactiveSemiSpace 674514f5e3Sopenharmony_civoid VerifyObjectVisitor::VerifyInactiveSemiSpaceMarkedObject(const BaseHeap *heap, void *addr) 684514f5e3Sopenharmony_ci{ 694514f5e3Sopenharmony_ci TaggedObject *object = reinterpret_cast<TaggedObject*>(addr); 704514f5e3Sopenharmony_ci Region *objectRegion = Region::ObjectAddressToRange(object); 714514f5e3Sopenharmony_ci if (!objectRegion->InInactiveSemiSpace()) { // LCOV_EXCL_START 724514f5e3Sopenharmony_ci LogErrorForObj(heap, "Verify InactiveSemiSpaceMarkedObject: Object is not in InactiveSemiSpace.", object); 734514f5e3Sopenharmony_ci } else { 744514f5e3Sopenharmony_ci MarkWord word(object); 754514f5e3Sopenharmony_ci if (!word.IsForwardingAddress()) { 764514f5e3Sopenharmony_ci LogErrorForObj(heap, "Verify InactiveSemiSpaceMarkedObject: not forwarding address.", object); 774514f5e3Sopenharmony_ci } else { 784514f5e3Sopenharmony_ci ObjectSlot slot(ToUintPtr(object)); 794514f5e3Sopenharmony_ci TaggedObject *value = word.ToForwardingAddress(); 804514f5e3Sopenharmony_ci Region *valueRegion = Region::ObjectAddressToRange(value); 814514f5e3Sopenharmony_ci if (valueRegion->InInactiveSemiSpace()) { 824514f5e3Sopenharmony_ci LogErrorForObjSlot(heap, "Verify InactiveSemiSpaceMarkedObject: forwarding address, " 834514f5e3Sopenharmony_ci "but InactiveSemiSpace(FromSpace) Object.", object, slot, value); 844514f5e3Sopenharmony_ci } 854514f5e3Sopenharmony_ci } 864514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 874514f5e3Sopenharmony_ci} 884514f5e3Sopenharmony_ci 894514f5e3Sopenharmony_ci// Verify the object body 904514f5e3Sopenharmony_civoid VerifyObjectVisitor::VisitAllObjects(TaggedObject *obj) 914514f5e3Sopenharmony_ci{ 924514f5e3Sopenharmony_ci auto jsHclass = obj->GetClass(); 934514f5e3Sopenharmony_ci ObjectXRay::VisitObjectBody<VisitType::OLD_GC_VISIT>( 944514f5e3Sopenharmony_ci obj, jsHclass, [this](TaggedObject *root, ObjectSlot start, ObjectSlot end, 954514f5e3Sopenharmony_ci VisitObjectArea area) { 964514f5e3Sopenharmony_ci if (area == VisitObjectArea::IN_OBJECT) { 974514f5e3Sopenharmony_ci auto hclass = root->GetClass(); 984514f5e3Sopenharmony_ci ASSERT(!hclass->IsAllTaggedProp()); 994514f5e3Sopenharmony_ci int index = 0; 1004514f5e3Sopenharmony_ci for (ObjectSlot slot = start; slot < end; slot++) { 1014514f5e3Sopenharmony_ci auto layout = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject()); 1024514f5e3Sopenharmony_ci auto attr = layout->GetAttr(index++); 1034514f5e3Sopenharmony_ci if (attr.IsTaggedRep()) { 1044514f5e3Sopenharmony_ci VerifyObjectSlotLegal(slot, root); 1054514f5e3Sopenharmony_ci } 1064514f5e3Sopenharmony_ci } 1074514f5e3Sopenharmony_ci return; 1084514f5e3Sopenharmony_ci } 1094514f5e3Sopenharmony_ci for (ObjectSlot slot = start; slot < end; slot++) { 1104514f5e3Sopenharmony_ci VerifyObjectSlotLegal(slot, root); 1114514f5e3Sopenharmony_ci } 1124514f5e3Sopenharmony_ci }); 1134514f5e3Sopenharmony_ci} 1144514f5e3Sopenharmony_ci 1154514f5e3Sopenharmony_civoid VerifyObjectVisitor::VerifyObjectSlotLegal(ObjectSlot slot, TaggedObject *object) const 1164514f5e3Sopenharmony_ci{ 1174514f5e3Sopenharmony_ci JSTaggedValue value(slot.GetTaggedType()); 1184514f5e3Sopenharmony_ci if (value.IsWeak()) { // LCOV_EXCL_START 1194514f5e3Sopenharmony_ci if (ToUintPtr(value.GetTaggedWeakRef()) < INVALID_THRESHOLD) { 1204514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Heap verify detected an invalid value.", 1214514f5e3Sopenharmony_ci object, slot, value.GetTaggedWeakRef()); 1224514f5e3Sopenharmony_ci } 1234514f5e3Sopenharmony_ci if (!heap_->IsAlive(value.GetTaggedWeakRef())) { 1244514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Heap verify detected a dead weak object.", 1254514f5e3Sopenharmony_ci object, slot, value.GetTaggedWeakRef()); 1264514f5e3Sopenharmony_ci ++(*failCount_); 1274514f5e3Sopenharmony_ci } 1284514f5e3Sopenharmony_ci } else if (value.IsHeapObject()) { 1294514f5e3Sopenharmony_ci VerifyHeapObjectSlotLegal(slot, value, object); 1304514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 1314514f5e3Sopenharmony_ci} 1324514f5e3Sopenharmony_ci 1334514f5e3Sopenharmony_civoid VerifyObjectVisitor::VerifyHeapObjectSlotLegal(ObjectSlot slot, 1344514f5e3Sopenharmony_ci JSTaggedValue slotValue, 1354514f5e3Sopenharmony_ci TaggedObject *object) const 1364514f5e3Sopenharmony_ci{ 1374514f5e3Sopenharmony_ci ASSERT(slotValue.IsHeapObject()); 1384514f5e3Sopenharmony_ci if (ToUintPtr(slotValue.GetTaggedObject()) < INVALID_THRESHOLD) { // LCOV_EXCL_START 1394514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Heap verify detected an invalid value.", 1404514f5e3Sopenharmony_ci object, slot, slotValue.GetTaggedObject()); 1414514f5e3Sopenharmony_ci } 1424514f5e3Sopenharmony_ci if (!heap_->IsAlive(slotValue.GetTaggedObject())) { 1434514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Heap verify detected a dead object.", 1444514f5e3Sopenharmony_ci object, slot, slotValue.GetTaggedObject()); 1454514f5e3Sopenharmony_ci ++(*failCount_); 1464514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 1474514f5e3Sopenharmony_ci switch (verifyKind_) { 1484514f5e3Sopenharmony_ci case VerifyKind::VERIFY_PRE_GC: 1494514f5e3Sopenharmony_ci case VerifyKind::VERIFY_POST_GC: 1504514f5e3Sopenharmony_ci break; 1514514f5e3Sopenharmony_ci case VerifyKind::VERIFY_MARK_EDEN: 1524514f5e3Sopenharmony_ci VerifyMarkEden(object, slot, slotValue.GetTaggedObject()); 1534514f5e3Sopenharmony_ci break; 1544514f5e3Sopenharmony_ci case VerifyKind::VERIFY_EVACUATE_EDEN: 1554514f5e3Sopenharmony_ci VerifyEvacuateEden(object, slot, slotValue.GetTaggedObject()); 1564514f5e3Sopenharmony_ci break; 1574514f5e3Sopenharmony_ci case VerifyKind::VERIFY_MARK_YOUNG: 1584514f5e3Sopenharmony_ci VerifyMarkYoung(object, slot, slotValue.GetTaggedObject()); 1594514f5e3Sopenharmony_ci break; 1604514f5e3Sopenharmony_ci case VerifyKind::VERIFY_EVACUATE_YOUNG: 1614514f5e3Sopenharmony_ci VerifyEvacuateYoung(object, slot, slotValue.GetTaggedObject()); 1624514f5e3Sopenharmony_ci break; 1634514f5e3Sopenharmony_ci case VerifyKind::VERIFY_MARK_FULL: 1644514f5e3Sopenharmony_ci VerifyMarkFull(object, slot, slotValue.GetTaggedObject()); 1654514f5e3Sopenharmony_ci break; 1664514f5e3Sopenharmony_ci case VerifyKind::VERIFY_EVACUATE_OLD: 1674514f5e3Sopenharmony_ci VerifyEvacuateOld(object, slot, slotValue.GetTaggedObject()); 1684514f5e3Sopenharmony_ci break; 1694514f5e3Sopenharmony_ci case VerifyKind::VERIFY_EVACUATE_FULL: 1704514f5e3Sopenharmony_ci VerifyEvacuateFull(object, slot, slotValue.GetTaggedObject()); 1714514f5e3Sopenharmony_ci break; 1724514f5e3Sopenharmony_ci case VerifyKind::VERIFY_SHARED_RSET_POST_FULL_GC: 1734514f5e3Sopenharmony_ci VerifySharedRSetPostFullGC(object, slot, slotValue.GetTaggedObject()); 1744514f5e3Sopenharmony_ci break; 1754514f5e3Sopenharmony_ci case VerifyKind::VERIFY_PRE_SHARED_GC: 1764514f5e3Sopenharmony_ci case VerifyKind::VERIFY_POST_SHARED_GC: 1774514f5e3Sopenharmony_ci VerifySharedObjectReference(object, slot, slotValue.GetTaggedObject()); 1784514f5e3Sopenharmony_ci break; 1794514f5e3Sopenharmony_ci default: // LCOV_EXCL_START 1804514f5e3Sopenharmony_ci LOG_GC(FATAL) << "unknown verify kind:" << static_cast<size_t>(verifyKind_); 1814514f5e3Sopenharmony_ci UNREACHABLE(); // LCOV_EXCL_STOP 1824514f5e3Sopenharmony_ci } 1834514f5e3Sopenharmony_ci} 1844514f5e3Sopenharmony_ci 1854514f5e3Sopenharmony_civoid VerifyObjectVisitor::VerifyMarkEden(TaggedObject *object, ObjectSlot slot, TaggedObject *value) const 1864514f5e3Sopenharmony_ci{ 1874514f5e3Sopenharmony_ci Region *objectRegion = Region::ObjectAddressToRange(object); 1884514f5e3Sopenharmony_ci Region *valueRegion = Region::ObjectAddressToRange(value); 1894514f5e3Sopenharmony_ci JSTaggedValue value1(object); 1904514f5e3Sopenharmony_ci JSTaggedValue value2(value); 1914514f5e3Sopenharmony_ci if (objectRegion->InGeneralOldSpace() && valueRegion->InEdenSpace()) { // LCOV_EXCL_START 1924514f5e3Sopenharmony_ci if (!objectRegion->TestOldToNew(slot.SlotAddress())) { 1934514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify MarkEden: Old object, slot miss old_to_new bit.", object, slot, value); 1944514f5e3Sopenharmony_ci } else if (!valueRegion->Test(value)) { 1954514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify MarkEden: Old object, slot has old_to_new bit, miss gc_mark bit.", 1964514f5e3Sopenharmony_ci object, slot, value); 1974514f5e3Sopenharmony_ci } 1984514f5e3Sopenharmony_ci } 1994514f5e3Sopenharmony_ci 2004514f5e3Sopenharmony_ci if (objectRegion->InYoungSpace() && valueRegion->InEdenSpace()) { 2014514f5e3Sopenharmony_ci if (!objectRegion->TestNewToEden(slot.SlotAddress())) { 2024514f5e3Sopenharmony_ci value1.D(); 2034514f5e3Sopenharmony_ci value2.D(); 2044514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify MarkEden: Young object, slot miss new_to_eden bit.", object, slot, value); 2054514f5e3Sopenharmony_ci } else if (!valueRegion->Test(value)) { 2064514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify MarkEden: Young object, slot has new_to_eden bit, miss gc_mark bit.", 2074514f5e3Sopenharmony_ci object, slot, value); 2084514f5e3Sopenharmony_ci } 2094514f5e3Sopenharmony_ci } 2104514f5e3Sopenharmony_ci 2114514f5e3Sopenharmony_ci if (objectRegion->Test(object)) { 2124514f5e3Sopenharmony_ci if (!objectRegion->InEdenSpace() && !objectRegion->InAppSpawnSpace() 2134514f5e3Sopenharmony_ci && !objectRegion->InReadOnlySpace()) { 2144514f5e3Sopenharmony_ci LogErrorForObj(heap_, "Verify MarkYoung: Marked object, NOT in Eden Space", object); 2154514f5e3Sopenharmony_ci } 2164514f5e3Sopenharmony_ci if (valueRegion->InEdenSpace() && !valueRegion->Test(value)) { 2174514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify MarkEden: Marked object, slot in EdenSpace, miss gc_mark bit.", 2184514f5e3Sopenharmony_ci object, slot, value); 2194514f5e3Sopenharmony_ci } 2204514f5e3Sopenharmony_ci if (valueRegion->Test(value) && !(valueRegion->InEdenSpace() || valueRegion->InAppSpawnSpace() 2214514f5e3Sopenharmony_ci || valueRegion->InReadOnlySpace() || valueRegion->InSharedHeap())) { 2224514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify MarkEden: Marked object, slot marked, but NOT in Eden Space.", 2234514f5e3Sopenharmony_ci object, slot, value); 2244514f5e3Sopenharmony_ci } 2254514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 2264514f5e3Sopenharmony_ci} 2274514f5e3Sopenharmony_ci 2284514f5e3Sopenharmony_ci 2294514f5e3Sopenharmony_civoid VerifyObjectVisitor::VerifyMarkYoung(TaggedObject *object, ObjectSlot slot, TaggedObject *value) const 2304514f5e3Sopenharmony_ci{ 2314514f5e3Sopenharmony_ci Region *objectRegion = Region::ObjectAddressToRange(object); 2324514f5e3Sopenharmony_ci Region *valueRegion = Region::ObjectAddressToRange(value); 2334514f5e3Sopenharmony_ci ASSERT(!objectRegion->InSharedHeap()); 2344514f5e3Sopenharmony_ci if (objectRegion->InGeneralOldSpace() && valueRegion->InGeneralNewSpace()) { // LCOV_EXCL_START 2354514f5e3Sopenharmony_ci if (!objectRegion->TestOldToNew(slot.SlotAddress())) { 2364514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify MarkYoung: Old object, slot miss old_to_new bit.", object, slot, value); 2374514f5e3Sopenharmony_ci } else if (!valueRegion->Test(value)) { 2384514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify MarkYoung: Old object, slot has old_to_new bit, miss gc_mark bit.", 2394514f5e3Sopenharmony_ci object, slot, value); 2404514f5e3Sopenharmony_ci } 2414514f5e3Sopenharmony_ci } 2424514f5e3Sopenharmony_ci if (!objectRegion->InSharedHeap() && valueRegion->InSharedSweepableSpace()) { 2434514f5e3Sopenharmony_ci if (!objectRegion->TestLocalToShare(slot.SlotAddress())) { 2444514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify MarkYoung: Local object, slot local_to_share bit = 0, " 2454514f5e3Sopenharmony_ci "but SharedHeap object.", object, slot, value); 2464514f5e3Sopenharmony_ci } 2474514f5e3Sopenharmony_ci } 2484514f5e3Sopenharmony_ci if (objectRegion->Test(object)) { 2494514f5e3Sopenharmony_ci if (!objectRegion->InGeneralNewSpace() && !objectRegion->InAppSpawnSpace() && 2504514f5e3Sopenharmony_ci !objectRegion->InReadOnlySpace()) { 2514514f5e3Sopenharmony_ci LogErrorForObj(heap_, "Verify MarkYoung: Marked object, NOT in Young/AppSpawn/ReadOnly Space", object); 2524514f5e3Sopenharmony_ci } 2534514f5e3Sopenharmony_ci if (valueRegion->InGeneralNewSpace() && !valueRegion->Test(value)) { 2544514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify MarkYoung: Marked object, slot in YoungSpace, miss gc_mark bit.", 2554514f5e3Sopenharmony_ci object, slot, value); 2564514f5e3Sopenharmony_ci } 2574514f5e3Sopenharmony_ci if (valueRegion->Test(value) && 2584514f5e3Sopenharmony_ci !(valueRegion->InYoungSpace() || valueRegion->InAppSpawnSpace() || valueRegion->InReadOnlySpace() || 2594514f5e3Sopenharmony_ci valueRegion->InSharedHeap() || valueRegion->InEdenSpace())) { 2604514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify MarkYoung: Marked object, slot marked, but NOT in " 2614514f5e3Sopenharmony_ci "Young/AppSpawn/ReadOnly Space.", object, slot, value); 2624514f5e3Sopenharmony_ci } 2634514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 2644514f5e3Sopenharmony_ci} 2654514f5e3Sopenharmony_ci 2664514f5e3Sopenharmony_civoid VerifyObjectVisitor::VerifyEvacuateEden(TaggedObject *object, ObjectSlot slot, TaggedObject *value) const 2674514f5e3Sopenharmony_ci{ 2684514f5e3Sopenharmony_ci Region *objectRegion = Region::ObjectAddressToRange(object); 2694514f5e3Sopenharmony_ci Region *valueRegion = Region::ObjectAddressToRange(value); 2704514f5e3Sopenharmony_ci if (objectRegion->InGeneralOldSpace()) { // LCOV_EXCL_START 2714514f5e3Sopenharmony_ci if (objectRegion->TestOldToNew(slot.SlotAddress())) { 2724514f5e3Sopenharmony_ci if (!valueRegion->InActiveSemiSpace()) { 2734514f5e3Sopenharmony_ci if (valueRegion->InEdenSpace()) { 2744514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify EvacuateEden: Old object, slot old_to_new bit = 1, " 2754514f5e3Sopenharmony_ci "but in EdenSpace object.", object, slot, value); 2764514f5e3Sopenharmony_ci } 2774514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify EvacuateEden: Old object, slot old_to_new bit = 1, " 2784514f5e3Sopenharmony_ci "but NOT ActiveSpace(ToSpace) object.", object, slot, value); 2794514f5e3Sopenharmony_ci } 2804514f5e3Sopenharmony_ci } else { 2814514f5e3Sopenharmony_ci if (valueRegion->InGeneralNewSpace()) { 2824514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify EvacuateEden: Old object, slot old_to_new bit = 0, " 2834514f5e3Sopenharmony_ci "but YoungSpace object.", object, slot, value); 2844514f5e3Sopenharmony_ci } 2854514f5e3Sopenharmony_ci } 2864514f5e3Sopenharmony_ci } 2874514f5e3Sopenharmony_ci if (objectRegion->InYoungSpace()) { 2884514f5e3Sopenharmony_ci if (objectRegion->TestNewToEden(slot.SlotAddress())) { 2894514f5e3Sopenharmony_ci if (!valueRegion->InEdenSpace()) { 2904514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify EvacuateEden: Young object, slot young_to_eden bit = 1, " 2914514f5e3Sopenharmony_ci "but NOT Eden object.", object, slot, value); 2924514f5e3Sopenharmony_ci } else { 2934514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify EvacuateEden: Young object, slot young_to_eden bit = 1, " 2944514f5e3Sopenharmony_ci "but Eden object.", object, slot, value); 2954514f5e3Sopenharmony_ci } 2964514f5e3Sopenharmony_ci } else { 2974514f5e3Sopenharmony_ci if (valueRegion->InEdenSpace()) { 2984514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify EvacuateEden: Young object, slot young_to_eden bit = 0, " 2994514f5e3Sopenharmony_ci "but Eden object.", object, slot, value); 3004514f5e3Sopenharmony_ci } 3014514f5e3Sopenharmony_ci } 3024514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 3034514f5e3Sopenharmony_ci} 3044514f5e3Sopenharmony_ci 3054514f5e3Sopenharmony_civoid VerifyObjectVisitor::VerifyEvacuateYoung(TaggedObject *object, ObjectSlot slot, TaggedObject *value) const 3064514f5e3Sopenharmony_ci{ 3074514f5e3Sopenharmony_ci Region *objectRegion = Region::ObjectAddressToRange(object); 3084514f5e3Sopenharmony_ci Region *valueRegion = Region::ObjectAddressToRange(value); 3094514f5e3Sopenharmony_ci 3104514f5e3Sopenharmony_ci if (objectRegion->InGeneralOldSpace()) { // LCOV_EXCL_START 3114514f5e3Sopenharmony_ci if (objectRegion->TestOldToNew(slot.SlotAddress())) { 3124514f5e3Sopenharmony_ci if (!valueRegion->InActiveSemiSpace()) { 3134514f5e3Sopenharmony_ci if (valueRegion->InEdenSpace()) { 3144514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify EvacuateYoung: Old object, slot old_to_new bit = 1, " 3154514f5e3Sopenharmony_ci "but in EdenSpace object.", object, slot, value); 3164514f5e3Sopenharmony_ci } 3174514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify EvacuateYoung: Old object, slot old_to_new bit = 1, " 3184514f5e3Sopenharmony_ci "but NOT ActiveSpace(ToSpace) object.", object, slot, value); 3194514f5e3Sopenharmony_ci } 3204514f5e3Sopenharmony_ci } else { 3214514f5e3Sopenharmony_ci if (valueRegion->InGeneralNewSpace()) { 3224514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify EvacuateYoung: Old object, slot old_to_new bit = 0, " 3234514f5e3Sopenharmony_ci "but YoungSpace object.", object, slot, value); 3244514f5e3Sopenharmony_ci } 3254514f5e3Sopenharmony_ci } 3264514f5e3Sopenharmony_ci } 3274514f5e3Sopenharmony_ci if (!objectRegion->InSharedHeap() && valueRegion->InSharedSweepableSpace()) { 3284514f5e3Sopenharmony_ci if (!objectRegion->TestLocalToShare(slot.SlotAddress())) { 3294514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify EvacuateYoung: Local object, slot local_to_share bit = 0, " 3304514f5e3Sopenharmony_ci "but SharedHeap object.", object, slot, value); 3314514f5e3Sopenharmony_ci } 3324514f5e3Sopenharmony_ci } 3334514f5e3Sopenharmony_ci if (objectRegion->InActiveSemiSpace()) { 3344514f5e3Sopenharmony_ci if (valueRegion->InInactiveSemiSpace()) { 3354514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify EvacuateYoung: ActiveSpace object, slot in InactiveSpace(FromSpace).", 3364514f5e3Sopenharmony_ci object, slot, value); 3374514f5e3Sopenharmony_ci } else if (valueRegion->InEdenSpace()) { 3384514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify EvacuateYoung: ActiveSpace object, slot in EdenSpace.", 3394514f5e3Sopenharmony_ci object, slot, value); 3404514f5e3Sopenharmony_ci } 3414514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 3424514f5e3Sopenharmony_ci} 3434514f5e3Sopenharmony_ci 3444514f5e3Sopenharmony_civoid VerifyObjectVisitor::VerifyMarkFull(TaggedObject *object, ObjectSlot slot, TaggedObject *value) const 3454514f5e3Sopenharmony_ci{ 3464514f5e3Sopenharmony_ci Region *objectRegion = Region::ObjectAddressToRange(object); 3474514f5e3Sopenharmony_ci Region *valueRegion = Region::ObjectAddressToRange(value); 3484514f5e3Sopenharmony_ci if (objectRegion->InGeneralOldSpace() && valueRegion->InGeneralNewSpace()) { // LCOV_EXCL_START 3494514f5e3Sopenharmony_ci if (!objectRegion->TestOldToNew(slot.SlotAddress())) { 3504514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify MarkFull: Old object, slot miss old_to_new bit.", object, slot, value); 3514514f5e3Sopenharmony_ci } 3524514f5e3Sopenharmony_ci } 3534514f5e3Sopenharmony_ci if (objectRegion->Test(object)) { 3544514f5e3Sopenharmony_ci if (!valueRegion->InSharedHeap() && !valueRegion->Test(value)) { 3554514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify MarkFull: Marked object, slot miss gc_mark bit.", object, slot, value); 3564514f5e3Sopenharmony_ci } 3574514f5e3Sopenharmony_ci } 3584514f5e3Sopenharmony_ci if (!objectRegion->InSharedHeap() && valueRegion->InSharedSweepableSpace()) { 3594514f5e3Sopenharmony_ci if (!objectRegion->TestLocalToShare(slot.SlotAddress())) { 3604514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify VerifyMarkFull: Local object, slot local_to_share bit = 0, " 3614514f5e3Sopenharmony_ci "but SharedHeap object.", object, slot, value); 3624514f5e3Sopenharmony_ci } 3634514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 3644514f5e3Sopenharmony_ci} 3654514f5e3Sopenharmony_ci 3664514f5e3Sopenharmony_civoid VerifyObjectVisitor::VerifyEvacuateOld([[maybe_unused]]TaggedObject *root, 3674514f5e3Sopenharmony_ci [[maybe_unused]]ObjectSlot slot, 3684514f5e3Sopenharmony_ci [[maybe_unused]]TaggedObject *value) const 3694514f5e3Sopenharmony_ci{ 3704514f5e3Sopenharmony_ci VerifyEvacuateYoung(root, slot, value); 3714514f5e3Sopenharmony_ci} 3724514f5e3Sopenharmony_ci 3734514f5e3Sopenharmony_civoid VerifyObjectVisitor::VerifyEvacuateFull([[maybe_unused]]TaggedObject *root, 3744514f5e3Sopenharmony_ci [[maybe_unused]]ObjectSlot slot, 3754514f5e3Sopenharmony_ci [[maybe_unused]]TaggedObject *value) const 3764514f5e3Sopenharmony_ci{ 3774514f5e3Sopenharmony_ci VerifyEvacuateYoung(root, slot, value); 3784514f5e3Sopenharmony_ci} 3794514f5e3Sopenharmony_ci 3804514f5e3Sopenharmony_civoid VerifyObjectVisitor::VerifySharedObjectReference(TaggedObject *object, ObjectSlot slot, TaggedObject *value) const 3814514f5e3Sopenharmony_ci{ 3824514f5e3Sopenharmony_ci Region *objectRegion = Region::ObjectAddressToRange(object); 3834514f5e3Sopenharmony_ci Region *valueRegion = Region::ObjectAddressToRange(value); 3844514f5e3Sopenharmony_ci if (objectRegion->InSharedHeap()) { // LCOV_EXCL_START 3854514f5e3Sopenharmony_ci if (!valueRegion->InSharedHeap()) { 3864514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify SharedObjectReference: Shared object references a local object", 3874514f5e3Sopenharmony_ci object, slot, value); 3884514f5e3Sopenharmony_ci } 3894514f5e3Sopenharmony_ci } else if (valueRegion->InSharedSweepableSpace()) { 3904514f5e3Sopenharmony_ci if (!objectRegion->TestLocalToShare(slot.SlotAddress())) { 3914514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify SharedObjectReference: Local object, slot local_to_share bit = 0, " 3924514f5e3Sopenharmony_ci "but SharedHeap object.", object, slot, value); 3934514f5e3Sopenharmony_ci } 3944514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 3954514f5e3Sopenharmony_ci} 3964514f5e3Sopenharmony_ci 3974514f5e3Sopenharmony_civoid VerifyObjectVisitor::VerifySharedRSetPostFullGC(TaggedObject *object, ObjectSlot slot, TaggedObject *value) const 3984514f5e3Sopenharmony_ci{ 3994514f5e3Sopenharmony_ci Region *objectRegion = Region::ObjectAddressToRange(object); 4004514f5e3Sopenharmony_ci Region *valueRegion = Region::ObjectAddressToRange(value); 4014514f5e3Sopenharmony_ci if (!objectRegion->InSharedHeap() && valueRegion->InSharedSweepableSpace()) { // LCOV_EXCL_START 4024514f5e3Sopenharmony_ci if (!objectRegion->TestLocalToShare(slot.SlotAddress())) { 4034514f5e3Sopenharmony_ci LogErrorForObjSlot(heap_, "Verify SharedRSetPostFullGC: Local object, slot local_to_share bit = 0, " 4044514f5e3Sopenharmony_ci "but SharedHeap object.", object, slot, value); 4054514f5e3Sopenharmony_ci } 4064514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 4074514f5e3Sopenharmony_ci} 4084514f5e3Sopenharmony_ci 4094514f5e3Sopenharmony_civoid VerifyObjectVisitor::operator()(TaggedObject *obj, JSTaggedValue value) 4104514f5e3Sopenharmony_ci{ 4114514f5e3Sopenharmony_ci ObjectSlot slot(reinterpret_cast<uintptr_t>(obj)); 4124514f5e3Sopenharmony_ci if (!value.IsHeapObject()) { 4134514f5e3Sopenharmony_ci LOG_GC(DEBUG) << "Heap object(" << slot.SlotAddress() << ") old to new rset fail: value is " 4144514f5e3Sopenharmony_ci << slot.GetTaggedType(); 4154514f5e3Sopenharmony_ci return; 4164514f5e3Sopenharmony_ci } 4174514f5e3Sopenharmony_ci 4184514f5e3Sopenharmony_ci TaggedObject *object = value.GetRawTaggedObject(); 4194514f5e3Sopenharmony_ci auto region = Region::ObjectAddressToRange(object); 4204514f5e3Sopenharmony_ci if (region->InGeneralOldSpace()) { // LCOV_EXCL_START 4214514f5e3Sopenharmony_ci LOG_GC(ERROR) << "Heap object(" << slot.GetTaggedType() << ") old to new rset fail: value(" 4224514f5e3Sopenharmony_ci << slot.GetTaggedObject() << "/" 4234514f5e3Sopenharmony_ci << JSHClass::DumpJSType(slot.GetTaggedObject()->GetClass()->GetObjectType()) 4244514f5e3Sopenharmony_ci << ")" << " in " << region->GetSpaceTypeName(); 4254514f5e3Sopenharmony_ci ++(*failCount_); 4264514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 4274514f5e3Sopenharmony_ci} 4284514f5e3Sopenharmony_ci 4294514f5e3Sopenharmony_civoid Verification::VerifyAll() const 4304514f5e3Sopenharmony_ci{ 4314514f5e3Sopenharmony_ci [[maybe_unused]] VerifyScope verifyScope(heap_); 4324514f5e3Sopenharmony_ci heap_->GetSweeper()->EnsureAllTaskFinished(); 4334514f5e3Sopenharmony_ci size_t result = VerifyRoot(); 4344514f5e3Sopenharmony_ci result += VerifyHeap(); 4354514f5e3Sopenharmony_ci if (result > 0) { // LCOV_EXCL_START 4364514f5e3Sopenharmony_ci LOG_GC(FATAL) << "Verify (type=" << static_cast<uint8_t>(verifyKind_) 4374514f5e3Sopenharmony_ci << ") corrupted and " << result << " corruptions"; 4384514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 4394514f5e3Sopenharmony_ci} 4404514f5e3Sopenharmony_ci 4414514f5e3Sopenharmony_cisize_t Verification::VerifyRoot() const 4424514f5e3Sopenharmony_ci{ 4434514f5e3Sopenharmony_ci size_t failCount = 0; 4444514f5e3Sopenharmony_ci RootVisitor visitor = [this, &failCount]([[maybe_unused]] Root type, ObjectSlot slot) { 4454514f5e3Sopenharmony_ci JSTaggedValue value(slot.GetTaggedType()); 4464514f5e3Sopenharmony_ci // Skip verifying shared object in local gc verification. 4474514f5e3Sopenharmony_ci if (value.IsInSharedHeap()) { 4484514f5e3Sopenharmony_ci return; 4494514f5e3Sopenharmony_ci } 4504514f5e3Sopenharmony_ci VerifyObjectSlot(slot, &failCount); 4514514f5e3Sopenharmony_ci }; 4524514f5e3Sopenharmony_ci RootRangeVisitor rangeVisitor = [this, &failCount]([[maybe_unused]] Root type, ObjectSlot start, ObjectSlot end) { 4534514f5e3Sopenharmony_ci for (ObjectSlot slot = start; slot < end; slot++) { 4544514f5e3Sopenharmony_ci JSTaggedValue value(slot.GetTaggedType()); 4554514f5e3Sopenharmony_ci // Skip verifying shared object in local gc verification. 4564514f5e3Sopenharmony_ci if (value.IsInSharedHeap()) { 4574514f5e3Sopenharmony_ci return; 4584514f5e3Sopenharmony_ci } 4594514f5e3Sopenharmony_ci VerifyObjectSlot(slot, &failCount); 4604514f5e3Sopenharmony_ci } 4614514f5e3Sopenharmony_ci }; 4624514f5e3Sopenharmony_ci RootBaseAndDerivedVisitor derivedVisitor = 4634514f5e3Sopenharmony_ci []([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot base, [[maybe_unused]] ObjectSlot derived, 4644514f5e3Sopenharmony_ci [[maybe_unused]] uintptr_t baseOldObject) { 4654514f5e3Sopenharmony_ci }; 4664514f5e3Sopenharmony_ci ObjectXRay::VisitVMRoots(heap_->GetEcmaVM(), visitor, rangeVisitor, derivedVisitor, VMRootVisitType::VERIFY); 4674514f5e3Sopenharmony_ci if (failCount > 0) { 4684514f5e3Sopenharmony_ci LOG_GC(ERROR) << "VerifyRoot detects deadObject count is " << failCount; 4694514f5e3Sopenharmony_ci } 4704514f5e3Sopenharmony_ci 4714514f5e3Sopenharmony_ci return failCount; 4724514f5e3Sopenharmony_ci} 4734514f5e3Sopenharmony_ci 4744514f5e3Sopenharmony_cisize_t Verification::VerifyHeap() const 4754514f5e3Sopenharmony_ci{ 4764514f5e3Sopenharmony_ci size_t failCount = heap_->VerifyHeapObjects(verifyKind_); 4774514f5e3Sopenharmony_ci if (failCount > 0) { 4784514f5e3Sopenharmony_ci LOG_GC(ERROR) << "VerifyHeap detects deadObject count is " << failCount; 4794514f5e3Sopenharmony_ci } 4804514f5e3Sopenharmony_ci return failCount; 4814514f5e3Sopenharmony_ci} 4824514f5e3Sopenharmony_ci 4834514f5e3Sopenharmony_cisize_t Verification::VerifyOldToNewRSet() const 4844514f5e3Sopenharmony_ci{ 4854514f5e3Sopenharmony_ci size_t failCount = heap_->VerifyOldToNewRSet(verifyKind_); 4864514f5e3Sopenharmony_ci if (failCount > 0) { 4874514f5e3Sopenharmony_ci LOG_GC(ERROR) << "VerifyOldToNewRSet detects non new space count is " << failCount; 4884514f5e3Sopenharmony_ci } 4894514f5e3Sopenharmony_ci return failCount; 4904514f5e3Sopenharmony_ci} 4914514f5e3Sopenharmony_ci 4924514f5e3Sopenharmony_civoid Verification::VerifyObjectSlot(const ObjectSlot &slot, size_t *failCount) const 4934514f5e3Sopenharmony_ci{ 4944514f5e3Sopenharmony_ci JSTaggedValue value(slot.GetTaggedType()); 4954514f5e3Sopenharmony_ci if (value.IsWeak()) { 4964514f5e3Sopenharmony_ci VerifyObjectVisitor(heap_, failCount, verifyKind_)(value.GetTaggedWeakRef()); 4974514f5e3Sopenharmony_ci } else if (value.IsHeapObject()) { 4984514f5e3Sopenharmony_ci VerifyObjectVisitor(heap_, failCount, verifyKind_)(value.GetTaggedObject()); 4994514f5e3Sopenharmony_ci } 5004514f5e3Sopenharmony_ci} 5014514f5e3Sopenharmony_ci 5024514f5e3Sopenharmony_civoid Verification::VerifyMark(Heap *heap) 5034514f5e3Sopenharmony_ci{ 5044514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "start verify mark"; 5054514f5e3Sopenharmony_ci switch (heap->GetMarkType()) { 5064514f5e3Sopenharmony_ci case MarkType::MARK_EDEN: 5074514f5e3Sopenharmony_ci Verification(heap, VerifyKind::VERIFY_MARK_EDEN).VerifyAll(); 5084514f5e3Sopenharmony_ci break; 5094514f5e3Sopenharmony_ci case MarkType::MARK_YOUNG: 5104514f5e3Sopenharmony_ci Verification(heap, VerifyKind::VERIFY_MARK_YOUNG).VerifyAll(); 5114514f5e3Sopenharmony_ci break; 5124514f5e3Sopenharmony_ci case MarkType::MARK_FULL: 5134514f5e3Sopenharmony_ci Verification(heap, VerifyKind::VERIFY_MARK_FULL).VerifyAll(); 5144514f5e3Sopenharmony_ci break; 5154514f5e3Sopenharmony_ci } 5164514f5e3Sopenharmony_ci} 5174514f5e3Sopenharmony_ci 5184514f5e3Sopenharmony_civoid Verification::VerifyEvacuate(Heap *heap) 5194514f5e3Sopenharmony_ci{ 5204514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "start verify evacuate and sweep"; 5214514f5e3Sopenharmony_ci switch (heap->GetMarkType()) { 5224514f5e3Sopenharmony_ci case MarkType::MARK_EDEN: 5234514f5e3Sopenharmony_ci Verification(heap, VerifyKind::VERIFY_EVACUATE_EDEN).VerifyAll(); 5244514f5e3Sopenharmony_ci break; 5254514f5e3Sopenharmony_ci case MarkType::MARK_YOUNG: 5264514f5e3Sopenharmony_ci Verification(heap, VerifyKind::VERIFY_EVACUATE_YOUNG).VerifyAll(); 5274514f5e3Sopenharmony_ci break; 5284514f5e3Sopenharmony_ci case MarkType::MARK_FULL: 5294514f5e3Sopenharmony_ci Verification(heap, VerifyKind::VERIFY_EVACUATE_OLD).VerifyAll(); 5304514f5e3Sopenharmony_ci break; 5314514f5e3Sopenharmony_ci } 5324514f5e3Sopenharmony_ci} 5334514f5e3Sopenharmony_ci 5344514f5e3Sopenharmony_civoid SharedHeapVerification::VerifyAll() const 5354514f5e3Sopenharmony_ci{ 5364514f5e3Sopenharmony_ci [[maybe_unused]] VerifyScope verifyScope(sHeap_); 5374514f5e3Sopenharmony_ci sHeap_->GetSweeper()->EnsureAllTaskFinished(); 5384514f5e3Sopenharmony_ci size_t result = VerifyRoot(); 5394514f5e3Sopenharmony_ci result += VerifyHeap(); 5404514f5e3Sopenharmony_ci if (result > 0) { // LCOV_EXCL_START 5414514f5e3Sopenharmony_ci LOG_GC(FATAL) << "Verify (type=" << static_cast<uint8_t>(verifyKind_) 5424514f5e3Sopenharmony_ci << ") corrupted and " << result << " corruptions"; 5434514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 5444514f5e3Sopenharmony_ci} 5454514f5e3Sopenharmony_ci 5464514f5e3Sopenharmony_civoid SharedHeapVerification::VerifyMark(bool cm) const 5474514f5e3Sopenharmony_ci{ 5484514f5e3Sopenharmony_ci LOG_GC(DEBUG) << "start verify shared mark"; 5494514f5e3Sopenharmony_ci [[maybe_unused]] VerifyScope verifyScope(sHeap_); 5504514f5e3Sopenharmony_ci sHeap_->GetSweeper()->EnsureAllTaskFinished(); 5514514f5e3Sopenharmony_ci Runtime::GetInstance()->GCIterateThreadList([cm](JSThread *thread) { 5524514f5e3Sopenharmony_ci auto vm = thread->GetEcmaVM(); 5534514f5e3Sopenharmony_ci auto heap = vm->GetHeap(); 5544514f5e3Sopenharmony_ci heap->GetSweeper()->EnsureAllTaskFinished(); 5554514f5e3Sopenharmony_ci const_cast<Heap*>(heap)->FillBumpPointerForTlab(); 5564514f5e3Sopenharmony_ci auto localBuffer = const_cast<Heap*>(heap)->GetMarkingObjectLocalBuffer(); 5574514f5e3Sopenharmony_ci if (localBuffer != nullptr) { // LCOV_EXCL_START 5584514f5e3Sopenharmony_ci LOG_GC(FATAL) << "verify shared node not null " << cm << ':' << thread; 5594514f5e3Sopenharmony_ci UNREACHABLE(); 5604514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 5614514f5e3Sopenharmony_ci heap->IterateOverObjects([cm](TaggedObject *obj) { 5624514f5e3Sopenharmony_ci auto jsHclass = obj->GetClass(); 5634514f5e3Sopenharmony_ci auto f = [cm] (ObjectSlot slot, TaggedObject *obj) { 5644514f5e3Sopenharmony_ci Region *objectRegion = Region::ObjectAddressToRange(obj); 5654514f5e3Sopenharmony_ci JSTaggedValue value(slot.GetTaggedType()); 5664514f5e3Sopenharmony_ci if (value.IsWeak() || !value.IsHeapObject()) { 5674514f5e3Sopenharmony_ci return; 5684514f5e3Sopenharmony_ci } 5694514f5e3Sopenharmony_ci Region *valueRegion = Region::ObjectAddressToRange(value.GetTaggedObject()); 5704514f5e3Sopenharmony_ci if (!valueRegion->InSharedSweepableSpace()) { 5714514f5e3Sopenharmony_ci return; 5724514f5e3Sopenharmony_ci } 5734514f5e3Sopenharmony_ci if (!objectRegion->TestLocalToShare(slot.SlotAddress())) { // LCOV_EXCL_START 5744514f5e3Sopenharmony_ci LOG_GC(FATAL) << "verify shared1 " << cm << ':' << slot.SlotAddress() 5754514f5e3Sopenharmony_ci << ' ' << value.GetTaggedObject(); 5764514f5e3Sopenharmony_ci UNREACHABLE(); 5774514f5e3Sopenharmony_ci } 5784514f5e3Sopenharmony_ci if (!valueRegion->Test(value.GetTaggedObject())) { 5794514f5e3Sopenharmony_ci LOG_GC(FATAL) << "verify shared2 " << cm << ':' << slot.SlotAddress() 5804514f5e3Sopenharmony_ci << ' ' << value.GetTaggedObject(); 5814514f5e3Sopenharmony_ci UNREACHABLE(); 5824514f5e3Sopenharmony_ci } 5834514f5e3Sopenharmony_ci if (value.GetTaggedObject()->GetClass()->IsFreeObject()) { 5844514f5e3Sopenharmony_ci LOG_GC(FATAL) << "verify shared3 " << cm << ':' << slot.SlotAddress() 5854514f5e3Sopenharmony_ci << ' ' << value.GetTaggedObject(); 5864514f5e3Sopenharmony_ci UNREACHABLE(); 5874514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 5884514f5e3Sopenharmony_ci }; 5894514f5e3Sopenharmony_ci ObjectXRay::VisitObjectBody<VisitType::OLD_GC_VISIT>( 5904514f5e3Sopenharmony_ci obj, jsHclass, [f](TaggedObject *root, ObjectSlot start, ObjectSlot end, 5914514f5e3Sopenharmony_ci VisitObjectArea area) { 5924514f5e3Sopenharmony_ci if (area == VisitObjectArea::IN_OBJECT) { 5934514f5e3Sopenharmony_ci auto hclass = root->GetClass(); 5944514f5e3Sopenharmony_ci ASSERT(!hclass->IsAllTaggedProp()); 5954514f5e3Sopenharmony_ci int index = 0; 5964514f5e3Sopenharmony_ci for (ObjectSlot slot = start; slot < end; slot++) { 5974514f5e3Sopenharmony_ci auto layout = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject()); 5984514f5e3Sopenharmony_ci auto attr = layout->GetAttr(index++); 5994514f5e3Sopenharmony_ci if (attr.IsTaggedRep()) { 6004514f5e3Sopenharmony_ci f(slot, root); 6014514f5e3Sopenharmony_ci } 6024514f5e3Sopenharmony_ci } 6034514f5e3Sopenharmony_ci return; 6044514f5e3Sopenharmony_ci } 6054514f5e3Sopenharmony_ci for (ObjectSlot slot = start; slot < end; slot++) { 6064514f5e3Sopenharmony_ci f(slot, root); 6074514f5e3Sopenharmony_ci } 6084514f5e3Sopenharmony_ci }); 6094514f5e3Sopenharmony_ci }); 6104514f5e3Sopenharmony_ci }); 6114514f5e3Sopenharmony_ci sHeap_->IterateOverObjects([cm](TaggedObject *obj) { 6124514f5e3Sopenharmony_ci auto jsHclass = obj->GetClass(); 6134514f5e3Sopenharmony_ci auto f = [cm] (ObjectSlot slot, TaggedObject *obj) { 6144514f5e3Sopenharmony_ci Region *objectRegion = Region::ObjectAddressToRange(obj); 6154514f5e3Sopenharmony_ci if (!objectRegion->Test(obj)) { 6164514f5e3Sopenharmony_ci return; 6174514f5e3Sopenharmony_ci } 6184514f5e3Sopenharmony_ci JSTaggedValue value(slot.GetTaggedType()); 6194514f5e3Sopenharmony_ci if (value.IsWeak() || !value.IsHeapObject()) { 6204514f5e3Sopenharmony_ci return; 6214514f5e3Sopenharmony_ci } 6224514f5e3Sopenharmony_ci [[maybe_unused]] Region *valueRegion = Region::ObjectAddressToRange(value.GetTaggedObject()); 6234514f5e3Sopenharmony_ci if (!valueRegion->InSharedHeap()) { // LCOV_EXCL_START 6244514f5e3Sopenharmony_ci LOG_GC(FATAL) << "verify shared4 " << cm << ':' << slot.SlotAddress() 6254514f5e3Sopenharmony_ci << ' ' << value.GetTaggedObject(); 6264514f5e3Sopenharmony_ci UNREACHABLE(); 6274514f5e3Sopenharmony_ci } 6284514f5e3Sopenharmony_ci if (!valueRegion->InSharedReadOnlySpace() 6294514f5e3Sopenharmony_ci && !valueRegion->Test(value.GetTaggedObject())) { 6304514f5e3Sopenharmony_ci LOG_GC(FATAL) << "verify shared5 " << cm << ':' << slot.SlotAddress() 6314514f5e3Sopenharmony_ci << ' ' << value.GetTaggedObject(); 6324514f5e3Sopenharmony_ci UNREACHABLE(); 6334514f5e3Sopenharmony_ci } 6344514f5e3Sopenharmony_ci if (value.GetTaggedObject()->GetClass()->IsFreeObject()) { 6354514f5e3Sopenharmony_ci LOG_GC(FATAL) << "verify shared6 " << cm << ':' << slot.SlotAddress() 6364514f5e3Sopenharmony_ci << ' ' << value.GetTaggedObject(); 6374514f5e3Sopenharmony_ci UNREACHABLE(); 6384514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 6394514f5e3Sopenharmony_ci }; 6404514f5e3Sopenharmony_ci ObjectXRay::VisitObjectBody<VisitType::OLD_GC_VISIT>( 6414514f5e3Sopenharmony_ci obj, jsHclass, [f](TaggedObject *root, ObjectSlot start, ObjectSlot end, 6424514f5e3Sopenharmony_ci VisitObjectArea area) { 6434514f5e3Sopenharmony_ci if (area == VisitObjectArea::IN_OBJECT) { 6444514f5e3Sopenharmony_ci auto hclass = root->GetClass(); 6454514f5e3Sopenharmony_ci ASSERT(!hclass->IsAllTaggedProp()); 6464514f5e3Sopenharmony_ci int index = 0; 6474514f5e3Sopenharmony_ci for (ObjectSlot slot = start; slot < end; slot++) { 6484514f5e3Sopenharmony_ci auto layout = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject()); 6494514f5e3Sopenharmony_ci auto attr = layout->GetAttr(index++); 6504514f5e3Sopenharmony_ci if (attr.IsTaggedRep()) { 6514514f5e3Sopenharmony_ci f(slot, root); 6524514f5e3Sopenharmony_ci } 6534514f5e3Sopenharmony_ci } 6544514f5e3Sopenharmony_ci return; 6554514f5e3Sopenharmony_ci } 6564514f5e3Sopenharmony_ci for (ObjectSlot slot = start; slot < end; slot++) { 6574514f5e3Sopenharmony_ci f(slot, root); 6584514f5e3Sopenharmony_ci } 6594514f5e3Sopenharmony_ci }); 6604514f5e3Sopenharmony_ci }); 6614514f5e3Sopenharmony_ci} 6624514f5e3Sopenharmony_ci 6634514f5e3Sopenharmony_civoid SharedHeapVerification::VerifySweep(bool cm) const 6644514f5e3Sopenharmony_ci{ 6654514f5e3Sopenharmony_ci LOG_GC(DEBUG) << "start verify shared sweep"; 6664514f5e3Sopenharmony_ci [[maybe_unused]] VerifyScope verifyScope(sHeap_); 6674514f5e3Sopenharmony_ci sHeap_->GetSweeper()->EnsureAllTaskFinished(); 6684514f5e3Sopenharmony_ci Runtime::GetInstance()->GCIterateThreadList([cm](JSThread *thread) { 6694514f5e3Sopenharmony_ci auto vm = thread->GetEcmaVM(); 6704514f5e3Sopenharmony_ci auto heap = vm->GetHeap(); 6714514f5e3Sopenharmony_ci heap->GetSweeper()->EnsureAllTaskFinished(); 6724514f5e3Sopenharmony_ci const_cast<Heap*>(heap)->FillBumpPointerForTlab(); 6734514f5e3Sopenharmony_ci heap->IterateOverObjects([cm](TaggedObject *obj) { 6744514f5e3Sopenharmony_ci auto jsHclass = obj->GetClass(); 6754514f5e3Sopenharmony_ci auto f = [cm] (ObjectSlot slot, TaggedObject *obj) { 6764514f5e3Sopenharmony_ci Region *objectRegion = Region::ObjectAddressToRange(obj); 6774514f5e3Sopenharmony_ci JSTaggedValue value(slot.GetTaggedType()); 6784514f5e3Sopenharmony_ci if (value.IsWeak() || !value.IsHeapObject()) { 6794514f5e3Sopenharmony_ci return; 6804514f5e3Sopenharmony_ci } 6814514f5e3Sopenharmony_ci Region *valueRegion = Region::ObjectAddressToRange(value.GetTaggedObject()); 6824514f5e3Sopenharmony_ci if (!valueRegion->InSharedSweepableSpace()) { 6834514f5e3Sopenharmony_ci return; 6844514f5e3Sopenharmony_ci } 6854514f5e3Sopenharmony_ci if (!objectRegion->TestLocalToShare(slot.SlotAddress())) { // LCOV_EXCL_START 6864514f5e3Sopenharmony_ci LOG_GC(FATAL) << "verify shared7 " << cm << ':' << slot.SlotAddress() 6874514f5e3Sopenharmony_ci << ' ' << value.GetTaggedObject(); 6884514f5e3Sopenharmony_ci UNREACHABLE(); 6894514f5e3Sopenharmony_ci } 6904514f5e3Sopenharmony_ci if (!valueRegion->Test(value.GetTaggedObject())) { 6914514f5e3Sopenharmony_ci LOG_GC(FATAL) << "verify shared8 " << cm << ':' << slot.SlotAddress() 6924514f5e3Sopenharmony_ci << ' ' << value.GetTaggedObject(); 6934514f5e3Sopenharmony_ci UNREACHABLE(); 6944514f5e3Sopenharmony_ci } 6954514f5e3Sopenharmony_ci if (value.GetTaggedObject()->GetClass()->IsFreeObject()) { 6964514f5e3Sopenharmony_ci LOG_GC(FATAL) << "verify shared9 " << cm << ':' << slot.SlotAddress() 6974514f5e3Sopenharmony_ci << ' ' << value.GetTaggedObject(); 6984514f5e3Sopenharmony_ci UNREACHABLE(); 6994514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 7004514f5e3Sopenharmony_ci }; 7014514f5e3Sopenharmony_ci ObjectXRay::VisitObjectBody<VisitType::OLD_GC_VISIT>( 7024514f5e3Sopenharmony_ci obj, jsHclass, [f](TaggedObject *root, ObjectSlot start, ObjectSlot end, 7034514f5e3Sopenharmony_ci VisitObjectArea area) { 7044514f5e3Sopenharmony_ci if (area == VisitObjectArea::IN_OBJECT) { 7054514f5e3Sopenharmony_ci auto hclass = root->GetClass(); 7064514f5e3Sopenharmony_ci ASSERT(!hclass->IsAllTaggedProp()); 7074514f5e3Sopenharmony_ci int index = 0; 7084514f5e3Sopenharmony_ci for (ObjectSlot slot = start; slot < end; slot++) { 7094514f5e3Sopenharmony_ci auto layout = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject()); 7104514f5e3Sopenharmony_ci auto attr = layout->GetAttr(index++); 7114514f5e3Sopenharmony_ci if (attr.IsTaggedRep()) { 7124514f5e3Sopenharmony_ci f(slot, root); 7134514f5e3Sopenharmony_ci } 7144514f5e3Sopenharmony_ci } 7154514f5e3Sopenharmony_ci return; 7164514f5e3Sopenharmony_ci } 7174514f5e3Sopenharmony_ci for (ObjectSlot slot = start; slot < end; slot++) { 7184514f5e3Sopenharmony_ci f(slot, root); 7194514f5e3Sopenharmony_ci } 7204514f5e3Sopenharmony_ci }); 7214514f5e3Sopenharmony_ci }); 7224514f5e3Sopenharmony_ci }); 7234514f5e3Sopenharmony_ci sHeap_->IterateOverObjects([cm](TaggedObject *obj) { 7244514f5e3Sopenharmony_ci auto jsHclass = obj->GetClass(); 7254514f5e3Sopenharmony_ci auto f = [cm] (ObjectSlot slot, TaggedObject *obj) { 7264514f5e3Sopenharmony_ci [[maybe_unused]] Region *objectRegion = Region::ObjectAddressToRange(obj); 7274514f5e3Sopenharmony_ci if (!objectRegion->Test(obj)) { // LCOV_EXCL_START 7284514f5e3Sopenharmony_ci LOG_GC(FATAL) << "verify shared10 " << cm << ':' << obj; 7294514f5e3Sopenharmony_ci UNREACHABLE(); 7304514f5e3Sopenharmony_ci } 7314514f5e3Sopenharmony_ci JSTaggedValue value(slot.GetTaggedType()); 7324514f5e3Sopenharmony_ci if (value.IsWeak() || !value.IsHeapObject()) { 7334514f5e3Sopenharmony_ci return; 7344514f5e3Sopenharmony_ci } 7354514f5e3Sopenharmony_ci [[maybe_unused]] Region *valueRegion = Region::ObjectAddressToRange(value.GetTaggedObject()); 7364514f5e3Sopenharmony_ci if (!valueRegion->InSharedHeap()) { 7374514f5e3Sopenharmony_ci LOG_GC(FATAL) << "verify shared11 " << cm << ':' << slot.SlotAddress() 7384514f5e3Sopenharmony_ci << ' ' << value.GetTaggedObject(); 7394514f5e3Sopenharmony_ci UNREACHABLE(); 7404514f5e3Sopenharmony_ci } 7414514f5e3Sopenharmony_ci if (!valueRegion->InSharedReadOnlySpace() 7424514f5e3Sopenharmony_ci && !valueRegion->Test(value.GetTaggedObject())) { 7434514f5e3Sopenharmony_ci LOG_GC(FATAL) << "verify shared12 " << cm << ':' << slot.SlotAddress() 7444514f5e3Sopenharmony_ci << ' ' << value.GetTaggedObject(); 7454514f5e3Sopenharmony_ci UNREACHABLE(); 7464514f5e3Sopenharmony_ci } 7474514f5e3Sopenharmony_ci if (value.GetTaggedObject()->GetClass()->IsFreeObject()) { 7484514f5e3Sopenharmony_ci LOG_GC(FATAL) << "verify shared13 " << cm << ':' << slot.SlotAddress() 7494514f5e3Sopenharmony_ci << ' ' << value.GetTaggedObject(); 7504514f5e3Sopenharmony_ci UNREACHABLE(); 7514514f5e3Sopenharmony_ci } // LCOV_EXCL_STOP 7524514f5e3Sopenharmony_ci }; 7534514f5e3Sopenharmony_ci ObjectXRay::VisitObjectBody<VisitType::OLD_GC_VISIT>( 7544514f5e3Sopenharmony_ci obj, jsHclass, [f](TaggedObject *root, ObjectSlot start, ObjectSlot end, 7554514f5e3Sopenharmony_ci VisitObjectArea area) { 7564514f5e3Sopenharmony_ci if (area == VisitObjectArea::IN_OBJECT) { 7574514f5e3Sopenharmony_ci auto hclass = root->GetClass(); 7584514f5e3Sopenharmony_ci ASSERT(!hclass->IsAllTaggedProp()); 7594514f5e3Sopenharmony_ci int index = 0; 7604514f5e3Sopenharmony_ci for (ObjectSlot slot = start; slot < end; slot++) { 7614514f5e3Sopenharmony_ci auto layout = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject()); 7624514f5e3Sopenharmony_ci auto attr = layout->GetAttr(index++); 7634514f5e3Sopenharmony_ci if (attr.IsTaggedRep()) { 7644514f5e3Sopenharmony_ci f(slot, root); 7654514f5e3Sopenharmony_ci } 7664514f5e3Sopenharmony_ci } 7674514f5e3Sopenharmony_ci return; 7684514f5e3Sopenharmony_ci } 7694514f5e3Sopenharmony_ci for (ObjectSlot slot = start; slot < end; slot++) { 7704514f5e3Sopenharmony_ci f(slot, root); 7714514f5e3Sopenharmony_ci } 7724514f5e3Sopenharmony_ci }); 7734514f5e3Sopenharmony_ci }); 7744514f5e3Sopenharmony_ci} 7754514f5e3Sopenharmony_ci 7764514f5e3Sopenharmony_cisize_t SharedHeapVerification::VerifyRoot() const 7774514f5e3Sopenharmony_ci{ 7784514f5e3Sopenharmony_ci size_t failCount = 0; 7794514f5e3Sopenharmony_ci RootVisitor visitor = [this, &failCount]([[maybe_unused]] Root type, ObjectSlot slot) { 7804514f5e3Sopenharmony_ci VerifyObjectSlot(slot, &failCount); 7814514f5e3Sopenharmony_ci }; 7824514f5e3Sopenharmony_ci RootRangeVisitor rangeVisitor = [this, &failCount]([[maybe_unused]] Root type, ObjectSlot start, ObjectSlot end) { 7834514f5e3Sopenharmony_ci for (ObjectSlot slot = start; slot < end; slot++) { 7844514f5e3Sopenharmony_ci VerifyObjectSlot(slot, &failCount); 7854514f5e3Sopenharmony_ci } 7864514f5e3Sopenharmony_ci }; 7874514f5e3Sopenharmony_ci RootBaseAndDerivedVisitor derivedVisitor = 7884514f5e3Sopenharmony_ci []([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot base, [[maybe_unused]] ObjectSlot derived, 7894514f5e3Sopenharmony_ci [[maybe_unused]] uintptr_t baseOldObject) { 7904514f5e3Sopenharmony_ci }; 7914514f5e3Sopenharmony_ci RootVisitor serializeVisitor = [this, &failCount]([[maybe_unused]] Root type, ObjectSlot slot) { 7924514f5e3Sopenharmony_ci JSTaggedValue value(slot.GetTaggedType()); 7934514f5e3Sopenharmony_ci if (!sHeap_->IsAlive(value.GetTaggedObject())) { 7944514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "Serialize Heap verify detected a dead object. " << value.GetTaggedObject(); 7954514f5e3Sopenharmony_ci ++failCount; 7964514f5e3Sopenharmony_ci } 7974514f5e3Sopenharmony_ci }; 7984514f5e3Sopenharmony_ci Runtime::GetInstance()->IterateSerializeRoot(serializeVisitor); 7994514f5e3Sopenharmony_ci Runtime::GetInstance()->GCIterateThreadList([&](JSThread *thread) { 8004514f5e3Sopenharmony_ci ASSERT(!thread->IsInRunningState()); 8014514f5e3Sopenharmony_ci auto vm = thread->GetEcmaVM(); 8024514f5e3Sopenharmony_ci auto localHeap = const_cast<Heap*>(vm->GetHeap()); 8034514f5e3Sopenharmony_ci localHeap->GetSweeper()->EnsureAllTaskFinished(); 8044514f5e3Sopenharmony_ci ObjectXRay::VisitVMRoots(vm, visitor, rangeVisitor, derivedVisitor, VMRootVisitType::VERIFY); 8054514f5e3Sopenharmony_ci if (failCount > 0) { 8064514f5e3Sopenharmony_ci LOG_GC(ERROR) << "SharedHeap VerifyRoot detects deadObject count is " << failCount; 8074514f5e3Sopenharmony_ci } 8084514f5e3Sopenharmony_ci }); 8094514f5e3Sopenharmony_ci return failCount; 8104514f5e3Sopenharmony_ci} 8114514f5e3Sopenharmony_ci 8124514f5e3Sopenharmony_cisize_t SharedHeapVerification::VerifyHeap() const 8134514f5e3Sopenharmony_ci{ 8144514f5e3Sopenharmony_ci Runtime::GetInstance()->GCIterateThreadList([&](JSThread *thread) { 8154514f5e3Sopenharmony_ci ASSERT(!thread->IsInRunningState()); 8164514f5e3Sopenharmony_ci const_cast<Heap*>(thread->GetEcmaVM()->GetHeap())->FillBumpPointerForTlab(); 8174514f5e3Sopenharmony_ci }); 8184514f5e3Sopenharmony_ci size_t failCount = sHeap_->VerifyHeapObjects(verifyKind_); 8194514f5e3Sopenharmony_ci if (failCount > 0) { 8204514f5e3Sopenharmony_ci LOG_GC(ERROR) << "SharedHeap VerifyHeap detects deadObject count is " << failCount; 8214514f5e3Sopenharmony_ci } 8224514f5e3Sopenharmony_ci VerifyKind localVerifyKind = VerifyKind::VERIFY_END; 8234514f5e3Sopenharmony_ci if (verifyKind_ == VerifyKind::VERIFY_PRE_SHARED_GC) { 8244514f5e3Sopenharmony_ci localVerifyKind = VerifyKind::VERIFY_PRE_GC; 8254514f5e3Sopenharmony_ci } else if (verifyKind_ == VerifyKind::VERIFY_POST_SHARED_GC) { 8264514f5e3Sopenharmony_ci localVerifyKind = VerifyKind::VERIFY_POST_GC; 8274514f5e3Sopenharmony_ci } 8284514f5e3Sopenharmony_ci 8294514f5e3Sopenharmony_ci Runtime::GetInstance()->GCIterateThreadList([&, localVerifyKind](JSThread *thread) { 8304514f5e3Sopenharmony_ci ASSERT(!thread->IsInRunningState()); 8314514f5e3Sopenharmony_ci auto vm = thread->GetEcmaVM(); 8324514f5e3Sopenharmony_ci auto localHeap = const_cast<Heap*>(vm->GetHeap()); 8334514f5e3Sopenharmony_ci localHeap->GetSweeper()->EnsureAllTaskFinished(); 8344514f5e3Sopenharmony_ci if (localVerifyKind != VerifyKind::VERIFY_END) { 8354514f5e3Sopenharmony_ci Verification(localHeap, localVerifyKind).VerifyAll(); 8364514f5e3Sopenharmony_ci } 8374514f5e3Sopenharmony_ci if (failCount > 0) { 8384514f5e3Sopenharmony_ci LOG_GC(ERROR) << "SharedHeap VerifyRoot detects deadObject in local heap count is " << failCount; 8394514f5e3Sopenharmony_ci } 8404514f5e3Sopenharmony_ci }); 8414514f5e3Sopenharmony_ci return failCount; 8424514f5e3Sopenharmony_ci} 8434514f5e3Sopenharmony_ci 8444514f5e3Sopenharmony_civoid SharedHeapVerification::VerifyObjectSlot(const ObjectSlot &slot, size_t *failCount) const 8454514f5e3Sopenharmony_ci{ 8464514f5e3Sopenharmony_ci JSTaggedValue value(slot.GetTaggedType()); 8474514f5e3Sopenharmony_ci if (value.IsWeak()) { 8484514f5e3Sopenharmony_ci VerifyObjectVisitor(sHeap_, failCount, verifyKind_)(value.GetTaggedWeakRef()); 8494514f5e3Sopenharmony_ci } else if (value.IsHeapObject()) { 8504514f5e3Sopenharmony_ci VerifyObjectVisitor(sHeap_, failCount, verifyKind_)(value.GetTaggedObject()); 8514514f5e3Sopenharmony_ci } 8524514f5e3Sopenharmony_ci} 8534514f5e3Sopenharmony_ci} // namespace panda::ecmascript 854