| 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 |