global-handles.cc revision 44f0eee88ff00398ff7f715fab053374d808c90d
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "api.h"
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "global-handles.h"
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "vm-state-inl.h"
34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockObjectGroup::~ObjectGroup() {
4044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (info_ != NULL) info_->Dispose();
4144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
4244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass GlobalHandles::Node : public Malloced {
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Initialize(Object* object) {
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Set the initial value of the handle.
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    object_ = object;
5044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    state_  = NORMAL;
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    parameter_or_next_free_.parameter = NULL;
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    callback_ = NULL;
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
56d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Node() {
57d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    state_ = DESTROYED;
58d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
59d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit Node(Object* object) {
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Initialize(object);
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Initialize link structure.
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    next_ = NULL;
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~Node() {
6744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (state_ != DESTROYED) Destroy(Isolate::Current()->global_handles());
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Zap the values for eager trapping.
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    object_ = NULL;
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    next_ = NULL;
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    parameter_or_next_free_.next_free = NULL;
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Destroy(GlobalHandles* global_handles) {
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (state_ == WEAK || IsNearDeath()) {
7844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      global_handles->number_of_weak_handles_--;
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object_->IsJSGlobalObject()) {
8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        global_handles->number_of_global_object_weak_handles_--;
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    state_ = DESTROYED;
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Accessors for next_.
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Node* next() { return next_; }
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_next(Node* value) { next_ = value; }
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Node** next_addr() { return &next_; }
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Accessors for next free node in the free list.
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Node* next_free() {
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(state_ == DESTROYED);
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return parameter_or_next_free_.next_free;
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_next_free(Node* value) {
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(state_ == DESTROYED);
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    parameter_or_next_free_.next_free = value;
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns a link from the handle.
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Node* FromLocation(Object** location) {
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(OFFSET_OF(Node, object_) == 0);
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return reinterpret_cast<Node*>(location);
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the handle.
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> handle() { return Handle<Object>(&object_); }
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make this handle weak.
11144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void MakeWeak(GlobalHandles* global_handles, void* parameter,
11244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                WeakReferenceCallback callback) {
11344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LOG(global_handles->isolate(),
11444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        HandleEvent("GlobalHandle::MakeWeak", handle().location()));
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(state_ != DESTROYED);
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (state_ != WEAK && !IsNearDeath()) {
11744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      global_handles->number_of_weak_handles_++;
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object_->IsJSGlobalObject()) {
11944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        global_handles->number_of_global_object_weak_handles_++;
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    state_ = WEAK;
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    set_parameter(parameter);
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    callback_ = callback;
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void ClearWeakness(GlobalHandles* global_handles) {
12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LOG(global_handles->isolate(),
12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        HandleEvent("GlobalHandle::ClearWeakness", handle().location()));
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(state_ != DESTROYED);
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (state_ == WEAK || IsNearDeath()) {
13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      global_handles->number_of_weak_handles_--;
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object_->IsJSGlobalObject()) {
13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        global_handles->number_of_global_object_weak_handles_--;
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    state_ = NORMAL;
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    set_parameter(NULL);
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool IsNearDeath() {
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check for PENDING to ensure correct answer when processing callbacks.
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return state_ == PENDING || state_ == NEAR_DEATH;
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool IsWeak() {
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return state_ == WEAK;
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool CanBeRetainer() {
15144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return state_ != DESTROYED && state_ != NEAR_DEATH;
15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
15344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
15444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void SetWrapperClassId(uint16_t class_id) {
15544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    class_id_ = class_id;
15644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
15744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the id for this weak handle.
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_parameter(void* parameter) {
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(state_ != DESTROYED);
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    parameter_or_next_free_.parameter = parameter;
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void* parameter() {
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(state_ != DESTROYED);
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return parameter_or_next_free_.parameter;
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the callback for this weak handle.
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  WeakReferenceCallback callback() { return callback_; }
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool PostGarbageCollectionProcessing(Isolate* isolate,
17244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       GlobalHandles* global_handles) {
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (state_ != Node::PENDING) return false;
17444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LOG(isolate, HandleEvent("GlobalHandle::Processing", handle().location()));
17550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    WeakReferenceCallback func = callback();
17650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    if (func == NULL) {
17744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Destroy(global_handles);
17850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      return false;
17950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    }
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    void* par = parameter();
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    state_ = NEAR_DEATH;
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    set_parameter(NULL);
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle());
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    {
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Forbid reuse of destroyed nodes as they might be already deallocated.
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // It's fine though to reuse nodes that were destroyed in weak callback
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // as those cannot be deallocated until we are back from the callback.
18944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      global_handles->set_first_free(NULL);
19044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (global_handles->first_deallocated()) {
19144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        global_handles->first_deallocated()->set_next(global_handles->head());
192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Check that we are not passing a finalized external string to
194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // the callback.
195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT(!object_->IsExternalAsciiString() ||
196e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke             ExternalAsciiString::cast(object_)->resource() != NULL);
197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT(!object_->IsExternalTwoByteString() ||
198e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke             ExternalTwoByteString::cast(object_)->resource() != NULL);
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Leaving V8.
20044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      VMState state(isolate, EXTERNAL);
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      func(object, par);
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
20350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    // Absense of explicit cleanup or revival of weak handle
20450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    // in most of the cases would lead to memory leak.
20550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    ASSERT(state_ != NEAR_DEATH);
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return true;
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Place the handle address first to avoid offset computation.
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* object_;  // Storage for object pointer.
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  uint16_t class_id_;
21344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Transition diagram:
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED }
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum State {
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    NORMAL,      // Normal global handle.
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    WEAK,        // Flagged as weak but not yet finalized.
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PENDING,     // Has been recognized as only reachable by weak handles.
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    NEAR_DEATH,  // Callback has informed the handle is near death.
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    DESTROYED
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
22344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  State state_ : 4;  // Need one more bit for MSVC as it treats enums as signed.
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle specific callback.
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  WeakReferenceCallback callback_;
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Provided data for callback.  In DESTROYED state, this is used for
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the free list link.
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  union {
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    void* parameter;
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Node* next_free;
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } parameter_or_next_free_;
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Linkage for the list.
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Node* next_;
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TRACK_MEMORY("GlobalHandles::Node")
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass GlobalHandles::Pool {
244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  public:
245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Pool() {
246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      current_ = new Chunk();
247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      current_->previous = NULL;
248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      next_ = current_->nodes;
249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      limit_ = current_->nodes + kNodesPerChunk;
250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
252bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    ~Pool() {
253bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      if (current_ != NULL) {
254bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        Release();
255bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      }
256bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    }
257bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Node* Allocate() {
259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (next_ < limit_) {
260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        return next_++;
261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      return SlowAllocate();
263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void Release() {
266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Chunk* current = current_;
267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      ASSERT(current != NULL);  // At least a single block must by allocated
268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      do {
269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        Chunk* previous = current->previous;
270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        delete current;
271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        current = previous;
272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } while (current != NULL);
273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      current_ = NULL;
274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      next_ = limit_ = NULL;
275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  private:
278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    static const int kNodesPerChunk = (1 << 12) - 1;
279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    struct Chunk : public Malloced {
280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Chunk* previous;
281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Node nodes[kNodesPerChunk];
282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    };
283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Node* SlowAllocate() {
285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Chunk* chunk = new Chunk();
286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      chunk->previous = current_;
287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      current_ = chunk;
288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Node* new_nodes = current_->nodes;
290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      next_ = new_nodes + 1;
291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      limit_ = new_nodes + kNodesPerChunk;
292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      return new_nodes;
293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Chunk* current_;
296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Node* next_;
297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Node* limit_;
298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block};
299d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
30144f0eee88ff00398ff7f715fab053374d808c90dSteve BlockGlobalHandles::GlobalHandles(Isolate* isolate)
30244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : isolate_(isolate),
30344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      number_of_weak_handles_(0),
30444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      number_of_global_object_weak_handles_(0),
30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      head_(NULL),
30644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      first_free_(NULL),
30744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      first_deallocated_(NULL),
30844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      pool_(new Pool()),
30944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      post_gc_processing_count_(0),
31044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      object_groups_(4) {
31144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
31244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
31344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
31444f0eee88ff00398ff7f715fab053374d808c90dSteve BlockGlobalHandles::~GlobalHandles() {
31544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  delete pool_;
31644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  pool_ = 0;
31744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Object> GlobalHandles::Create(Object* value) {
32144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate_->counters()->global_handles()->Increment();
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Node* result;
323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (first_free()) {
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Take the first node in the free list.
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result = first_free();
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    set_first_free(result->next_free());
327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (first_deallocated()) {
328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Next try deallocated list
329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    result = first_deallocated();
330d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    set_first_deallocated(result->next_free());
331d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(result->next() == head());
332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    set_head(result);
333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Allocate a new node.
33544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    result = pool_->Allocate();
336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    result->set_next(head());
337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    set_head(result);
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  result->Initialize(value);
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result->handle();
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::Destroy(Object** location) {
34544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate_->counters()->global_handles()->Decrement();
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (location == NULL) return;
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Node* node = Node::FromLocation(location);
34844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  node->Destroy(this);
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Link the destroyed.
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  node->set_next_free(first_free());
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  set_first_free(node);
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::MakeWeak(Object** location, void* parameter,
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             WeakReferenceCallback callback) {
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(callback != NULL);
35844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Node::FromLocation(location)->MakeWeak(this, parameter, callback);
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::ClearWeakness(Object** location) {
36344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Node::FromLocation(location)->ClearWeakness(this);
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool GlobalHandles::IsNearDeath(Object** location) {
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Node::FromLocation(location)->IsNearDeath();
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool GlobalHandles::IsWeak(Object** location) {
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Node::FromLocation(location)->IsWeak();
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid GlobalHandles::SetWrapperClassId(Object** location, uint16_t class_id) {
37844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Node::FromLocation(location)->SetWrapperClassId(class_id);
37944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
38044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
38144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::IterateWeakRoots(ObjectVisitor* v) {
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Traversal of GC roots in the global handle list that are marked as
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // WEAK or PENDING.
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (Node* current = head_; current != NULL; current = current->next()) {
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (current->state_ == Node::WEAK
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      || current->state_ == Node::PENDING
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      || current->state_ == Node::NEAR_DEATH) {
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v->VisitPointer(&current->object_);
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid GlobalHandles::IterateWeakRoots(WeakReferenceGuest f,
3963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                     WeakReferenceCallback callback) {
3973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (Node* current = head_; current != NULL; current = current->next()) {
3983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (current->IsWeak() && current->callback() == callback) {
3993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      f(current->object_, current->parameter());
4003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
4013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
4023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
4033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) {
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (Node* current = head_; current != NULL; current = current->next()) {
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (current->state_ == Node::WEAK) {
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (f(&current->object_)) {
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        current->state_ = Node::PENDING;
41044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        LOG(isolate_,
41144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            HandleEvent("GlobalHandle::Pending", current->handle().location()));
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhubool GlobalHandles::PostGarbageCollectionProcessing() {
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Process weak global handle callbacks. This must be done after the
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // GC is completely done, because the callbacks may invoke arbitrary
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // API functions.
422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // At the same time deallocate all DESTROYED nodes.
42344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(isolate_->heap()->gc_state() == Heap::NOT_IN_GC);
42444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int initial_post_gc_processing_count = ++post_gc_processing_count_;
4253e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  bool next_gc_likely_to_collect_more = false;
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Node** p = &head_;
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (*p != NULL) {
42844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if ((*p)->PostGarbageCollectionProcessing(isolate_, this)) {
42944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (initial_post_gc_processing_count != post_gc_processing_count_) {
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Weak callback triggered another GC and another round of
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // PostGarbageCollection processing.  The current node might
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // have been deleted in that round, so we need to bail out (or
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // restart the processing).
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((*p)->state_ == Node::DESTROYED) {
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Delete the link.
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Node* node = *p;
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *p = node->next();  // Update the link.
441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (first_deallocated()) {
442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        first_deallocated()->set_next(node);
443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      node->set_next_free(first_deallocated());
445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      set_first_deallocated(node);
4463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      next_gc_likely_to_collect_more = true;
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      p = (*p)->next_addr();
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  set_first_free(NULL);
452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (first_deallocated()) {
453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    first_deallocated()->set_next(head());
454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
4553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
4563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  return next_gc_likely_to_collect_more;
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid GlobalHandles::IterateStrongRoots(ObjectVisitor* v) {
461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Traversal of global handles marked as NORMAL.
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (Node* current = head_; current != NULL; current = current->next()) {
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (current->state_ == Node::NORMAL) {
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v->VisitPointer(&current->object_);
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid GlobalHandles::IterateAllRoots(ObjectVisitor* v) {
471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (Node* current = head_; current != NULL; current = current->next()) {
472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (current->state_ != Node::DESTROYED) {
473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      v->VisitPointer(&current->object_);
474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
476d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
477d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
47944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid GlobalHandles::IterateAllRootsWithClassIds(ObjectVisitor* v) {
48044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (Node* current = head_; current != NULL; current = current->next()) {
48144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (current->class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId &&
48244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        current->CanBeRetainer()) {
48344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      v->VisitEmbedderReference(&current->object_, current->class_id_);
48444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
48544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
48644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
48744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
48844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
489d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid GlobalHandles::TearDown() {
490d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Reset all the lists.
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  set_head(NULL);
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  set_first_free(NULL);
493d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  set_first_deallocated(NULL);
49444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  pool_->Release();
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid GlobalHandles::RecordStats(HeapStats* stats) {
499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  *stats->global_handle_count = 0;
500d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  *stats->weak_global_handle_count = 0;
501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  *stats->pending_global_handle_count = 0;
502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  *stats->near_death_global_handle_count = 0;
503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  *stats->destroyed_global_handle_count = 0;
504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (Node* current = head_; current != NULL; current = current->next()) {
505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    *stats->global_handle_count += 1;
506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (current->state_ == Node::WEAK) {
507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      *stats->weak_global_handle_count += 1;
508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else if (current->state_ == Node::PENDING) {
509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      *stats->pending_global_handle_count += 1;
510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else if (current->state_ == Node::NEAR_DEATH) {
511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      *stats->near_death_global_handle_count += 1;
512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else if (current->state_ == Node::DESTROYED) {
513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      *stats->destroyed_global_handle_count += 1;
514d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
515d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
516d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::PrintStats() {
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int total = 0;
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int weak = 0;
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int pending = 0;
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int near_death = 0;
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int destroyed = 0;
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (Node* current = head_; current != NULL; current = current->next()) {
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    total++;
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (current->state_ == Node::WEAK) weak++;
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (current->state_ == Node::PENDING) pending++;
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (current->state_ == Node::NEAR_DEATH) near_death++;
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (current->state_ == Node::DESTROYED) destroyed++;
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("Global Handle Statistics:\n");
536f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  PrintF("  allocated memory = %" V8_PTR_PREFIX "dB\n", sizeof(Node) * total);
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("  # weak       = %d\n", weak);
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("  # pending    = %d\n", pending);
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("  # near_death = %d\n", near_death);
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("  # destroyed  = %d\n", destroyed);
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("  # total      = %d\n", total);
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::Print() {
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("Global handles:\n");
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (Node* current = head_; current != NULL; current = current->next()) {
547f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    PrintF("  handle %p to %p (weak=%d)\n",
548f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch           reinterpret_cast<void*>(current->handle().location()),
549f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch           reinterpret_cast<void*>(*current->handle()),
550f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch           current->state_ == Node::WEAK);
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
55744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
55844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid GlobalHandles::AddObjectGroup(Object*** handles,
55944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   size_t length,
56044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   v8::RetainedObjectInfo* info) {
56144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ObjectGroup* new_entry = new ObjectGroup(length, info);
56244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (size_t i = 0; i < length; ++i) {
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    new_entry->objects_.Add(handles[i]);
56444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
56544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  object_groups_.Add(new_entry);
56644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
56744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
56844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
56944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid GlobalHandles::AddImplicitReferences(HeapObject* parent,
57044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                          Object*** children,
57144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                          size_t length) {
57244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ImplicitRefGroup* new_entry = new ImplicitRefGroup(parent, length);
57344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (size_t i = 0; i < length; ++i) {
57444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    new_entry->children_.Add(children[i]);
57544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
57644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  implicit_ref_groups_.Add(new_entry);
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::RemoveObjectGroups() {
58144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < object_groups_.length(); i++) {
58244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    delete object_groups_.at(i);
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
58444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  object_groups_.Clear();
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
58744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
58844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid GlobalHandles::RemoveImplicitRefGroups() {
58944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < implicit_ref_groups_.length(); i++) {
59044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    delete implicit_ref_groups_.at(i);
59144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
59244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  implicit_ref_groups_.Clear();
59344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
59444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
59544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
597