| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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/object_graph.h" | 5 #include "vm/object_graph.h" |
| 6 | 6 |
| 7 #include "vm/dart.h" | 7 #include "vm/dart.h" |
| 8 #include "vm/growable_array.h" | 8 #include "vm/growable_array.h" |
| 9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
| 10 #include "vm/object.h" | 10 #include "vm/object.h" |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 // and it is less informative than its alternatives. | 312 // and it is less informative than its alternatives. |
| 313 intptr_t cid = obj->GetClassId(); | 313 intptr_t cid = obj->GetClassId(); |
| 314 switch (cid) { | 314 switch (cid) { |
| 315 case kICDataCid: | 315 case kICDataCid: |
| 316 return true; | 316 return true; |
| 317 default: | 317 default: |
| 318 return false; | 318 return false; |
| 319 } | 319 } |
| 320 } | 320 } |
| 321 | 321 |
| 322 bool ShouldStop(RawObject* obj) { |
| 323 // A static field is considered a root from a language point of view. |
| 324 if (obj->IsField()) { |
| 325 const Field& field = Field::Handle(static_cast<RawField*>(obj)); |
| 326 return field.is_static(); |
| 327 } |
| 328 return false; |
| 329 } |
| 330 |
| 331 void StartList() { |
| 332 was_last_array_ = false; |
| 333 } |
| 334 |
| 335 intptr_t HideNDescendant(RawObject* obj) { |
| 336 // A GrowableObjectArray overwrites its internal storage. |
| 337 // Keeping both of them in the list is redundant. |
| 338 if (was_last_array_ && obj->IsGrowableObjectArray()) { |
| 339 was_last_array_ = false; |
| 340 return 1; |
| 341 } |
| 342 // A LinkedHasMap overwrites its internal storage. |
| 343 // Keeping both of them in the list is redundant. |
| 344 if (was_last_array_ && obj->IsLinkedHashMap()) { |
| 345 was_last_array_ = false; |
| 346 return 1; |
| 347 } |
| 348 was_last_array_ = obj->IsArray(); |
| 349 return 0; |
| 350 } |
| 351 |
| 322 virtual Direction VisitObject(ObjectGraph::StackIterator* it) { | 352 virtual Direction VisitObject(ObjectGraph::StackIterator* it) { |
| 323 if (it->Get() != obj_) { | 353 if (it->Get() != obj_) { |
| 324 if (ShouldSkip(it->Get())) { | 354 if (ShouldSkip(it->Get())) { |
| 325 return kBacktrack; | 355 return kBacktrack; |
| 326 } else { | 356 } else { |
| 327 return kProceed; | 357 return kProceed; |
| 328 } | 358 } |
| 329 } else { | 359 } else { |
| 330 HANDLESCOPE(thread_); | 360 HANDLESCOPE(thread_); |
| 331 Object& current = Object::Handle(); | 361 Object& current = Object::Handle(); |
| 332 Smi& offset_from_parent = Smi::Handle(); | 362 Smi& offset_from_parent = Smi::Handle(); |
| 363 StartList(); |
| 333 do { | 364 do { |
| 365 // We collapse the backingstore of some internal objects. |
| 366 length_ -= HideNDescendant(it->Get()); |
| 334 intptr_t obj_index = length_ * 2; | 367 intptr_t obj_index = length_ * 2; |
| 335 intptr_t offset_index = obj_index + 1; | 368 intptr_t offset_index = obj_index + 1; |
| 336 if (!path_.IsNull() && offset_index < path_.Length()) { | 369 if (!path_.IsNull() && offset_index < path_.Length()) { |
| 337 current = it->Get(); | 370 current = it->Get(); |
| 338 path_.SetAt(obj_index, current); | 371 path_.SetAt(obj_index, current); |
| 339 offset_from_parent = Smi::New(it->OffsetFromParentInWords()); | 372 offset_from_parent = Smi::New(it->OffsetFromParentInWords()); |
| 340 path_.SetAt(offset_index, offset_from_parent); | 373 path_.SetAt(offset_index, offset_from_parent); |
| 341 } | 374 } |
| 342 ++length_; | 375 ++length_; |
| 343 } while (it->MoveToParent()); | 376 } while (!ShouldStop(it->Get()) && it->MoveToParent()); |
| 344 return kAbort; | 377 return kAbort; |
| 345 } | 378 } |
| 346 } | 379 } |
| 347 | 380 |
| 348 private: | 381 private: |
| 349 Thread* thread_; | 382 Thread* thread_; |
| 350 RawObject* obj_; | 383 RawObject* obj_; |
| 351 const Array& path_; | 384 const Array& path_; |
| 352 intptr_t length_; | 385 intptr_t length_; |
| 386 bool was_last_array_; |
| 353 }; | 387 }; |
| 354 | 388 |
| 355 | 389 |
| 356 intptr_t ObjectGraph::RetainingPath(Object* obj, const Array& path) { | 390 intptr_t ObjectGraph::RetainingPath(Object* obj, const Array& path) { |
| 357 NoSafepointScope no_safepoint_scope_; | 391 NoSafepointScope no_safepoint_scope_; |
| 358 // To break the trivial path, the handle 'obj' is temporarily cleared during | 392 // To break the trivial path, the handle 'obj' is temporarily cleared during |
| 359 // the search, but restored before returning. | 393 // the search, but restored before returning. |
| 360 RawObject* raw = obj->raw(); | 394 RawObject* raw = obj->raw(); |
| 361 *obj = Object::null(); | 395 *obj = Object::null(); |
| 362 RetainingPathVisitor visitor(raw, path); | 396 RetainingPathVisitor visitor(raw, path); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 { | 558 { |
| 525 WritePointerVisitor ptr_writer(isolate(), stream); | 559 WritePointerVisitor ptr_writer(isolate(), stream); |
| 526 isolate()->IterateObjectPointers(&ptr_writer, false); | 560 isolate()->IterateObjectPointers(&ptr_writer, false); |
| 527 } | 561 } |
| 528 stream->WriteUnsigned(0); | 562 stream->WriteUnsigned(0); |
| 529 IterateObjects(&visitor); | 563 IterateObjects(&visitor); |
| 530 return visitor.count() + 1; // + root | 564 return visitor.count() + 1; // + root |
| 531 } | 565 } |
| 532 | 566 |
| 533 } // namespace dart | 567 } // namespace dart |
| OLD | NEW |