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 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
162 | 162 |
163 bool IsNearDeath() const { | 163 bool IsNearDeath() const { |
164 // Check for PENDING to ensure correct answer when processing callbacks. | 164 // Check for PENDING to ensure correct answer when processing callbacks. |
165 return state() == PENDING || state() == NEAR_DEATH; | 165 return state() == PENDING || state() == NEAR_DEATH; |
166 } | 166 } |
167 | 167 |
168 bool IsWeak() const { return state() == WEAK; } | 168 bool IsWeak() const { return state() == WEAK; } |
169 | 169 |
170 bool IsInUse() const { return state() != FREE; } | 170 bool IsInUse() const { return state() != FREE; } |
171 | 171 |
172 bool IsRetainer() const { return state() != FREE; } | 172 bool IsRetainer() const { |
173 return state() != FREE && | |
174 !(state() == NEAR_DEATH && weakness_type() != NORMAL_WEAK); | |
Hannes Payer (out of office)
2015/04/13 11:50:45
please simplify this statement
dcarney
2015/04/13 12:27:05
this was the clearest version i could think of. wh
| |
175 } | |
173 | 176 |
174 bool IsStrongRetainer() const { return state() == NORMAL; } | 177 bool IsStrongRetainer() const { return state() == NORMAL; } |
175 | 178 |
176 bool IsWeakRetainer() const { | 179 bool IsWeakRetainer() const { |
177 return state() == WEAK || state() == PENDING || state() == NEAR_DEATH; | 180 return state() == WEAK || state() == PENDING || |
181 (state() == NEAR_DEATH && weakness_type() == NORMAL_WEAK); | |
178 } | 182 } |
179 | 183 |
180 void MarkPending() { | 184 void MarkPending() { |
181 DCHECK(state() == WEAK); | 185 DCHECK(state() == WEAK); |
182 set_state(PENDING); | 186 set_state(PENDING); |
183 } | 187 } |
184 | 188 |
185 // Independent flag accessors. | 189 // Independent flag accessors. |
186 void MarkIndependent() { | 190 void MarkIndependent() { |
187 DCHECK(IsInUse()); | 191 DCHECK(IsInUse()); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
253 DCHECK(IsInUse()); | 257 DCHECK(IsInUse()); |
254 void* p = parameter(); | 258 void* p = parameter(); |
255 set_state(NORMAL); | 259 set_state(NORMAL); |
256 set_parameter(NULL); | 260 set_parameter(NULL); |
257 return p; | 261 return p; |
258 } | 262 } |
259 | 263 |
260 void CollectPhantomCallbackData( | 264 void CollectPhantomCallbackData( |
261 Isolate* isolate, | 265 Isolate* isolate, |
262 List<PendingPhantomCallback>* pending_phantom_callbacks) { | 266 List<PendingPhantomCallback>* pending_phantom_callbacks) { |
263 if (state() != PENDING) return; | 267 DCHECK(weakness_type() == PHANTOM_WEAK || |
264 if (weak_callback_ != NULL) { | 268 weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS); |
265 if (weakness_type() == NORMAL_WEAK) return; | 269 DCHECK(state() == PENDING); |
266 | 270 |
267 DCHECK(weakness_type() == PHANTOM_WEAK || | 271 void* internal_fields[v8::kInternalFieldsInWeakCallback] = {nullptr, |
268 weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS); | 272 nullptr}; |
273 if (weakness_type() != PHANTOM_WEAK && object()->IsJSObject()) { | |
274 auto jsobject = JSObject::cast(object()); | |
275 int field_count = jsobject->GetInternalFieldCount(); | |
276 for (int i = 0; i < v8::kInternalFieldsInWeakCallback; ++i) { | |
277 if (field_count == i) break; | |
278 auto field = jsobject->GetInternalField(i); | |
279 if (field->IsSmi()) internal_fields[i] = field; | |
280 } | |
281 } | |
269 | 282 |
270 void* internal_fields[v8::kInternalFieldsInWeakCallback] = {nullptr, | 283 // Zap with something dangerous. |
271 nullptr}; | 284 *location() = reinterpret_cast<Object*>(0x6057ca11); |
272 if (weakness_type() != PHANTOM_WEAK && object()->IsJSObject()) { | |
273 auto jsobject = JSObject::cast(object()); | |
274 int field_count = jsobject->GetInternalFieldCount(); | |
275 for (int i = 0; i < v8::kInternalFieldsInWeakCallback; ++i) { | |
276 if (field_count == i) break; | |
277 auto field = jsobject->GetInternalField(i); | |
278 if (field->IsSmi()) internal_fields[i] = field; | |
279 } | |
280 } | |
281 | 285 |
282 // Zap with something dangerous. | 286 typedef v8::WeakCallbackInfo<void> Data; |
283 *location() = reinterpret_cast<Object*>(0x6057ca11); | 287 auto callback = reinterpret_cast<Data::Callback>(weak_callback_); |
284 | 288 pending_phantom_callbacks->Add( |
285 typedef v8::WeakCallbackInfo<void> Data; | 289 PendingPhantomCallback(this, callback, parameter(), internal_fields)); |
286 auto callback = reinterpret_cast<Data::Callback>(weak_callback_); | 290 DCHECK(IsInUse()); |
287 pending_phantom_callbacks->Add( | 291 set_state(NEAR_DEATH); |
288 PendingPhantomCallback(this, callback, parameter(), internal_fields)); | |
289 DCHECK(IsInUse()); | |
290 set_state(NEAR_DEATH); | |
291 } | |
292 } | 292 } |
293 | 293 |
294 bool PostGarbageCollectionProcessing(Isolate* isolate) { | 294 bool PostGarbageCollectionProcessing(Isolate* isolate) { |
295 // Handles only weak handles (not phantom) that are dying. | 295 // Handles only weak handles (not phantom) that are dying. |
296 if (state() != Node::PENDING) return false; | 296 if (state() != Node::PENDING) return false; |
297 if (weak_callback_ == NULL) { | 297 if (weak_callback_ == NULL) { |
298 Release(); | 298 Release(); |
299 return false; | 299 return false; |
300 } | 300 } |
301 set_state(NEAR_DEATH); | 301 set_state(NEAR_DEATH); |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
555 typedef v8::WeakCallbackInfo<void>::Callback GenericCallback; | 555 typedef v8::WeakCallbackInfo<void>::Callback GenericCallback; |
556 | 556 |
557 | 557 |
558 void GlobalHandles::MakeWeak(Object** location, void* parameter, | 558 void GlobalHandles::MakeWeak(Object** location, void* parameter, |
559 GenericCallback phantom_callback, | 559 GenericCallback phantom_callback, |
560 v8::WeakCallbackType type) { | 560 v8::WeakCallbackType type) { |
561 Node::FromLocation(location)->MakeWeak(parameter, phantom_callback, type); | 561 Node::FromLocation(location)->MakeWeak(parameter, phantom_callback, type); |
562 } | 562 } |
563 | 563 |
564 | 564 |
565 void GlobalHandles::CollectAllPhantomCallbackData() { | |
566 for (NodeIterator it(this); !it.done(); it.Advance()) { | |
567 Node* node = it.node(); | |
568 node->CollectPhantomCallbackData(isolate(), &pending_phantom_callbacks_); | |
569 } | |
570 } | |
571 | |
572 | |
573 void GlobalHandles::CollectYoungPhantomCallbackData() { | |
574 for (int i = 0; i < new_space_nodes_.length(); ++i) { | |
575 Node* node = new_space_nodes_[i]; | |
576 DCHECK(node->is_in_new_space_list()); | |
577 node->CollectPhantomCallbackData(isolate(), &pending_phantom_callbacks_); | |
578 } | |
579 } | |
580 | |
581 | |
582 void* GlobalHandles::ClearWeakness(Object** location) { | 565 void* GlobalHandles::ClearWeakness(Object** location) { |
583 return Node::FromLocation(location)->ClearWeakness(); | 566 return Node::FromLocation(location)->ClearWeakness(); |
584 } | 567 } |
585 | 568 |
586 | 569 |
587 void GlobalHandles::MarkIndependent(Object** location) { | 570 void GlobalHandles::MarkIndependent(Object** location) { |
588 Node::FromLocation(location)->MarkIndependent(); | 571 Node::FromLocation(location)->MarkIndependent(); |
589 } | 572 } |
590 | 573 |
591 | 574 |
(...skipping 17 matching lines...) Expand all Loading... | |
609 } | 592 } |
610 | 593 |
611 | 594 |
612 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { | 595 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { |
613 for (NodeIterator it(this); !it.done(); it.Advance()) { | 596 for (NodeIterator it(this); !it.done(); it.Advance()) { |
614 Node* node = it.node(); | 597 Node* node = it.node(); |
615 if (node->IsWeakRetainer()) { | 598 if (node->IsWeakRetainer()) { |
616 // Weakness type can be normal or phantom, with or without internal | 599 // Weakness type can be normal or phantom, with or without internal |
617 // fields). For normal weakness we mark through the handle so that the | 600 // fields). For normal weakness we mark through the handle so that the |
618 // object and things reachable from it are available to the callback. | 601 // object and things reachable from it are available to the callback. |
619 // | |
620 // In the case of phantom with no internal fields, we can zap the object | |
621 // handle now and we won't need it, so we don't need to mark through it. | |
622 // In the internal fields case we will need the internal | |
623 // fields, so we can't zap the handle. | |
624 if (node->state() == Node::PENDING) { | 602 if (node->state() == Node::PENDING) { |
625 if (node->weakness_type() == PHANTOM_WEAK) { | 603 if (node->weakness_type() == NORMAL_WEAK) { |
626 *(node->location()) = Smi::FromInt(0); | |
627 } else if (node->weakness_type() == NORMAL_WEAK) { | |
628 v->VisitPointer(node->location()); | 604 v->VisitPointer(node->location()); |
629 } else { | 605 } else { |
630 DCHECK(node->weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS); | 606 node->CollectPhantomCallbackData(isolate(), |
607 &pending_phantom_callbacks_); | |
631 } | 608 } |
632 } else { | 609 } else { |
633 // Node is not pending, so that means the object survived. We still | 610 // Node is not pending, so that means the object survived. We still |
634 // need to visit the pointer in case the object moved, eg. because of | 611 // need to visit the pointer in case the object moved, eg. because of |
635 // compaction. | 612 // compaction. |
636 v->VisitPointer(node->location()); | 613 v->VisitPointer(node->location()); |
637 } | 614 } |
638 } | 615 } |
639 } | 616 } |
640 } | 617 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
673 } | 650 } |
674 } | 651 } |
675 | 652 |
676 | 653 |
677 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { | 654 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { |
678 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 655 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
679 Node* node = new_space_nodes_[i]; | 656 Node* node = new_space_nodes_[i]; |
680 DCHECK(node->is_in_new_space_list()); | 657 DCHECK(node->is_in_new_space_list()); |
681 if ((node->is_independent() || node->is_partially_dependent()) && | 658 if ((node->is_independent() || node->is_partially_dependent()) && |
682 node->IsWeakRetainer()) { | 659 node->IsWeakRetainer()) { |
683 if (node->weakness_type() == PHANTOM_WEAK) { | 660 if (node->weakness_type() == NORMAL_WEAK) { |
684 *(node->location()) = Smi::FromInt(0); | |
685 } else if (node->weakness_type() == NORMAL_WEAK) { | |
686 v->VisitPointer(node->location()); | 661 v->VisitPointer(node->location()); |
687 } else { | 662 } else if (node->state() == Node::PENDING) { |
688 DCHECK(node->weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS); | 663 node->CollectPhantomCallbackData(isolate(), |
689 // For this case we only need to trace if it's alive: The tracing of | 664 &pending_phantom_callbacks_); |
690 // something that is already alive is just to get the pointer updated | |
691 // to the new location of the object). | |
692 DCHECK(node->state() != Node::NEAR_DEATH); | |
693 if (node->state() != Node::PENDING) { | |
694 v->VisitPointer(node->location()); | |
695 } | |
696 } | 665 } |
697 } | 666 } |
698 } | 667 } |
699 } | 668 } |
700 | 669 |
701 | 670 |
702 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, | 671 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, |
703 WeakSlotCallbackWithHeap can_skip) { | 672 WeakSlotCallbackWithHeap can_skip) { |
704 ComputeObjectGroupsAndImplicitReferences(); | 673 ComputeObjectGroupsAndImplicitReferences(); |
705 int last = 0; | 674 int last = 0; |
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1259 DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); | 1228 DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); |
1260 blocks_[block][offset] = object; | 1229 blocks_[block][offset] = object; |
1261 if (isolate->heap()->InNewSpace(object)) { | 1230 if (isolate->heap()->InNewSpace(object)) { |
1262 new_space_indices_.Add(size_); | 1231 new_space_indices_.Add(size_); |
1263 } | 1232 } |
1264 *index = size_++; | 1233 *index = size_++; |
1265 } | 1234 } |
1266 | 1235 |
1267 | 1236 |
1268 } } // namespace v8::internal | 1237 } } // namespace v8::internal |
OLD | NEW |