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