global-handles.cc revision 958fae7ec3f466955f8e5b50fa5b8d38b9e91675
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 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.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h"
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/api.h"
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/global-handles.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/vm-state-inl.h"
11b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1644f0eee88ff00398ff7f715fab053374d808c90dSteve BlockObjectGroup::~ObjectGroup() {
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (info != NULL) info->Dispose();
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete[] objects;
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochImplicitRefGroup::~ImplicitRefGroup() {
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete[] children;
2444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
2544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass GlobalHandles::Node {
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // State transition diagram:
303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE }
313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  enum State {
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FREE = 0,
33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    NORMAL,      // Normal global handle.
34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    WEAK,        // Flagged as weak but not yet finalized.
35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    PENDING,     // Has been recognized as only reachable by weak handles.
36958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    NEAR_DEATH,  // Callback has informed the handle is near death.
37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    NUMBER_OF_NODE_STATES
383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  };
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Maps handle location (slot) to the containing node.
413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static Node* FromLocation(Object** location) {
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(OFFSET_OF(Node, object_) == 0);
433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return reinterpret_cast<Node*>(location);
44d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
45d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node() {
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(OFFSET_OF(Node, class_id_) == Internals::kNodeClassIdOffset);
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(OFFSET_OF(Node, flags_) == Internals::kNodeFlagsOffset);
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<int>(NodeState::kMask) ==
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Internals::kNodeStateMask);
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(WEAK == Internals::kNodeStateIsWeakValue);
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(PENDING == Internals::kNodeStateIsPendingValue);
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(NEAR_DEATH == Internals::kNodeStateIsNearDeathValue);
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<int>(IsIndependent::kShift) ==
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Internals::kNodeIsIndependentShift);
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(static_cast<int>(IsPartiallyDependent::kShift) ==
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Internals::kNodeIsPartiallyDependentShift);
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef ENABLE_HANDLE_ZAPPING
613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ~Node() {
623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // TODO(1428): if it's a weak handle we should have invoked its callback.
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Zap the values for eager trapping.
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue);
653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    index_ = 0;
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_independent(false);
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_partially_dependent(false);
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_in_new_space_list(false);
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    parameter_or_next_free_.next_free = NULL;
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    weak_callback_ = NULL;
723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Initialize(int index, Node** first_free) {
763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    index_ = static_cast<uint8_t>(index);
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(static_cast<int>(index_) == index);
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_state(FREE);
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_in_new_space_list(false);
803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    parameter_or_next_free_.next_free = *first_free;
813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    *first_free = this;
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Acquire(Object* object) {
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(state() == FREE);
863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    object_ = object;
873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_independent(false);
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_partially_dependent(false);
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_state(NORMAL);
913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    parameter_or_next_free_.parameter = NULL;
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    weak_callback_ = NULL;
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    IncreaseBlockUses();
943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void Zap() {
97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(IsInUse());
98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Zap the values for eager trapping.
99958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue);
100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Release() {
103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(IsInUse());
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_state(FREE);
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Zap the values for eager trapping.
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue);
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_independent(false);
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_partially_dependent(false);
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    weak_callback_ = NULL;
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DecreaseBlockUses();
1123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Object slot accessors.
1153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Object* object() const { return object_; }
1163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Object** location() { return &object_; }
1173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Object> handle() { return Handle<Object>(location()); }
1183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Wrapper class ID accessors.
1203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool has_wrapper_class_id() const {
1213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId;
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint16_t wrapper_class_id() const { return class_id_; }
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // State and flag accessors.
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  State state() const {
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return NodeState::decode(flags_);
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void set_state(State state) {
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    flags_ = NodeState::update(flags_, state);
1333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_independent() {
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return IsIndependent::decode(flags_);
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void set_independent(bool v) {
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    flags_ = IsIndependent::update(flags_, v);
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_partially_dependent() {
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return IsPartiallyDependent::decode(flags_);
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void set_partially_dependent(bool v) {
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    flags_ = IsPartiallyDependent::update(flags_, v);
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_in_new_space_list() {
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return IsInNewSpaceList::decode(flags_);
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void set_in_new_space_list(bool v) {
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    flags_ = IsInNewSpaceList::update(flags_, v);
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  WeaknessType weakness_type() const {
157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return NodeWeaknessType::decode(flags_);
158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void set_weakness_type(WeaknessType weakness_type) {
160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    flags_ = NodeWeaknessType::update(flags_, weakness_type);
161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool IsNearDeath() const {
1643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check for PENDING to ensure correct answer when processing callbacks.
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return state() == PENDING || state() == NEAR_DEATH;
1663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool IsWeak() const { return state() == WEAK; }
1693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool IsInUse() const { return state() != FREE; }
171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool IsRetainer() const { return state() != FREE; }
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool IsStrongRetainer() const { return state() == NORMAL; }
1753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool IsWeakRetainer() const {
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return state() == WEAK || state() == PENDING || state() == NEAR_DEATH;
1783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void MarkPending() {
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(state() == WEAK);
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_state(PENDING);
1833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Independent flag accessors.
1863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void MarkIndependent() {
187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(IsInUse());
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_independent(true);
1893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MarkPartiallyDependent() {
192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(IsInUse());
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (GetGlobalHandles()->isolate()->heap()->InNewSpace(object_)) {
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      set_partially_dependent(true);
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void clear_partially_dependent() { set_partially_dependent(false); }
1983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Callback accessor.
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(svenpanne) Re-enable or nuke later.
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // WeakReferenceCallback callback() { return callback_; }
2023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Callback parameter accessors.
2043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void set_parameter(void* parameter) {
205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(IsInUse());
206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(weakness_type() == NORMAL_WEAK || weakness_type() == PHANTOM_WEAK);
2073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    parameter_or_next_free_.parameter = parameter;
2083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
2093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void* parameter() const {
210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(IsInUse());
2113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return parameter_or_next_free_.parameter;
2123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void set_internal_fields(int internal_field_index1,
215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                           int internal_field_index2) {
216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(weakness_type() == INTERNAL_FIELDS_WEAK);
217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // These are stored in an int16_t.
218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(internal_field_index1 < 1 << 16);
219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(internal_field_index1 >= -(1 << 16));
220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(internal_field_index2 < 1 << 16);
221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(internal_field_index2 >= -(1 << 16));
222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    parameter_or_next_free_.internal_field_indeces.internal_field1 =
223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        static_cast<int16_t>(internal_field_index1);
224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    parameter_or_next_free_.internal_field_indeces.internal_field2 =
225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        static_cast<int16_t>(internal_field_index2);
226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int internal_field1() const {
229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(weakness_type() == INTERNAL_FIELDS_WEAK);
230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return parameter_or_next_free_.internal_field_indeces.internal_field1;
231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int internal_field2() const {
234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(weakness_type() == INTERNAL_FIELDS_WEAK);
235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return parameter_or_next_free_.internal_field_indeces.internal_field2;
236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Accessors for next free node in the free list.
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Node* next_free() {
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(state() == FREE);
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return parameter_or_next_free_.next_free;
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_next_free(Node* value) {
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(state() == FREE);
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    parameter_or_next_free_.next_free = value;
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MakeWeak(void* parameter, WeakCallback weak_callback) {
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(weak_callback != NULL);
250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(IsInUse());
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(object_ != NULL);
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_state(WEAK);
253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    set_weakness_type(NORMAL_WEAK);
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    set_parameter(parameter);
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    weak_callback_ = weak_callback;
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void MakePhantom(void* parameter,
259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   PhantomCallbackData<void>::Callback phantom_callback,
260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   int16_t internal_field_index1,
261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   int16_t internal_field_index2) {
262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(phantom_callback != NULL);
263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(IsInUse());
264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    CHECK(object_ != NULL);
265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    set_state(WEAK);
266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (parameter == NULL) {
267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      set_weakness_type(INTERNAL_FIELDS_WEAK);
268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      set_internal_fields(internal_field_index1, internal_field_index2);
269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(internal_field_index1 == v8::Object::kNoInternalFieldIndex);
271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(internal_field_index2 == v8::Object::kNoInternalFieldIndex);
272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      set_weakness_type(PHANTOM_WEAK);
273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      set_parameter(parameter);
274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    weak_callback_ = reinterpret_cast<WeakCallback>(phantom_callback);
276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void* ClearWeakness() {
279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(IsInUse());
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void* p = parameter();
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_state(NORMAL);
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    set_parameter(NULL);
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return p;
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void CollectPhantomCallbackData(
287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Isolate* isolate, List<PendingPhantomCallback>* pending_phantom_callbacks,
288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      List<PendingInternalFieldsCallback>* pending_internal_fields_callbacks) {
289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (state() != Node::PENDING) return;
290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    bool do_release = true;
291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (weak_callback_ != NULL) {
292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (weakness_type() == NORMAL_WEAK) return;
293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      v8::Isolate* api_isolate = reinterpret_cast<v8::Isolate*>(isolate);
295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (weakness_type() == PHANTOM_WEAK) {
297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Phantom weak pointer case. Zap with harmless value.
298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        DCHECK(*location() == Smi::FromInt(0));
299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        typedef PhantomCallbackData<void> Data;
300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Data data(api_isolate, parameter());
302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Data::Callback callback =
303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            reinterpret_cast<Data::Callback>(weak_callback_);
304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        pending_phantom_callbacks->Add(
306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            PendingPhantomCallback(this, data, callback));
307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Postpone the release of the handle. The embedder can't use the
309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // handle (it's zapped), but it may be using the location, and we
310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // don't want to confuse things by reusing that.
311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        do_release = false;
312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        DCHECK(weakness_type() == INTERNAL_FIELDS_WEAK);
314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        typedef InternalFieldsCallbackData<void, void> Data;
315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Phantom weak pointer case, passing internal fields instead of
317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // parameter. Don't use a handle here during GC, because it will
318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // create a handle pointing to a dying object, which can confuse
319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // the next GC.
320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        JSObject* jsobject = reinterpret_cast<JSObject*>(object());
321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        DCHECK(jsobject->IsJSObject());
322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Data data(api_isolate, jsobject->GetInternalField(internal_field1()),
323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                  jsobject->GetInternalField(internal_field2()));
324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Data::Callback callback =
325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            reinterpret_cast<Data::Callback>(weak_callback_);
326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // In the future, we want to delay the callback. In that case we will
328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // zap when we queue up, to stop the C++ side accessing the dead V8
329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // object, but we will call Release only after the callback (allowing
330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // the node to be reused).
331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        pending_internal_fields_callbacks->Add(
332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            PendingInternalFieldsCallback(data, callback));
333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // TODO(erikcorry): At the moment the callbacks are not postponed much,
336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // but if we really postpone them until after the mutator has run, we
337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // need to divide things up, so that an early callback clears the handle,
338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // while a later one destroys the objects involved, possibley triggering
339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // some work when decremented ref counts hit zero.
340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (do_release) Release();
341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool PostGarbageCollectionProcessing(Isolate* isolate) {
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (state() != Node::PENDING) return false;
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (weak_callback_ == NULL) {
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Release();
34750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      return false;
34850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    }
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_state(NEAR_DEATH);
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Check that we are not passing a finalized external string to
352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // the callback.
353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(!object_->IsExternalOneByteString() ||
354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier           ExternalOneByteString::cast(object_)->resource() != NULL);
355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(!object_->IsExternalTwoByteString() ||
356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier           ExternalTwoByteString::cast(object_)->resource() != NULL);
357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Leaving V8.
358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    VMState<EXTERNAL> vmstate(isolate);
359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    HandleScope handle_scope(isolate);
360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (weakness_type() == PHANTOM_WEAK) return false;
361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(weakness_type() == NORMAL_WEAK);
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object** object = location();
363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<Object> handle(*object, isolate);
364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    v8::WeakCallbackData<v8::Value, void> data(
365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        reinterpret_cast<v8::Isolate*>(isolate), parameter(),
366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        v8::Utils::ToLocal(handle));
367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    set_parameter(NULL);
368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    weak_callback_(data);
369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Absence of explicit cleanup or revival of weak handle
37150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    // in most of the cases would lead to memory leak.
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(state() != NEAR_DEATH);
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return true;
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline GlobalHandles* GetGlobalHandles();
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private:
3793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  inline NodeBlock* FindBlock();
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void IncreaseBlockUses();
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void DecreaseBlockUses();
3823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Storage for object pointer.
3843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Placed first to avoid offset computation.
3853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Object* object_;
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Next word stores class_id, index, state, and independent.
3883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Note: the most aligned fields should go first.
3893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Wrapper class ID.
39144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  uint16_t class_id_;
39244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Index in the containing handle block.
3943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint8_t index_;
3953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This stores three flags (independent, partially_dependent and
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // in_new_space_list) and a State.
398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  class NodeState : public BitField<State, 0, 3> {};
399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  class IsIndependent : public BitField<bool, 3, 1> {};
400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  class IsPartiallyDependent : public BitField<bool, 4, 1> {};
401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  class IsInNewSpaceList : public BitField<bool, 5, 1> {};
402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  class NodeWeaknessType : public BitField<WeaknessType, 6, 2> {};
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint8_t flags_;
405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Handle specific callback - might be a weak reference in disguise.
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallback weak_callback_;
4083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Provided data for callback.  In FREE state, this is used for
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the free list link.
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  union {
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    void* parameter;
413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    struct {
414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int16_t internal_field1;
415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int16_t internal_field2;
416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } internal_field_indeces;
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Node* next_free;
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } parameter_or_next_free_;
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(Node);
4213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch};
4223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass GlobalHandles::NodeBlock {
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
4263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static const int kSize = 256;
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit NodeBlock(GlobalHandles* global_handles, NodeBlock* next)
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : next_(next),
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        used_nodes_(0),
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        next_used_(NULL),
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        prev_used_(NULL),
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        global_handles_(global_handles) {}
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void PutNodesOnFreeList(Node** first_free) {
4363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    for (int i = kSize - 1; i >= 0; --i) {
4373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      nodes_[i].Initialize(i, first_free);
438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Node* node_at(int index) {
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(0 <= index && index < kSize);
4433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return &nodes_[index];
4443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
4453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void IncreaseUses() {
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(used_nodes_ < kSize);
4483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (used_nodes_++ == 0) {
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      NodeBlock* old_first = global_handles_->first_used_block_;
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      global_handles_->first_used_block_ = this;
4513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      next_used_ = old_first;
4523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      prev_used_ = NULL;
4533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (old_first == NULL) return;
4543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      old_first->prev_used_ = this;
455bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    }
4563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
457bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DecreaseUses() {
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(used_nodes_ > 0);
4603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (--used_nodes_ == 0) {
4613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (next_used_ != NULL) next_used_->prev_used_ = prev_used_;
4623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (prev_used_ != NULL) prev_used_->next_used_ = next_used_;
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (this == global_handles_->first_used_block_) {
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        global_handles_->first_used_block_ = next_used_;
465d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GlobalHandles* global_handles() { return global_handles_; }
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Next block in the list of all blocks.
4723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  NodeBlock* next() const { return next_; }
473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Next/previous block in the list of blocks with used nodes.
4753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  NodeBlock* next_used() const { return next_used_; }
4763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  NodeBlock* prev_used() const { return prev_used_; }
4773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private:
4793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Node nodes_[kSize];
4803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  NodeBlock* const next_;
4813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int used_nodes_;
4823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  NodeBlock* next_used_;
4833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  NodeBlock* prev_used_;
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GlobalHandles* global_handles_;
4853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch};
4863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochGlobalHandles* GlobalHandles::Node::GetGlobalHandles() {
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return FindBlock()->global_handles();
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4933fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochGlobalHandles::NodeBlock* GlobalHandles::Node::FindBlock() {
4943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  intptr_t ptr = reinterpret_cast<intptr_t>(this);
4953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ptr = ptr - index_ * sizeof(Node);
4963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  NodeBlock* block = reinterpret_cast<NodeBlock*>(ptr);
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(block->node_at(index_) == this);
4983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return block;
4993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
5003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid GlobalHandles::Node::IncreaseBlockUses() {
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NodeBlock* node_block = FindBlock();
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node_block->IncreaseUses();
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GlobalHandles* global_handles = node_block->global_handles();
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global_handles->isolate()->counters()->global_handles()->Increment();
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global_handles->number_of_global_handles_++;
5083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
5093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid GlobalHandles::Node::DecreaseBlockUses() {
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NodeBlock* node_block = FindBlock();
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GlobalHandles* global_handles = node_block->global_handles();
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  parameter_or_next_free_.next_free = global_handles->first_free_;
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global_handles->first_free_ = this;
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node_block->DecreaseUses();
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global_handles->isolate()->counters()->global_handles()->Decrement();
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global_handles->number_of_global_handles_--;
5193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
5203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass GlobalHandles::NodeIterator {
5233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public:
5243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  explicit NodeIterator(GlobalHandles* global_handles)
5253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      : block_(global_handles->first_used_block_),
5263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        index_(0) {}
5273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool done() const { return block_ == NULL; }
5293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Node* node() const {
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!done());
5323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return block_->node_at(index_);
5333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Advance() {
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!done());
5373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (++index_ < NodeBlock::kSize) return;
5383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    index_ = 0;
5393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    block_ = block_->next_used();
5403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private:
5433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  NodeBlock* block_;
5443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int index_;
5453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(NodeIterator);
547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block};
548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
55044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockGlobalHandles::GlobalHandles(Isolate* isolate)
55144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : isolate_(isolate),
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      number_of_global_handles_(0),
5533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      first_block_(NULL),
5543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      first_used_block_(NULL),
55544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      first_free_(NULL),
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      post_gc_processing_count_(0),
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      object_group_connections_(kObjectGroupConnectionsCapacity) {}
55844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
55944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
56044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockGlobalHandles::~GlobalHandles() {
5613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  NodeBlock* block = first_block_;
5623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  while (block != NULL) {
5633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    NodeBlock* tmp = block->next();
5643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    delete block;
5653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    block = tmp;
5663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  first_block_ = NULL;
56844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Object> GlobalHandles::Create(Object* value) {
5723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (first_free_ == NULL) {
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    first_block_ = new NodeBlock(this, first_block_);
5743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    first_block_->PutNodesOnFreeList(&first_free_);
5753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(first_free_ != NULL);
5773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Take the first node in the free list.
5783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Node* result = first_free_;
5793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  first_free_ = result->next_free();
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->Acquire(value);
5813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (isolate_->heap()->InNewSpace(value) &&
5823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      !result->is_in_new_space_list()) {
5833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    new_space_nodes_.Add(result);
5843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    result->set_in_new_space_list(true);
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result->handle();
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Object> GlobalHandles::CopyGlobal(Object** location) {
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(location != NULL);
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Node::FromLocation(location)->GetGlobalHandles()->Create(*location);
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::Destroy(Object** location) {
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (location != NULL) Node::FromLocation(location)->Release();
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
601958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid GlobalHandles::MakeWeak(Object** location, void* parameter,
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             WeakCallback weak_callback) {
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node::FromLocation(location)->MakeWeak(parameter, weak_callback);
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef PhantomCallbackData<void>::Callback GenericCallback;
608958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
609958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
610958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid GlobalHandles::MakePhantom(
611958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Object** location,
612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    v8::InternalFieldsCallbackData<void, void>::Callback phantom_callback,
613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int16_t internal_field_index1, int16_t internal_field_index2) {
614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Node::FromLocation(location)
615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ->MakePhantom(NULL, reinterpret_cast<GenericCallback>(phantom_callback),
616958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                    internal_field_index1, internal_field_index2);
617958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
619958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid GlobalHandles::MakePhantom(Object** location, void* parameter,
621958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                GenericCallback phantom_callback) {
622958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Node::FromLocation(location)->MakePhantom(parameter, phantom_callback,
623958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                            v8::Object::kNoInternalFieldIndex,
624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                            v8::Object::kNoInternalFieldIndex);
625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
627958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
628958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid GlobalHandles::CollectPhantomCallbackData() {
629958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (NodeIterator it(this); !it.done(); it.Advance()) {
630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Node* node = it.node();
631958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    node->CollectPhantomCallbackData(isolate(), &pending_phantom_callbacks_,
632958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     &pending_internal_fields_callbacks_);
633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
636958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid* GlobalHandles::ClearWeakness(Object** location) {
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Node::FromLocation(location)->ClearWeakness();
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid GlobalHandles::MarkIndependent(Object** location) {
6433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Node::FromLocation(location)->MarkIndependent();
644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid GlobalHandles::MarkPartiallyDependent(Object** location) {
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node::FromLocation(location)->MarkPartiallyDependent();
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool GlobalHandles::IsIndependent(Object** location) {
653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Node::FromLocation(location)->is_independent();
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool GlobalHandles::IsNearDeath(Object** location) {
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Node::FromLocation(location)->IsNearDeath();
65944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
66044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
66144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool GlobalHandles::IsWeak(Object** location) {
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Node::FromLocation(location)->IsWeak();
6643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
6653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid GlobalHandles::IterateWeakRoots(ObjectVisitor* v) {
6683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (NodeIterator it(this); !it.done(); it.Advance()) {
669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Node* node = it.node();
670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (node->IsWeakRetainer()) {
671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Weakness type can be normal, phantom or internal fields.
672958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // For normal weakness we mark through the handle so that
673958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // the object and things reachable from it are available
674958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // to the callback.
675958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // In the case of phantom we can zap the object handle now
676958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // and we won't need it, so we don't need to mark through it.
677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // In the internal fields case we will need the internal
678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // fields, so we can't zap the handle, but we don't need to
679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // mark through it, because it will die in this GC round.
680958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (node->state() == Node::PENDING) {
681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (node->weakness_type() == PHANTOM_WEAK) {
682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          *(node->location()) = Smi::FromInt(0);
683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        } else if (node->weakness_type() == NORMAL_WEAK) {
684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          v->VisitPointer(node->location());
685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        } else {
686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          DCHECK(node->weakness_type() == INTERNAL_FIELDS_WEAK);
687958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
689958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Node is not pending, so that means the object survived.  We still
690958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // need to visit the pointer in case the object moved, eg. because of
691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // compaction.
692958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        v->VisitPointer(node->location());
693958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) {
7003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (NodeIterator it(this); !it.done(); it.Advance()) {
7013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (it.node()->IsWeak() && f(it.node()->location())) {
7023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      it.node()->MarkPending();
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid GlobalHandles::IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v) {
7093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < new_space_nodes_.length(); ++i) {
7103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Node* node = new_space_nodes_[i];
7113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (node->IsStrongRetainer() ||
712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        (node->IsWeakRetainer() && !node->is_independent() &&
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         !node->is_partially_dependent())) {
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v->VisitPointer(node->location());
7153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
7163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
7173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
7183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid GlobalHandles::IdentifyNewSpaceWeakIndependentHandles(
7213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    WeakSlotCallbackWithHeap f) {
7223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < new_space_nodes_.length(); ++i) {
7233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Node* node = new_space_nodes_[i];
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(node->is_in_new_space_list());
725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if ((node->is_independent() || node->is_partially_dependent()) &&
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        node->IsWeak() && f(isolate_->heap(), node->location())) {
7273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      node->MarkPending();
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) {
7343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < new_space_nodes_.length(); ++i) {
7353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Node* node = new_space_nodes_[i];
736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(node->is_in_new_space_list());
737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if ((node->is_independent() || node->is_partially_dependent()) &&
738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        node->IsWeakRetainer()) {
739958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (node->weakness_type() == PHANTOM_WEAK) {
740958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        *(node->location()) = Smi::FromInt(0);
741958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else if (node->weakness_type() == NORMAL_WEAK) {
742958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        v->VisitPointer(node->location());
743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        DCHECK(node->weakness_type() == INTERNAL_FIELDS_WEAK);
745958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // For this case we only need to trace if it's alive: The tracing of
746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // something that is already alive is just to get the pointer updated
747958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // to the new location of the object).
748958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        DCHECK(node->state() != Node::NEAR_DEATH);
749958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (node->state() != Node::PENDING) {
750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          v->VisitPointer(node->location());
751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool GlobalHandles::IterateObjectGroups(ObjectVisitor* v,
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        WeakSlotCallbackWithHeap can_skip) {
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ComputeObjectGroupsAndImplicitReferences();
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int last = 0;
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool any_group_was_visited = false;
763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < object_groups_.length(); i++) {
764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ObjectGroup* entry = object_groups_.at(i);
765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(entry != NULL);
766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object*** objects = entry->objects;
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool group_should_be_visited = false;
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (size_t j = 0; j < entry->length; j++) {
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Object* object = *objects[j];
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (object->IsHeapObject()) {
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (!can_skip(isolate_->heap(), &object)) {
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          group_should_be_visited = true;
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!group_should_be_visited) {
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      object_groups_[last++] = entry;
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      continue;
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // An object in the group requires visiting, so iterate over all
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // objects in the group.
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (size_t j = 0; j < entry->length; ++j) {
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Object* object = *objects[j];
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (object->IsHeapObject()) {
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v->VisitPointer(&object);
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        any_group_was_visited = true;
791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Once the entire group has been iterated over, set the object
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // group to NULL so it won't be processed again.
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    delete entry;
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    object_groups_.at(i) = NULL;
798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_groups_.Rewind(last);
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return any_group_was_visited;
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
804958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierint GlobalHandles::PostScavengeProcessing(
805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    const int initial_post_gc_processing_count) {
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int freed_nodes = 0;
807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (int i = 0; i < new_space_nodes_.length(); ++i) {
808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Node* node = new_space_nodes_[i];
809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(node->is_in_new_space_list());
810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!node->IsRetainer()) {
811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Free nodes do not have weak callbacks. Do not use them to compute
812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // the freed_nodes.
813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      continue;
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
815958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Skip dependent handles. Their weak callbacks might expect to be
816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // called between two global garbage collection callbacks which
817958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // are not called for minor collections.
818958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!node->is_independent() && !node->is_partially_dependent()) {
819958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      continue;
820958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
821958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    node->clear_partially_dependent();
822958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (node->PostGarbageCollectionProcessing(isolate_)) {
823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (initial_post_gc_processing_count != post_gc_processing_count_) {
824958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Weak callback triggered another GC and another round of
825958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // PostGarbageCollection processing.  The current node might
826958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // have been deleted in that round, so we need to bail out (or
827958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // restart the processing).
828958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return freed_nodes;
8293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
830958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
831958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!node->IsRetainer()) {
832958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      freed_nodes++;
833958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
834958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
835958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return freed_nodes;
836958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
837958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
838958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
839958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierint GlobalHandles::PostMarkSweepProcessing(
840958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    const int initial_post_gc_processing_count) {
841958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int freed_nodes = 0;
842958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (NodeIterator it(this); !it.done(); it.Advance()) {
843958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!it.node()->IsRetainer()) {
844958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Free nodes do not have weak callbacks. Do not use them to compute
845958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // the freed_nodes.
846958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      continue;
847958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
848958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    it.node()->clear_partially_dependent();
849958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (it.node()->PostGarbageCollectionProcessing(isolate_)) {
850958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (initial_post_gc_processing_count != post_gc_processing_count_) {
851958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // See the comment above.
852958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return freed_nodes;
853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
855958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!it.node()->IsRetainer()) {
856958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      freed_nodes++;
857958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
859958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return freed_nodes;
860958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
861958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
862958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
863958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid GlobalHandles::UpdateListOfNewSpaceNodes() {
8643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int last = 0;
8653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < new_space_nodes_.length(); ++i) {
8663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Node* node = new_space_nodes_[i];
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(node->is_in_new_space_list());
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (node->IsRetainer()) {
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (isolate_->heap()->InNewSpace(node->object())) {
870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new_space_nodes_[last++] = node;
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate_->heap()->IncrementNodesCopiedInNewSpace();
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        node->set_in_new_space_list(false);
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate_->heap()->IncrementNodesPromoted();
875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
8763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
8773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      node->set_in_new_space_list(false);
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate_->heap()->IncrementNodesDiedInNewSpace();
8793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
880d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
8813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  new_space_nodes_.Rewind(last);
882958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
883958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
884958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
885958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierint GlobalHandles::DispatchPendingPhantomCallbacks() {
886958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int freed_nodes = 0;
887958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  while (pending_phantom_callbacks_.length() != 0) {
888958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    PendingPhantomCallback callback = pending_phantom_callbacks_.RemoveLast();
889958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    callback.invoke();
890958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    freed_nodes++;
891958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
892958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  while (pending_internal_fields_callbacks_.length() != 0) {
893958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    PendingInternalFieldsCallback callback =
894958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        pending_internal_fields_callbacks_.RemoveLast();
895958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    callback.invoke();
896958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    freed_nodes++;
897958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return freed_nodes;
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
902958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierint GlobalHandles::PostGarbageCollectionProcessing(GarbageCollector collector) {
903958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Process weak global handle callbacks. This must be done after the
904958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // GC is completely done, because the callbacks may invoke arbitrary
905958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // API functions.
906958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(isolate_->heap()->gc_state() == Heap::NOT_IN_GC);
907958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const int initial_post_gc_processing_count = ++post_gc_processing_count_;
908958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int freed_nodes = 0;
909958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (collector == SCAVENGER) {
910958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    freed_nodes = PostScavengeProcessing(initial_post_gc_processing_count);
911958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
912958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    freed_nodes = PostMarkSweepProcessing(initial_post_gc_processing_count);
913958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
914958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (initial_post_gc_processing_count != post_gc_processing_count_) {
915958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // If the callbacks caused a nested GC, then return.  See comment in
916958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // PostScavengeProcessing.
917958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return freed_nodes;
918958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
919958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  freed_nodes += DispatchPendingPhantomCallbacks();
920958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (initial_post_gc_processing_count == post_gc_processing_count_) {
921958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    UpdateListOfNewSpaceNodes();
922958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
923958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return freed_nodes;
924958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
925958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
926958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
927958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid GlobalHandles::PendingPhantomCallback::invoke() {
928958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (node_->state() == Node::FREE) return;
929958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(node_->state() == Node::NEAR_DEATH);
930958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  callback_(data_);
931958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (node_->state() != Node::FREE) node_->Release();
932958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
933958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
934958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid GlobalHandles::IterateStrongRoots(ObjectVisitor* v) {
9363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (NodeIterator it(this); !it.done(); it.Advance()) {
9373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (it.node()->IsStrongRetainer()) {
9383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      v->VisitPointer(it.node()->location());
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
944d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid GlobalHandles::IterateAllRoots(ObjectVisitor* v) {
9453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (NodeIterator it(this); !it.done(); it.Advance()) {
9463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (it.node()->IsRetainer()) {
9473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      v->VisitPointer(it.node()->location());
948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
95344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid GlobalHandles::IterateAllRootsWithClassIds(ObjectVisitor* v) {
9543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (NodeIterator it(this); !it.done(); it.Advance()) {
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (it.node()->IsRetainer() && it.node()->has_wrapper_class_id()) {
9563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      v->VisitEmbedderReference(it.node()->location(),
9573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                it.node()->wrapper_class_id());
95844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
95944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
96044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
96144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
96244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid GlobalHandles::IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v) {
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < new_space_nodes_.length(); ++i) {
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Node* node = new_space_nodes_[i];
966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (node->IsRetainer() && node->has_wrapper_class_id()) {
967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v->VisitEmbedderReference(node->location(),
968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                node->wrapper_class_id());
969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint GlobalHandles::NumberOfWeakHandles() {
975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int count = 0;
976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (NodeIterator it(this); !it.done(); it.Advance()) {
977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (it.node()->IsWeakRetainer()) {
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      count++;
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return count;
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint GlobalHandles::NumberOfGlobalObjectWeakHandles() {
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int count = 0;
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (NodeIterator it(this); !it.done(); it.Advance()) {
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (it.node()->IsWeakRetainer() &&
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        it.node()->object()->IsJSGlobalObject()) {
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      count++;
991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return count;
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
997d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid GlobalHandles::RecordStats(HeapStats* stats) {
998d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  *stats->global_handle_count = 0;
999d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  *stats->weak_global_handle_count = 0;
1000d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  *stats->pending_global_handle_count = 0;
1001d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  *stats->near_death_global_handle_count = 0;
10023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  *stats->free_global_handle_count = 0;
10033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (NodeIterator it(this); !it.done(); it.Advance()) {
1004d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    *stats->global_handle_count += 1;
10053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (it.node()->state() == Node::WEAK) {
1006d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      *stats->weak_global_handle_count += 1;
10073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else if (it.node()->state() == Node::PENDING) {
1008d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      *stats->pending_global_handle_count += 1;
10093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else if (it.node()->state() == Node::NEAR_DEATH) {
1010d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      *stats->near_death_global_handle_count += 1;
10113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else if (it.node()->state() == Node::FREE) {
10123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      *stats->free_global_handle_count += 1;
1013d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1014d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1015d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::PrintStats() {
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int total = 0;
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int weak = 0;
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int pending = 0;
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int near_death = 0;
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int destroyed = 0;
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (NodeIterator it(this); !it.done(); it.Advance()) {
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    total++;
10283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (it.node()->state() == Node::WEAK) weak++;
10293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (it.node()->state() == Node::PENDING) pending++;
10303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (it.node()->state() == Node::NEAR_DEATH) near_death++;
10313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (it.node()->state() == Node::FREE) destroyed++;
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("Global Handle Statistics:\n");
1035f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  PrintF("  allocated memory = %" V8_PTR_PREFIX "dB\n", sizeof(Node) * total);
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("  # weak       = %d\n", weak);
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("  # pending    = %d\n", pending);
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("  # near_death = %d\n", near_death);
10393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  PrintF("  # free       = %d\n", destroyed);
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("  # total      = %d\n", total);
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::Print() {
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("Global handles:\n");
10463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (NodeIterator it(this); !it.done(); it.Advance()) {
10473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    PrintF("  handle %p to %p%s\n",
10483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           reinterpret_cast<void*>(it.node()->location()),
10493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           reinterpret_cast<void*>(it.node()->object()),
10503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           it.node()->IsWeak() ? " (weak)" : "");
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
105744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
105844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid GlobalHandles::AddObjectGroup(Object*** handles,
105944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   size_t length,
106044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   v8::RetainedObjectInfo* info) {
1061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG
1062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (size_t i = 0; i < length; ++i) {
1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!Node::FromLocation(handles[i])->is_independent());
1064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
10668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (length == 0) {
10678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (info != NULL) info->Dispose();
10688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return;
106944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ObjectGroup* group = new ObjectGroup(length);
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (size_t i = 0; i < length; ++i)
1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    group->objects[i] = handles[i];
1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  group->info = info;
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_groups_.Add(group);
107544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
107644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
107744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid GlobalHandles::SetObjectGroupId(Object** handle,
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     UniqueId id) {
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_group_connections_.Add(ObjectGroupConnection(id, handle));
1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid GlobalHandles::SetRetainedObjectInfo(UniqueId id,
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          RetainedObjectInfo* info) {
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  retainer_infos_.Add(ObjectGroupRetainerInfo(id, info));
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid GlobalHandles::SetReferenceFromGroup(UniqueId id, Object** child) {
1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!Node::FromLocation(child)->is_independent());
1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  implicit_ref_connections_.Add(ObjectGroupConnection(id, child));
1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid GlobalHandles::SetReference(HeapObject** parent, Object** child) {
1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!Node::FromLocation(child)->is_independent());
1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ImplicitRefGroup* group = new ImplicitRefGroup(parent, 1);
1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  group->children[0] = child;
1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  implicit_ref_groups_.Add(group);
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::RemoveObjectGroups() {
1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < object_groups_.length(); i++)
1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    delete object_groups_.at(i);
110744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  object_groups_.Clear();
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < retainer_infos_.length(); ++i)
1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    retainer_infos_[i].info->Dispose();
1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  retainer_infos_.Clear();
1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_group_connections_.Clear();
1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_group_connections_.Initialize(kObjectGroupConnectionsCapacity);
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
111544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
111644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid GlobalHandles::RemoveImplicitRefGroups() {
111744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < implicit_ref_groups_.length(); i++) {
1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    delete implicit_ref_groups_.at(i);
111944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
112044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  implicit_ref_groups_.Clear();
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  implicit_ref_connections_.Clear();
112244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
112344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
112444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid GlobalHandles::TearDown() {
11263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // TODO(1428): invoke weak callbacks.
11273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
11283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
11293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid GlobalHandles::ComputeObjectGroupsAndImplicitReferences() {
1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (object_group_connections_.length() == 0) {
1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < retainer_infos_.length(); ++i)
1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      retainer_infos_[i].info->Dispose();
1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    retainer_infos_.Clear();
1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    implicit_ref_connections_.Clear();
1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_group_connections_.Sort();
1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  retainer_infos_.Sort();
1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  implicit_ref_connections_.Sort();
1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int info_index = 0;  // For iterating retainer_infos_.
1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UniqueId current_group_id(0);
1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int current_group_start = 0;
1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int current_implicit_refs_start = 0;
1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int current_implicit_refs_end = 0;
1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i <= object_group_connections_.length(); ++i) {
1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (i == 0)
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      current_group_id = object_group_connections_[i].id;
1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (i == object_group_connections_.length() ||
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        current_group_id != object_group_connections_[i].id) {
1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Group detected: objects in indices [current_group_start, i[.
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Find out which implicit references are related to this group. (We want
1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // to ignore object groups which only have 1 object, but that object is
1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // needed as a representative object for the implicit refrerence group.)
1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      while (current_implicit_refs_start < implicit_ref_connections_.length() &&
1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             implicit_ref_connections_[current_implicit_refs_start].id <
1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 current_group_id)
1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ++current_implicit_refs_start;
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      current_implicit_refs_end = current_implicit_refs_start;
1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      while (current_implicit_refs_end < implicit_ref_connections_.length() &&
1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             implicit_ref_connections_[current_implicit_refs_end].id ==
1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 current_group_id)
1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ++current_implicit_refs_end;
1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (current_implicit_refs_end > current_implicit_refs_start) {
1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Find a representative object for the implicit references.
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        HeapObject** representative = NULL;
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        for (int j = current_group_start; j < i; ++j) {
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Object** object = object_group_connections_[j].object;
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if ((*object)->IsHeapObject()) {
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            representative = reinterpret_cast<HeapObject**>(object);
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            break;
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          }
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (representative) {
1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ImplicitRefGroup* group = new ImplicitRefGroup(
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              representative,
1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              current_implicit_refs_end - current_implicit_refs_start);
1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          for (int j = current_implicit_refs_start;
1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               j < current_implicit_refs_end;
1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               ++j) {
1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            group->children[j - current_implicit_refs_start] =
1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                implicit_ref_connections_[j].object;
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          }
1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          implicit_ref_groups_.Add(group);
1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        current_implicit_refs_start = current_implicit_refs_end;
1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Find a RetainedObjectInfo for the group.
1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RetainedObjectInfo* info = NULL;
1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      while (info_index < retainer_infos_.length() &&
1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             retainer_infos_[info_index].id < current_group_id) {
1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        retainer_infos_[info_index].info->Dispose();
1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ++info_index;
1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (info_index < retainer_infos_.length() &&
1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          retainer_infos_[info_index].id == current_group_id) {
1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // This object group has an associated ObjectGroupRetainerInfo.
1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        info = retainer_infos_[info_index].info;
1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ++info_index;
1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Ignore groups which only contain one object.
1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (i > current_group_start + 1) {
1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ObjectGroup* group = new ObjectGroup(i - current_group_start);
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        for (int j = current_group_start; j < i; ++j) {
1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          group->objects[j - current_group_start] =
1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              object_group_connections_[j].object;
1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        group->info = info;
1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        object_groups_.Add(group);
1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else if (info) {
1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        info->Dispose();
1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (i < object_group_connections_.length()) {
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        current_group_id = object_group_connections_[i].id;
1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        current_group_start = i;
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_group_connections_.Clear();
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_group_connections_.Initialize(kObjectGroupConnectionsCapacity);
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  retainer_infos_.Clear();
1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  implicit_ref_connections_.Clear();
1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochEternalHandles::EternalHandles() : size_(0) {
1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (unsigned i = 0; i < arraysize(singleton_handles_); i++) {
1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    singleton_handles_[i] = kInvalidIndex;
1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochEternalHandles::~EternalHandles() {
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < blocks_.length(); i++) delete[] blocks_[i];
1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid EternalHandles::IterateAllRoots(ObjectVisitor* visitor) {
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int limit = size_;
1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < blocks_.length(); i++) {
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(limit > 0);
1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object** block = blocks_[i];
1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    visitor->VisitPointers(block, block + Min(limit, kSize));
1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    limit -= kSize;
1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid EternalHandles::IterateNewSpaceRoots(ObjectVisitor* visitor) {
1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < new_space_indices_.length(); i++) {
1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    visitor->VisitPointer(GetLocation(new_space_indices_[i]));
1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid EternalHandles::PostGarbageCollectionProcessing(Heap* heap) {
1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int last = 0;
1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < new_space_indices_.length(); i++) {
1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int index = new_space_indices_[i];
1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (heap->InNewSpace(*GetLocation(index))) {
1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new_space_indices_[last++] = index;
1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space_indices_.Rewind(last);
1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid EternalHandles::Create(Isolate* isolate, Object* object, int* index) {
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(kInvalidIndex, *index);
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (object == NULL) return;
1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_NE(isolate->heap()->the_hole_value(), object);
1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int block = size_ >> kShift;
1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int offset = size_ & kMask;
1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // need to resize
1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (offset == 0) {
1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object** next_block = new Object*[kSize];
1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object* the_hole = isolate->heap()->the_hole_value();
1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemsetPointer(next_block, the_hole, kSize);
1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    blocks_.Add(next_block);
1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]);
1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  blocks_[block][offset] = object;
1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate->heap()->InNewSpace(object)) {
1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    new_space_indices_.Add(size_);
1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *index = size_++;
1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1299