| // Copyright 2015 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/context-measure.h" |
| |
| #include "src/base/logging.h" |
| #include "src/contexts.h" |
| #include "src/objects-inl.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| ContextMeasure::ContextMeasure(Context* context) |
| : context_(context), |
| root_index_map_(context->GetIsolate()), |
| recursion_depth_(0), |
| count_(0), |
| size_(0) { |
| DCHECK(context_->IsNativeContext()); |
| Object* next_link = context_->next_context_link(); |
| MeasureObject(context_); |
| MeasureDeferredObjects(); |
| context_->set(Context::NEXT_CONTEXT_LINK, next_link); |
| } |
| |
| |
| bool ContextMeasure::IsShared(HeapObject* object) { |
| if (object->IsScript()) return true; |
| if (object->IsSharedFunctionInfo()) return true; |
| if (object->IsScopeInfo()) return true; |
| if (object->IsCode() && !Code::cast(object)->is_optimized_code()) return true; |
| if (object->IsAccessorInfo()) return true; |
| if (object->IsWeakCell()) return true; |
| return false; |
| } |
| |
| |
| void ContextMeasure::MeasureObject(HeapObject* object) { |
| if (reference_map_.Lookup(object).is_valid()) return; |
| if (root_index_map_.Lookup(object) != RootIndexMap::kInvalidRootIndex) return; |
| if (IsShared(object)) return; |
| reference_map_.Add(object, SerializerReference::DummyReference()); |
| recursion_depth_++; |
| if (recursion_depth_ > kMaxRecursion) { |
| deferred_objects_.Add(object); |
| } else { |
| MeasureAndRecurse(object); |
| } |
| recursion_depth_--; |
| } |
| |
| |
| void ContextMeasure::MeasureDeferredObjects() { |
| while (deferred_objects_.length() > 0) { |
| MeasureAndRecurse(deferred_objects_.RemoveLast()); |
| } |
| } |
| |
| |
| void ContextMeasure::MeasureAndRecurse(HeapObject* object) { |
| int size = object->Size(); |
| count_++; |
| size_ += size; |
| Map* map = object->map(); |
| MeasureObject(map); |
| object->IterateBody(map->instance_type(), size, this); |
| } |
| |
| |
| void ContextMeasure::VisitPointers(Object** start, Object** end) { |
| for (Object** current = start; current < end; current++) { |
| if ((*current)->IsSmi()) continue; |
| MeasureObject(HeapObject::cast(*current)); |
| } |
| } |
| } // namespace internal |
| } // namespace v8 |