1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_GLOBAL_HANDLES_H_
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_GLOBAL_HANDLES_H_
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "include/v8.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "include/v8-profiler.h"
108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/handles.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/list.h"
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/utils.h"
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass HeapStats;
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ObjectVisitor;
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Structure for tracking global handles.
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A single list keeps all the allocated global handles.
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Destroyed handles stay in the list but is added to the free list.
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// At GC the destroyed global handles are removed from the free list
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and deallocated.
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Data structures for tracking object groups and implicit references.
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// An object group is treated like a single JS object: if one of object in
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the group is alive, all objects in the same group are considered alive.
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// An object group is used to simulate object relationship in a DOM tree.
328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// An implicit references group consists of two parts: a parent object and a
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// list of children objects.  If the parent is alive, all the children are alive
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// too.
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct ObjectGroup {
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit ObjectGroup(size_t length)
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : info(NULL), length(length) {
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(length > 0);
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    objects = new Object**[length];
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ~ObjectGroup();
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::RetainedObjectInfo* info;
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object*** objects;
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t length;
4844f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
4944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct ImplicitRefGroup {
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ImplicitRefGroup(HeapObject** parent, size_t length)
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : parent(parent), length(length) {
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(length > 0);
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    children = new Object**[length];
568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ~ImplicitRefGroup();
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject** parent;
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object*** children;
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t length;
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// For internal bookkeeping.
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct ObjectGroupConnection {
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ObjectGroupConnection(UniqueId id, Object** object)
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : id(id), object(object) {}
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool operator==(const ObjectGroupConnection& other) const {
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return id == other.id;
728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
7344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool operator<(const ObjectGroupConnection& other) const {
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return id < other.id;
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
7744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UniqueId id;
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object** object;
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct ObjectGroupRetainerInfo {
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ObjectGroupRetainerInfo(UniqueId id, RetainedObjectInfo* info)
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : id(id), info(info) {}
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool operator==(const ObjectGroupRetainerInfo& other) const {
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return id == other.id;
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool operator<(const ObjectGroupRetainerInfo& other) const {
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return id < other.id;
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UniqueId id;
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RetainedObjectInfo* info;
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass GlobalHandles {
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
10244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ~GlobalHandles();
10344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Creates a new global handle that is alive until Destroy is called.
10544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Object> Create(Object* value);
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Copy a global handle
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static Handle<Object> CopyGlobal(Object** location);
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Destroy a global handle.
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void Destroy(Object** location);
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  typedef WeakCallbackData<v8::Value, void>::Callback WeakCallback;
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make the global handle weak and set the callback parameter for the
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // handle.  When the garbage collector recognizes that only weak global
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // handles point to an object the handles are cleared and the callback
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // function is invoked (for each handle) with the handle and corresponding
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // parameter as arguments.  Note: cleared means set to Smi::FromInt(0). The
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // reason is that Smi::FromInt(0) does not change during garage collection.
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void MakeWeak(Object** location,
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       void* parameter,
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       WeakCallback weak_callback);
12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordStats(HeapStats* stats);
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the current number of weak handles.
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int NumberOfWeakHandles();
129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the current number of weak handles to global objects.
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // These handles are also included in NumberOfWeakHandles().
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int NumberOfGlobalObjectWeakHandles();
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns the current number of handles to global objects.
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int global_handles_count() const {
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return number_of_global_handles_;
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the weakness of a global handle.
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void* ClearWeakness(Object** location);
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Clear the weakness of a global handle.
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void MarkIndependent(Object** location);
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark the reference to this object externaly unreachable.
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void MarkPartiallyDependent(Object** location);
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsIndependent(Object** location);
149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tells whether global handle is near death.
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static bool IsNearDeath(Object** location);
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tells whether global handle is weak.
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static bool IsWeak(Object** location);
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // Process pending weak handles.
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Returns the number of freed nodes.
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int PostGarbageCollectionProcessing(GarbageCollector collector);
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Iterates over all strong handles.
16144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void IterateStrongRoots(ObjectVisitor* v);
162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Iterates over all handles.
16444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void IterateAllRoots(ObjectVisitor* v);
16544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
16644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Iterates over all handles that have embedder-assigned class ID.
16744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void IterateAllRootsWithClassIds(ObjectVisitor* v);
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Iterates over all handles in the new space that have embedder-assigned
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // class ID.
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v);
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Iterates over all weak roots in heap.
17444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void IterateWeakRoots(ObjectVisitor* v);
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Find all weak handles satisfying the callback predicate, mark
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // them as pending.
17844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void IdentifyWeakHandles(WeakSlotCallback f);
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // NOTE: Three ...NewSpace... functions below are used during
1813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // scavenge collections and iterate over sets of handles that are
1823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // guaranteed to contain all handles holding new space objects (but
1833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // may also include old space objects).
1843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Iterates over strong and dependent handles. See the node above.
1863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v);
1873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Finds weak independent or partially independent handles satisfying
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the callback predicate and marks them as pending. See the note above.
1903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void IdentifyNewSpaceWeakIndependentHandles(WeakSlotCallbackWithHeap f);
1913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Iterates over weak independent or partially independent handles.
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // See the note above.
1943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v);
195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Iterate over objects in object groups that have at least one object
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // which requires visiting. The callback has to return true if objects
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // can be skipped and false otherwise.
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool IterateObjectGroups(ObjectVisitor* v, WeakSlotCallbackWithHeap can_skip);
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add an object group.
20244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Should be only used in GC callback function before a collection.
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All groups are destroyed after a garbage collection.
20444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void AddObjectGroup(Object*** handles,
20544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      size_t length,
20644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      v8::RetainedObjectInfo* info);
20744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Associates handle with the object group represented by id.
20944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Should be only used in GC callback function before a collection.
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All groups are destroyed after a garbage collection.
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SetObjectGroupId(Object** handle, UniqueId id);
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set RetainedObjectInfo for an object group. Should not be called more than
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // once for a group. Should not be called for a group which contains no
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // handles.
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Adds an implicit reference from a group to an object. Should be only used
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // in GC callback function before a collection. All implicit references are
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // destroyed after a mark-compact collection.
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SetReferenceFromGroup(UniqueId id, Object** child);
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Adds an implicit reference from a parent object to a child object. Should
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // be only used in GC callback function before a collection. All implicit
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // references are destroyed after a mark-compact collection.
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SetReference(HeapObject** parent, Object** child);
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<ObjectGroup*>* object_groups() {
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ComputeObjectGroupsAndImplicitReferences();
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return &object_groups_;
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
23244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
23344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  List<ImplicitRefGroup*>* implicit_ref_groups() {
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ComputeObjectGroupsAndImplicitReferences();
23544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return &implicit_ref_groups_;
23644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove bags, this should only happen after GC.
23944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void RemoveObjectGroups();
24044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void RemoveImplicitRefGroups();
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tear down the global handle structure.
24344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void TearDown();
24444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
24544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate() { return isolate_; }
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
24844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void PrintStats();
24944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Print();
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
25344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit GlobalHandles(Isolate* isolate);
25444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Migrates data from the internal representation (object_group_connections_,
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // retainer_infos_ and implicit_ref_connections_) to the public and more
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // efficient representation (object_groups_ and implicit_ref_groups_).
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ComputeObjectGroupsAndImplicitReferences();
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // v8::internal::List is inefficient even for small number of elements, if we
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // don't assign any initial capacity.
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kObjectGroupConnectionsCapacity = 20;
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Internal node structures.
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  class Node;
2663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  class NodeBlock;
2673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  class NodeIterator;
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate_;
27044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Field always containing the number of handles to global objects.
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int number_of_global_handles_;
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // List of all allocated node blocks.
2753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  NodeBlock* first_block_;
2763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // List of node blocks with used nodes.
2783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  NodeBlock* first_used_block_;
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Free list of nodes.
28144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Node* first_free_;
28244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Contains all nodes holding new space objects. Note: when the list
2843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // is accessed, some of the objects may have been promoted already.
2853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  List<Node*> new_space_nodes_;
2863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
28744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int post_gc_processing_count_;
2883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Object groups and implicit references, public and more efficient
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // representation.
29144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  List<ObjectGroup*> object_groups_;
29244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  List<ImplicitRefGroup*> implicit_ref_groups_;
29344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Object groups and implicit references, temporary representation while
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // constructing the groups.
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<ObjectGroupConnection> object_group_connections_;
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<ObjectGroupRetainerInfo> retainer_infos_;
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<ObjectGroupConnection> implicit_ref_connections_;
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
30044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  friend class Isolate;
30144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
30244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass EternalHandles {
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum SingletonHandle {
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    I18N_TEMPLATE_ONE,
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    I18N_TEMPLATE_TWO,
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DATE_CACHE_VERSION,
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    NUMBER_OF_SINGLETON_HANDLES
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EternalHandles();
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ~EternalHandles();
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int NumberOfHandles() { return size_; }
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create an EternalHandle, overwriting the index.
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Create(Isolate* isolate, Object* object, int* index);
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Grab the handle for an existing EternalHandle.
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline Handle<Object> Get(int index) {
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Handle<Object>(GetLocation(index));
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Grab the handle for an existing SingletonHandle.
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline Handle<Object> GetSingleton(SingletonHandle singleton) {
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Exists(singleton));
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Get(singleton_handles_[singleton]);
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Checks whether a SingletonHandle has been assigned.
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline bool Exists(SingletonHandle singleton) {
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return singleton_handles_[singleton] != kInvalidIndex;
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Assign a SingletonHandle to an empty slot and returns the handle.
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> CreateSingleton(Isolate* isolate,
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Object* object,
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 SingletonHandle singleton) {
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Create(isolate, object, &singleton_handles_[singleton]);
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Get(singleton_handles_[singleton]);
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Iterates over all handles.
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void IterateAllRoots(ObjectVisitor* visitor);
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Iterates over all handles which might be in new space.
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void IterateNewSpaceRoots(ObjectVisitor* visitor);
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Rebuilds new space list.
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void PostGarbageCollectionProcessing(Heap* heap);
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kInvalidIndex = -1;
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kShift = 8;
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kSize = 1 << kShift;
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kMask = 0xff;
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Gets the slot for an index
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline Object** GetLocation(int index) {
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(index >= 0 && index < size_);
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return &blocks_[index >> kShift][index & kMask];
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size_;
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<Object**> blocks_;
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<int> new_space_indices_;
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DISALLOW_COPY_AND_ASSIGN(EternalHandles);
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_GLOBAL_HANDLES_H_
379