1// Copyright 2012 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/handles/local-handles.h"
6
7#include "src/api/api.h"
8#include "src/execution/isolate.h"
9#include "src/handles/handles-inl.h"
10#include "src/handles/handles.h"
11#include "src/heap/heap-inl.h"
12
13namespace v8 {
14namespace internal {
15
16Address* LocalHandleScope::GetMainThreadHandle(LocalHeap* local_heap,
17                                               Address value) {
18  Isolate* isolate = local_heap->heap()->isolate();
19  return HandleScope::GetHandle(isolate, value);
20}
21
22void LocalHandleScope::OpenMainThreadScope(LocalHeap* local_heap) {
23  Isolate* isolate = local_heap->heap()->isolate();
24  HandleScopeData* data = isolate->handle_scope_data();
25  local_heap_ = local_heap;
26  prev_next_ = data->next;
27  prev_limit_ = data->limit;
28  data->level++;
29}
30
31void LocalHandleScope::CloseMainThreadScope(LocalHeap* local_heap,
32                                            Address* prev_next,
33                                            Address* prev_limit) {
34  Isolate* isolate = local_heap->heap()->isolate();
35  HandleScope::CloseScope(isolate, prev_next, prev_limit);
36}
37
38LocalHandles::LocalHandles() { scope_.Initialize(); }
39LocalHandles::~LocalHandles() {
40  scope_.limit = nullptr;
41  RemoveUnusedBlocks();
42  DCHECK(blocks_.empty());
43}
44
45void LocalHandles::Iterate(RootVisitor* visitor) {
46  for (int i = 0; i < static_cast<int>(blocks_.size()) - 1; i++) {
47    Address* block = blocks_[i];
48    visitor->VisitRootPointers(Root::kHandleScope, nullptr,
49                               FullObjectSlot(block),
50                               FullObjectSlot(&block[kHandleBlockSize]));
51  }
52
53  if (!blocks_.empty()) {
54    Address* block = blocks_.back();
55    visitor->VisitRootPointers(Root::kHandleScope, nullptr,
56                               FullObjectSlot(block),
57                               FullObjectSlot(scope_.next));
58  }
59}
60
61#ifdef DEBUG
62bool LocalHandles::Contains(Address* location) {
63  // We have to search in all blocks since they have no guarantee of order.
64  for (auto it = blocks_.begin(); it != blocks_.end(); ++it) {
65    Address* lower_bound = *it;
66    // The last block is a special case because it may have less than
67    // block_size_ handles.
68    Address* upper_bound = lower_bound != blocks_.back()
69                               ? lower_bound + kHandleBlockSize
70                               : scope_.next;
71    if (lower_bound <= location && location < upper_bound) {
72      return true;
73    }
74  }
75  return false;
76}
77#endif
78
79Address* LocalHandles::AddBlock() {
80  DCHECK_EQ(scope_.next, scope_.limit);
81  Address* block = NewArray<Address>(kHandleBlockSize);
82  blocks_.push_back(block);
83  scope_.next = block;
84  scope_.limit = block + kHandleBlockSize;
85  return block;
86}
87
88void LocalHandles::RemoveUnusedBlocks() {
89  while (!blocks_.empty()) {
90    Address* block_start = blocks_.back();
91    Address* block_limit = block_start + kHandleBlockSize;
92
93    if (block_limit == scope_.limit) {
94      break;
95    }
96
97    blocks_.pop_back();
98
99#ifdef ENABLE_HANDLE_ZAPPING
100    ZapRange(block_start, block_limit);
101#endif
102
103    DeleteArray(block_start);
104  }
105}
106
107#ifdef ENABLE_HANDLE_ZAPPING
108void LocalHandles::ZapRange(Address* start, Address* end) {
109  HandleScope::ZapRange(start, end);
110}
111#endif
112
113}  // namespace internal
114}  // namespace v8
115