Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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/gc_marker.h" | 5 #include "vm/gc_marker.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "vm/allocation.h" | 10 #include "vm/allocation.h" |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 116 | 116 |
| 117 DISALLOW_COPY_AND_ASSIGN(MarkingStack); | 117 DISALLOW_COPY_AND_ASSIGN(MarkingStack); |
| 118 }; | 118 }; |
| 119 | 119 |
| 120 | 120 |
| 121 class MarkingVisitor : public ObjectPointerVisitor { | 121 class MarkingVisitor : public ObjectPointerVisitor { |
| 122 public: | 122 public: |
| 123 MarkingVisitor(Isolate* isolate, | 123 MarkingVisitor(Isolate* isolate, |
| 124 Heap* heap, | 124 Heap* heap, |
| 125 PageSpace* page_space, | 125 PageSpace* page_space, |
| 126 MarkingStack* marking_stack) | 126 MarkingStack* marking_stack, |
| 127 bool visit_function_code) | |
| 127 : ObjectPointerVisitor(isolate), | 128 : ObjectPointerVisitor(isolate), |
| 128 heap_(heap), | 129 heap_(heap), |
| 129 vm_heap_(Dart::vm_isolate()->heap()), | 130 vm_heap_(Dart::vm_isolate()->heap()), |
| 130 page_space_(page_space), | 131 page_space_(page_space), |
| 131 marking_stack_(marking_stack), | 132 marking_stack_(marking_stack), |
| 132 visiting_old_object_(NULL) { | 133 visiting_old_object_(NULL), |
| 134 visit_function_code_(visit_function_code) { | |
| 133 ASSERT(heap_ != vm_heap_); | 135 ASSERT(heap_ != vm_heap_); |
| 134 } | 136 } |
| 135 | 137 |
| 136 MarkingStack* marking_stack() const { return marking_stack_; } | 138 MarkingStack* marking_stack() const { return marking_stack_; } |
| 137 | 139 |
| 138 void VisitPointers(RawObject** first, RawObject** last) { | 140 void VisitPointers(RawObject** first, RawObject** last) { |
| 139 for (RawObject** current = first; current <= last; current++) { | 141 for (RawObject** current = first; current <= last; current++) { |
| 140 MarkObject(*current, current); | 142 MarkObject(*current, current); |
| 141 } | 143 } |
| 142 } | 144 } |
| 143 | 145 |
| 146 bool visit_function_code() { return visit_function_code_; } | |
|
srdjan
2013/11/19 19:18:29
const
zra
2013/11/22 17:18:54
Done.
| |
| 147 | |
| 148 GrowableArray<RawFunction*>* skipped_code_functions() { | |
| 149 return &skipped_code_functions_; | |
| 150 } | |
| 151 | |
| 144 void DelayWeakProperty(RawWeakProperty* raw_weak) { | 152 void DelayWeakProperty(RawWeakProperty* raw_weak) { |
| 145 RawObject* raw_key = raw_weak->ptr()->key_; | 153 RawObject* raw_key = raw_weak->ptr()->key_; |
| 146 DelaySet::iterator it = delay_set_.find(raw_key); | 154 DelaySet::iterator it = delay_set_.find(raw_key); |
| 147 if (it != delay_set_.end()) { | 155 if (it != delay_set_.end()) { |
| 148 ASSERT(raw_key->IsWatched()); | 156 ASSERT(raw_key->IsWatched()); |
| 149 } else { | 157 } else { |
| 150 ASSERT(!raw_key->IsWatched()); | 158 ASSERT(!raw_key->IsWatched()); |
| 151 raw_key->SetWatchedBit(); | 159 raw_key->SetWatchedBit(); |
| 152 } | 160 } |
| 153 delay_set_.insert(std::make_pair(raw_key, raw_weak)); | 161 delay_set_.insert(std::make_pair(raw_key, raw_weak)); |
| 154 } | 162 } |
| 155 | 163 |
| 156 void Finalize() { | 164 void Finalize() { |
| 157 DelaySet::iterator it = delay_set_.begin(); | 165 DelaySet::iterator it = delay_set_.begin(); |
| 158 for (; it != delay_set_.end(); ++it) { | 166 for (; it != delay_set_.end(); ++it) { |
| 159 WeakProperty::Clear(it->second); | 167 WeakProperty::Clear(it->second); |
| 160 } | 168 } |
| 169 if (!visit_function_code_) { | |
| 170 TryDetachingCode(); | |
|
Ivan Posva
2013/11/19 19:24:48
DetachCode()
zra
2013/11/22 17:18:54
Done.
| |
| 171 } | |
| 161 } | 172 } |
| 162 | 173 |
| 163 void VisitingOldObject(RawObject* obj) { | 174 void VisitingOldObject(RawObject* obj) { |
| 164 ASSERT((obj == NULL) || obj->IsOldObject()); | 175 ASSERT((obj == NULL) || obj->IsOldObject()); |
| 165 visiting_old_object_ = obj; | 176 visiting_old_object_ = obj; |
| 166 } | 177 } |
| 167 | 178 |
| 168 private: | 179 private: |
| 169 void MarkAndPush(RawObject* raw_obj) { | 180 void MarkAndPush(RawObject* raw_obj) { |
| 170 ASSERT(raw_obj->IsHeapObject()); | 181 ASSERT(raw_obj->IsHeapObject()); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 188 raw_obj->ClearWatchedBit(); | 199 raw_obj->ClearWatchedBit(); |
| 189 } | 200 } |
| 190 marking_stack_->Push(raw_obj); | 201 marking_stack_->Push(raw_obj); |
| 191 | 202 |
| 192 // TODO(iposva): Should we mark the classes early? | 203 // TODO(iposva): Should we mark the classes early? |
| 193 MarkObject(raw_class, NULL); | 204 MarkObject(raw_class, NULL); |
| 194 } | 205 } |
| 195 | 206 |
| 196 void MarkObject(RawObject* raw_obj, RawObject** p) { | 207 void MarkObject(RawObject* raw_obj, RawObject** p) { |
| 197 // Fast exit if the raw object is a Smi. | 208 // Fast exit if the raw object is a Smi. |
| 198 if (!raw_obj->IsHeapObject()) return; | 209 if (!raw_obj->IsHeapObject()) { |
| 210 return; | |
| 211 } | |
| 199 | 212 |
| 200 // Fast exit if the raw object is marked. | 213 // Fast exit if the raw object is marked. |
| 201 if (raw_obj->IsMarked()) return; | 214 if (raw_obj->IsMarked()) { |
| 215 return; | |
| 216 } | |
| 202 | 217 |
| 203 // Skip over new objects, but verify consistency of heap while at it. | 218 // Skip over new objects, but verify consistency of heap while at it. |
| 204 if (raw_obj->IsNewObject()) { | 219 if (raw_obj->IsNewObject()) { |
| 205 // TODO(iposva): Add consistency check. | 220 // TODO(iposva): Add consistency check. |
| 206 if ((visiting_old_object_ != NULL) && | 221 if ((visiting_old_object_ != NULL) && |
| 207 !visiting_old_object_->IsRemembered()) { | 222 !visiting_old_object_->IsRemembered()) { |
| 208 ASSERT(p != NULL); | 223 ASSERT(p != NULL); |
| 209 visiting_old_object_->SetRememberedBit(); | 224 visiting_old_object_->SetRememberedBit(); |
| 210 isolate()->store_buffer()->AddObjectGC(visiting_old_object_); | 225 isolate()->store_buffer()->AddObjectGC(visiting_old_object_); |
| 211 } | 226 } |
| 212 return; | 227 return; |
| 213 } | 228 } |
| 214 | 229 |
| 215 MarkAndPush(raw_obj); | 230 MarkAndPush(raw_obj); |
| 216 } | 231 } |
| 217 | 232 |
| 233 void TryDetachingCode() { | |
| 234 for (int i = 0; i < skipped_code_functions_.length(); i++) { | |
| 235 RawFunction* func = skipped_code_functions_[i]; | |
| 236 RawCode* code = func->ptr()->code_; | |
| 237 if (!code->IsMarked()) { | |
| 238 // If the code wasn't marked even after skipping the function's code | |
|
Ivan Posva
2013/11/19 19:24:48
// If the code wasn't strongly visited by other re
zra
2013/11/22 17:18:54
Done.
| |
| 239 // pointer, then we disconnect the code from the function. It will | |
| 240 // be swept. | |
| 241 func->ptr()->code_ = Code::null(); | |
| 242 func->ptr()->unoptimized_code_ = Code::null(); | |
| 243 if (FLAG_log_code_drop) { | |
| 244 // NOTE: This code runs while GC is in progress and runs within | |
| 245 // a NoHandleScope block. Hence it is not okay to use a regular Zone | |
| 246 // or Scope handle. We use a direct stack handle so the raw pointer in | |
| 247 // this handle is not traversed. The use of a handle is mainly to | |
| 248 // be able to reuse the handle based code and avoid having to add | |
| 249 // helper functions to the raw object interface. | |
| 250 String name; | |
| 251 name = func->ptr()->name_; | |
| 252 OS::Print("Detaching code: %s\n", name.ToCString()); | |
| 253 } | |
| 254 } | |
| 255 } | |
| 256 } | |
| 257 | |
| 218 Heap* heap_; | 258 Heap* heap_; |
| 219 Heap* vm_heap_; | 259 Heap* vm_heap_; |
| 220 PageSpace* page_space_; | 260 PageSpace* page_space_; |
| 221 MarkingStack* marking_stack_; | 261 MarkingStack* marking_stack_; |
| 222 RawObject* visiting_old_object_; | 262 RawObject* visiting_old_object_; |
| 223 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet; | 263 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet; |
| 224 DelaySet delay_set_; | 264 DelaySet delay_set_; |
| 265 bool visit_function_code_; | |
|
srdjan
2013/11/19 19:18:29
const
zra
2013/11/22 17:18:54
Done.
| |
| 266 GrowableArray<RawFunction*> skipped_code_functions_; | |
| 225 | 267 |
| 226 DISALLOW_IMPLICIT_CONSTRUCTORS(MarkingVisitor); | 268 DISALLOW_IMPLICIT_CONSTRUCTORS(MarkingVisitor); |
| 227 }; | 269 }; |
| 228 | 270 |
| 229 | 271 |
| 230 bool IsUnreachable(const RawObject* raw_obj) { | 272 bool IsUnreachable(const RawObject* raw_obj) { |
| 231 if (!raw_obj->IsHeapObject()) { | 273 if (!raw_obj->IsHeapObject()) { |
| 232 return false; | 274 return false; |
| 233 } | 275 } |
| 234 if (raw_obj == Object::null()) { | 276 if (raw_obj == Object::null()) { |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 422 void GCMarker::ProcessObjectIdTable(Isolate* isolate) { | 464 void GCMarker::ProcessObjectIdTable(Isolate* isolate) { |
| 423 ObjectIdRingClearPointerVisitor visitor(isolate); | 465 ObjectIdRingClearPointerVisitor visitor(isolate); |
| 424 ObjectIdRing* ring = isolate->object_id_ring(); | 466 ObjectIdRing* ring = isolate->object_id_ring(); |
| 425 ASSERT(ring != NULL); | 467 ASSERT(ring != NULL); |
| 426 ring->VisitPointers(&visitor); | 468 ring->VisitPointers(&visitor); |
| 427 } | 469 } |
| 428 | 470 |
| 429 | 471 |
| 430 void GCMarker::MarkObjects(Isolate* isolate, | 472 void GCMarker::MarkObjects(Isolate* isolate, |
| 431 PageSpace* page_space, | 473 PageSpace* page_space, |
| 432 bool invoke_api_callbacks) { | 474 bool invoke_api_callbacks, |
| 475 bool try_collecting_code) { | |
|
Ivan Posva
2013/11/19 19:24:48
The "try" is unnecessary here. Either you collect
zra
2013/11/22 17:18:54
Done.
| |
| 476 bool visit_function_code = !try_collecting_code; | |
|
srdjan
2013/11/19 19:18:29
const bool
zra
2013/11/22 17:18:54
Done.
| |
| 433 MarkingStack marking_stack; | 477 MarkingStack marking_stack; |
| 434 Prologue(isolate, invoke_api_callbacks); | 478 Prologue(isolate, invoke_api_callbacks); |
| 435 MarkingVisitor mark(isolate, heap_, page_space, &marking_stack); | 479 MarkingVisitor mark( |
| 480 isolate, heap_, page_space, &marking_stack, visit_function_code); | |
| 436 IterateRoots(isolate, &mark, !invoke_api_callbacks); | 481 IterateRoots(isolate, &mark, !invoke_api_callbacks); |
| 437 DrainMarkingStack(isolate, &mark); | 482 DrainMarkingStack(isolate, &mark); |
| 438 IterateWeakReferences(isolate, &mark); | 483 IterateWeakReferences(isolate, &mark); |
| 439 MarkingWeakVisitor mark_weak; | 484 MarkingWeakVisitor mark_weak; |
| 440 IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks); | 485 IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks); |
| 441 mark.Finalize(); | 486 mark.Finalize(); |
| 442 ProcessWeakTables(page_space); | 487 ProcessWeakTables(page_space); |
| 443 ProcessObjectIdTable(isolate); | 488 ProcessObjectIdTable(isolate); |
| 444 | 489 |
| 445 | |
| 446 Epilogue(isolate, invoke_api_callbacks); | 490 Epilogue(isolate, invoke_api_callbacks); |
| 447 } | 491 } |
| 448 | 492 |
| 449 } // namespace dart | 493 } // namespace dart |
| OLD | NEW |