1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/context-measure.h" 6 7 #include "src/base/logging.h" 8 #include "src/contexts.h" 9 #include "src/objects-inl.h" 10 11 namespace v8 { 12 namespace internal { 13 14 ContextMeasure::ContextMeasure(Context* context) 15 : context_(context), 16 root_index_map_(context->GetIsolate()), 17 recursion_depth_(0), 18 count_(0), 19 size_(0) { 20 DCHECK(context_->IsNativeContext()); 21 Object* next_link = context_->get(Context::NEXT_CONTEXT_LINK); 22 MeasureObject(context_); 23 MeasureDeferredObjects(); 24 context_->set(Context::NEXT_CONTEXT_LINK, next_link); 25 } 26 27 28 bool ContextMeasure::IsShared(HeapObject* object) { 29 if (object->IsScript()) return true; 30 if (object->IsSharedFunctionInfo()) return true; 31 if (object->IsScopeInfo()) return true; 32 if (object->IsCode() && !Code::cast(object)->is_optimized_code()) return true; 33 if (object->IsExecutableAccessorInfo()) return true; 34 if (object->IsWeakCell()) return true; 35 return false; 36 } 37 38 39 void ContextMeasure::MeasureObject(HeapObject* object) { 40 if (back_reference_map_.Lookup(object).is_valid()) return; 41 if (root_index_map_.Lookup(object) != RootIndexMap::kInvalidRootIndex) return; 42 if (IsShared(object)) return; 43 back_reference_map_.Add(object, BackReference::DummyReference()); 44 recursion_depth_++; 45 if (recursion_depth_ > kMaxRecursion) { 46 deferred_objects_.Add(object); 47 } else { 48 MeasureAndRecurse(object); 49 } 50 recursion_depth_--; 51 } 52 53 54 void ContextMeasure::MeasureDeferredObjects() { 55 while (deferred_objects_.length() > 0) { 56 MeasureAndRecurse(deferred_objects_.RemoveLast()); 57 } 58 } 59 60 61 void ContextMeasure::MeasureAndRecurse(HeapObject* object) { 62 int size = object->Size(); 63 count_++; 64 size_ += size; 65 Map* map = object->map(); 66 MeasureObject(map); 67 object->IterateBody(map->instance_type(), size, this); 68 } 69 70 71 void ContextMeasure::VisitPointers(Object** start, Object** end) { 72 for (Object** current = start; current < end; current++) { 73 if ((*current)->IsSmi()) continue; 74 MeasureObject(HeapObject::cast(*current)); 75 } 76 } 77 } // namespace internal 78 } // namespace v8 79