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 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "vm/allocation.h" | 11 #include "vm/allocation.h" |
| 12 #include "vm/dart_api_state.h" | 12 #include "vm/dart_api_state.h" |
| 13 #include "vm/isolate.h" | 13 #include "vm/isolate.h" |
| 14 #include "vm/log.h" | |
| 14 #include "vm/pages.h" | 15 #include "vm/pages.h" |
| 15 #include "vm/raw_object.h" | 16 #include "vm/raw_object.h" |
| 16 #include "vm/stack_frame.h" | 17 #include "vm/stack_frame.h" |
| 17 #include "vm/visitor.h" | 18 #include "vm/visitor.h" |
| 18 #include "vm/object_id_ring.h" | 19 #include "vm/object_id_ring.h" |
| 19 | 20 |
| 20 namespace dart { | 21 namespace dart { |
| 21 | 22 |
| 22 // A simple chunked marking stack. | 23 // A simple chunked marking stack. |
| 23 class MarkingStack : public ValueObject { | 24 class MarkingStack : public ValueObject { |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 140 MarkingStack* marking_stack() const { return marking_stack_; } | 141 MarkingStack* marking_stack() const { return marking_stack_; } |
| 141 | 142 |
| 142 void VisitPointers(RawObject** first, RawObject** last) { | 143 void VisitPointers(RawObject** first, RawObject** last) { |
| 143 for (RawObject** current = first; current <= last; current++) { | 144 for (RawObject** current = first; current <= last; current++) { |
| 144 MarkObject(*current, current); | 145 MarkObject(*current, current); |
| 145 } | 146 } |
| 146 } | 147 } |
| 147 | 148 |
| 148 bool visit_function_code() const { return visit_function_code_; } | 149 bool visit_function_code() const { return visit_function_code_; } |
| 149 | 150 |
| 150 GrowableArray<RawFunction*>* skipped_code_functions() { | 151 virtual GrowableArray<RawFunction*>* skipped_current_code_functions() { |
| 151 return &skipped_code_functions_; | 152 return &skipped_current_code_functions_; |
|
Vyacheslav Egorov (Google)
2015/04/09 12:23:07
I think there is no reason to have two separate li
Florian Schneider
2015/04/09 14:58:43
Done.
| |
| 153 } | |
| 154 | |
| 155 virtual GrowableArray<RawFunction*>* skipped_unoptimized_code_functions() { | |
| 156 return &skipped_unoptimized_code_functions_; | |
| 152 } | 157 } |
| 153 | 158 |
| 154 void DelayWeakProperty(RawWeakProperty* raw_weak) { | 159 void DelayWeakProperty(RawWeakProperty* raw_weak) { |
| 155 RawObject* raw_key = raw_weak->ptr()->key_; | 160 RawObject* raw_key = raw_weak->ptr()->key_; |
| 156 DelaySet::iterator it = delay_set_.find(raw_key); | 161 DelaySet::iterator it = delay_set_.find(raw_key); |
| 157 if (it != delay_set_.end()) { | 162 if (it != delay_set_.end()) { |
| 158 ASSERT(raw_key->IsWatched()); | 163 ASSERT(raw_key->IsWatched()); |
| 159 } else { | 164 } else { |
| 160 ASSERT(!raw_key->IsWatched()); | 165 ASSERT(!raw_key->IsWatched()); |
| 161 raw_key->SetWatchedBitUnsynchronized(); | 166 raw_key->SetWatchedBitUnsynchronized(); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 232 if (RawObject::IsVariableSizeClassId(raw_obj->GetClassId())) { | 237 if (RawObject::IsVariableSizeClassId(raw_obj->GetClassId())) { |
| 233 class_table_->UpdateLiveOld(raw_obj->GetClassId(), raw_obj->Size()); | 238 class_table_->UpdateLiveOld(raw_obj->GetClassId(), raw_obj->Size()); |
| 234 } else { | 239 } else { |
| 235 class_table_->UpdateLiveOld(raw_obj->GetClassId(), 0); | 240 class_table_->UpdateLiveOld(raw_obj->GetClassId(), 0); |
| 236 } | 241 } |
| 237 | 242 |
| 238 MarkAndPush(raw_obj); | 243 MarkAndPush(raw_obj); |
| 239 } | 244 } |
| 240 | 245 |
| 241 void DetachCode() { | 246 void DetachCode() { |
| 242 for (int i = 0; i < skipped_code_functions_.length(); i++) { | 247 intptr_t unoptimized_code_count = 0; |
| 243 RawFunction* func = skipped_code_functions_[i]; | 248 intptr_t current_code_count = 0; |
| 249 for (int i = 0; i < skipped_current_code_functions_.length(); i++) { | |
| 250 RawFunction* func = skipped_current_code_functions_[i]; | |
| 244 RawCode* code = func->ptr()->instructions_->ptr()->code_; | 251 RawCode* code = func->ptr()->instructions_->ptr()->code_; |
| 245 if (!code->IsMarked()) { | 252 if (!code->IsMarked()) { |
| 246 // If the code wasn't strongly visited through other references | 253 // If the code wasn't strongly visited through other references |
| 247 // after skipping the function's code pointer, then we disconnect the | 254 // after skipping the function's code pointer, then we disconnect the |
| 248 // code from the function. | 255 // code from the function. |
| 249 StubCode* stub_code = isolate()->stub_code(); | 256 StubCode* stub_code = isolate()->stub_code(); |
| 250 func->StorePointer( | 257 func->StorePointer( |
| 251 &(func->ptr()->instructions_), | 258 &(func->ptr()->instructions_), |
| 252 stub_code->LazyCompile_entry()->code()->ptr()->instructions_); | 259 stub_code->LazyCompile_entry()->code()->ptr()->instructions_); |
| 253 func->StorePointer(&(func->ptr()->unoptimized_code_), Code::null()); | |
| 254 if (FLAG_log_code_drop) { | 260 if (FLAG_log_code_drop) { |
| 255 // NOTE: This code runs while GC is in progress and runs within | 261 // NOTE: This code runs while GC is in progress and runs within |
| 256 // a NoHandleScope block. Hence it is not okay to use a regular Zone | 262 // a NoHandleScope block. Hence it is not okay to use a regular Zone |
| 257 // or Scope handle. We use a direct stack handle so the raw pointer in | 263 // or Scope handle. We use a direct stack handle so the raw pointer in |
| 258 // this handle is not traversed. The use of a handle is mainly to | 264 // this handle is not traversed. The use of a handle is mainly to |
| 259 // be able to reuse the handle based code and avoid having to add | 265 // be able to reuse the handle based code and avoid having to add |
| 260 // helper functions to the raw object interface. | 266 // helper functions to the raw object interface. |
| 261 String name; | 267 String name; |
| 262 name = func->ptr()->name_; | 268 name = func->ptr()->name_; |
| 263 OS::Print("Detaching code: %s\n", name.ToCString()); | 269 ISL_Print("Detaching code: %s\n", name.ToCString()); |
| 270 current_code_count++; | |
| 264 } | 271 } |
| 265 } | 272 } |
| 266 } | 273 } |
| 274 for (int i = 0; i < skipped_unoptimized_code_functions_.length(); i++) { | |
| 275 RawFunction* func = skipped_unoptimized_code_functions_[i]; | |
| 276 RawCode* code = func->ptr()->unoptimized_code_; | |
| 277 if (!code->IsMarked()) { | |
| 278 // If the code wasn't strongly visited through other references | |
| 279 // after skipping the function's code pointer, then we disconnect the | |
| 280 // code from the function. | |
| 281 func->StorePointer(&(func->ptr()->unoptimized_code_), Code::null()); | |
| 282 if (FLAG_log_code_drop) { | |
| 283 unoptimized_code_count++; | |
| 284 } | |
| 285 } | |
| 286 } | |
| 287 if (FLAG_log_code_drop) { | |
| 288 ISL_Print(" total detached current: %" Pd "\n", current_code_count); | |
| 289 ISL_Print(" total detached unoptimized: %" Pd "\n", | |
| 290 unoptimized_code_count); | |
| 291 } | |
| 267 } | 292 } |
| 268 | 293 |
| 269 Heap* heap_; | 294 Heap* heap_; |
| 270 Heap* vm_heap_; | 295 Heap* vm_heap_; |
| 271 ClassTable* class_table_; | 296 ClassTable* class_table_; |
| 272 PageSpace* page_space_; | 297 PageSpace* page_space_; |
| 273 MarkingStack* marking_stack_; | 298 MarkingStack* marking_stack_; |
| 274 RawObject* visiting_old_object_; | 299 RawObject* visiting_old_object_; |
| 275 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet; | 300 typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet; |
| 276 typedef std::pair<RawObject*, RawWeakProperty*> DelaySetEntry; | 301 typedef std::pair<RawObject*, RawWeakProperty*> DelaySetEntry; |
| 277 DelaySet delay_set_; | 302 DelaySet delay_set_; |
| 278 const bool visit_function_code_; | 303 const bool visit_function_code_; |
| 279 GrowableArray<RawFunction*> skipped_code_functions_; | 304 GrowableArray<RawFunction*> skipped_current_code_functions_; |
| 305 GrowableArray<RawFunction*> skipped_unoptimized_code_functions_; | |
| 280 | 306 |
| 281 DISALLOW_IMPLICIT_CONSTRUCTORS(MarkingVisitor); | 307 DISALLOW_IMPLICIT_CONSTRUCTORS(MarkingVisitor); |
| 282 }; | 308 }; |
| 283 | 309 |
| 284 | 310 |
| 285 static bool IsUnreachable(const RawObject* raw_obj) { | 311 static bool IsUnreachable(const RawObject* raw_obj) { |
| 286 if (!raw_obj->IsHeapObject()) { | 312 if (!raw_obj->IsHeapObject()) { |
| 287 return false; | 313 return false; |
| 288 } | 314 } |
| 289 if (raw_obj == Object::null()) { | 315 if (raw_obj == Object::null()) { |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 515 MarkingWeakVisitor mark_weak; | 541 MarkingWeakVisitor mark_weak; |
| 516 IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks); | 542 IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks); |
| 517 mark.Finalize(); | 543 mark.Finalize(); |
| 518 ProcessWeakTables(page_space); | 544 ProcessWeakTables(page_space); |
| 519 ProcessObjectIdTable(isolate); | 545 ProcessObjectIdTable(isolate); |
| 520 } | 546 } |
| 521 Epilogue(isolate, invoke_api_callbacks); | 547 Epilogue(isolate, invoke_api_callbacks); |
| 522 } | 548 } |
| 523 | 549 |
| 524 } // namespace dart | 550 } // namespace dart |
| OLD | NEW |