blob: 282ca2d5d86a63d86dd00b1eb4b43888c3289e6b [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2009 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/v8.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007#include "src/api.h"
8#include "src/global-handles.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00009
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/vm-state-inl.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010011
Steve Blocka7e24c12009-10-30 11:49:00 +000012namespace v8 {
13namespace internal {
14
Steve Block44f0eee2011-05-26 01:26:41 +010015
16ObjectGroup::~ObjectGroup() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017 if (info != NULL) info->Dispose();
18 delete[] objects;
19}
20
21
22ImplicitRefGroup::~ImplicitRefGroup() {
23 delete[] children;
Steve Block44f0eee2011-05-26 01:26:41 +010024}
25
26
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000027class GlobalHandles::Node {
Steve Blocka7e24c12009-10-30 11:49:00 +000028 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000029 // State transition diagram:
30 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE }
31 enum State {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032 FREE = 0,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000033 NORMAL, // Normal global handle.
34 WEAK, // Flagged as weak but not yet finalized.
35 PENDING, // Has been recognized as only reachable by weak handles.
36 NEAR_DEATH // Callback has informed the handle is near death.
37 };
Steve Blocka7e24c12009-10-30 11:49:00 +000038
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000039 // Maps handle location (slot) to the containing node.
40 static Node* FromLocation(Object** location) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000041 DCHECK(OFFSET_OF(Node, object_) == 0);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000042 return reinterpret_cast<Node*>(location);
43 }
44
Ben Murdochb8a8cc12014-11-26 15:28:44 +000045 Node() {
46 DCHECK(OFFSET_OF(Node, class_id_) == Internals::kNodeClassIdOffset);
47 DCHECK(OFFSET_OF(Node, flags_) == Internals::kNodeFlagsOffset);
48 STATIC_ASSERT(static_cast<int>(NodeState::kMask) ==
49 Internals::kNodeStateMask);
50 STATIC_ASSERT(WEAK == Internals::kNodeStateIsWeakValue);
51 STATIC_ASSERT(PENDING == Internals::kNodeStateIsPendingValue);
52 STATIC_ASSERT(NEAR_DEATH == Internals::kNodeStateIsNearDeathValue);
53 STATIC_ASSERT(static_cast<int>(IsIndependent::kShift) ==
54 Internals::kNodeIsIndependentShift);
55 STATIC_ASSERT(static_cast<int>(IsPartiallyDependent::kShift) ==
56 Internals::kNodeIsPartiallyDependentShift);
57 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000058
Ben Murdochb8a8cc12014-11-26 15:28:44 +000059#ifdef ENABLE_HANDLE_ZAPPING
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000060 ~Node() {
61 // TODO(1428): if it's a weak handle we should have invoked its callback.
62 // Zap the values for eager trapping.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000063 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000064 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
65 index_ = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000066 set_independent(false);
67 set_partially_dependent(false);
68 set_in_new_space_list(false);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000069 parameter_or_next_free_.next_free = NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000070 weak_callback_ = NULL;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000071 }
72#endif
73
74 void Initialize(int index, Node** first_free) {
75 index_ = static_cast<uint8_t>(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000076 DCHECK(static_cast<int>(index_) == index);
77 set_state(FREE);
78 set_in_new_space_list(false);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000079 parameter_or_next_free_.next_free = *first_free;
80 *first_free = this;
81 }
82
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083 void Acquire(Object* object) {
84 DCHECK(state() == FREE);
Steve Blocka7e24c12009-10-30 11:49:00 +000085 object_ = object;
Steve Block44f0eee2011-05-26 01:26:41 +010086 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000087 set_independent(false);
88 set_partially_dependent(false);
89 set_state(NORMAL);
Steve Blocka7e24c12009-10-30 11:49:00 +000090 parameter_or_next_free_.parameter = NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000091 weak_callback_ = NULL;
92 IncreaseBlockUses();
Steve Blocka7e24c12009-10-30 11:49:00 +000093 }
94
Ben Murdochb8a8cc12014-11-26 15:28:44 +000095 void Release() {
96 DCHECK(state() != FREE);
97 set_state(FREE);
98 // Zap the values for eager trapping.
99 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue);
100 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
101 set_independent(false);
102 set_partially_dependent(false);
103 weak_callback_ = NULL;
104 DecreaseBlockUses();
Steve Blocka7e24c12009-10-30 11:49:00 +0000105 }
106
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000107 // Object slot accessors.
108 Object* object() const { return object_; }
109 Object** location() { return &object_; }
110 Handle<Object> handle() { return Handle<Object>(location()); }
111
112 // Wrapper class ID accessors.
113 bool has_wrapper_class_id() const {
114 return class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId;
115 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000116
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000117 uint16_t wrapper_class_id() const { return class_id_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118
119 // State and flag accessors.
120
121 State state() const {
122 return NodeState::decode(flags_);
123 }
124 void set_state(State state) {
125 flags_ = NodeState::update(flags_, state);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000126 }
127
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000128 bool is_independent() {
129 return IsIndependent::decode(flags_);
130 }
131 void set_independent(bool v) {
132 flags_ = IsIndependent::update(flags_, v);
133 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000134
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000135 bool is_partially_dependent() {
136 return IsPartiallyDependent::decode(flags_);
137 }
138 void set_partially_dependent(bool v) {
139 flags_ = IsPartiallyDependent::update(flags_, v);
140 }
141
142 bool is_in_new_space_list() {
143 return IsInNewSpaceList::decode(flags_);
144 }
145 void set_in_new_space_list(bool v) {
146 flags_ = IsInNewSpaceList::update(flags_, v);
147 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000148
149 bool IsNearDeath() const {
150 // Check for PENDING to ensure correct answer when processing callbacks.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000151 return state() == PENDING || state() == NEAR_DEATH;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000152 }
153
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000154 bool IsWeak() const { return state() == WEAK; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000155
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000156 bool IsRetainer() const { return state() != FREE; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000157
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000158 bool IsStrongRetainer() const { return state() == NORMAL; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000159
160 bool IsWeakRetainer() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000161 return state() == WEAK || state() == PENDING || state() == NEAR_DEATH;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000162 }
163
164 void MarkPending() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000165 DCHECK(state() == WEAK);
166 set_state(PENDING);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000167 }
168
169 // Independent flag accessors.
170 void MarkIndependent() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000171 DCHECK(state() != FREE);
172 set_independent(true);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000173 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000174
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000175 void MarkPartiallyDependent() {
176 DCHECK(state() != FREE);
177 if (GetGlobalHandles()->isolate()->heap()->InNewSpace(object_)) {
178 set_partially_dependent(true);
179 }
180 }
181 void clear_partially_dependent() { set_partially_dependent(false); }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000182
183 // Callback accessor.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184 // TODO(svenpanne) Re-enable or nuke later.
185 // WeakReferenceCallback callback() { return callback_; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000186
187 // Callback parameter accessors.
188 void set_parameter(void* parameter) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 DCHECK(state() != FREE);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000190 parameter_or_next_free_.parameter = parameter;
191 }
192 void* parameter() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000193 DCHECK(state() != FREE);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000194 return parameter_or_next_free_.parameter;
195 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000196
197 // Accessors for next free node in the free list.
198 Node* next_free() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199 DCHECK(state() == FREE);
Steve Blocka7e24c12009-10-30 11:49:00 +0000200 return parameter_or_next_free_.next_free;
201 }
202 void set_next_free(Node* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000203 DCHECK(state() == FREE);
Steve Blocka7e24c12009-10-30 11:49:00 +0000204 parameter_or_next_free_.next_free = value;
205 }
206
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 void MakeWeak(void* parameter, WeakCallback weak_callback) {
208 DCHECK(weak_callback != NULL);
209 DCHECK(state() != FREE);
210 CHECK(object_ != NULL);
211 set_state(WEAK);
Steve Blocka7e24c12009-10-30 11:49:00 +0000212 set_parameter(parameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000213 weak_callback_ = weak_callback;
Steve Blocka7e24c12009-10-30 11:49:00 +0000214 }
215
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216 void* ClearWeakness() {
217 DCHECK(state() != FREE);
218 void* p = parameter();
219 set_state(NORMAL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000220 set_parameter(NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221 return p;
Steve Blocka7e24c12009-10-30 11:49:00 +0000222 }
223
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000224 bool PostGarbageCollectionProcessing(Isolate* isolate) {
225 if (state() != Node::PENDING) return false;
226 if (weak_callback_ == NULL) {
227 Release();
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100228 return false;
229 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000230 void* par = parameter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231 set_state(NEAR_DEATH);
Steve Blocka7e24c12009-10-30 11:49:00 +0000232 set_parameter(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000233
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000234 Object** object = location();
Steve Blocka7e24c12009-10-30 11:49:00 +0000235 {
Leon Clarkee46be812010-01-19 14:06:41 +0000236 // Check that we are not passing a finalized external string to
237 // the callback.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238 DCHECK(!object_->IsExternalOneByteString() ||
239 ExternalOneByteString::cast(object_)->resource() != NULL);
240 DCHECK(!object_->IsExternalTwoByteString() ||
Leon Clarkee46be812010-01-19 14:06:41 +0000241 ExternalTwoByteString::cast(object_)->resource() != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000242 // Leaving V8.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243 VMState<EXTERNAL> state(isolate);
244 HandleScope handle_scope(isolate);
245 Handle<Object> handle(*object, isolate);
246 v8::WeakCallbackData<v8::Value, void> data(
247 reinterpret_cast<v8::Isolate*>(isolate),
248 v8::Utils::ToLocal(handle),
249 par);
250 weak_callback_(data);
Steve Blocka7e24c12009-10-30 11:49:00 +0000251 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100252 // Absence of explicit cleanup or revival of weak handle
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100253 // in most of the cases would lead to memory leak.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000254 CHECK(state() != NEAR_DEATH);
Steve Blocka7e24c12009-10-30 11:49:00 +0000255 return true;
256 }
257
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000258 inline GlobalHandles* GetGlobalHandles();
259
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000260 private:
261 inline NodeBlock* FindBlock();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000262 inline void IncreaseBlockUses();
263 inline void DecreaseBlockUses();
Steve Blocka7e24c12009-10-30 11:49:00 +0000264
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000265 // Storage for object pointer.
266 // Placed first to avoid offset computation.
267 Object* object_;
268
269 // Next word stores class_id, index, state, and independent.
270 // Note: the most aligned fields should go first.
271
272 // Wrapper class ID.
Steve Block44f0eee2011-05-26 01:26:41 +0100273 uint16_t class_id_;
274
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000275 // Index in the containing handle block.
276 uint8_t index_;
277
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278 // This stores three flags (independent, partially_dependent and
279 // in_new_space_list) and a State.
280 class NodeState: public BitField<State, 0, 4> {};
281 class IsIndependent: public BitField<bool, 4, 1> {};
282 class IsPartiallyDependent: public BitField<bool, 5, 1> {};
283 class IsInNewSpaceList: public BitField<bool, 6, 1> {};
Steve Blocka7e24c12009-10-30 11:49:00 +0000284
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285 uint8_t flags_;
Ben Murdoch257744e2011-11-30 15:57:28 +0000286
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000287 // Handle specific callback - might be a weak reference in disguise.
288 WeakCallback weak_callback_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000289
290 // Provided data for callback. In FREE state, this is used for
Steve Blocka7e24c12009-10-30 11:49:00 +0000291 // the free list link.
292 union {
293 void* parameter;
294 Node* next_free;
295 } parameter_or_next_free_;
296
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000297 DISALLOW_COPY_AND_ASSIGN(Node);
Steve Blocka7e24c12009-10-30 11:49:00 +0000298};
299
300
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000301class GlobalHandles::NodeBlock {
302 public:
303 static const int kSize = 256;
Steve Blockd0582a62009-12-15 09:54:21 +0000304
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000305 explicit NodeBlock(GlobalHandles* global_handles, NodeBlock* next)
306 : next_(next),
307 used_nodes_(0),
308 next_used_(NULL),
309 prev_used_(NULL),
310 global_handles_(global_handles) {}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000311
312 void PutNodesOnFreeList(Node** first_free) {
313 for (int i = kSize - 1; i >= 0; --i) {
314 nodes_[i].Initialize(i, first_free);
315 }
316 }
317
318 Node* node_at(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000319 DCHECK(0 <= index && index < kSize);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000320 return &nodes_[index];
321 }
322
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000323 void IncreaseUses() {
324 DCHECK(used_nodes_ < kSize);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000325 if (used_nodes_++ == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000326 NodeBlock* old_first = global_handles_->first_used_block_;
327 global_handles_->first_used_block_ = this;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000328 next_used_ = old_first;
329 prev_used_ = NULL;
330 if (old_first == NULL) return;
331 old_first->prev_used_ = this;
332 }
333 }
334
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000335 void DecreaseUses() {
336 DCHECK(used_nodes_ > 0);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000337 if (--used_nodes_ == 0) {
338 if (next_used_ != NULL) next_used_->prev_used_ = prev_used_;
339 if (prev_used_ != NULL) prev_used_->next_used_ = next_used_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000340 if (this == global_handles_->first_used_block_) {
341 global_handles_->first_used_block_ = next_used_;
Ben Murdochbb769b22010-08-11 14:56:33 +0100342 }
343 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000344 }
Ben Murdochbb769b22010-08-11 14:56:33 +0100345
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000346 GlobalHandles* global_handles() { return global_handles_; }
347
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000348 // Next block in the list of all blocks.
349 NodeBlock* next() const { return next_; }
Steve Blockd0582a62009-12-15 09:54:21 +0000350
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000351 // Next/previous block in the list of blocks with used nodes.
352 NodeBlock* next_used() const { return next_used_; }
353 NodeBlock* prev_used() const { return prev_used_; }
Steve Blockd0582a62009-12-15 09:54:21 +0000354
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000355 private:
356 Node nodes_[kSize];
357 NodeBlock* const next_;
358 int used_nodes_;
359 NodeBlock* next_used_;
360 NodeBlock* prev_used_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000361 GlobalHandles* global_handles_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000362};
Steve Blockd0582a62009-12-15 09:54:21 +0000363
Steve Blockd0582a62009-12-15 09:54:21 +0000364
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000365GlobalHandles* GlobalHandles::Node::GetGlobalHandles() {
366 return FindBlock()->global_handles();
367}
368
369
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000370GlobalHandles::NodeBlock* GlobalHandles::Node::FindBlock() {
371 intptr_t ptr = reinterpret_cast<intptr_t>(this);
372 ptr = ptr - index_ * sizeof(Node);
373 NodeBlock* block = reinterpret_cast<NodeBlock*>(ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000374 DCHECK(block->node_at(index_) == this);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000375 return block;
376}
Steve Blockd0582a62009-12-15 09:54:21 +0000377
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000378
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000379void GlobalHandles::Node::IncreaseBlockUses() {
380 NodeBlock* node_block = FindBlock();
381 node_block->IncreaseUses();
382 GlobalHandles* global_handles = node_block->global_handles();
383 global_handles->isolate()->counters()->global_handles()->Increment();
384 global_handles->number_of_global_handles_++;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000385}
386
387
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388void GlobalHandles::Node::DecreaseBlockUses() {
389 NodeBlock* node_block = FindBlock();
390 GlobalHandles* global_handles = node_block->global_handles();
391 parameter_or_next_free_.next_free = global_handles->first_free_;
392 global_handles->first_free_ = this;
393 node_block->DecreaseUses();
394 global_handles->isolate()->counters()->global_handles()->Decrement();
395 global_handles->number_of_global_handles_--;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000396}
397
398
399class GlobalHandles::NodeIterator {
400 public:
401 explicit NodeIterator(GlobalHandles* global_handles)
402 : block_(global_handles->first_used_block_),
403 index_(0) {}
404
405 bool done() const { return block_ == NULL; }
406
407 Node* node() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000408 DCHECK(!done());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000409 return block_->node_at(index_);
410 }
411
412 void Advance() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413 DCHECK(!done());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000414 if (++index_ < NodeBlock::kSize) return;
415 index_ = 0;
416 block_ = block_->next_used();
417 }
418
419 private:
420 NodeBlock* block_;
421 int index_;
422
423 DISALLOW_COPY_AND_ASSIGN(NodeIterator);
Steve Blockd0582a62009-12-15 09:54:21 +0000424};
425
426
Steve Block44f0eee2011-05-26 01:26:41 +0100427GlobalHandles::GlobalHandles(Isolate* isolate)
428 : isolate_(isolate),
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100429 number_of_global_handles_(0),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000430 first_block_(NULL),
431 first_used_block_(NULL),
Steve Block44f0eee2011-05-26 01:26:41 +0100432 first_free_(NULL),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000433 post_gc_processing_count_(0),
434 object_group_connections_(kObjectGroupConnectionsCapacity) {}
Steve Block44f0eee2011-05-26 01:26:41 +0100435
436
437GlobalHandles::~GlobalHandles() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000438 NodeBlock* block = first_block_;
439 while (block != NULL) {
440 NodeBlock* tmp = block->next();
441 delete block;
442 block = tmp;
443 }
444 first_block_ = NULL;
Steve Block44f0eee2011-05-26 01:26:41 +0100445}
Steve Blockd0582a62009-12-15 09:54:21 +0000446
447
Steve Blocka7e24c12009-10-30 11:49:00 +0000448Handle<Object> GlobalHandles::Create(Object* value) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000449 if (first_free_ == NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000450 first_block_ = new NodeBlock(this, first_block_);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000451 first_block_->PutNodesOnFreeList(&first_free_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000452 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000453 DCHECK(first_free_ != NULL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000454 // Take the first node in the free list.
455 Node* result = first_free_;
456 first_free_ = result->next_free();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000457 result->Acquire(value);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000458 if (isolate_->heap()->InNewSpace(value) &&
459 !result->is_in_new_space_list()) {
460 new_space_nodes_.Add(result);
461 result->set_in_new_space_list(true);
462 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000463 return result->handle();
464}
465
466
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000467Handle<Object> GlobalHandles::CopyGlobal(Object** location) {
468 DCHECK(location != NULL);
469 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location);
470}
471
472
Steve Blocka7e24c12009-10-30 11:49:00 +0000473void GlobalHandles::Destroy(Object** location) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000474 if (location != NULL) Node::FromLocation(location)->Release();
Steve Blocka7e24c12009-10-30 11:49:00 +0000475}
476
477
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000478void GlobalHandles::MakeWeak(Object** location,
479 void* parameter,
480 WeakCallback weak_callback) {
481 Node::FromLocation(location)->MakeWeak(parameter, weak_callback);
Steve Blocka7e24c12009-10-30 11:49:00 +0000482}
483
484
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000485void* GlobalHandles::ClearWeakness(Object** location) {
486 return Node::FromLocation(location)->ClearWeakness();
Steve Blocka7e24c12009-10-30 11:49:00 +0000487}
488
489
Ben Murdoch257744e2011-11-30 15:57:28 +0000490void GlobalHandles::MarkIndependent(Object** location) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000491 Node::FromLocation(location)->MarkIndependent();
Ben Murdoch257744e2011-11-30 15:57:28 +0000492}
493
494
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000495void GlobalHandles::MarkPartiallyDependent(Object** location) {
496 Node::FromLocation(location)->MarkPartiallyDependent();
497}
498
499
500bool GlobalHandles::IsIndependent(Object** location) {
501 return Node::FromLocation(location)->is_independent();
502}
503
504
Steve Blocka7e24c12009-10-30 11:49:00 +0000505bool GlobalHandles::IsNearDeath(Object** location) {
506 return Node::FromLocation(location)->IsNearDeath();
507}
508
509
510bool GlobalHandles::IsWeak(Object** location) {
511 return Node::FromLocation(location)->IsWeak();
512}
513
514
515void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000516 for (NodeIterator it(this); !it.done(); it.Advance()) {
517 if (it.node()->IsWeakRetainer()) v->VisitPointer(it.node()->location());
Ben Murdoch257744e2011-11-30 15:57:28 +0000518 }
519}
520
521
Steve Blocka7e24c12009-10-30 11:49:00 +0000522void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000523 for (NodeIterator it(this); !it.done(); it.Advance()) {
524 if (it.node()->IsWeak() && f(it.node()->location())) {
525 it.node()->MarkPending();
Steve Blocka7e24c12009-10-30 11:49:00 +0000526 }
527 }
528}
529
530
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000531void GlobalHandles::IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v) {
532 for (int i = 0; i < new_space_nodes_.length(); ++i) {
533 Node* node = new_space_nodes_[i];
534 if (node->IsStrongRetainer() ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000535 (node->IsWeakRetainer() && !node->is_independent() &&
536 !node->is_partially_dependent())) {
537 v->VisitPointer(node->location());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000538 }
539 }
540}
541
542
543void GlobalHandles::IdentifyNewSpaceWeakIndependentHandles(
544 WeakSlotCallbackWithHeap f) {
545 for (int i = 0; i < new_space_nodes_.length(); ++i) {
546 Node* node = new_space_nodes_[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000547 DCHECK(node->is_in_new_space_list());
548 if ((node->is_independent() || node->is_partially_dependent()) &&
549 node->IsWeak() && f(isolate_->heap(), node->location())) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000550 node->MarkPending();
551 }
552 }
553}
554
555
556void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) {
557 for (int i = 0; i < new_space_nodes_.length(); ++i) {
558 Node* node = new_space_nodes_[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000559 DCHECK(node->is_in_new_space_list());
560 if ((node->is_independent() || node->is_partially_dependent()) &&
561 node->IsWeakRetainer()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000562 v->VisitPointer(node->location());
Ben Murdoch257744e2011-11-30 15:57:28 +0000563 }
564 }
565}
566
567
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000568bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v,
569 WeakSlotCallbackWithHeap can_skip) {
570 ComputeObjectGroupsAndImplicitReferences();
571 int last = 0;
572 bool any_group_was_visited = false;
573 for (int i = 0; i < object_groups_.length(); i++) {
574 ObjectGroup* entry = object_groups_.at(i);
575 DCHECK(entry != NULL);
576
577 Object*** objects = entry->objects;
578 bool group_should_be_visited = false;
579 for (size_t j = 0; j < entry->length; j++) {
580 Object* object = *objects[j];
581 if (object->IsHeapObject()) {
582 if (!can_skip(isolate_->heap(), &object)) {
583 group_should_be_visited = true;
584 break;
585 }
586 }
587 }
588
589 if (!group_should_be_visited) {
590 object_groups_[last++] = entry;
591 continue;
592 }
593
594 // An object in the group requires visiting, so iterate over all
595 // objects in the group.
596 for (size_t j = 0; j < entry->length; ++j) {
597 Object* object = *objects[j];
598 if (object->IsHeapObject()) {
599 v->VisitPointer(&object);
600 any_group_was_visited = true;
601 }
602 }
603
604 // Once the entire group has been iterated over, set the object
605 // group to NULL so it won't be processed again.
606 delete entry;
607 object_groups_.at(i) = NULL;
608 }
609 object_groups_.Rewind(last);
610 return any_group_was_visited;
611}
612
613
614int GlobalHandles::PostGarbageCollectionProcessing(
Ben Murdoch257744e2011-11-30 15:57:28 +0000615 GarbageCollector collector) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000616 // Process weak global handle callbacks. This must be done after the
617 // GC is completely done, because the callbacks may invoke arbitrary
618 // API functions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000619 DCHECK(isolate_->heap()->gc_state() == Heap::NOT_IN_GC);
Steve Block44f0eee2011-05-26 01:26:41 +0100620 const int initial_post_gc_processing_count = ++post_gc_processing_count_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000621 int freed_nodes = 0;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000622 if (collector == SCAVENGER) {
623 for (int i = 0; i < new_space_nodes_.length(); ++i) {
624 Node* node = new_space_nodes_[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000625 DCHECK(node->is_in_new_space_list());
626 if (!node->IsRetainer()) {
627 // Free nodes do not have weak callbacks. Do not use them to compute
628 // the freed_nodes.
629 continue;
630 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000631 // Skip dependent handles. Their weak callbacks might expect to be
632 // called between two global garbage collection callbacks which
633 // are not called for minor collections.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000634 if (!node->is_independent() && !node->is_partially_dependent()) {
635 continue;
636 }
637 node->clear_partially_dependent();
638 if (node->PostGarbageCollectionProcessing(isolate_)) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000639 if (initial_post_gc_processing_count != post_gc_processing_count_) {
640 // Weak callback triggered another GC and another round of
641 // PostGarbageCollection processing. The current node might
642 // have been deleted in that round, so we need to bail out (or
643 // restart the processing).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000644 return freed_nodes;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000645 }
646 }
647 if (!node->IsRetainer()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000648 freed_nodes++;
Steve Blocka7e24c12009-10-30 11:49:00 +0000649 }
650 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000651 } else {
652 for (NodeIterator it(this); !it.done(); it.Advance()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000653 if (!it.node()->IsRetainer()) {
654 // Free nodes do not have weak callbacks. Do not use them to compute
655 // the freed_nodes.
656 continue;
657 }
658 it.node()->clear_partially_dependent();
659 if (it.node()->PostGarbageCollectionProcessing(isolate_)) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000660 if (initial_post_gc_processing_count != post_gc_processing_count_) {
661 // See the comment above.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000662 return freed_nodes;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000663 }
Steve Blockd0582a62009-12-15 09:54:21 +0000664 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000665 if (!it.node()->IsRetainer()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000666 freed_nodes++;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000667 }
668 }
669 }
670 // Update the list of new space nodes.
671 int last = 0;
672 for (int i = 0; i < new_space_nodes_.length(); ++i) {
673 Node* node = new_space_nodes_[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000674 DCHECK(node->is_in_new_space_list());
675 if (node->IsRetainer()) {
676 if (isolate_->heap()->InNewSpace(node->object())) {
677 new_space_nodes_[last++] = node;
678 isolate_->heap()->IncrementNodesCopiedInNewSpace();
679 } else {
680 node->set_in_new_space_list(false);
681 isolate_->heap()->IncrementNodesPromoted();
682 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000683 } else {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000684 node->set_in_new_space_list(false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000685 isolate_->heap()->IncrementNodesDiedInNewSpace();
Steve Blocka7e24c12009-10-30 11:49:00 +0000686 }
687 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000688 new_space_nodes_.Rewind(last);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000689 return freed_nodes;
Steve Blocka7e24c12009-10-30 11:49:00 +0000690}
691
692
Steve Blockd0582a62009-12-15 09:54:21 +0000693void GlobalHandles::IterateStrongRoots(ObjectVisitor* v) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000694 for (NodeIterator it(this); !it.done(); it.Advance()) {
695 if (it.node()->IsStrongRetainer()) {
696 v->VisitPointer(it.node()->location());
Steve Blocka7e24c12009-10-30 11:49:00 +0000697 }
698 }
699}
700
Steve Blockd0582a62009-12-15 09:54:21 +0000701
702void GlobalHandles::IterateAllRoots(ObjectVisitor* v) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000703 for (NodeIterator it(this); !it.done(); it.Advance()) {
704 if (it.node()->IsRetainer()) {
705 v->VisitPointer(it.node()->location());
Ben Murdoch257744e2011-11-30 15:57:28 +0000706 }
707 }
708}
709
710
Steve Block44f0eee2011-05-26 01:26:41 +0100711void GlobalHandles::IterateAllRootsWithClassIds(ObjectVisitor* v) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000712 for (NodeIterator it(this); !it.done(); it.Advance()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000713 if (it.node()->IsRetainer() && it.node()->has_wrapper_class_id()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000714 v->VisitEmbedderReference(it.node()->location(),
715 it.node()->wrapper_class_id());
Steve Block44f0eee2011-05-26 01:26:41 +0100716 }
717 }
718}
719
720
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000721void GlobalHandles::IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v) {
722 for (int i = 0; i < new_space_nodes_.length(); ++i) {
723 Node* node = new_space_nodes_[i];
724 if (node->IsRetainer() && node->has_wrapper_class_id()) {
725 v->VisitEmbedderReference(node->location(),
726 node->wrapper_class_id());
727 }
728 }
729}
730
731
732int GlobalHandles::NumberOfWeakHandles() {
733 int count = 0;
734 for (NodeIterator it(this); !it.done(); it.Advance()) {
735 if (it.node()->IsWeakRetainer()) {
736 count++;
737 }
738 }
739 return count;
740}
741
742
743int GlobalHandles::NumberOfGlobalObjectWeakHandles() {
744 int count = 0;
745 for (NodeIterator it(this); !it.done(); it.Advance()) {
746 if (it.node()->IsWeakRetainer() &&
747 it.node()->object()->IsJSGlobalObject()) {
748 count++;
749 }
750 }
751 return count;
752}
753
754
Steve Blockd0582a62009-12-15 09:54:21 +0000755void GlobalHandles::RecordStats(HeapStats* stats) {
756 *stats->global_handle_count = 0;
757 *stats->weak_global_handle_count = 0;
758 *stats->pending_global_handle_count = 0;
759 *stats->near_death_global_handle_count = 0;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000760 *stats->free_global_handle_count = 0;
761 for (NodeIterator it(this); !it.done(); it.Advance()) {
Steve Blockd0582a62009-12-15 09:54:21 +0000762 *stats->global_handle_count += 1;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000763 if (it.node()->state() == Node::WEAK) {
Steve Blockd0582a62009-12-15 09:54:21 +0000764 *stats->weak_global_handle_count += 1;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000765 } else if (it.node()->state() == Node::PENDING) {
Steve Blockd0582a62009-12-15 09:54:21 +0000766 *stats->pending_global_handle_count += 1;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000767 } else if (it.node()->state() == Node::NEAR_DEATH) {
Steve Blockd0582a62009-12-15 09:54:21 +0000768 *stats->near_death_global_handle_count += 1;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000769 } else if (it.node()->state() == Node::FREE) {
770 *stats->free_global_handle_count += 1;
Steve Blockd0582a62009-12-15 09:54:21 +0000771 }
772 }
773}
Steve Blocka7e24c12009-10-30 11:49:00 +0000774
775#ifdef DEBUG
776
777void GlobalHandles::PrintStats() {
778 int total = 0;
779 int weak = 0;
780 int pending = 0;
781 int near_death = 0;
782 int destroyed = 0;
783
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000784 for (NodeIterator it(this); !it.done(); it.Advance()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000785 total++;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000786 if (it.node()->state() == Node::WEAK) weak++;
787 if (it.node()->state() == Node::PENDING) pending++;
788 if (it.node()->state() == Node::NEAR_DEATH) near_death++;
789 if (it.node()->state() == Node::FREE) destroyed++;
Steve Blocka7e24c12009-10-30 11:49:00 +0000790 }
791
792 PrintF("Global Handle Statistics:\n");
Ben Murdochf87a2032010-10-22 12:50:53 +0100793 PrintF(" allocated memory = %" V8_PTR_PREFIX "dB\n", sizeof(Node) * total);
Steve Blocka7e24c12009-10-30 11:49:00 +0000794 PrintF(" # weak = %d\n", weak);
795 PrintF(" # pending = %d\n", pending);
796 PrintF(" # near_death = %d\n", near_death);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000797 PrintF(" # free = %d\n", destroyed);
Steve Blocka7e24c12009-10-30 11:49:00 +0000798 PrintF(" # total = %d\n", total);
799}
800
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000801
Steve Blocka7e24c12009-10-30 11:49:00 +0000802void GlobalHandles::Print() {
803 PrintF("Global handles:\n");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000804 for (NodeIterator it(this); !it.done(); it.Advance()) {
805 PrintF(" handle %p to %p%s\n",
806 reinterpret_cast<void*>(it.node()->location()),
807 reinterpret_cast<void*>(it.node()->object()),
808 it.node()->IsWeak() ? " (weak)" : "");
Steve Blocka7e24c12009-10-30 11:49:00 +0000809 }
810}
811
812#endif
813
Steve Block44f0eee2011-05-26 01:26:41 +0100814
815
816void GlobalHandles::AddObjectGroup(Object*** handles,
817 size_t length,
818 v8::RetainedObjectInfo* info) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000819#ifdef DEBUG
820 for (size_t i = 0; i < length; ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000821 DCHECK(!Node::FromLocation(handles[i])->is_independent());
Ben Murdoch257744e2011-11-30 15:57:28 +0000822 }
823#endif
Ben Murdoch8b112d22011-06-08 16:22:53 +0100824 if (length == 0) {
825 if (info != NULL) info->Dispose();
826 return;
Steve Block44f0eee2011-05-26 01:26:41 +0100827 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000828 ObjectGroup* group = new ObjectGroup(length);
829 for (size_t i = 0; i < length; ++i)
830 group->objects[i] = handles[i];
831 group->info = info;
832 object_groups_.Add(group);
Steve Blocka7e24c12009-10-30 11:49:00 +0000833}
834
Steve Block44f0eee2011-05-26 01:26:41 +0100835
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000836void GlobalHandles::SetObjectGroupId(Object** handle,
837 UniqueId id) {
838 object_group_connections_.Add(ObjectGroupConnection(id, handle));
839}
840
841
842void GlobalHandles::SetRetainedObjectInfo(UniqueId id,
843 RetainedObjectInfo* info) {
844 retainer_infos_.Add(ObjectGroupRetainerInfo(id, info));
845}
846
847
848void GlobalHandles::SetReferenceFromGroup(UniqueId id, Object** child) {
849 DCHECK(!Node::FromLocation(child)->is_independent());
850 implicit_ref_connections_.Add(ObjectGroupConnection(id, child));
851}
852
853
854void GlobalHandles::SetReference(HeapObject** parent, Object** child) {
855 DCHECK(!Node::FromLocation(child)->is_independent());
856 ImplicitRefGroup* group = new ImplicitRefGroup(parent, 1);
857 group->children[0] = child;
858 implicit_ref_groups_.Add(group);
Steve Blocka7e24c12009-10-30 11:49:00 +0000859}
860
861
862void GlobalHandles::RemoveObjectGroups() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000863 for (int i = 0; i < object_groups_.length(); i++)
864 delete object_groups_.at(i);
Steve Block44f0eee2011-05-26 01:26:41 +0100865 object_groups_.Clear();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000866 for (int i = 0; i < retainer_infos_.length(); ++i)
867 retainer_infos_[i].info->Dispose();
868 retainer_infos_.Clear();
869 object_group_connections_.Clear();
870 object_group_connections_.Initialize(kObjectGroupConnectionsCapacity);
Steve Blocka7e24c12009-10-30 11:49:00 +0000871}
872
Steve Block44f0eee2011-05-26 01:26:41 +0100873
874void GlobalHandles::RemoveImplicitRefGroups() {
875 for (int i = 0; i < implicit_ref_groups_.length(); i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000876 delete implicit_ref_groups_.at(i);
Steve Block44f0eee2011-05-26 01:26:41 +0100877 }
878 implicit_ref_groups_.Clear();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000879 implicit_ref_connections_.Clear();
Steve Block44f0eee2011-05-26 01:26:41 +0100880}
881
882
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000883void GlobalHandles::TearDown() {
884 // TODO(1428): invoke weak callbacks.
885}
886
887
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000888void GlobalHandles::ComputeObjectGroupsAndImplicitReferences() {
889 if (object_group_connections_.length() == 0) {
890 for (int i = 0; i < retainer_infos_.length(); ++i)
891 retainer_infos_[i].info->Dispose();
892 retainer_infos_.Clear();
893 implicit_ref_connections_.Clear();
894 return;
895 }
896
897 object_group_connections_.Sort();
898 retainer_infos_.Sort();
899 implicit_ref_connections_.Sort();
900
901 int info_index = 0; // For iterating retainer_infos_.
902 UniqueId current_group_id(0);
903 int current_group_start = 0;
904
905 int current_implicit_refs_start = 0;
906 int current_implicit_refs_end = 0;
907 for (int i = 0; i <= object_group_connections_.length(); ++i) {
908 if (i == 0)
909 current_group_id = object_group_connections_[i].id;
910 if (i == object_group_connections_.length() ||
911 current_group_id != object_group_connections_[i].id) {
912 // Group detected: objects in indices [current_group_start, i[.
913
914 // Find out which implicit references are related to this group. (We want
915 // to ignore object groups which only have 1 object, but that object is
916 // needed as a representative object for the implicit refrerence group.)
917 while (current_implicit_refs_start < implicit_ref_connections_.length() &&
918 implicit_ref_connections_[current_implicit_refs_start].id <
919 current_group_id)
920 ++current_implicit_refs_start;
921 current_implicit_refs_end = current_implicit_refs_start;
922 while (current_implicit_refs_end < implicit_ref_connections_.length() &&
923 implicit_ref_connections_[current_implicit_refs_end].id ==
924 current_group_id)
925 ++current_implicit_refs_end;
926
927 if (current_implicit_refs_end > current_implicit_refs_start) {
928 // Find a representative object for the implicit references.
929 HeapObject** representative = NULL;
930 for (int j = current_group_start; j < i; ++j) {
931 Object** object = object_group_connections_[j].object;
932 if ((*object)->IsHeapObject()) {
933 representative = reinterpret_cast<HeapObject**>(object);
934 break;
935 }
936 }
937 if (representative) {
938 ImplicitRefGroup* group = new ImplicitRefGroup(
939 representative,
940 current_implicit_refs_end - current_implicit_refs_start);
941 for (int j = current_implicit_refs_start;
942 j < current_implicit_refs_end;
943 ++j) {
944 group->children[j - current_implicit_refs_start] =
945 implicit_ref_connections_[j].object;
946 }
947 implicit_ref_groups_.Add(group);
948 }
949 current_implicit_refs_start = current_implicit_refs_end;
950 }
951
952 // Find a RetainedObjectInfo for the group.
953 RetainedObjectInfo* info = NULL;
954 while (info_index < retainer_infos_.length() &&
955 retainer_infos_[info_index].id < current_group_id) {
956 retainer_infos_[info_index].info->Dispose();
957 ++info_index;
958 }
959 if (info_index < retainer_infos_.length() &&
960 retainer_infos_[info_index].id == current_group_id) {
961 // This object group has an associated ObjectGroupRetainerInfo.
962 info = retainer_infos_[info_index].info;
963 ++info_index;
964 }
965
966 // Ignore groups which only contain one object.
967 if (i > current_group_start + 1) {
968 ObjectGroup* group = new ObjectGroup(i - current_group_start);
969 for (int j = current_group_start; j < i; ++j) {
970 group->objects[j - current_group_start] =
971 object_group_connections_[j].object;
972 }
973 group->info = info;
974 object_groups_.Add(group);
975 } else if (info) {
976 info->Dispose();
977 }
978
979 if (i < object_group_connections_.length()) {
980 current_group_id = object_group_connections_[i].id;
981 current_group_start = i;
982 }
983 }
984 }
985 object_group_connections_.Clear();
986 object_group_connections_.Initialize(kObjectGroupConnectionsCapacity);
987 retainer_infos_.Clear();
988 implicit_ref_connections_.Clear();
989}
990
991
992EternalHandles::EternalHandles() : size_(0) {
993 for (unsigned i = 0; i < arraysize(singleton_handles_); i++) {
994 singleton_handles_[i] = kInvalidIndex;
995 }
996}
997
998
999EternalHandles::~EternalHandles() {
1000 for (int i = 0; i < blocks_.length(); i++) delete[] blocks_[i];
1001}
1002
1003
1004void EternalHandles::IterateAllRoots(ObjectVisitor* visitor) {
1005 int limit = size_;
1006 for (int i = 0; i < blocks_.length(); i++) {
1007 DCHECK(limit > 0);
1008 Object** block = blocks_[i];
1009 visitor->VisitPointers(block, block + Min(limit, kSize));
1010 limit -= kSize;
1011 }
1012}
1013
1014
1015void EternalHandles::IterateNewSpaceRoots(ObjectVisitor* visitor) {
1016 for (int i = 0; i < new_space_indices_.length(); i++) {
1017 visitor->VisitPointer(GetLocation(new_space_indices_[i]));
1018 }
1019}
1020
1021
1022void EternalHandles::PostGarbageCollectionProcessing(Heap* heap) {
1023 int last = 0;
1024 for (int i = 0; i < new_space_indices_.length(); i++) {
1025 int index = new_space_indices_[i];
1026 if (heap->InNewSpace(*GetLocation(index))) {
1027 new_space_indices_[last++] = index;
1028 }
1029 }
1030 new_space_indices_.Rewind(last);
1031}
1032
1033
1034void EternalHandles::Create(Isolate* isolate, Object* object, int* index) {
1035 DCHECK_EQ(kInvalidIndex, *index);
1036 if (object == NULL) return;
1037 DCHECK_NE(isolate->heap()->the_hole_value(), object);
1038 int block = size_ >> kShift;
1039 int offset = size_ & kMask;
1040 // need to resize
1041 if (offset == 0) {
1042 Object** next_block = new Object*[kSize];
1043 Object* the_hole = isolate->heap()->the_hole_value();
1044 MemsetPointer(next_block, the_hole, kSize);
1045 blocks_.Add(next_block);
1046 }
1047 DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]);
1048 blocks_[block][offset] = object;
1049 if (isolate->heap()->InNewSpace(object)) {
1050 new_space_indices_.Add(size_);
1051 }
1052 *index = size_++;
1053}
1054
1055
Steve Blocka7e24c12009-10-30 11:49:00 +00001056} } // namespace v8::internal