Chromium Code Reviews| 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 |