OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/become.h" | 5 #include "vm/become.h" |
6 | 6 |
7 #include "platform/assert.h" | 7 #include "platform/assert.h" |
8 #include "platform/utils.h" | 8 #include "platform/utils.h" |
9 | 9 |
10 #include "vm/dart_api_state.h" | 10 #include "vm/dart_api_state.h" |
(...skipping 17 matching lines...) Expand all Loading... |
28 tags = RawObject::ClassIdTag::update(kForwardingCorpse, tags); | 28 tags = RawObject::ClassIdTag::update(kForwardingCorpse, tags); |
29 | 29 |
30 result->tags_ = tags; | 30 result->tags_ = tags; |
31 if (size > RawObject::SizeTag::kMaxSizeTag) { | 31 if (size > RawObject::SizeTag::kMaxSizeTag) { |
32 *result->SizeAddress() = size; | 32 *result->SizeAddress() = size; |
33 } | 33 } |
34 result->set_target(Object::null()); | 34 result->set_target(Object::null()); |
35 return result; | 35 return result; |
36 } | 36 } |
37 | 37 |
38 | |
39 void ForwardingCorpse::InitOnce() { | 38 void ForwardingCorpse::InitOnce() { |
40 ASSERT(sizeof(ForwardingCorpse) == kObjectAlignment); | 39 ASSERT(sizeof(ForwardingCorpse) == kObjectAlignment); |
41 ASSERT(OFFSET_OF(ForwardingCorpse, tags_) == Object::tags_offset()); | 40 ASSERT(OFFSET_OF(ForwardingCorpse, tags_) == Object::tags_offset()); |
42 } | 41 } |
43 | 42 |
44 | |
45 // Free list elements are used as a marker for forwarding objects. This is | 43 // Free list elements are used as a marker for forwarding objects. This is |
46 // safe because we cannot reach free list elements from live objects. Ideally | 44 // safe because we cannot reach free list elements from live objects. Ideally |
47 // forwarding objects would have their own class id. See TODO below. | 45 // forwarding objects would have their own class id. See TODO below. |
48 static bool IsForwardingObject(RawObject* object) { | 46 static bool IsForwardingObject(RawObject* object) { |
49 return object->IsHeapObject() && object->IsForwardingCorpse(); | 47 return object->IsHeapObject() && object->IsForwardingCorpse(); |
50 } | 48 } |
51 | 49 |
52 | |
53 static RawObject* GetForwardedObject(RawObject* object) { | 50 static RawObject* GetForwardedObject(RawObject* object) { |
54 ASSERT(IsForwardingObject(object)); | 51 ASSERT(IsForwardingObject(object)); |
55 uword addr = reinterpret_cast<uword>(object) - kHeapObjectTag; | 52 uword addr = reinterpret_cast<uword>(object) - kHeapObjectTag; |
56 ForwardingCorpse* forwarder = reinterpret_cast<ForwardingCorpse*>(addr); | 53 ForwardingCorpse* forwarder = reinterpret_cast<ForwardingCorpse*>(addr); |
57 return forwarder->target(); | 54 return forwarder->target(); |
58 } | 55 } |
59 | 56 |
60 | |
61 static void ForwardObjectTo(RawObject* before_obj, RawObject* after_obj) { | 57 static void ForwardObjectTo(RawObject* before_obj, RawObject* after_obj) { |
62 const intptr_t size_before = before_obj->Size(); | 58 const intptr_t size_before = before_obj->Size(); |
63 | 59 |
64 uword corpse_addr = reinterpret_cast<uword>(before_obj) - kHeapObjectTag; | 60 uword corpse_addr = reinterpret_cast<uword>(before_obj) - kHeapObjectTag; |
65 ForwardingCorpse* forwarder = | 61 ForwardingCorpse* forwarder = |
66 ForwardingCorpse::AsForwarder(corpse_addr, size_before); | 62 ForwardingCorpse::AsForwarder(corpse_addr, size_before); |
67 forwarder->set_target(after_obj); | 63 forwarder->set_target(after_obj); |
68 if (!IsForwardingObject(before_obj)) { | 64 if (!IsForwardingObject(before_obj)) { |
69 FATAL("become: ForwardObjectTo failure."); | 65 FATAL("become: ForwardObjectTo failure."); |
70 } | 66 } |
71 // Still need to be able to iterate over the forwarding corpse. | 67 // Still need to be able to iterate over the forwarding corpse. |
72 const intptr_t size_after = before_obj->Size(); | 68 const intptr_t size_after = before_obj->Size(); |
73 if (size_before != size_after) { | 69 if (size_before != size_after) { |
74 FATAL("become: Before and after sizes do not match."); | 70 FATAL("become: Before and after sizes do not match."); |
75 } | 71 } |
76 } | 72 } |
77 | 73 |
78 | |
79 class ForwardPointersVisitor : public ObjectPointerVisitor { | 74 class ForwardPointersVisitor : public ObjectPointerVisitor { |
80 public: | 75 public: |
81 explicit ForwardPointersVisitor(Isolate* isolate) | 76 explicit ForwardPointersVisitor(Isolate* isolate) |
82 : ObjectPointerVisitor(isolate), visiting_object_(NULL), count_(0) {} | 77 : ObjectPointerVisitor(isolate), visiting_object_(NULL), count_(0) {} |
83 | 78 |
84 virtual void VisitPointers(RawObject** first, RawObject** last) { | 79 virtual void VisitPointers(RawObject** first, RawObject** last) { |
85 for (RawObject** p = first; p <= last; p++) { | 80 for (RawObject** p = first; p <= last; p++) { |
86 RawObject* old_target = *p; | 81 RawObject* old_target = *p; |
87 if (IsForwardingObject(old_target)) { | 82 if (IsForwardingObject(old_target)) { |
88 RawObject* new_target = GetForwardedObject(old_target); | 83 RawObject* new_target = GetForwardedObject(old_target); |
(...skipping 11 matching lines...) Expand all Loading... |
100 | 95 |
101 intptr_t count() const { return count_; } | 96 intptr_t count() const { return count_; } |
102 | 97 |
103 private: | 98 private: |
104 RawObject* visiting_object_; | 99 RawObject* visiting_object_; |
105 intptr_t count_; | 100 intptr_t count_; |
106 | 101 |
107 DISALLOW_COPY_AND_ASSIGN(ForwardPointersVisitor); | 102 DISALLOW_COPY_AND_ASSIGN(ForwardPointersVisitor); |
108 }; | 103 }; |
109 | 104 |
110 | |
111 class ForwardHeapPointersVisitor : public ObjectVisitor { | 105 class ForwardHeapPointersVisitor : public ObjectVisitor { |
112 public: | 106 public: |
113 explicit ForwardHeapPointersVisitor(ForwardPointersVisitor* pointer_visitor) | 107 explicit ForwardHeapPointersVisitor(ForwardPointersVisitor* pointer_visitor) |
114 : pointer_visitor_(pointer_visitor) {} | 108 : pointer_visitor_(pointer_visitor) {} |
115 | 109 |
116 virtual void VisitObject(RawObject* obj) { | 110 virtual void VisitObject(RawObject* obj) { |
117 pointer_visitor_->VisitingObject(obj); | 111 pointer_visitor_->VisitingObject(obj); |
118 obj->VisitPointers(pointer_visitor_); | 112 obj->VisitPointers(pointer_visitor_); |
119 } | 113 } |
120 | 114 |
121 private: | 115 private: |
122 ForwardPointersVisitor* pointer_visitor_; | 116 ForwardPointersVisitor* pointer_visitor_; |
123 | 117 |
124 DISALLOW_COPY_AND_ASSIGN(ForwardHeapPointersVisitor); | 118 DISALLOW_COPY_AND_ASSIGN(ForwardHeapPointersVisitor); |
125 }; | 119 }; |
126 | 120 |
127 | |
128 class ForwardHeapPointersHandleVisitor : public HandleVisitor { | 121 class ForwardHeapPointersHandleVisitor : public HandleVisitor { |
129 public: | 122 public: |
130 ForwardHeapPointersHandleVisitor() | 123 ForwardHeapPointersHandleVisitor() |
131 : HandleVisitor(Thread::Current()), count_(0) {} | 124 : HandleVisitor(Thread::Current()), count_(0) {} |
132 | 125 |
133 virtual void VisitHandle(uword addr) { | 126 virtual void VisitHandle(uword addr) { |
134 FinalizablePersistentHandle* handle = | 127 FinalizablePersistentHandle* handle = |
135 reinterpret_cast<FinalizablePersistentHandle*>(addr); | 128 reinterpret_cast<FinalizablePersistentHandle*>(addr); |
136 if (IsForwardingObject(handle->raw())) { | 129 if (IsForwardingObject(handle->raw())) { |
137 *handle->raw_addr() = GetForwardedObject(handle->raw()); | 130 *handle->raw_addr() = GetForwardedObject(handle->raw()); |
138 count_++; | 131 count_++; |
139 } | 132 } |
140 } | 133 } |
141 | 134 |
142 intptr_t count() const { return count_; } | 135 intptr_t count() const { return count_; } |
143 | 136 |
144 private: | 137 private: |
145 int count_; | 138 int count_; |
146 | 139 |
147 DISALLOW_COPY_AND_ASSIGN(ForwardHeapPointersHandleVisitor); | 140 DISALLOW_COPY_AND_ASSIGN(ForwardHeapPointersHandleVisitor); |
148 }; | 141 }; |
149 | 142 |
150 | |
151 // On IA32, object pointers are embedded directly in the instruction stream, | 143 // On IA32, object pointers are embedded directly in the instruction stream, |
152 // which is normally write-protected, so we need to make it temporarily writable | 144 // which is normally write-protected, so we need to make it temporarily writable |
153 // to forward the pointers. On all other architectures, object pointers are | 145 // to forward the pointers. On all other architectures, object pointers are |
154 // accessed through ObjectPools. | 146 // accessed through ObjectPools. |
155 #if defined(TARGET_ARCH_IA32) | 147 #if defined(TARGET_ARCH_IA32) |
156 class WritableCodeLiteralsScope : public ValueObject { | 148 class WritableCodeLiteralsScope : public ValueObject { |
157 public: | 149 public: |
158 explicit WritableCodeLiteralsScope(Heap* heap) : heap_(heap) { | 150 explicit WritableCodeLiteralsScope(Heap* heap) : heap_(heap) { |
159 if (FLAG_write_protect_code) { | 151 if (FLAG_write_protect_code) { |
160 heap_->WriteProtectCode(false); | 152 heap_->WriteProtectCode(false); |
(...skipping 10 matching lines...) Expand all Loading... |
171 Heap* heap_; | 163 Heap* heap_; |
172 }; | 164 }; |
173 #else | 165 #else |
174 class WritableCodeLiteralsScope : public ValueObject { | 166 class WritableCodeLiteralsScope : public ValueObject { |
175 public: | 167 public: |
176 explicit WritableCodeLiteralsScope(Heap* heap) {} | 168 explicit WritableCodeLiteralsScope(Heap* heap) {} |
177 ~WritableCodeLiteralsScope() {} | 169 ~WritableCodeLiteralsScope() {} |
178 }; | 170 }; |
179 #endif | 171 #endif |
180 | 172 |
181 | |
182 void Become::MakeDummyObject(const Instance& instance) { | 173 void Become::MakeDummyObject(const Instance& instance) { |
183 // Make the forward pointer point to itself. | 174 // Make the forward pointer point to itself. |
184 // This is needed to distinguish it from a real forward object. | 175 // This is needed to distinguish it from a real forward object. |
185 ForwardObjectTo(instance.raw(), instance.raw()); | 176 ForwardObjectTo(instance.raw(), instance.raw()); |
186 } | 177 } |
187 | 178 |
188 | |
189 static bool IsDummyObject(RawObject* object) { | 179 static bool IsDummyObject(RawObject* object) { |
190 if (!object->IsForwardingCorpse()) return false; | 180 if (!object->IsForwardingCorpse()) return false; |
191 return GetForwardedObject(object) == object; | 181 return GetForwardedObject(object) == object; |
192 } | 182 } |
193 | 183 |
194 | |
195 void Become::CrashDump(RawObject* before_obj, RawObject* after_obj) { | 184 void Become::CrashDump(RawObject* before_obj, RawObject* after_obj) { |
196 OS::PrintErr("DETECTED FATAL ISSUE IN BECOME MAPPINGS\n"); | 185 OS::PrintErr("DETECTED FATAL ISSUE IN BECOME MAPPINGS\n"); |
197 | 186 |
198 OS::PrintErr("BEFORE ADDRESS: %p\n", before_obj); | 187 OS::PrintErr("BEFORE ADDRESS: %p\n", before_obj); |
199 OS::PrintErr("BEFORE IS HEAP OBJECT: %s", | 188 OS::PrintErr("BEFORE IS HEAP OBJECT: %s", |
200 before_obj->IsHeapObject() ? "YES" : "NO"); | 189 before_obj->IsHeapObject() ? "YES" : "NO"); |
201 OS::PrintErr("BEFORE IS VM HEAP OBJECT: %s", | 190 OS::PrintErr("BEFORE IS VM HEAP OBJECT: %s", |
202 before_obj->IsVMHeapObject() ? "YES" : "NO"); | 191 before_obj->IsVMHeapObject() ? "YES" : "NO"); |
203 | 192 |
204 OS::PrintErr("AFTER ADDRESS: %p\n", after_obj); | 193 OS::PrintErr("AFTER ADDRESS: %p\n", after_obj); |
205 OS::PrintErr("AFTER IS HEAP OBJECT: %s", | 194 OS::PrintErr("AFTER IS HEAP OBJECT: %s", |
206 after_obj->IsHeapObject() ? "YES" : "NO"); | 195 after_obj->IsHeapObject() ? "YES" : "NO"); |
207 OS::PrintErr("AFTER IS VM HEAP OBJECT: %s", | 196 OS::PrintErr("AFTER IS VM HEAP OBJECT: %s", |
208 after_obj->IsVMHeapObject() ? "YES" : "NO"); | 197 after_obj->IsVMHeapObject() ? "YES" : "NO"); |
209 | 198 |
210 if (before_obj->IsHeapObject()) { | 199 if (before_obj->IsHeapObject()) { |
211 OS::PrintErr("BEFORE OBJECT CLASS ID=%" Pd "\n", before_obj->GetClassId()); | 200 OS::PrintErr("BEFORE OBJECT CLASS ID=%" Pd "\n", before_obj->GetClassId()); |
212 const Object& obj = Object::Handle(before_obj); | 201 const Object& obj = Object::Handle(before_obj); |
213 OS::PrintErr("BEFORE OBJECT AS STRING=%s\n", obj.ToCString()); | 202 OS::PrintErr("BEFORE OBJECT AS STRING=%s\n", obj.ToCString()); |
214 } | 203 } |
215 | 204 |
216 if (after_obj->IsHeapObject()) { | 205 if (after_obj->IsHeapObject()) { |
217 OS::PrintErr("AFTER OBJECT CLASS ID=%" Pd "\n", after_obj->GetClassId()); | 206 OS::PrintErr("AFTER OBJECT CLASS ID=%" Pd "\n", after_obj->GetClassId()); |
218 const Object& obj = Object::Handle(after_obj); | 207 const Object& obj = Object::Handle(after_obj); |
219 OS::PrintErr("AFTER OBJECT AS STRING=%s\n", obj.ToCString()); | 208 OS::PrintErr("AFTER OBJECT AS STRING=%s\n", obj.ToCString()); |
220 } | 209 } |
221 } | 210 } |
222 | 211 |
223 | |
224 void Become::ElementsForwardIdentity(const Array& before, const Array& after) { | 212 void Become::ElementsForwardIdentity(const Array& before, const Array& after) { |
225 Thread* thread = Thread::Current(); | 213 Thread* thread = Thread::Current(); |
226 Isolate* isolate = thread->isolate(); | 214 Isolate* isolate = thread->isolate(); |
227 Heap* heap = isolate->heap(); | 215 Heap* heap = isolate->heap(); |
228 | 216 |
229 TIMELINE_FUNCTION_GC_DURATION(thread, "Become::ElementsForwardIdentity"); | 217 TIMELINE_FUNCTION_GC_DURATION(thread, "Become::ElementsForwardIdentity"); |
230 HeapIterationScope his; | 218 HeapIterationScope his; |
231 | 219 |
232 // Setup forwarding pointers. | 220 // Setup forwarding pointers. |
233 ASSERT(before.Length() == after.Length()); | 221 ASSERT(before.Length() == after.Length()); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 } | 290 } |
303 | 291 |
304 #if defined(DEBUG) | 292 #if defined(DEBUG) |
305 for (intptr_t i = 0; i < before.Length(); i++) { | 293 for (intptr_t i = 0; i < before.Length(); i++) { |
306 ASSERT(before.At(i) == after.At(i)); | 294 ASSERT(before.At(i) == after.At(i)); |
307 } | 295 } |
308 #endif | 296 #endif |
309 } | 297 } |
310 | 298 |
311 } // namespace dart | 299 } // namespace dart |
OLD | NEW |