| 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/global-handles.h" | 5 #include "src/global-handles.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/v8.h" | 8 #include "src/v8.h" |
| 9 #include "src/vm-state-inl.h" | 9 #include "src/vm-state-inl.h" |
| 10 | 10 |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 | 187 |
| 188 bool IsNearDeath() const { | 188 bool IsNearDeath() const { |
| 189 // Check for PENDING to ensure correct answer when processing callbacks. | 189 // Check for PENDING to ensure correct answer when processing callbacks. |
| 190 return state() == PENDING || state() == NEAR_DEATH; | 190 return state() == PENDING || state() == NEAR_DEATH; |
| 191 } | 191 } |
| 192 | 192 |
| 193 bool IsWeak() const { return state() == WEAK; } | 193 bool IsWeak() const { return state() == WEAK; } |
| 194 | 194 |
| 195 bool IsInUse() const { return state() != FREE; } | 195 bool IsInUse() const { return state() != FREE; } |
| 196 | 196 |
| 197 bool IsPendingPhantomCallback() const { |
| 198 return state() == PENDING && |
| 199 (weakness_type() == PHANTOM_WEAK || |
| 200 weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS); |
| 201 } |
| 202 |
| 203 bool IsPendingPhantomResetHandle() const { |
| 204 return state() == PENDING && weakness_type() == PHANTOM_WEAK_RESET_HANDLE; |
| 205 } |
| 206 |
| 197 bool IsRetainer() const { | 207 bool IsRetainer() const { |
| 198 return state() != FREE && | 208 return state() != FREE && |
| 199 !(state() == NEAR_DEATH && weakness_type() != FINALIZER_WEAK); | 209 !(state() == NEAR_DEATH && weakness_type() != FINALIZER_WEAK); |
| 200 } | 210 } |
| 201 | 211 |
| 202 bool IsStrongRetainer() const { return state() == NORMAL; } | 212 bool IsStrongRetainer() const { return state() == NORMAL; } |
| 203 | 213 |
| 204 bool IsWeakRetainer() const { | 214 bool IsWeakRetainer() const { |
| 205 return state() == WEAK || state() == PENDING || | 215 return state() == WEAK || state() == PENDING || |
| 206 (state() == NEAR_DEATH && weakness_type() == FINALIZER_WEAK); | 216 (state() == NEAR_DEATH && weakness_type() == FINALIZER_WEAK); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 set_weakness_type(PHANTOM_WEAK_2_INTERNAL_FIELDS); | 274 set_weakness_type(PHANTOM_WEAK_2_INTERNAL_FIELDS); |
| 265 break; | 275 break; |
| 266 case v8::WeakCallbackType::kFinalizer: | 276 case v8::WeakCallbackType::kFinalizer: |
| 267 set_weakness_type(FINALIZER_WEAK); | 277 set_weakness_type(FINALIZER_WEAK); |
| 268 break; | 278 break; |
| 269 } | 279 } |
| 270 set_parameter(parameter); | 280 set_parameter(parameter); |
| 271 weak_callback_ = phantom_callback; | 281 weak_callback_ = phantom_callback; |
| 272 } | 282 } |
| 273 | 283 |
| 284 void MakeWeak(Object*** location_addr) { |
| 285 DCHECK(IsInUse()); |
| 286 CHECK_NE(object_, reinterpret_cast<Object*>(kGlobalHandleZapValue)); |
| 287 set_state(WEAK); |
| 288 set_weakness_type(PHANTOM_WEAK_RESET_HANDLE); |
| 289 set_parameter(location_addr); |
| 290 weak_callback_ = nullptr; |
| 291 } |
| 292 |
| 274 void* ClearWeakness() { | 293 void* ClearWeakness() { |
| 275 DCHECK(IsInUse()); | 294 DCHECK(IsInUse()); |
| 276 void* p = parameter(); | 295 void* p = parameter(); |
| 277 set_state(NORMAL); | 296 set_state(NORMAL); |
| 278 set_parameter(NULL); | 297 set_parameter(NULL); |
| 279 return p; | 298 return p; |
| 280 } | 299 } |
| 281 | 300 |
| 282 void CollectPhantomCallbackData( | 301 void CollectPhantomCallbackData( |
| 283 Isolate* isolate, | 302 Isolate* isolate, |
| 284 List<PendingPhantomCallback>* pending_phantom_callbacks) { | 303 List<PendingPhantomCallback>* pending_phantom_callbacks) { |
| 285 DCHECK(weakness_type() == PHANTOM_WEAK || | 304 DCHECK(weakness_type() == PHANTOM_WEAK || |
| 286 weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS); | 305 weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS); |
| 287 DCHECK(state() == PENDING); | 306 DCHECK(state() == PENDING); |
| 307 DCHECK(weak_callback_ != nullptr); |
| 288 | 308 |
| 289 void* internal_fields[v8::kInternalFieldsInWeakCallback] = {nullptr, | 309 void* internal_fields[v8::kInternalFieldsInWeakCallback] = {nullptr, |
| 290 nullptr}; | 310 nullptr}; |
| 291 if (weakness_type() != PHANTOM_WEAK && object()->IsJSObject()) { | 311 if (weakness_type() != PHANTOM_WEAK && object()->IsJSObject()) { |
| 292 auto jsobject = JSObject::cast(object()); | 312 auto jsobject = JSObject::cast(object()); |
| 293 int field_count = jsobject->GetInternalFieldCount(); | 313 int field_count = jsobject->GetInternalFieldCount(); |
| 294 for (int i = 0; i < v8::kInternalFieldsInWeakCallback; ++i) { | 314 for (int i = 0; i < v8::kInternalFieldsInWeakCallback; ++i) { |
| 295 if (field_count == i) break; | 315 if (field_count == i) break; |
| 296 auto field = jsobject->GetInternalField(i); | 316 auto field = jsobject->GetInternalField(i); |
| 297 if (field->IsSmi()) internal_fields[i] = field; | 317 if (field->IsSmi()) internal_fields[i] = field; |
| 298 } | 318 } |
| 299 } | 319 } |
| 300 | 320 |
| 301 // Zap with something dangerous. | 321 // Zap with something dangerous. |
| 302 *location() = reinterpret_cast<Object*>(0x6057ca11); | 322 *location() = reinterpret_cast<Object*>(0x6057ca11); |
| 303 | 323 |
| 304 typedef v8::WeakCallbackInfo<void> Data; | 324 typedef v8::WeakCallbackInfo<void> Data; |
| 305 auto callback = reinterpret_cast<Data::Callback>(weak_callback_); | 325 auto callback = reinterpret_cast<Data::Callback>(weak_callback_); |
| 306 pending_phantom_callbacks->Add( | 326 pending_phantom_callbacks->Add( |
| 307 PendingPhantomCallback(this, callback, parameter(), internal_fields)); | 327 PendingPhantomCallback(this, callback, parameter(), internal_fields)); |
| 308 DCHECK(IsInUse()); | 328 DCHECK(IsInUse()); |
| 309 set_state(NEAR_DEATH); | 329 set_state(NEAR_DEATH); |
| 310 } | 330 } |
| 311 | 331 |
| 332 void ResetPhantomHandle() { |
| 333 DCHECK(weakness_type() == PHANTOM_WEAK_RESET_HANDLE); |
| 334 DCHECK(state() == PENDING); |
| 335 DCHECK(weak_callback_ == nullptr); |
| 336 Object*** handle = reinterpret_cast<Object***>(parameter()); |
| 337 *handle = nullptr; |
| 338 Release(); |
| 339 } |
| 340 |
| 312 bool PostGarbageCollectionProcessing(Isolate* isolate) { | 341 bool PostGarbageCollectionProcessing(Isolate* isolate) { |
| 313 // Handles only weak handles (not phantom) that are dying. | 342 // Handles only weak handles (not phantom) that are dying. |
| 314 if (state() != Node::PENDING) return false; | 343 if (state() != Node::PENDING) return false; |
| 315 if (weak_callback_ == NULL) { | 344 if (weak_callback_ == NULL) { |
| 316 Release(); | 345 Release(); |
| 317 return false; | 346 return false; |
| 318 } | 347 } |
| 319 set_state(NEAR_DEATH); | 348 set_state(NEAR_DEATH); |
| 320 | 349 |
| 321 // Check that we are not passing a finalized external string to | 350 // Check that we are not passing a finalized external string to |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 isolate()->heap()->CallGCEpilogueCallbacks( | 562 isolate()->heap()->CallGCEpilogueCallbacks( |
| 534 GCType::kGCTypeProcessWeakCallbacks, kNoGCCallbackFlags); | 563 GCType::kGCTypeProcessWeakCallbacks, kNoGCCallbackFlags); |
| 535 } | 564 } |
| 536 | 565 |
| 537 private: | 566 private: |
| 538 List<PendingPhantomCallback> pending_phantom_callbacks_; | 567 List<PendingPhantomCallback> pending_phantom_callbacks_; |
| 539 | 568 |
| 540 DISALLOW_COPY_AND_ASSIGN(PendingPhantomCallbacksSecondPassTask); | 569 DISALLOW_COPY_AND_ASSIGN(PendingPhantomCallbacksSecondPassTask); |
| 541 }; | 570 }; |
| 542 | 571 |
| 543 | |
| 544 GlobalHandles::GlobalHandles(Isolate* isolate) | 572 GlobalHandles::GlobalHandles(Isolate* isolate) |
| 545 : isolate_(isolate), | 573 : isolate_(isolate), |
| 546 number_of_global_handles_(0), | 574 number_of_global_handles_(0), |
| 547 first_block_(NULL), | 575 first_block_(NULL), |
| 548 first_used_block_(NULL), | 576 first_used_block_(NULL), |
| 549 first_free_(NULL), | 577 first_free_(NULL), |
| 550 post_gc_processing_count_(0), | 578 post_gc_processing_count_(0), |
| 579 number_of_phantom_handle_resets_(0), |
| 551 object_group_connections_(kObjectGroupConnectionsCapacity) {} | 580 object_group_connections_(kObjectGroupConnectionsCapacity) {} |
| 552 | 581 |
| 553 | |
| 554 GlobalHandles::~GlobalHandles() { | 582 GlobalHandles::~GlobalHandles() { |
| 555 NodeBlock* block = first_block_; | 583 NodeBlock* block = first_block_; |
| 556 while (block != NULL) { | 584 while (block != NULL) { |
| 557 NodeBlock* tmp = block->next(); | 585 NodeBlock* tmp = block->next(); |
| 558 delete block; | 586 delete block; |
| 559 block = tmp; | 587 block = tmp; |
| 560 } | 588 } |
| 561 first_block_ = NULL; | 589 first_block_ = NULL; |
| 562 } | 590 } |
| 563 | 591 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 594 | 622 |
| 595 typedef v8::WeakCallbackInfo<void>::Callback GenericCallback; | 623 typedef v8::WeakCallbackInfo<void>::Callback GenericCallback; |
| 596 | 624 |
| 597 | 625 |
| 598 void GlobalHandles::MakeWeak(Object** location, void* parameter, | 626 void GlobalHandles::MakeWeak(Object** location, void* parameter, |
| 599 GenericCallback phantom_callback, | 627 GenericCallback phantom_callback, |
| 600 v8::WeakCallbackType type) { | 628 v8::WeakCallbackType type) { |
| 601 Node::FromLocation(location)->MakeWeak(parameter, phantom_callback, type); | 629 Node::FromLocation(location)->MakeWeak(parameter, phantom_callback, type); |
| 602 } | 630 } |
| 603 | 631 |
| 632 void GlobalHandles::MakeWeak(Object*** location_addr) { |
| 633 Node::FromLocation(*location_addr)->MakeWeak(location_addr); |
| 634 } |
| 604 | 635 |
| 605 void* GlobalHandles::ClearWeakness(Object** location) { | 636 void* GlobalHandles::ClearWeakness(Object** location) { |
| 606 return Node::FromLocation(location)->ClearWeakness(); | 637 return Node::FromLocation(location)->ClearWeakness(); |
| 607 } | 638 } |
| 608 | 639 |
| 609 | 640 |
| 610 void GlobalHandles::MarkIndependent(Object** location) { | 641 void GlobalHandles::MarkIndependent(Object** location) { |
| 611 Node::FromLocation(location)->MarkIndependent(); | 642 Node::FromLocation(location)->MarkIndependent(); |
| 612 } | 643 } |
| 613 | 644 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 629 | 660 |
| 630 bool GlobalHandles::IsWeak(Object** location) { | 661 bool GlobalHandles::IsWeak(Object** location) { |
| 631 return Node::FromLocation(location)->IsWeak(); | 662 return Node::FromLocation(location)->IsWeak(); |
| 632 } | 663 } |
| 633 | 664 |
| 634 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { | 665 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { |
| 635 for (NodeIterator it(this); !it.done(); it.Advance()) { | 666 for (NodeIterator it(this); !it.done(); it.Advance()) { |
| 636 Node* node = it.node(); | 667 Node* node = it.node(); |
| 637 if (node->IsWeakRetainer()) { | 668 if (node->IsWeakRetainer()) { |
| 638 // Pending weak phantom handles die immediately. Everything else survives. | 669 // Pending weak phantom handles die immediately. Everything else survives. |
| 639 if (node->state() == Node::PENDING && | 670 if (node->IsPendingPhantomResetHandle()) { |
| 640 node->weakness_type() != FINALIZER_WEAK) { | 671 node->ResetPhantomHandle(); |
| 672 ++number_of_phantom_handle_resets_; |
| 673 } else if (node->IsPendingPhantomCallback()) { |
| 641 node->CollectPhantomCallbackData(isolate(), | 674 node->CollectPhantomCallbackData(isolate(), |
| 642 &pending_phantom_callbacks_); | 675 &pending_phantom_callbacks_); |
| 643 } else { | 676 } else { |
| 644 v->VisitPointer(node->location()); | 677 v->VisitPointer(node->location()); |
| 645 } | 678 } |
| 646 } | 679 } |
| 647 } | 680 } |
| 648 } | 681 } |
| 649 | 682 |
| 650 | 683 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 690 } | 723 } |
| 691 | 724 |
| 692 | 725 |
| 693 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { | 726 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { |
| 694 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 727 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
| 695 Node* node = new_space_nodes_[i]; | 728 Node* node = new_space_nodes_[i]; |
| 696 DCHECK(node->is_in_new_space_list()); | 729 DCHECK(node->is_in_new_space_list()); |
| 697 if ((node->is_independent() || node->is_partially_dependent()) && | 730 if ((node->is_independent() || node->is_partially_dependent()) && |
| 698 node->IsWeakRetainer()) { | 731 node->IsWeakRetainer()) { |
| 699 // Pending weak phantom handles die immediately. Everything else survives. | 732 // Pending weak phantom handles die immediately. Everything else survives. |
| 700 if (node->state() == Node::PENDING && | 733 if (node->IsPendingPhantomResetHandle()) { |
| 701 node->weakness_type() != FINALIZER_WEAK) { | 734 node->ResetPhantomHandle(); |
| 735 ++number_of_phantom_handle_resets_; |
| 736 } else if (node->IsPendingPhantomCallback()) { |
| 702 node->CollectPhantomCallbackData(isolate(), | 737 node->CollectPhantomCallbackData(isolate(), |
| 703 &pending_phantom_callbacks_); | 738 &pending_phantom_callbacks_); |
| 704 } else { | 739 } else { |
| 705 v->VisitPointer(node->location()); | 740 v->VisitPointer(node->location()); |
| 706 } | 741 } |
| 707 } | 742 } |
| 708 } | 743 } |
| 709 } | 744 } |
| 710 | 745 |
| 711 | 746 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 733 } | 768 } |
| 734 | 769 |
| 735 | 770 |
| 736 void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots(ObjectVisitor* v) { | 771 void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots(ObjectVisitor* v) { |
| 737 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 772 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
| 738 Node* node = new_space_nodes_[i]; | 773 Node* node = new_space_nodes_[i]; |
| 739 DCHECK(node->is_in_new_space_list()); | 774 DCHECK(node->is_in_new_space_list()); |
| 740 if ((node->is_independent() || !node->is_active()) && | 775 if ((node->is_independent() || !node->is_active()) && |
| 741 node->IsWeakRetainer()) { | 776 node->IsWeakRetainer()) { |
| 742 // Pending weak phantom handles die immediately. Everything else survives. | 777 // Pending weak phantom handles die immediately. Everything else survives. |
| 743 if (node->state() == Node::PENDING && | 778 if (node->IsPendingPhantomResetHandle()) { |
| 744 node->weakness_type() != FINALIZER_WEAK) { | 779 node->ResetPhantomHandle(); |
| 780 ++number_of_phantom_handle_resets_; |
| 781 } else if (node->IsPendingPhantomCallback()) { |
| 745 node->CollectPhantomCallbackData(isolate(), | 782 node->CollectPhantomCallbackData(isolate(), |
| 746 &pending_phantom_callbacks_); | 783 &pending_phantom_callbacks_); |
| 747 } else { | 784 } else { |
| 748 v->VisitPointer(node->location()); | 785 v->VisitPointer(node->location()); |
| 749 } | 786 } |
| 750 } | 787 } |
| 751 } | 788 } |
| 752 } | 789 } |
| 753 | 790 |
| 754 | 791 |
| (...skipping 713 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1468 blocks_[block][offset] = object; | 1505 blocks_[block][offset] = object; |
| 1469 if (isolate->heap()->InNewSpace(object)) { | 1506 if (isolate->heap()->InNewSpace(object)) { |
| 1470 new_space_indices_.Add(size_); | 1507 new_space_indices_.Add(size_); |
| 1471 } | 1508 } |
| 1472 *index = size_++; | 1509 *index = size_++; |
| 1473 } | 1510 } |
| 1474 | 1511 |
| 1475 | 1512 |
| 1476 } // namespace internal | 1513 } // namespace internal |
| 1477 } // namespace v8 | 1514 } // namespace v8 |
| OLD | NEW |