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 #ifndef ECMASCRIPT_MEM_HEAP_VERIFICATION_H 17 #define ECMASCRIPT_MEM_HEAP_VERIFICATION_H 18 19 #include <cstdint> 20 21 #include "ecmascript/cross_vm/verification_hybrid.h" 22 #include "ecmascript/js_tagged_value.h" 23 #include "ecmascript/mem/heap.h" 24 #include "ecmascript/mem/object_xray.h" 25 #include "ecmascript/mem/mem.h" 26 #include "ecmascript/mem/slots.h" 27 28 namespace panda::ecmascript { 29 static constexpr uint32_t INVALID_THRESHOLD = 0x40000; 30 31 class VerifyScope { 32 public: VerifyScope(BaseHeap * heap)33 VerifyScope(BaseHeap *heap) : heap_(heap) 34 { 35 heap_->SetVerifying(true); 36 } 37 ~VerifyScope()38 ~VerifyScope() 39 { 40 heap_->SetVerifying(false); 41 } 42 private: 43 BaseHeap *heap_ {nullptr}; 44 }; 45 46 // Verify the object body 47 // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions, hicpp-special-member-functions) 48 class VerifyObjectVisitor { 49 public: 50 // Only used for verify InactiveSemiSpace 51 static void VerifyInactiveSemiSpaceMarkedObject(const BaseHeap *heap, void *addr); 52 53 VerifyObjectVisitor(const BaseHeap *heap, size_t *failCount, 54 VerifyKind verifyKind = VerifyKind::VERIFY_PRE_GC) heap_(heap)55 : heap_(heap), failCount_(failCount), verifyKind_(verifyKind) 56 { 57 } 58 ~VerifyObjectVisitor() = default; 59 operator()60 void operator()(TaggedObject *obj) 61 { 62 VisitAllObjects(obj); 63 } 64 65 void operator()(TaggedObject *obj, JSTaggedValue value); 66 GetFailedCount()67 size_t GetFailedCount() const 68 { 69 return *failCount_; 70 } 71 72 private: 73 VERIFYOBJECTVISITOR_PRIVATE_HYBRID_EXTENSION(); 74 void VisitAllObjects(TaggedObject *obj); 75 void VerifyObjectSlotLegal(ObjectSlot slot, TaggedObject *obj) const; 76 void VerifyHeapObjectSlotLegal(ObjectSlot slot, JSTaggedValue value, TaggedObject *obj) const; 77 void VerifyMarkYoung(TaggedObject *obj, ObjectSlot slot, TaggedObject *value) const; 78 void VerifyEvacuateYoung(TaggedObject *obj, ObjectSlot slot, TaggedObject *value) const; 79 void VerifyMarkFull(TaggedObject *obj, ObjectSlot slot, TaggedObject *value) const; 80 void VerifyEvacuateOld(TaggedObject *obj, ObjectSlot slot, TaggedObject *value) const; 81 void VerifyEvacuateFull(TaggedObject *obj, ObjectSlot slot, TaggedObject *value) const; 82 void VerifySharedRSetPostFullGC(TaggedObject *obj, ObjectSlot slot, TaggedObject *value) const; 83 void VerifySharedObjectReference(TaggedObject *obj, ObjectSlot slot, TaggedObject *value) const; 84 85 const BaseHeap* const heap_ {nullptr}; 86 size_t* const failCount_ {nullptr}; 87 VerifyKind verifyKind_; 88 }; 89 90 class Verification { 91 public: 92 explicit Verification(Heap *heap, VerifyKind verifyKind = VerifyKind::VERIFY_PRE_GC) heap_(heap)93 : heap_(heap), verifyKind_(verifyKind) {} 94 ~Verification() = default; 95 96 static void VerifyMark(Heap *heap); 97 static void VerifyEvacuate(Heap *heap); 98 void VerifyAll() const; 99 100 size_t VerifyRoot() const; 101 size_t VerifyHeap() const; 102 size_t VerifyOldToNewRSet() const; 103 private: 104 class VerificationRootVisitor final : public RootVisitor { 105 public: VerificationRootVisitor(const Verification * verification,size_t & failCount)106 explicit VerificationRootVisitor(const Verification *verification, size_t &failCount) 107 : verification_(verification), failCount_(failCount) {} 108 ~VerificationRootVisitor() = default; 109 110 void VisitRoot([[maybe_unused]] Root type, ObjectSlot slot) override; 111 void VisitRangeRoot([[maybe_unused]] Root type, ObjectSlot start, ObjectSlot end) override; 112 void VisitBaseAndDerivedRoot([[maybe_unused]] Root type, ObjectSlot base, ObjectSlot derived, 113 uintptr_t baseOldObject) override; 114 private: 115 const Verification *verification_; 116 size_t &failCount_; 117 }; 118 119 void VerifyObjectSlot(const ObjectSlot &slot, size_t *failCount) const; 120 121 NO_COPY_SEMANTIC(Verification); 122 NO_MOVE_SEMANTIC(Verification); 123 124 Heap *heap_ {nullptr}; 125 VerifyKind verifyKind_; 126 }; 127 128 class SharedHeapVerification { 129 public: SharedHeapVerification(SharedHeap * heap,VerifyKind verifyKind)130 explicit SharedHeapVerification(SharedHeap *heap, VerifyKind verifyKind) 131 : sHeap_(heap), verifyKind_(verifyKind) {} 132 ~SharedHeapVerification() = default; 133 134 void VerifyAll() const; 135 void VerifyMark(bool cm) const; 136 void VerifySweep(bool cm) const; 137 138 size_t VerifyRoot() const; 139 size_t VerifyHeap() const; 140 private: 141 class VerificationRootVisitor final : public RootVisitor { 142 public: VerificationRootVisitor(const SharedHeapVerification * sVerification,size_t & failCount)143 explicit VerificationRootVisitor(const SharedHeapVerification *sVerification, size_t &failCount) 144 : sVerification_(sVerification), failCount_(failCount) {} 145 ~VerificationRootVisitor() = default; 146 147 void VisitRoot([[maybe_unused]] Root type, ObjectSlot slot) override; 148 void VisitRangeRoot([[maybe_unused]] Root type, ObjectSlot start, ObjectSlot end) override; 149 void VisitBaseAndDerivedRoot([[maybe_unused]] Root type, ObjectSlot base, ObjectSlot derived, 150 uintptr_t baseOldObject) override; 151 private: 152 const SharedHeapVerification *sVerification_; 153 size_t &failCount_; 154 }; 155 156 class VerificationSerializeRootVisitor final : public RootVisitor { 157 public: VerificationSerializeRootVisitor(SharedHeap * sHeap,size_t & failCount)158 explicit VerificationSerializeRootVisitor(SharedHeap *sHeap, size_t &failCount) 159 : sHeap_(sHeap), failCount_(failCount) {} 160 ~VerificationSerializeRootVisitor() = default; 161 162 void VisitRoot([[maybe_unused]] Root type, ObjectSlot slot) override; 163 void VisitRangeRoot([[maybe_unused]] Root type, ObjectSlot start, ObjectSlot end) override; 164 void VisitBaseAndDerivedRoot([[maybe_unused]] Root type, ObjectSlot base, ObjectSlot derived, 165 uintptr_t baseOldObject) override; 166 private: 167 SharedHeap *sHeap_; 168 size_t &failCount_; 169 }; 170 171 void VerifyObjectSlot(const ObjectSlot &slot, size_t *failCount) const; 172 173 NO_COPY_SEMANTIC(SharedHeapVerification); 174 NO_MOVE_SEMANTIC(SharedHeapVerification); 175 176 SharedHeap *sHeap_ {nullptr}; 177 VerifyKind verifyKind_; 178 }; 179 180 template <class Callback> 181 class VerifyVisitor final : public BaseObjectVisitor<VerifyVisitor<Callback>> { 182 public: VerifyVisitor(Callback & cb)183 explicit VerifyVisitor(Callback &cb) : thread_(JSThread::GetCurrent()), cb_(cb) {} 184 ~VerifyVisitor() = default; VisitObjectRangeImpl(BaseObject * root,uintptr_t startAddr,uintptr_t endAddr,VisitObjectArea area)185 void VisitObjectRangeImpl(BaseObject *root, uintptr_t startAddr, uintptr_t endAddr, VisitObjectArea area) override 186 { 187 ObjectSlot start(startAddr); 188 ObjectSlot end(endAddr); 189 if (UNLIKELY(area == VisitObjectArea::IN_OBJECT)) { 190 auto hclass = TaggedObject::Cast(root)->GetClass(); 191 ASSERT(!hclass->IsAllTaggedProp()); 192 int index = 0; 193 for (ObjectSlot slot = start; slot < end; slot++) { 194 auto layout = LayoutInfo::Cast(hclass->GetLayout(thread_).GetTaggedObject()); 195 auto attr = layout->GetAttr(thread_, index++); 196 if (attr.IsTaggedRep()) { 197 cb_(slot, TaggedObject::Cast(root)); 198 } 199 } 200 return; 201 } 202 for (ObjectSlot slot = start; slot < end; slot++) { 203 cb_(slot, TaggedObject::Cast(root)); 204 } 205 } 206 private: 207 const JSThread *thread_; 208 Callback &cb_; 209 }; 210 } // namespace panda::ecmascript 211 212 #endif // ECMASCRIPT_MEM_HEAP_VERIFICATION_H 213