1// Copyright 2006-2008 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_INL_H_
6#define V8_HANDLES_INL_H_
7
8#include "src/handles.h"
9#include "src/isolate.h"
10#include "src/msan.h"
11
12namespace v8 {
13namespace internal {
14
15HandleBase::HandleBase(Address object, Isolate* isolate)
16 : location_(HandleScope::GetHandle(isolate, object)) {}
17
18// Allocate a new handle for the object, do not canonicalize.
19
20template <typename T>
21Handle<T> Handle<T>::New(T object, Isolate* isolate) {
22 return Handle(HandleScope::CreateHandle(isolate, object.ptr()));
23}
24
25template <typename T>
26template <typename S>
27const Handle<T> Handle<T>::cast(Handle<S> that) {
28 T::cast(*FullObjectSlot(that.location()));
29 return Handle<T>(that.location_);
30}
31
32HandleScope::HandleScope(Isolate* isolate) {
33 HandleScopeData* data = isolate->handle_scope_data();
34 isolate_ = isolate;
35 prev_next_ = data->next;
36 prev_limit_ = data->limit;
37 data->level++;
38}
39
40template <typename T>
41Handle<T>::Handle(T object, Isolate* isolate)
42 : HandleBase(object.ptr(), isolate) {}
43
44template <typename T>
45V8_INLINE Handle<T> handle(T object, Isolate* isolate) {
46 return Handle<T>(object, isolate);
47}
48
49template <typename T>
50inline std::ostream& operator<<(std::ostream& os, Handle<T> handle) {
51 return os << Brief(*handle);
52}
53
54HandleScope::~HandleScope() {
55#ifdef DEBUG
56 if (FLAG_check_handle_count) {
57 int before = NumberOfHandles(isolate_);
58 CloseScope(isolate_, prev_next_, prev_limit_);
59 int after = NumberOfHandles(isolate_);
60 DCHECK_LT(after - before, kCheckHandleThreshold);
61 DCHECK_LT(before, kCheckHandleThreshold);
62 } else {
63#endif // DEBUG
64 CloseScope(isolate_, prev_next_, prev_limit_);
65#ifdef DEBUG
66 }
67#endif // DEBUG
68}
69
70void HandleScope::CloseScope(Isolate* isolate, Address* prev_next,
71 Address* prev_limit) {
72 HandleScopeData* current = isolate->handle_scope_data();
73
74 std::swap(current->next, prev_next);
75 current->level--;
76 Address* limit = prev_next;
77 if (current->limit != prev_limit) {
78 current->limit = prev_limit;
79 limit = prev_limit;
80 DeleteExtensions(isolate);
81 }
82#ifdef ENABLE_HANDLE_ZAPPING
83 ZapRange(current->next, limit);
84#endif
85 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(
86 current->next,
87 static_cast<size_t>(reinterpret_cast<Address>(limit) -
88 reinterpret_cast<Address>(current->next)));
89}
90
91template <typename T>
92Handle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) {
93 HandleScopeData* current = isolate_->handle_scope_data();
94 T value = *handle_value;
95 // Throw away all handles in the current scope.
96 CloseScope(isolate_, prev_next_, prev_limit_);
97 // Allocate one handle in the parent scope.
98 DCHECK(current->level > current->sealed_level);
99 Handle<T> result(value, isolate_);
100 // Reinitialize the current scope (so that it's ready
101 // to be used or closed again).
102 prev_next_ = current->next;
103 prev_limit_ = current->limit;
104 current->level++;
105 return result;
106}
107
108Address* HandleScope::CreateHandle(Isolate* isolate, Address value) {
109 DCHECK(AllowHandleAllocation::IsAllowed());
110 HandleScopeData* data = isolate->handle_scope_data();
111 Address* result = data->next;
112 if (result == data->limit) {
113 result = Extend(isolate);
114 }
115 // Update the current next field, set the value in the created handle,
116 // and return the result.
117 DCHECK_LT(reinterpret_cast<Address>(result),
118 reinterpret_cast<Address>(data->limit));
119 data->next = reinterpret_cast<Address*>(reinterpret_cast<Address>(result) +
120 sizeof(Address));
121 *result = value;
122 return result;
123}
124
125Address* HandleScope::GetHandle(Isolate* isolate, Address value) {
126 DCHECK(AllowHandleAllocation::IsAllowed());
127 HandleScopeData* data = isolate->handle_scope_data();
128 CanonicalHandleScope* canonical = data->canonical_scope;
129 return canonical ? canonical->Lookup(value) : CreateHandle(isolate, value);
130}
131
132
133#ifdef DEBUG
134inline SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(isolate) {
135 // Make sure the current thread is allowed to create handles to begin with.
136 DCHECK(AllowHandleAllocation::IsAllowed());
137 HandleScopeData* current = isolate_->handle_scope_data();
138 // Shrink the current handle scope to make it impossible to do
139 // handle allocations without an explicit handle scope.
140 prev_limit_ = current->limit;
141 current->limit = current->next;
142 prev_sealed_level_ = current->sealed_level;
143 current->sealed_level = current->level;
144}
145
146
147inline SealHandleScope::~SealHandleScope() {
148 // Restore state in current handle scope to re-enable handle
149 // allocations.
150 HandleScopeData* current = isolate_->handle_scope_data();
151 DCHECK_EQ(current->next, current->limit);
152 current->limit = prev_limit_;
153 DCHECK_EQ(current->level, current->sealed_level);
154 current->sealed_level = prev_sealed_level_;
155}
156
157#endif
158
159} // namespace internal
160} // namespace v8
161
162#endif // V8_HANDLES_INL_H_
163