• 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/js_tagged_value-inl.h"
19 #include "ecmascript/mem/slots.h"
20 #include "ecmascript/mem/visitor.h"
21 
22 namespace panda::ecmascript {
23 // Verify the object body
VisitAllObjects(TaggedObject * obj)24 void VerifyObjectVisitor::VisitAllObjects(TaggedObject *obj)
25 {
26     auto jsHclass = obj->GetClass();
27     objXRay_.VisitObjectBody<VisitType::OLD_GC_VISIT>(
28         obj, jsHclass, [this](TaggedObject *root, ObjectSlot start, ObjectSlot end,
29                               VisitObjectArea area) {
30             if (area == VisitObjectArea::IN_OBJECT) {
31                 auto hclass = root->GetClass();
32                 if (!hclass->IsAllTaggedProp()) {
33                     int index = 0;
34                     for (ObjectSlot slot = start; slot < end; slot++) {
35                         auto layout = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject());
36                         auto attr = layout->GetAttr(index++);
37                         if (attr.IsTaggedRep()) {
38                             VisitObject(slot);
39                         }
40                     }
41                     return;
42                 }
43             }
44             for (ObjectSlot slot = start; slot < end; slot++) {
45                 VisitObject(slot);
46             }
47         });
48 }
49 
VisitObject(ObjectSlot slot)50 void VerifyObjectVisitor::VisitObject(ObjectSlot slot)
51 {
52     JSTaggedValue value(slot.GetTaggedType());
53     if (value.IsWeak()) {
54         if (!heap_->IsAlive(value.GetTaggedWeakRef())) {
55             LOG_GC(ERROR) << "Heap verify detected a dead weak object " << value.GetTaggedObject()
56                                 << " at object:" << slot.SlotAddress();
57             ++(*failCount_);
58         }
59     } else if (value.IsHeapObject()) {
60         if (!heap_->IsAlive(value.GetTaggedObject())) {
61             LOG_GC(ERROR) << "Heap verify detected a dead object at " << value.GetTaggedObject()
62                                 << " at object:" << slot.SlotAddress();
63             ++(*failCount_);
64         }
65     }
66 }
67 
operator ()(TaggedObject * obj,JSTaggedValue value)68 void VerifyObjectVisitor::operator()(TaggedObject *obj, JSTaggedValue value)
69 {
70     ObjectSlot slot(reinterpret_cast<uintptr_t>(obj));
71     if (!value.IsHeapObject()) {
72         LOG_GC(DEBUG) << "Heap object(" << slot.SlotAddress() << ") old to new rset fail: value is "
73                       << slot.GetTaggedType();
74         return;
75     }
76 
77     TaggedObject *object = value.GetRawTaggedObject();
78     auto region = Region::ObjectAddressToRange(object);
79     if (!region->InYoungSpace()) {
80         LOG_GC(ERROR) << "Heap object(" << slot.GetTaggedType() << ") old to new rset fail: value("
81                       << slot.GetTaggedObject() << "/"
82                       << JSHClass::DumpJSType(slot.GetTaggedObject()->GetClass()->GetObjectType())
83                       << ")" << " in " << region->GetSpaceTypeName();
84         ++(*failCount_);
85     }
86 }
87 
VerifyRoot() const88 size_t Verification::VerifyRoot() const
89 {
90     size_t failCount = 0;
91     RootVisitor visitor = [this, &failCount]([[maybe_unused]] Root type, ObjectSlot slot) {
92         VerifyObjectSlot(slot, &failCount);
93     };
94     RootRangeVisitor rangeVisitor = [this, &failCount]([[maybe_unused]] Root type, ObjectSlot start, ObjectSlot end) {
95         for (ObjectSlot slot = start; slot < end; slot++) {
96             VerifyObjectSlot(slot, &failCount);
97         }
98     };
99     RootBaseAndDerivedVisitor derivedVisitor =
100         []([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot base, [[maybe_unused]] ObjectSlot derived,
101            [[maybe_unused]] uintptr_t baseOldObject) {
102     };
103     objXRay_.VisitVMRoots(visitor, rangeVisitor, derivedVisitor);
104     if (failCount > 0) {
105         LOG_GC(ERROR) << "VerifyRoot detects deadObject count is " << failCount;
106     }
107 
108     return failCount;
109 }
110 
VerifyHeap() const111 size_t Verification::VerifyHeap() const
112 {
113     size_t failCount = heap_->VerifyHeapObjects();
114     if (failCount > 0) {
115         LOG_GC(ERROR) << "VerifyHeap detects deadObject count is " << failCount;
116     }
117     return failCount;
118 }
119 
VerifyOldToNewRSet() const120 size_t Verification::VerifyOldToNewRSet() const
121 {
122     size_t failCount = heap_->VerifyOldToNewRSet();
123     if (failCount > 0) {
124         LOG_GC(ERROR) << "VerifyOldToNewRSet detects non new space count is " << failCount;
125     }
126     return failCount;
127 }
128 
VerifyObjectSlot(const ObjectSlot & slot,size_t * failCount) const129 void Verification::VerifyObjectSlot(const ObjectSlot &slot, size_t *failCount) const
130 {
131     JSTaggedValue value(slot.GetTaggedType());
132     if (value.IsWeak()) {
133         VerifyObjectVisitor(heap_, failCount)(value.GetTaggedWeakRef());
134     } else if (value.IsHeapObject()) {
135         VerifyObjectVisitor(heap_, failCount)(value.GetTaggedObject());
136     }
137 }
138 }  // namespace panda::ecmascript
139