blob: 4f5e9fe720e0b68710ee9e2e6dc23709513c6f89 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27//
28
29#ifndef V8_HANDLES_INL_H_
30#define V8_HANDLES_INL_H_
31
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000032#include "api.h"
ager@chromium.orgddb913d2009-01-27 10:01:48 +000033#include "apiutils.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000034#include "handles.h"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000035#include "isolate.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036
kasperl@chromium.org71affb52009-05-26 05:44:31 +000037namespace v8 {
38namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000039
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000040template<typename T>
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000041Handle<T>::Handle(T* obj) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +000042 ASSERT(!obj->IsFailure());
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000043 location_ = HandleScope::CreateHandle(obj->GetIsolate(), obj);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000044}
45
46
47template<typename T>
48Handle<T>::Handle(T* obj, Isolate* isolate) {
49 ASSERT(!obj->IsFailure());
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000050 location_ = HandleScope::CreateHandle(isolate, obj);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000051}
52
53
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000054template <typename T>
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000055inline bool Handle<T>::is_identical_to(const Handle<T> other) const {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000056 ASSERT(location_ == NULL || !(*location_)->IsFailure());
57 if (location_ == other.location_) return true;
58 if (location_ == NULL || other.location_ == NULL) return false;
ulan@chromium.org32d7dba2013-04-24 10:59:06 +000059 // Dereferencing deferred handles to check object equality is safe.
60 SLOW_ASSERT(IsDereferenceAllowed(true) && other.IsDereferenceAllowed(true));
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000061 return *location_ == *other.location_;
62}
63
64
65template <typename T>
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000066inline T* Handle<T>::operator*() const {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000067 ASSERT(location_ != NULL && !(*location_)->IsFailure());
ulan@chromium.org32d7dba2013-04-24 10:59:06 +000068 SLOW_ASSERT(IsDereferenceAllowed(false));
vegorov@chromium.org26c16f82010-08-11 13:41:03 +000069 return *BitCast<T**>(location_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000070}
71
yangguo@chromium.org003650e2013-01-24 16:31:08 +000072template <typename T>
73inline T** Handle<T>::location() const {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000074 ASSERT(location_ == NULL || !(*location_)->IsFailure());
75 SLOW_ASSERT(location_ == NULL || IsDereferenceAllowed(false));
yangguo@chromium.org003650e2013-01-24 16:31:08 +000076 return location_;
77}
78
ulan@chromium.org32d7dba2013-04-24 10:59:06 +000079#ifdef DEBUG
80template <typename T>
81bool Handle<T>::IsDereferenceAllowed(bool allow_deferred) const {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000082 ASSERT(location_ != NULL);
ulan@chromium.org32d7dba2013-04-24 10:59:06 +000083 Object* object = *BitCast<T**>(location_);
84 if (object->IsSmi()) return true;
85 HeapObject* heap_object = HeapObject::cast(object);
86 Isolate* isolate = heap_object->GetIsolate();
87 Object** handle = reinterpret_cast<Object**>(location_);
88 Object** roots_array_start = isolate->heap()->roots_array_start();
89 if (roots_array_start <= handle &&
90 handle < roots_array_start + Heap::kStrongRootListLength) {
91 return true;
92 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +000093 if (isolate->optimizing_compiler_thread()->IsOptimizerThread() &&
94 !Heap::RelocationLock::IsLockedByOptimizerThread(isolate->heap())) {
95 return false;
96 }
ulan@chromium.org32d7dba2013-04-24 10:59:06 +000097 switch (isolate->HandleDereferenceGuardState()) {
98 case HandleDereferenceGuard::ALLOW:
99 return true;
100 case HandleDereferenceGuard::DISALLOW:
101 return false;
102 case HandleDereferenceGuard::DISALLOW_DEFERRED:
103 // Accessing maps and internalized strings is safe.
104 if (heap_object->IsMap()) return true;
105 if (heap_object->IsInternalizedString()) return true;
106 return allow_deferred || !isolate->IsDeferredHandle(handle);
107 }
108 return false;
109}
110#endif
111
112
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000113
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000114HandleScope::HandleScope(Isolate* isolate) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000115 v8::ImplementationUtilities::HandleScopeData* current =
116 isolate->handle_scope_data();
117 isolate_ = isolate;
118 prev_next_ = current->next;
119 prev_limit_ = current->limit;
120 current->level++;
121}
122
123
124HandleScope::~HandleScope() {
125 CloseScope();
126}
127
128void HandleScope::CloseScope() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000129 v8::ImplementationUtilities::HandleScopeData* current =
130 isolate_->handle_scope_data();
131 current->next = prev_next_;
132 current->level--;
133 if (current->limit != prev_limit_) {
134 current->limit = prev_limit_;
135 DeleteExtensions(isolate_);
136 }
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000137#ifdef ENABLE_EXTRA_CHECKS
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000138 ZapRange(prev_next_, prev_limit_);
139#endif
140}
141
142
143template <typename T>
144Handle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) {
145 T* value = *handle_value;
146 // Throw away all handles in the current scope.
147 CloseScope();
148 v8::ImplementationUtilities::HandleScopeData* current =
149 isolate_->handle_scope_data();
150 // Allocate one handle in the parent scope.
151 ASSERT(current->level > 0);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000152 Handle<T> result(CreateHandle<T>(isolate_, value));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000153 // Reinitialize the current scope (so that it's ready
154 // to be used or closed again).
155 prev_next_ = current->next;
156 prev_limit_ = current->limit;
157 current->level++;
158 return result;
159}
160
161
162template <typename T>
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000163T** HandleScope::CreateHandle(Isolate* isolate, T* value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000164 v8::ImplementationUtilities::HandleScopeData* current =
165 isolate->handle_scope_data();
166
167 internal::Object** cur = current->next;
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000168 if (cur == current->limit) cur = Extend(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000169 // Update the current next field, set the value in the created
170 // handle, and return the result.
171 ASSERT(cur < current->limit);
172 current->next = cur + 1;
173
174 T** result = reinterpret_cast<T**>(cur);
175 *result = value;
176 return result;
177}
178
179
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000180#ifdef DEBUG
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000181inline NoHandleAllocation::NoHandleAllocation(Isolate* isolate)
182 : isolate_(isolate) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000183 v8::ImplementationUtilities::HandleScopeData* current =
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000184 isolate_->handle_scope_data();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000185
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000186 active_ = !isolate->optimizing_compiler_thread()->IsOptimizerThread();
187 if (active_) {
188 // Shrink the current handle scope to make it impossible to do
189 // handle allocations without an explicit handle scope.
190 current->limit = current->next;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000191
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000192 level_ = current->level;
193 current->level = 0;
194 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000195}
196
197
198inline NoHandleAllocation::~NoHandleAllocation() {
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000199 if (active_) {
200 // Restore state in current handle scope to re-enable handle
201 // allocations.
202 v8::ImplementationUtilities::HandleScopeData* data =
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000203 isolate_->handle_scope_data();
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000204 ASSERT_EQ(0, data->level);
205 data->level = level_;
206 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000207}
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000208
209
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000210HandleDereferenceGuard::HandleDereferenceGuard(Isolate* isolate, State state)
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000211 : isolate_(isolate) {
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000212 old_state_ = isolate_->HandleDereferenceGuardState();
213 isolate_->SetHandleDereferenceGuardState(state);
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000214}
215
216
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000217HandleDereferenceGuard::~HandleDereferenceGuard() {
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000218 isolate_->SetHandleDereferenceGuardState(old_state_);
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000219}
220
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000221#endif
222
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000223} } // namespace v8::internal
224
225#endif // V8_HANDLES_INL_H_