1 // Copyright 2020 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 #ifndef V8_HANDLES_LOCAL_HANDLES_INL_H_
6 #define V8_HANDLES_LOCAL_HANDLES_INL_H_
7
8 #include "src/base/sanitizer/msan.h"
9 #include "src/execution/isolate.h"
10 #include "src/execution/local-isolate.h"
11 #include "src/handles/local-handles.h"
12
13 namespace v8 {
14 namespace internal {
15
16 // static
GetHandle(LocalHeap * local_heap,Address value)17 V8_INLINE Address* LocalHandleScope::GetHandle(LocalHeap* local_heap,
18 Address value) {
19 DCHECK(local_heap->IsRunning());
20 if (local_heap->is_main_thread())
21 return LocalHandleScope::GetMainThreadHandle(local_heap, value);
22
23 LocalHandles* handles = local_heap->handles();
24 Address* result = handles->scope_.next;
25 if (result == handles->scope_.limit) {
26 result = handles->AddBlock();
27 }
28 DCHECK_LT(result, handles->scope_.limit);
29 handles->scope_.next++;
30 *result = value;
31 return result;
32 }
33
LocalHandleScope(LocalIsolate * local_isolate)34 LocalHandleScope::LocalHandleScope(LocalIsolate* local_isolate)
35 : LocalHandleScope(local_isolate->heap()) {}
36
LocalHandleScope(LocalHeap * local_heap)37 LocalHandleScope::LocalHandleScope(LocalHeap* local_heap) {
38 DCHECK(local_heap->IsRunning());
39
40 if (local_heap->is_main_thread()) {
41 OpenMainThreadScope(local_heap);
42 } else {
43 LocalHandles* handles = local_heap->handles();
44 local_heap_ = local_heap;
45 prev_next_ = handles->scope_.next;
46 prev_limit_ = handles->scope_.limit;
47 handles->scope_.level++;
48 }
49 }
50
~LocalHandleScope()51 LocalHandleScope::~LocalHandleScope() {
52 if (local_heap_->is_main_thread()) {
53 CloseMainThreadScope(local_heap_, prev_next_, prev_limit_);
54 } else {
55 CloseScope(local_heap_, prev_next_, prev_limit_);
56 }
57 }
58
59 template <typename T>
CloseAndEscape(Handle<T> handle_value)60 Handle<T> LocalHandleScope::CloseAndEscape(Handle<T> handle_value) {
61 HandleScopeData* current;
62 T value = *handle_value;
63 // Throw away all handles in the current scope.
64 if (local_heap_->is_main_thread()) {
65 current = local_heap_->heap()->isolate()->handle_scope_data();
66 CloseMainThreadScope(local_heap_, prev_next_, prev_limit_);
67 } else {
68 current = &local_heap_->handles()->scope_;
69 CloseScope(local_heap_, prev_next_, prev_limit_);
70 }
71 // Allocate one handle in the parent scope.
72 DCHECK(current->level > current->sealed_level);
73 Handle<T> result(value, local_heap_);
74 // Reinitialize the current scope (so that it's ready
75 // to be used or closed again).
76 prev_next_ = current->next;
77 prev_limit_ = current->limit;
78 current->level++;
79 return result;
80 }
81
CloseScope(LocalHeap * local_heap,Address * prev_next,Address * prev_limit)82 void LocalHandleScope::CloseScope(LocalHeap* local_heap, Address* prev_next,
83 Address* prev_limit) {
84 LocalHandles* handles = local_heap->handles();
85 Address* old_limit = handles->scope_.limit;
86
87 handles->scope_.next = prev_next;
88 handles->scope_.limit = prev_limit;
89 handles->scope_.level--;
90
91 if (old_limit != handles->scope_.limit) {
92 handles->RemoveUnusedBlocks();
93 old_limit = handles->scope_.limit;
94 }
95
96 #ifdef ENABLE_HANDLE_ZAPPING
97 LocalHandles::ZapRange(handles->scope_.next, old_limit);
98 #endif
99
100 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(
101 handles->scope_.next,
102 static_cast<size_t>(reinterpret_cast<Address>(old_limit) -
103 reinterpret_cast<Address>(handles->scope_.next)));
104 }
105
106 } // namespace internal
107 } // namespace v8
108
109 #endif // V8_HANDLES_LOCAL_HANDLES_INL_H_
110