| 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 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 IterateObjects(&excluding_class); | 248 IterateObjects(&excluding_class); |
| 249 intptr_t size_excluding_class = excluding_class.size(); | 249 intptr_t size_excluding_class = excluding_class.size(); |
| 250 return size_total - size_excluding_class; | 250 return size_total - size_excluding_class; |
| 251 } | 251 } |
| 252 | 252 |
| 253 | 253 |
| 254 class RetainingPathVisitor : public ObjectGraph::Visitor { | 254 class RetainingPathVisitor : public ObjectGraph::Visitor { |
| 255 public: | 255 public: |
| 256 // We cannot use a GrowableObjectArray, since we must not trigger GC. | 256 // We cannot use a GrowableObjectArray, since we must not trigger GC. |
| 257 RetainingPathVisitor(RawObject* obj, const Array& path) | 257 RetainingPathVisitor(RawObject* obj, const Array& path) |
| 258 : obj_(obj), path_(path), length_(0) { | 258 : thread_(Thread::Current()), obj_(obj), path_(path), length_(0) { |
| 259 ASSERT(Thread::Current()->no_safepoint_scope_depth() != 0); | 259 ASSERT(Thread::Current()->no_safepoint_scope_depth() != 0); |
| 260 } | 260 } |
| 261 | 261 |
| 262 intptr_t length() const { return length_; } | 262 intptr_t length() const { return length_; } |
| 263 | 263 |
| 264 bool ShouldSkip(RawObject* obj) { | 264 bool ShouldSkip(RawObject* obj) { |
| 265 // A retaining path through ICData is never the only retaining path, | 265 // A retaining path through ICData is never the only retaining path, |
| 266 // and it is less informative than its alternatives. | 266 // and it is less informative than its alternatives. |
| 267 intptr_t cid = obj->GetClassId(); | 267 intptr_t cid = obj->GetClassId(); |
| 268 switch (cid) { | 268 switch (cid) { |
| 269 case kICDataCid: | 269 case kICDataCid: |
| 270 return true; | 270 return true; |
| 271 default: | 271 default: |
| 272 return false; | 272 return false; |
| 273 } | 273 } |
| 274 } | 274 } |
| 275 | 275 |
| 276 virtual Direction VisitObject(ObjectGraph::StackIterator* it) { | 276 virtual Direction VisitObject(ObjectGraph::StackIterator* it) { |
| 277 if (it->Get() != obj_) { | 277 if (it->Get() != obj_) { |
| 278 if (ShouldSkip(it->Get())) { | 278 if (ShouldSkip(it->Get())) { |
| 279 return kBacktrack; | 279 return kBacktrack; |
| 280 } else { | 280 } else { |
| 281 return kProceed; | 281 return kProceed; |
| 282 } | 282 } |
| 283 } else { | 283 } else { |
| 284 HANDLESCOPE(Isolate::Current()); | 284 HANDLESCOPE(thread_); |
| 285 Object& current = Object::Handle(); | 285 Object& current = Object::Handle(); |
| 286 Smi& offset_from_parent = Smi::Handle(); | 286 Smi& offset_from_parent = Smi::Handle(); |
| 287 do { | 287 do { |
| 288 intptr_t obj_index = length_ * 2; | 288 intptr_t obj_index = length_ * 2; |
| 289 intptr_t offset_index = obj_index + 1; | 289 intptr_t offset_index = obj_index + 1; |
| 290 if (!path_.IsNull() && offset_index < path_.Length()) { | 290 if (!path_.IsNull() && offset_index < path_.Length()) { |
| 291 current = it->Get(); | 291 current = it->Get(); |
| 292 path_.SetAt(obj_index, current); | 292 path_.SetAt(obj_index, current); |
| 293 offset_from_parent = Smi::New(it->OffsetFromParentInWords()); | 293 offset_from_parent = Smi::New(it->OffsetFromParentInWords()); |
| 294 path_.SetAt(offset_index, offset_from_parent); | 294 path_.SetAt(offset_index, offset_from_parent); |
| 295 } | 295 } |
| 296 ++length_; | 296 ++length_; |
| 297 } while (it->MoveToParent()); | 297 } while (it->MoveToParent()); |
| 298 return kAbort; | 298 return kAbort; |
| 299 } | 299 } |
| 300 } | 300 } |
| 301 | 301 |
| 302 private: | 302 private: |
| 303 Thread* thread_; |
| 303 RawObject* obj_; | 304 RawObject* obj_; |
| 304 const Array& path_; | 305 const Array& path_; |
| 305 intptr_t length_; | 306 intptr_t length_; |
| 306 }; | 307 }; |
| 307 | 308 |
| 308 | 309 |
| 309 intptr_t ObjectGraph::RetainingPath(Object* obj, const Array& path) { | 310 intptr_t ObjectGraph::RetainingPath(Object* obj, const Array& path) { |
| 310 NoSafepointScope no_safepoint_scope_; | 311 NoSafepointScope no_safepoint_scope_; |
| 311 // To break the trivial path, the handle 'obj' is temporarily cleared during | 312 // To break the trivial path, the handle 'obj' is temporarily cleared during |
| 312 // the search, but restored before returning. | 313 // the search, but restored before returning. |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 { | 474 { |
| 474 WritePointerVisitor ptr_writer(isolate(), stream); | 475 WritePointerVisitor ptr_writer(isolate(), stream); |
| 475 isolate()->IterateObjectPointers(&ptr_writer, false, false); | 476 isolate()->IterateObjectPointers(&ptr_writer, false, false); |
| 476 } | 477 } |
| 477 stream->WriteUnsigned(0); | 478 stream->WriteUnsigned(0); |
| 478 IterateObjects(&visitor); | 479 IterateObjects(&visitor); |
| 479 return visitor.count() + 1; // + root | 480 return visitor.count() + 1; // + root |
| 480 } | 481 } |
| 481 | 482 |
| 482 } // namespace dart | 483 } // namespace dart |
| OLD | NEW |