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 |