Line data Source code
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.h"
6 :
7 : #include "src/address-map.h"
8 : #include "src/api.h"
9 : #include "src/base/logging.h"
10 : #include "src/identity-map.h"
11 : #include "src/objects-inl.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 :
16 : // Handles should be trivially copyable so that they can be efficiently passed
17 : // by value. If they are not trivially copyable, they cannot be passed in
18 : // registers.
19 : static_assert(IS_TRIVIALLY_COPYABLE(HandleBase),
20 : "HandleBase should be trivially copyable");
21 : static_assert(IS_TRIVIALLY_COPYABLE(Handle<Object>),
22 : "Handle<Object> should be trivially copyable");
23 : static_assert(IS_TRIVIALLY_COPYABLE(MaybeHandle<Object>),
24 : "MaybeHandle<Object> should be trivially copyable");
25 :
26 : #ifdef DEBUG
27 : bool HandleBase::IsDereferenceAllowed(DereferenceCheckMode mode) const {
28 : DCHECK_NOT_NULL(location_);
29 : Object* object = *location_;
30 : if (object->IsSmi()) return true;
31 : HeapObject* heap_object = HeapObject::cast(object);
32 : Heap* heap = heap_object->GetHeap();
33 : Object** roots_array_start = heap->roots_array_start();
34 : if (roots_array_start <= location_ &&
35 : location_ < roots_array_start + Heap::kStrongRootListLength &&
36 : heap->RootCanBeTreatedAsConstant(
37 : static_cast<Heap::RootListIndex>(location_ - roots_array_start))) {
38 : return true;
39 : }
40 : if (!AllowHandleDereference::IsAllowed()) return false;
41 : if (mode == INCLUDE_DEFERRED_CHECK &&
42 : !AllowDeferredHandleDereference::IsAllowed()) {
43 : // Accessing cells, maps and internalized strings is safe.
44 : if (heap_object->IsCell()) return true;
45 : if (heap_object->IsMap()) return true;
46 : if (heap_object->IsInternalizedString()) return true;
47 : return !heap->isolate()->IsDeferredHandle(location_);
48 : }
49 : return true;
50 : }
51 : #endif
52 :
53 :
54 6058 : int HandleScope::NumberOfHandles(Isolate* isolate) {
55 : HandleScopeImplementer* impl = isolate->handle_scope_implementer();
56 6058 : int n = static_cast<int>(impl->blocks()->size());
57 6058 : if (n == 0) return 0;
58 12080 : return ((n - 1) * kHandleBlockSize) +
59 : static_cast<int>(
60 18120 : (isolate->handle_scope_data()->next - impl->blocks()->back()));
61 : }
62 :
63 :
64 2762833 : Object** HandleScope::Extend(Isolate* isolate) {
65 : HandleScopeData* current = isolate->handle_scope_data();
66 :
67 1381417 : Object** result = current->next;
68 :
69 : DCHECK(result == current->limit);
70 : // Make sure there's at least one scope on the stack and that the
71 : // top of the scope stack isn't a barrier.
72 1381416 : if (!Utils::ApiCheck(current->level != current->sealed_level,
73 : "v8::HandleScope::CreateHandle()",
74 1381417 : "Cannot create a handle without a HandleScope")) {
75 : return nullptr;
76 : }
77 : HandleScopeImplementer* impl = isolate->handle_scope_implementer();
78 : // If there's more room in the last block, we use that. This is used
79 : // for fast creation of scopes after scope barriers.
80 1381416 : if (!impl->blocks()->empty()) {
81 665279 : Object** limit = &impl->blocks()->back()[kHandleBlockSize];
82 665279 : if (current->limit != limit) {
83 0 : current->limit = limit;
84 : DCHECK_LT(limit - current->next, kHandleBlockSize);
85 : }
86 : }
87 :
88 : // If we still haven't found a slot for the handle, we extend the
89 : // current handle scope by allocating a new handle block.
90 1381416 : if (result == current->limit) {
91 : // If there's a spare block, use it for growing the current scope.
92 1381416 : result = impl->GetSpareOrNewBlock();
93 : // Add the extension to the global list of blocks, but count the
94 : // extension as part of the current scope.
95 1381416 : impl->blocks()->push_back(result);
96 1381414 : current->limit = &result[kHandleBlockSize];
97 : }
98 :
99 1381414 : return result;
100 : }
101 :
102 :
103 2323412 : void HandleScope::DeleteExtensions(Isolate* isolate) {
104 : HandleScopeData* current = isolate->handle_scope_data();
105 2323412 : isolate->handle_scope_implementer()->DeleteExtensions(current->limit);
106 1161723 : }
107 :
108 :
109 : #ifdef ENABLE_HANDLE_ZAPPING
110 940753980 : void HandleScope::ZapRange(Object** start, Object** end) {
111 : DCHECK_LE(end - start, kHandleBlockSize);
112 3959074125 : for (Object** p = start; p != end; p++) {
113 3018320145 : *reinterpret_cast<Address*>(p) = kHandleZapValue;
114 : }
115 940753980 : }
116 : #endif
117 :
118 :
119 58822 : Address HandleScope::current_level_address(Isolate* isolate) {
120 58822 : return reinterpret_cast<Address>(&isolate->handle_scope_data()->level);
121 : }
122 :
123 :
124 58822 : Address HandleScope::current_next_address(Isolate* isolate) {
125 58822 : return reinterpret_cast<Address>(&isolate->handle_scope_data()->next);
126 : }
127 :
128 :
129 58822 : Address HandleScope::current_limit_address(Isolate* isolate) {
130 58822 : return reinterpret_cast<Address>(&isolate->handle_scope_data()->limit);
131 : }
132 :
133 1025154 : CanonicalHandleScope::CanonicalHandleScope(Isolate* isolate)
134 1025154 : : isolate_(isolate), zone_(isolate->allocator(), ZONE_NAME) {
135 512576 : HandleScopeData* handle_scope_data = isolate_->handle_scope_data();
136 512576 : prev_canonical_scope_ = handle_scope_data->canonical_scope;
137 512576 : handle_scope_data->canonical_scope = this;
138 512576 : root_index_map_ = new RootIndexMap(isolate);
139 : identity_map_ = new IdentityMap<Object**, ZoneAllocationPolicy>(
140 1025155 : isolate->heap(), ZoneAllocationPolicy(&zone_));
141 512578 : canonical_level_ = handle_scope_data->level;
142 512578 : }
143 :
144 :
145 1025154 : CanonicalHandleScope::~CanonicalHandleScope() {
146 512576 : delete root_index_map_;
147 512578 : delete identity_map_;
148 512578 : isolate_->handle_scope_data()->canonical_scope = prev_canonical_scope_;
149 512577 : }
150 :
151 :
152 28415207 : Object** CanonicalHandleScope::Lookup(Object* object) {
153 : DCHECK_LE(canonical_level_, isolate_->handle_scope_data()->level);
154 28415207 : if (isolate_->handle_scope_data()->level != canonical_level_) {
155 : // We are in an inner handle scope. Do not canonicalize since we will leave
156 : // this handle scope while still being in the canonical scope.
157 33414 : return HandleScope::CreateHandle(isolate_, object);
158 : }
159 28381793 : if (object->IsHeapObject()) {
160 27795812 : int index = root_index_map_->Lookup(HeapObject::cast(object));
161 27795836 : if (index != RootIndexMap::kInvalidRootIndex) {
162 : return isolate_->heap()
163 1730854 : ->root_handle(static_cast<Heap::RootListIndex>(index))
164 : .location();
165 : }
166 : }
167 26650963 : Object*** entry = identity_map_->Get(object);
168 26650943 : if (*entry == nullptr) {
169 : // Allocate new handle location.
170 31940471 : *entry = HandleScope::CreateHandle(isolate_, object);
171 : }
172 26650940 : return reinterpret_cast<Object**>(*entry);
173 : }
174 :
175 :
176 9393 : DeferredHandleScope::DeferredHandleScope(Isolate* isolate)
177 9393 : : impl_(isolate->handle_scope_implementer()) {
178 18786 : impl_->BeginDeferredScope();
179 9393 : HandleScopeData* data = impl_->isolate()->handle_scope_data();
180 9393 : Object** new_next = impl_->GetSpareOrNewBlock();
181 9393 : Object** new_limit = &new_next[kHandleBlockSize];
182 : // Check that at least one HandleScope exists, see the class description.
183 : DCHECK(!impl_->blocks()->empty());
184 : // Check that we are not in a SealedHandleScope.
185 : DCHECK(data->limit == &impl_->blocks()->back()[kHandleBlockSize]);
186 9393 : impl_->blocks()->push_back(new_next);
187 :
188 : #ifdef DEBUG
189 : prev_level_ = data->level;
190 : #endif
191 9393 : data->level++;
192 9393 : prev_limit_ = data->limit;
193 9393 : prev_next_ = data->next;
194 9393 : data->next = new_next;
195 9393 : data->limit = new_limit;
196 9393 : }
197 :
198 :
199 9393 : DeferredHandleScope::~DeferredHandleScope() {
200 9393 : impl_->isolate()->handle_scope_data()->level--;
201 : DCHECK(handles_detached_);
202 : DCHECK(impl_->isolate()->handle_scope_data()->level == prev_level_);
203 9393 : }
204 :
205 :
206 9393 : DeferredHandles* DeferredHandleScope::Detach() {
207 18786 : DeferredHandles* deferred = impl_->Detach(prev_limit_);
208 9393 : HandleScopeData* data = impl_->isolate()->handle_scope_data();
209 9393 : data->next = prev_next_;
210 9393 : data->limit = prev_limit_;
211 : #ifdef DEBUG
212 : handles_detached_ = true;
213 : #endif
214 9393 : return deferred;
215 : }
216 :
217 : } // namespace internal
218 : } // namespace v8
|