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
11namespace v8 {
12namespace internal {
13
14ContextMeasure::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_->next_context_link();
22  MeasureObject(context_);
23  MeasureDeferredObjects();
24  context_->set(Context::NEXT_CONTEXT_LINK, next_link);
25}
26
27
28bool 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->IsAccessorInfo()) return true;
34  if (object->IsWeakCell()) return true;
35  return false;
36}
37
38
39void ContextMeasure::MeasureObject(HeapObject* object) {
40  if (reference_map_.Lookup(object).is_valid()) return;
41  if (root_index_map_.Lookup(object) != RootIndexMap::kInvalidRootIndex) return;
42  if (IsShared(object)) return;
43  reference_map_.Add(object, SerializerReference::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
54void ContextMeasure::MeasureDeferredObjects() {
55  while (deferred_objects_.length() > 0) {
56    MeasureAndRecurse(deferred_objects_.RemoveLast());
57  }
58}
59
60
61void 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
71void 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