1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2008 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_HANDLES_INL_H_
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_HANDLES_INL_H_
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/api.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/handles.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/heap/heap.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/isolate.h"
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochtemplate<typename T>
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<T>::Handle(T* obj) {
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  location_ = HandleScope::CreateHandle(obj->GetIsolate(), obj);
2044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
2144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2344f0eee88ff00398ff7f715fab053374d808c90dSteve Blocktemplate<typename T>
2444f0eee88ff00398ff7f715fab053374d808c90dSteve BlockHandle<T>::Handle(T* obj, Isolate* isolate) {
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  location_ = HandleScope::CreateHandle(isolate, obj);
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename T>
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline bool Handle<T>::is_identical_to(const Handle<T> o) const {
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Dereferencing deferred handles to check object equality is safe.
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SLOW_DCHECK(
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (location_ == NULL || IsDereferenceAllowed(NO_DEFERRED_CHECK)) &&
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (o.location_ == NULL || o.IsDereferenceAllowed(NO_DEFERRED_CHECK)));
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (location_ == o.location_) return true;
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (location_ == NULL || o.location_ == NULL) return false;
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return *location_ == *o.location_;
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochtemplate <typename T>
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline T* Handle<T>::operator*() const {
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return *bit_cast<T**>(location_);
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename T>
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline T** Handle<T>::location() const {
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SLOW_DCHECK(location_ == NULL ||
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return location_;
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename T>
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Handle<T>::IsDereferenceAllowed(DereferenceCheckMode mode) const {
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(location_ != NULL);
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* object = *bit_cast<T**>(location_);
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (object->IsSmi()) return true;
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* heap_object = HeapObject::cast(object);
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap* heap = heap_object->GetHeap();
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object** handle = reinterpret_cast<Object**>(location_);
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object** roots_array_start = heap->roots_array_start();
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (roots_array_start <= handle &&
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      handle < roots_array_start + Heap::kStrongRootListLength &&
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      heap->RootCanBeTreatedAsConstant(
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        static_cast<Heap::RootListIndex>(handle - roots_array_start))) {
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return true;
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!AllowHandleDereference::IsAllowed()) return false;
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mode == INCLUDE_DEFERRED_CHECK &&
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      !AllowDeferredHandleDereference::IsAllowed()) {
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Accessing cells, maps and internalized strings is safe.
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (heap_object->IsCell()) return true;
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (heap_object->IsMap()) return true;
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (heap_object->IsInternalizedString()) return true;
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return !heap->isolate()->IsDeferredHandle(handle);
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return true;
8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8544f0eee88ff00398ff7f715fab053374d808c90dSteve BlockHandleScope::HandleScope(Isolate* isolate) {
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScopeData* current = isolate->handle_scope_data();
8744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate_ = isolate;
8844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  prev_next_ = current->next;
8944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  prev_limit_ = current->limit;
9044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  current->level++;
9144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9444f0eee88ff00398ff7f715fab053374d808c90dSteve BlockHandleScope::~HandleScope() {
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CloseScope(isolate_, prev_next_, prev_limit_);
9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
9744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HandleScope::CloseScope(Isolate* isolate,
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Object** prev_next,
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Object** prev_limit) {
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScopeData* current = isolate->handle_scope_data();
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  std::swap(current->next, prev_next);
10544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  current->level--;
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (current->limit != prev_limit) {
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    current->limit = prev_limit;
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeleteExtensions(isolate);
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef ENABLE_HANDLE_ZAPPING
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ZapRange(current->next, prev_limit);
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ZapRange(current->next, prev_next);
11344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
11544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
11644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11844f0eee88ff00398ff7f715fab053374d808c90dSteve Blocktemplate <typename T>
11944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockHandle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) {
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScopeData* current = isolate_->handle_scope_data();
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  T* value = *handle_value;
12344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Throw away all handles in the current scope.
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CloseScope(isolate_, prev_next_, prev_limit_);
12544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Allocate one handle in the parent scope.
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(current->level > 0);
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<T> result(CreateHandle<T>(isolate_, value));
12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Reinitialize the current scope (so that it's ready
12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // to be used or closed again).
13044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  prev_next_ = current->next;
13144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  prev_limit_ = current->limit;
13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  current->level++;
13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return result;
13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
13544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13744f0eee88ff00398ff7f715fab053374d808c90dSteve Blocktemplate <typename T>
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochT** HandleScope::CreateHandle(Isolate* isolate, T* value) {
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(AllowHandleAllocation::IsAllowed());
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScopeData* current = isolate->handle_scope_data();
14144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
14244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  internal::Object** cur = current->next;
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cur == current->limit) cur = Extend(isolate);
14444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Update the current next field, set the value in the created
14544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // handle, and return the result.
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cur < current->limit);
14744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  current->next = cur + 1;
14844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
14944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  T** result = reinterpret_cast<T**>(cur);
15044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  *result = value;
15144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return result;
15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
15344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
15444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(isolate) {
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Make sure the current thread is allowed to create handles to begin with.
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(AllowHandleAllocation::IsAllowed());
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScopeData* current = isolate_->handle_scope_data();
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shrink the current handle scope to make it impossible to do
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // handle allocations without an explicit handle scope.
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  limit_ = current->limit;
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current->limit = current->next;
1645913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  level_ = current->level;
1655913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  current->level = 0;
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline SealHandleScope::~SealHandleScope() {
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore state in current handle scope to re-enable handle
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // allocations.
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScopeData* current = isolate_->handle_scope_data();
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, current->level);
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  current->level = level_;
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(current->next, current->limit);
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  current->limit = limit_;
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_HANDLES_INL_H_
184