OLD | NEW |
---|---|
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/global-handles.h" | 8 #include "src/global-handles.h" |
9 | 9 |
10 #include "src/vm-state-inl.h" | 10 #include "src/vm-state-inl.h" |
(...skipping 12 matching lines...) Expand all Loading... | |
23 delete[] children; | 23 delete[] children; |
24 } | 24 } |
25 | 25 |
26 | 26 |
27 class GlobalHandles::Node { | 27 class GlobalHandles::Node { |
28 public: | 28 public: |
29 // State transition diagram: | 29 // State transition diagram: |
30 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } | 30 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } |
31 enum State { | 31 enum State { |
32 FREE = 0, | 32 FREE = 0, |
33 NORMAL, // Normal global handle. | 33 NORMAL, // Normal global handle. |
34 WEAK, // Flagged as weak but not yet finalized. | 34 WEAK, // Flagged as weak but not yet finalized. |
35 PENDING, // Has been recognized as only reachable by weak handles. | 35 PENDING, // Has been recognized as only reachable by weak handles. |
36 NEAR_DEATH // Callback has informed the handle is near death. | 36 NEAR_DEATH, // Callback has informed the handle is near death. |
37 NUMBER_OF_NODE_STATES | |
38 }; | |
39 | |
40 enum WeaknessType { | |
41 NORMAL_WEAK, // Embedder gets a handle to the dying object. | |
42 PHANTOM_WEAK, // Embedder gets the parameter they passed in earlier. | |
43 INTERNAL_FIELDS_WEAK // Embedded gets 2 internal fields from dying object. | |
37 }; | 44 }; |
38 | 45 |
39 // Maps handle location (slot) to the containing node. | 46 // Maps handle location (slot) to the containing node. |
40 static Node* FromLocation(Object** location) { | 47 static Node* FromLocation(Object** location) { |
41 DCHECK(OFFSET_OF(Node, object_) == 0); | 48 DCHECK(OFFSET_OF(Node, object_) == 0); |
42 return reinterpret_cast<Node*>(location); | 49 return reinterpret_cast<Node*>(location); |
43 } | 50 } |
44 | 51 |
45 Node() { | 52 Node() { |
46 DCHECK(OFFSET_OF(Node, class_id_) == Internals::kNodeClassIdOffset); | 53 DCHECK(OFFSET_OF(Node, class_id_) == Internals::kNodeClassIdOffset); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
85 object_ = object; | 92 object_ = object; |
86 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 93 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
87 set_independent(false); | 94 set_independent(false); |
88 set_partially_dependent(false); | 95 set_partially_dependent(false); |
89 set_state(NORMAL); | 96 set_state(NORMAL); |
90 parameter_or_next_free_.parameter = NULL; | 97 parameter_or_next_free_.parameter = NULL; |
91 weak_callback_ = NULL; | 98 weak_callback_ = NULL; |
92 IncreaseBlockUses(); | 99 IncreaseBlockUses(); |
93 } | 100 } |
94 | 101 |
102 void Zap() { | |
picksi1
2014/11/28 12:15:11
Is 'Zap' a known term in the world of GC? For the
Erik Corry
2014/11/28 14:21:25
It's pretty well established, I think.
| |
103 DCHECK(state() != FREE); | |
104 // Zap the values for eager trapping. | |
105 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | |
106 } | |
107 | |
95 void Release() { | 108 void Release() { |
96 DCHECK(state() != FREE); | 109 DCHECK(state() != FREE); |
97 set_state(FREE); | 110 set_state(FREE); |
98 // Zap the values for eager trapping. | 111 // Zap the values for eager trapping. |
99 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 112 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
100 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 113 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
101 set_independent(false); | 114 set_independent(false); |
102 set_partially_dependent(false); | 115 set_partially_dependent(false); |
103 weak_callback_ = NULL; | 116 weak_callback_ = NULL; |
104 DecreaseBlockUses(); | 117 DecreaseBlockUses(); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
139 flags_ = IsPartiallyDependent::update(flags_, v); | 152 flags_ = IsPartiallyDependent::update(flags_, v); |
140 } | 153 } |
141 | 154 |
142 bool is_in_new_space_list() { | 155 bool is_in_new_space_list() { |
143 return IsInNewSpaceList::decode(flags_); | 156 return IsInNewSpaceList::decode(flags_); |
144 } | 157 } |
145 void set_in_new_space_list(bool v) { | 158 void set_in_new_space_list(bool v) { |
146 flags_ = IsInNewSpaceList::update(flags_, v); | 159 flags_ = IsInNewSpaceList::update(flags_, v); |
147 } | 160 } |
148 | 161 |
149 bool is_zapped_during_weak_callback() { | 162 WeaknessType weakness_type() const { |
150 return IsZappedDuringWeakCallback::decode(flags_); | 163 return NodeWeaknessType::decode(flags_); |
151 } | 164 } |
152 void set_is_zapped_during_weak_callback(bool v) { | 165 void set_weakness_type(WeaknessType t) { |
153 flags_ = IsZappedDuringWeakCallback::update(flags_, v); | 166 flags_ = NodeWeaknessType::update(flags_, t); |
picksi1
2014/11/28 12:15:11
is t a good variable name here? should it be weakn
Erik Corry
2014/11/28 14:21:25
Done.
| |
154 } | 167 } |
155 | 168 |
156 bool IsNearDeath() const { | 169 bool IsNearDeath() const { |
157 // Check for PENDING to ensure correct answer when processing callbacks. | 170 // Check for PENDING to ensure correct answer when processing callbacks. |
158 return state() == PENDING || state() == NEAR_DEATH; | 171 return state() == PENDING || state() == NEAR_DEATH; |
159 } | 172 } |
160 | 173 |
161 bool IsWeak() const { return state() == WEAK; } | 174 bool IsWeak() const { return state() == WEAK; } |
162 | 175 |
163 bool IsRetainer() const { return state() != FREE; } | 176 bool IsRetainer() const { return state() != FREE; } |
(...skipping 23 matching lines...) Expand all Loading... | |
187 } | 200 } |
188 void clear_partially_dependent() { set_partially_dependent(false); } | 201 void clear_partially_dependent() { set_partially_dependent(false); } |
189 | 202 |
190 // Callback accessor. | 203 // Callback accessor. |
191 // TODO(svenpanne) Re-enable or nuke later. | 204 // TODO(svenpanne) Re-enable or nuke later. |
192 // WeakReferenceCallback callback() { return callback_; } | 205 // WeakReferenceCallback callback() { return callback_; } |
193 | 206 |
194 // Callback parameter accessors. | 207 // Callback parameter accessors. |
195 void set_parameter(void* parameter) { | 208 void set_parameter(void* parameter) { |
196 DCHECK(state() != FREE); | 209 DCHECK(state() != FREE); |
210 DCHECK(weakness_type() == NORMAL_WEAK || weakness_type() == PHANTOM_WEAK); | |
197 parameter_or_next_free_.parameter = parameter; | 211 parameter_or_next_free_.parameter = parameter; |
198 } | 212 } |
199 void* parameter() const { | 213 void* parameter() const { |
200 DCHECK(state() != FREE); | 214 DCHECK(state() != FREE); |
201 return parameter_or_next_free_.parameter; | 215 return parameter_or_next_free_.parameter; |
202 } | 216 } |
203 | 217 |
218 void set_internal_fields( | |
219 int internal_field_index1, int internal_field_index2) { | |
220 DCHECK(weakness_type() == INTERNAL_FIELDS_WEAK); | |
221 parameter_or_next_free_.internal_field_indeces.internal_field1 = | |
222 internal_field_index1; | |
223 parameter_or_next_free_.internal_field_indeces.internal_field2 = | |
224 internal_field_index2; | |
225 } | |
226 | |
227 int internal_field1() const { | |
228 DCHECK(weakness_type() == INTERNAL_FIELDS_WEAK); | |
229 return parameter_or_next_free_.internal_field_indeces.internal_field1; | |
230 } | |
231 | |
232 int internal_field2() const { | |
233 DCHECK(weakness_type() == INTERNAL_FIELDS_WEAK); | |
234 return parameter_or_next_free_.internal_field_indeces.internal_field2; | |
235 } | |
236 | |
204 // Accessors for next free node in the free list. | 237 // Accessors for next free node in the free list. |
205 Node* next_free() { | 238 Node* next_free() { |
206 DCHECK(state() == FREE); | 239 DCHECK(state() == FREE); |
207 return parameter_or_next_free_.next_free; | 240 return parameter_or_next_free_.next_free; |
208 } | 241 } |
209 void set_next_free(Node* value) { | 242 void set_next_free(Node* value) { |
210 DCHECK(state() == FREE); | 243 DCHECK(state() == FREE); |
211 parameter_or_next_free_.next_free = value; | 244 parameter_or_next_free_.next_free = value; |
212 } | 245 } |
213 | 246 |
214 void MakeWeak(void* parameter, WeakCallback weak_callback, | 247 void MakeWeak(void* parameter, WeakCallback weak_callback) { |
215 bool is_zapped_during_weak_callback = false) { | |
216 DCHECK(weak_callback != NULL); | 248 DCHECK(weak_callback != NULL); |
217 DCHECK(state() != FREE); | 249 DCHECK(state() != FREE); |
218 CHECK(object_ != NULL); | 250 CHECK(object_ != NULL); |
219 set_state(WEAK); | 251 set_state(WEAK); |
252 set_weakness_type(Node::NORMAL_WEAK); | |
220 set_parameter(parameter); | 253 set_parameter(parameter); |
221 set_is_zapped_during_weak_callback(is_zapped_during_weak_callback); | |
222 weak_callback_ = weak_callback; | 254 weak_callback_ = weak_callback; |
223 } | 255 } |
224 | 256 |
257 void MakePhantom(void* parameter, PhantomCallback phantom_callback, | |
258 int internal_field_index1, int internal_field_index2) { | |
259 DCHECK(phantom_callback != NULL); | |
260 DCHECK(state() != FREE); | |
261 CHECK(object_ != NULL); | |
262 set_state(WEAK); | |
263 if (parameter != NULL) { | |
picksi1
2014/11/28 12:15:11
Bikeshed: Might be clearer to swap the if/else bod
Erik Corry
2014/11/28 14:21:25
Done.
| |
264 DCHECK(internal_field_index1 == v8::Object::kNoInternalFieldIndex); | |
265 DCHECK(internal_field_index2 == v8::Object::kNoInternalFieldIndex); | |
266 set_weakness_type(Node::PHANTOM_WEAK); | |
267 set_parameter(parameter); | |
268 } else { | |
269 set_weakness_type(Node::INTERNAL_FIELDS_WEAK); | |
270 set_internal_fields(internal_field_index1, internal_field_index2); | |
271 } | |
272 weak_callback_ = reinterpret_cast<WeakCallback>(phantom_callback); | |
273 } | |
274 | |
225 void* ClearWeakness() { | 275 void* ClearWeakness() { |
226 DCHECK(state() != FREE); | 276 DCHECK(state() != FREE); |
227 void* p = parameter(); | 277 void* p = parameter(); |
228 set_state(NORMAL); | 278 set_state(NORMAL); |
229 set_parameter(NULL); | 279 set_parameter(NULL); |
230 return p; | 280 return p; |
231 } | 281 } |
232 | 282 |
233 bool PostGarbageCollectionProcessing(Isolate* isolate) { | 283 bool PostGarbageCollectionProcessing(Isolate* isolate) { |
234 if (state() != Node::PENDING) return false; | 284 if (state() != Node::PENDING) return false; |
235 if (weak_callback_ == NULL) { | 285 if (weak_callback_ == NULL) { |
236 Release(); | 286 Release(); |
237 return false; | 287 return false; |
238 } | 288 } |
239 void* param = parameter(); | |
240 set_state(NEAR_DEATH); | 289 set_state(NEAR_DEATH); |
241 set_parameter(NULL); | |
242 | 290 |
243 Object** object = location(); | |
244 { | 291 { |
245 // Check that we are not passing a finalized external string to | 292 // Check that we are not passing a finalized external string to |
246 // the callback. | 293 // the callback. |
247 DCHECK(!object_->IsExternalOneByteString() || | 294 DCHECK(!object_->IsExternalOneByteString() || |
248 ExternalOneByteString::cast(object_)->resource() != NULL); | 295 ExternalOneByteString::cast(object_)->resource() != NULL); |
249 DCHECK(!object_->IsExternalTwoByteString() || | 296 DCHECK(!object_->IsExternalTwoByteString() || |
250 ExternalTwoByteString::cast(object_)->resource() != NULL); | 297 ExternalTwoByteString::cast(object_)->resource() != NULL); |
251 // Leaving V8. | 298 // Leaving V8. |
252 VMState<EXTERNAL> vmstate(isolate); | 299 VMState<EXTERNAL> vmstate(isolate); |
253 HandleScope handle_scope(isolate); | 300 HandleScope handle_scope(isolate); |
254 if (is_zapped_during_weak_callback()) { | 301 if (weakness_type() == Node::NORMAL_WEAK) { |
picksi1
2014/11/28 12:15:11
Could this code be refactored to switch on the wea
Erik Corry
2014/11/28 14:21:25
I have to rewrite this anyway because I have worke
| |
255 // Phantom weak pointer case. | 302 Object** object = location(); |
256 DCHECK(*object == Smi::FromInt(kPhantomReferenceZap)); | |
257 // Make data with a null handle. | |
258 v8::WeakCallbackData<v8::Value, void> data( | |
259 reinterpret_cast<v8::Isolate*>(isolate), v8::Local<v8::Object>(), | |
260 param); | |
261 weak_callback_(data); | |
262 if (state() != FREE) { | |
263 // Callback does not have to clear the global handle if it is a | |
264 // phantom handle. | |
265 Release(); | |
266 } | |
267 } else { | |
268 Handle<Object> handle(*object, isolate); | 303 Handle<Object> handle(*object, isolate); |
269 v8::WeakCallbackData<v8::Value, void> data( | 304 v8::WeakCallbackData<v8::Value, void> data( |
270 reinterpret_cast<v8::Isolate*>(isolate), v8::Utils::ToLocal(handle), | 305 reinterpret_cast<v8::Isolate*>(isolate), v8::Utils::ToLocal(handle), |
271 param); | 306 parameter()); |
307 set_parameter(NULL); | |
272 weak_callback_(data); | 308 weak_callback_(data); |
309 } else { | |
310 v8::PhantomCallbackData<void>::Callback callback = | |
311 reinterpret_cast<v8::PhantomCallbackData<void>::Callback>( | |
312 weak_callback_); | |
313 if (weakness_type() == Node::PHANTOM_WEAK) { | |
314 // Phantom weak pointer case. | |
315 DCHECK(*location() == Smi::FromInt(kPhantomReferenceZap)); | |
316 // Make data with a null handle. | |
317 v8::PhantomCallbackData<void> data( | |
318 reinterpret_cast<v8::Isolate*>(isolate), parameter()); | |
319 callback(data); | |
320 if (state() != FREE) { | |
picksi1
2014/11/28 12:15:11
There are lots of 'state() != FREE's in the code,
Erik Corry
2014/11/28 14:21:25
Created IsInUse() for this.
| |
321 // Callback does not have to clear the global handle if it is a | |
322 // phantom handle. | |
323 Release(); | |
324 } | |
325 } else { | |
326 DCHECK(weakness_type() == Node::INTERNAL_FIELDS_WEAK); | |
327 // Phantom weak pointer case, passing internal fields instead of | |
328 // parameter. | |
329 Handle<Object> handle(object(), isolate); | |
330 Handle<JSObject> jsobject = Handle<JSObject>::cast(handle); | |
331 v8::PhantomCallbackData<void> data( | |
332 reinterpret_cast<v8::Isolate*>(isolate), | |
333 jsobject->GetInternalField(internal_field1()), | |
334 jsobject->GetInternalField(internal_field2())); | |
335 // In the future, we want to delay the callback. In that case we will | |
336 // zap when we queue up, to stop the C++ side accessing the dead V8 | |
337 // object, but we will call Release only after the callback (allowing | |
338 // the node to be reused). | |
339 Zap(); | |
340 callback(data); | |
341 Release(); | |
342 } | |
273 } | 343 } |
274 } | 344 } |
275 // Absence of explicit cleanup or revival of weak handle | 345 // Absence of explicit cleanup or revival of weak handle |
276 // in most of the cases would lead to memory leak. | 346 // in most of the cases would lead to memory leak. |
277 CHECK(state() != NEAR_DEATH); | 347 CHECK(state() != NEAR_DEATH); |
278 return true; | 348 return true; |
279 } | 349 } |
280 | 350 |
281 inline GlobalHandles* GetGlobalHandles(); | 351 inline GlobalHandles* GetGlobalHandles(); |
282 | 352 |
(...skipping 10 matching lines...) Expand all Loading... | |
293 // Note: the most aligned fields should go first. | 363 // Note: the most aligned fields should go first. |
294 | 364 |
295 // Wrapper class ID. | 365 // Wrapper class ID. |
296 uint16_t class_id_; | 366 uint16_t class_id_; |
297 | 367 |
298 // Index in the containing handle block. | 368 // Index in the containing handle block. |
299 uint8_t index_; | 369 uint8_t index_; |
300 | 370 |
301 // This stores three flags (independent, partially_dependent and | 371 // This stores three flags (independent, partially_dependent and |
302 // in_new_space_list) and a State. | 372 // in_new_space_list) and a State. |
303 class NodeState : public BitField<State, 0, 4> {}; | 373 class NodeState : public BitField<State, 0, 3> {}; |
304 class IsIndependent : public BitField<bool, 4, 1> {}; | 374 class IsIndependent : public BitField<bool, 3, 1> {}; |
305 class IsPartiallyDependent : public BitField<bool, 5, 1> {}; | 375 class IsPartiallyDependent : public BitField<bool, 4, 1> {}; |
306 class IsInNewSpaceList : public BitField<bool, 6, 1> {}; | 376 class IsInNewSpaceList : public BitField<bool, 5, 1> {}; |
307 class IsZappedDuringWeakCallback : public BitField<bool, 7, 1> {}; | 377 class NodeWeaknessType : public BitField<WeaknessType, 6, 2> {}; |
308 | 378 |
309 uint8_t flags_; | 379 uint8_t flags_; |
310 | 380 |
311 // Handle specific callback - might be a weak reference in disguise. | 381 // Handle specific callback - might be a weak reference in disguise. |
312 WeakCallback weak_callback_; | 382 WeakCallback weak_callback_; |
313 | 383 |
314 // Provided data for callback. In FREE state, this is used for | 384 // Provided data for callback. In FREE state, this is used for |
315 // the free list link. | 385 // the free list link. |
316 union { | 386 union { |
317 void* parameter; | 387 void* parameter; |
388 struct { | |
389 uint16_t internal_field1; | |
390 uint16_t internal_field2; | |
391 } internal_field_indeces; | |
318 Node* next_free; | 392 Node* next_free; |
319 } parameter_or_next_free_; | 393 } parameter_or_next_free_; |
320 | 394 |
321 DISALLOW_COPY_AND_ASSIGN(Node); | 395 DISALLOW_COPY_AND_ASSIGN(Node); |
322 }; | 396 }; |
323 | 397 |
324 | 398 |
325 class GlobalHandles::NodeBlock { | 399 class GlobalHandles::NodeBlock { |
326 public: | 400 public: |
327 static const int kSize = 256; | 401 static const int kSize = 256; |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
493 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location); | 567 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location); |
494 } | 568 } |
495 | 569 |
496 | 570 |
497 void GlobalHandles::Destroy(Object** location) { | 571 void GlobalHandles::Destroy(Object** location) { |
498 if (location != NULL) Node::FromLocation(location)->Release(); | 572 if (location != NULL) Node::FromLocation(location)->Release(); |
499 } | 573 } |
500 | 574 |
501 | 575 |
502 void GlobalHandles::MakeWeak(Object** location, void* parameter, | 576 void GlobalHandles::MakeWeak(Object** location, void* parameter, |
503 WeakCallback weak_callback, PhantomState phantom) { | 577 WeakCallback weak_callback) { |
504 Node::FromLocation(location) | 578 Node::FromLocation(location)->MakeWeak(parameter, weak_callback); |
505 ->MakeWeak(parameter, weak_callback, phantom == Phantom); | |
506 } | 579 } |
507 | 580 |
508 | 581 |
582 void GlobalHandles::MakePhantom(Object** location, void* parameter, | |
583 PhantomCallback phantom_callback, | |
584 int internal_field_index1, | |
585 int internal_field_index2) { | |
586 Node::FromLocation(location) | |
picksi1
2014/11/28 12:15:11
Do internal_field_index1/2 have anything to do wit
Erik Corry
2014/11/28 14:21:25
Done.
| |
587 ->MakePhantom(parameter, phantom_callback, internal_field_index1, | |
588 internal_field_index2); | |
589 } | |
590 | |
591 | |
509 void* GlobalHandles::ClearWeakness(Object** location) { | 592 void* GlobalHandles::ClearWeakness(Object** location) { |
510 return Node::FromLocation(location)->ClearWeakness(); | 593 return Node::FromLocation(location)->ClearWeakness(); |
511 } | 594 } |
512 | 595 |
513 | 596 |
514 void GlobalHandles::MarkIndependent(Object** location) { | 597 void GlobalHandles::MarkIndependent(Object** location) { |
515 Node::FromLocation(location)->MarkIndependent(); | 598 Node::FromLocation(location)->MarkIndependent(); |
516 } | 599 } |
517 | 600 |
518 | 601 |
(...skipping 14 matching lines...) Expand all Loading... | |
533 | 616 |
534 bool GlobalHandles::IsWeak(Object** location) { | 617 bool GlobalHandles::IsWeak(Object** location) { |
535 return Node::FromLocation(location)->IsWeak(); | 618 return Node::FromLocation(location)->IsWeak(); |
536 } | 619 } |
537 | 620 |
538 | 621 |
539 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { | 622 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { |
540 for (NodeIterator it(this); !it.done(); it.Advance()) { | 623 for (NodeIterator it(this); !it.done(); it.Advance()) { |
541 Node* node = it.node(); | 624 Node* node = it.node(); |
542 if (node->IsWeakRetainer()) { | 625 if (node->IsWeakRetainer()) { |
543 if (node->state() == Node::PENDING && | 626 // Weakness type can be normal, phantom or internal fields. |
544 node->is_zapped_during_weak_callback()) { | 627 // For normal weakness we mark through the handle so that |
545 *(node->location()) = Smi::FromInt(kPhantomReferenceZap); | 628 // the object and things reachable from it are available |
629 // to the callback. | |
630 // In the case of phantom we can zap the object handle now | |
631 // and we won't need it, so we don't need to mark through it. | |
632 // In the internal fields case we will need the internal | |
633 // fields, so we can't zap the handle, but we don't need to | |
634 // mark through it, because it will die in this GC round. | |
635 if (node->state() == Node::PENDING) { | |
picksi1
2014/11/28 12:15:11
switch? Not sure if a 3 case switch beats 2 ifs on
Erik Corry
2014/11/28 14:21:25
The compiler will certainly convert a 3 case switc
| |
636 if (node->weakness_type() == Node::PHANTOM_WEAK) { | |
637 *(node->location()) = Smi::FromInt(kPhantomReferenceZap); | |
638 } else if (node->weakness_type() == Node::NORMAL_WEAK) { | |
639 v->VisitPointer(node->location()); | |
640 } else { | |
641 DCHECK(node->weakness_type() == Node::INTERNAL_FIELDS_WEAK); | |
642 } | |
546 } else { | 643 } else { |
547 v->VisitPointer(node->location()); | 644 v->VisitPointer(node->location()); |
548 } | 645 } |
549 } | 646 } |
550 } | 647 } |
551 } | 648 } |
552 | 649 |
553 | 650 |
554 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { | 651 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { |
555 for (NodeIterator it(this); !it.done(); it.Advance()) { | 652 for (NodeIterator it(this); !it.done(); it.Advance()) { |
(...skipping 28 matching lines...) Expand all Loading... | |
584 } | 681 } |
585 } | 682 } |
586 | 683 |
587 | 684 |
588 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { | 685 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { |
589 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 686 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
590 Node* node = new_space_nodes_[i]; | 687 Node* node = new_space_nodes_[i]; |
591 DCHECK(node->is_in_new_space_list()); | 688 DCHECK(node->is_in_new_space_list()); |
592 if ((node->is_independent() || node->is_partially_dependent()) && | 689 if ((node->is_independent() || node->is_partially_dependent()) && |
593 node->IsWeakRetainer()) { | 690 node->IsWeakRetainer()) { |
594 if (node->is_zapped_during_weak_callback()) { | 691 if (node->weakness_type() == Node::PHANTOM_WEAK) { |
595 *(node->location()) = Smi::FromInt(kPhantomReferenceZap); | 692 *(node->location()) = Smi::FromInt(kPhantomReferenceZap); |
693 } else if (node->weakness_type() == Node::NORMAL_WEAK) { | |
694 v->VisitPointer(node->location()); | |
596 } else { | 695 } else { |
597 v->VisitPointer(node->location()); | 696 DCHECK(node->weakness_type() == Node::INTERNAL_FIELDS_WEAK); |
697 // For this case we only need to trace if it's alive: The tracing of | |
698 // something that is already alive is just to get the pointer updated | |
699 // to the new location of the object). | |
700 if (!node->IsNearDeath()) { | |
701 v->VisitPointer(node->location()); | |
702 } | |
598 } | 703 } |
599 } | 704 } |
600 } | 705 } |
601 } | 706 } |
602 | 707 |
603 | 708 |
604 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, | 709 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, |
605 WeakSlotCallbackWithHeap can_skip) { | 710 WeakSlotCallbackWithHeap can_skip) { |
606 ComputeObjectGroupsAndImplicitReferences(); | 711 ComputeObjectGroupsAndImplicitReferences(); |
607 int last = 0; | 712 int last = 0; |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1083 DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); | 1188 DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); |
1084 blocks_[block][offset] = object; | 1189 blocks_[block][offset] = object; |
1085 if (isolate->heap()->InNewSpace(object)) { | 1190 if (isolate->heap()->InNewSpace(object)) { |
1086 new_space_indices_.Add(size_); | 1191 new_space_indices_.Add(size_); |
1087 } | 1192 } |
1088 *index = size_++; | 1193 *index = size_++; |
1089 } | 1194 } |
1090 | 1195 |
1091 | 1196 |
1092 } } // namespace v8::internal | 1197 } } // namespace v8::internal |
OLD | NEW |