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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 parameter_or_next_free_.next_free = NULL; | 75 parameter_or_next_free_.next_free = NULL; |
76 weak_callback_ = NULL; | 76 weak_callback_ = NULL; |
77 } | 77 } |
78 #endif | 78 #endif |
79 | 79 |
80 void Initialize(int index, Node** first_free) { | 80 void Initialize(int index, Node** first_free) { |
81 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 81 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
82 index_ = static_cast<uint8_t>(index); | 82 index_ = static_cast<uint8_t>(index); |
83 DCHECK(static_cast<int>(index_) == index); | 83 DCHECK(static_cast<int>(index_) == index); |
84 set_state(FREE); | 84 set_state(FREE); |
85 set_weakness_type(NORMAL_WEAK); | |
86 set_in_new_space_list(false); | 85 set_in_new_space_list(false); |
87 parameter_or_next_free_.next_free = *first_free; | 86 parameter_or_next_free_.next_free = *first_free; |
88 *first_free = this; | 87 *first_free = this; |
89 } | 88 } |
90 | 89 |
91 void Acquire(Object* object) { | 90 void Acquire(Object* object) { |
92 DCHECK(state() == FREE); | 91 DCHECK(state() == FREE); |
93 object_ = object; | 92 object_ = object; |
94 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 93 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
95 set_independent(false); | 94 set_independent(false); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 // Check for PENDING to ensure correct answer when processing callbacks. | 189 // Check for PENDING to ensure correct answer when processing callbacks. |
191 return state() == PENDING || state() == NEAR_DEATH; | 190 return state() == PENDING || state() == NEAR_DEATH; |
192 } | 191 } |
193 | 192 |
194 bool IsWeak() const { return state() == WEAK; } | 193 bool IsWeak() const { return state() == WEAK; } |
195 | 194 |
196 bool IsInUse() const { return state() != FREE; } | 195 bool IsInUse() const { return state() != FREE; } |
197 | 196 |
198 bool IsRetainer() const { | 197 bool IsRetainer() const { |
199 return state() != FREE && | 198 return state() != FREE && |
200 !(state() == NEAR_DEATH && weakness_type() != NORMAL_WEAK && | 199 !(state() == NEAR_DEATH && weakness_type() != FINALIZER_WEAK); |
201 weakness_type() != FINALIZER_WEAK); | |
202 } | 200 } |
203 | 201 |
204 bool IsStrongRetainer() const { return state() == NORMAL; } | 202 bool IsStrongRetainer() const { return state() == NORMAL; } |
205 | 203 |
206 bool IsWeakRetainer() const { | 204 bool IsWeakRetainer() const { |
207 return state() == WEAK || state() == PENDING || | 205 return state() == WEAK || state() == PENDING || |
208 (state() == NEAR_DEATH && (weakness_type() == NORMAL_WEAK || | 206 (state() == NEAR_DEATH && weakness_type() == FINALIZER_WEAK); |
209 weakness_type() == FINALIZER_WEAK)); | |
210 } | 207 } |
211 | 208 |
212 void MarkPending() { | 209 void MarkPending() { |
213 DCHECK(state() == WEAK); | 210 DCHECK(state() == WEAK); |
214 set_state(PENDING); | 211 set_state(PENDING); |
215 } | 212 } |
216 | 213 |
217 // Independent flag accessors. | 214 // Independent flag accessors. |
218 void MarkIndependent() { | 215 void MarkIndependent() { |
219 DCHECK(IsInUse()); | 216 DCHECK(IsInUse()); |
(...skipping 25 matching lines...) Expand all Loading... |
245 // Accessors for next free node in the free list. | 242 // Accessors for next free node in the free list. |
246 Node* next_free() { | 243 Node* next_free() { |
247 DCHECK(state() == FREE); | 244 DCHECK(state() == FREE); |
248 return parameter_or_next_free_.next_free; | 245 return parameter_or_next_free_.next_free; |
249 } | 246 } |
250 void set_next_free(Node* value) { | 247 void set_next_free(Node* value) { |
251 DCHECK(state() == FREE); | 248 DCHECK(state() == FREE); |
252 parameter_or_next_free_.next_free = value; | 249 parameter_or_next_free_.next_free = value; |
253 } | 250 } |
254 | 251 |
255 void MakeWeak(void* parameter, WeakCallback weak_callback) { | |
256 DCHECK(weak_callback != nullptr); | |
257 DCHECK(IsInUse()); | |
258 CHECK_NE(object_, reinterpret_cast<Object*>(kGlobalHandleZapValue)); | |
259 set_state(WEAK); | |
260 set_weakness_type(NORMAL_WEAK); | |
261 set_parameter(parameter); | |
262 weak_callback_ = weak_callback; | |
263 } | |
264 | |
265 void MakeWeak(void* parameter, | 252 void MakeWeak(void* parameter, |
266 WeakCallbackInfo<void>::Callback phantom_callback, | 253 WeakCallbackInfo<void>::Callback phantom_callback, |
267 v8::WeakCallbackType type) { | 254 v8::WeakCallbackType type) { |
268 DCHECK(phantom_callback != nullptr); | 255 DCHECK(phantom_callback != nullptr); |
269 DCHECK(IsInUse()); | 256 DCHECK(IsInUse()); |
270 CHECK_NE(object_, reinterpret_cast<Object*>(kGlobalHandleZapValue)); | 257 CHECK_NE(object_, reinterpret_cast<Object*>(kGlobalHandleZapValue)); |
271 set_state(WEAK); | 258 set_state(WEAK); |
272 switch (type) { | 259 switch (type) { |
273 case v8::WeakCallbackType::kParameter: | 260 case v8::WeakCallbackType::kParameter: |
274 set_weakness_type(PHANTOM_WEAK); | 261 set_weakness_type(PHANTOM_WEAK); |
275 break; | 262 break; |
276 case v8::WeakCallbackType::kInternalFields: | 263 case v8::WeakCallbackType::kInternalFields: |
277 set_weakness_type(PHANTOM_WEAK_2_INTERNAL_FIELDS); | 264 set_weakness_type(PHANTOM_WEAK_2_INTERNAL_FIELDS); |
278 break; | 265 break; |
279 case v8::WeakCallbackType::kFinalizer: | 266 case v8::WeakCallbackType::kFinalizer: |
280 set_weakness_type(FINALIZER_WEAK); | 267 set_weakness_type(FINALIZER_WEAK); |
281 break; | 268 break; |
282 } | 269 } |
283 set_parameter(parameter); | 270 set_parameter(parameter); |
284 weak_callback_ = reinterpret_cast<WeakCallback>(phantom_callback); | 271 weak_callback_ = phantom_callback; |
285 } | 272 } |
286 | 273 |
287 void* ClearWeakness() { | 274 void* ClearWeakness() { |
288 DCHECK(IsInUse()); | 275 DCHECK(IsInUse()); |
289 void* p = parameter(); | 276 void* p = parameter(); |
290 set_state(NORMAL); | 277 set_state(NORMAL); |
291 set_parameter(NULL); | 278 set_parameter(NULL); |
292 return p; | 279 return p; |
293 } | 280 } |
294 | 281 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 return false; | 317 return false; |
331 } | 318 } |
332 set_state(NEAR_DEATH); | 319 set_state(NEAR_DEATH); |
333 | 320 |
334 // Check that we are not passing a finalized external string to | 321 // Check that we are not passing a finalized external string to |
335 // the callback. | 322 // the callback. |
336 DCHECK(!object_->IsExternalOneByteString() || | 323 DCHECK(!object_->IsExternalOneByteString() || |
337 ExternalOneByteString::cast(object_)->resource() != NULL); | 324 ExternalOneByteString::cast(object_)->resource() != NULL); |
338 DCHECK(!object_->IsExternalTwoByteString() || | 325 DCHECK(!object_->IsExternalTwoByteString() || |
339 ExternalTwoByteString::cast(object_)->resource() != NULL); | 326 ExternalTwoByteString::cast(object_)->resource() != NULL); |
340 if (weakness_type() != NORMAL_WEAK && weakness_type() != FINALIZER_WEAK) { | 327 if (weakness_type() != FINALIZER_WEAK) { |
341 return false; | 328 return false; |
342 } | 329 } |
343 | 330 |
344 // Leaving V8. | 331 // Leaving V8. |
345 VMState<EXTERNAL> vmstate(isolate); | 332 VMState<EXTERNAL> vmstate(isolate); |
346 HandleScope handle_scope(isolate); | 333 HandleScope handle_scope(isolate); |
347 if (weakness_type() == NORMAL_WEAK) { | 334 void* internal_fields[v8::kInternalFieldsInWeakCallback] = {nullptr, |
348 Object** object = location(); | 335 nullptr}; |
349 Handle<Object> handle(*object, isolate); | 336 v8::WeakCallbackInfo<void> data(reinterpret_cast<v8::Isolate*>(isolate), |
350 v8::WeakCallbackData<v8::Value, void> data( | 337 parameter(), internal_fields, nullptr); |
351 reinterpret_cast<v8::Isolate*>(isolate), parameter(), | 338 weak_callback_(data); |
352 v8::Utils::ToLocal(handle)); | |
353 set_parameter(NULL); | |
354 weak_callback_(data); | |
355 } else { | |
356 void* internal_fields[v8::kInternalFieldsInWeakCallback] = {nullptr, | |
357 nullptr}; | |
358 v8::WeakCallbackInfo<void> data(reinterpret_cast<v8::Isolate*>(isolate), | |
359 parameter(), internal_fields, nullptr); | |
360 auto callback = reinterpret_cast<v8::WeakCallbackInfo<void>::Callback>( | |
361 weak_callback_); | |
362 callback(data); | |
363 } | |
364 | 339 |
365 // Absence of explicit cleanup or revival of weak handle | 340 // Absence of explicit cleanup or revival of weak handle |
366 // in most of the cases would lead to memory leak. | 341 // in most of the cases would lead to memory leak. |
367 CHECK(state() != NEAR_DEATH); | 342 CHECK(state() != NEAR_DEATH); |
368 return true; | 343 return true; |
369 } | 344 } |
370 | 345 |
371 inline GlobalHandles* GetGlobalHandles(); | 346 inline GlobalHandles* GetGlobalHandles(); |
372 | 347 |
373 private: | 348 private: |
(...skipping 20 matching lines...) Expand all Loading... |
394 class IsIndependent : public BitField<bool, 3, 1> {}; | 369 class IsIndependent : public BitField<bool, 3, 1> {}; |
395 // The following two fields are mutually exclusive | 370 // The following two fields are mutually exclusive |
396 class IsActive : public BitField<bool, 4, 1> {}; | 371 class IsActive : public BitField<bool, 4, 1> {}; |
397 class IsPartiallyDependent : public BitField<bool, 4, 1> {}; | 372 class IsPartiallyDependent : public BitField<bool, 4, 1> {}; |
398 class IsInNewSpaceList : public BitField<bool, 5, 1> {}; | 373 class IsInNewSpaceList : public BitField<bool, 5, 1> {}; |
399 class NodeWeaknessType : public BitField<WeaknessType, 6, 2> {}; | 374 class NodeWeaknessType : public BitField<WeaknessType, 6, 2> {}; |
400 | 375 |
401 uint8_t flags_; | 376 uint8_t flags_; |
402 | 377 |
403 // Handle specific callback - might be a weak reference in disguise. | 378 // Handle specific callback - might be a weak reference in disguise. |
404 WeakCallback weak_callback_; | 379 WeakCallbackInfo<void>::Callback weak_callback_; |
405 | 380 |
406 // Provided data for callback. In FREE state, this is used for | 381 // Provided data for callback. In FREE state, this is used for |
407 // the free list link. | 382 // the free list link. |
408 union { | 383 union { |
409 void* parameter; | 384 void* parameter; |
410 Node* next_free; | 385 Node* next_free; |
411 } parameter_or_next_free_; | 386 } parameter_or_next_free_; |
412 | 387 |
413 DISALLOW_COPY_AND_ASSIGN(Node); | 388 DISALLOW_COPY_AND_ASSIGN(Node); |
414 }; | 389 }; |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
610 DCHECK(location != NULL); | 585 DCHECK(location != NULL); |
611 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location); | 586 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location); |
612 } | 587 } |
613 | 588 |
614 | 589 |
615 void GlobalHandles::Destroy(Object** location) { | 590 void GlobalHandles::Destroy(Object** location) { |
616 if (location != NULL) Node::FromLocation(location)->Release(); | 591 if (location != NULL) Node::FromLocation(location)->Release(); |
617 } | 592 } |
618 | 593 |
619 | 594 |
620 void GlobalHandles::MakeWeak(Object** location, void* parameter, | |
621 WeakCallback weak_callback) { | |
622 Node::FromLocation(location)->MakeWeak(parameter, weak_callback); | |
623 } | |
624 | |
625 | |
626 typedef v8::WeakCallbackInfo<void>::Callback GenericCallback; | 595 typedef v8::WeakCallbackInfo<void>::Callback GenericCallback; |
627 | 596 |
628 | 597 |
629 void GlobalHandles::MakeWeak(Object** location, void* parameter, | 598 void GlobalHandles::MakeWeak(Object** location, void* parameter, |
630 GenericCallback phantom_callback, | 599 GenericCallback phantom_callback, |
631 v8::WeakCallbackType type) { | 600 v8::WeakCallbackType type) { |
632 Node::FromLocation(location)->MakeWeak(parameter, phantom_callback, type); | 601 Node::FromLocation(location)->MakeWeak(parameter, phantom_callback, type); |
633 } | 602 } |
634 | 603 |
635 | 604 |
(...skipping 25 matching lines...) Expand all Loading... |
661 bool GlobalHandles::IsWeak(Object** location) { | 630 bool GlobalHandles::IsWeak(Object** location) { |
662 return Node::FromLocation(location)->IsWeak(); | 631 return Node::FromLocation(location)->IsWeak(); |
663 } | 632 } |
664 | 633 |
665 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { | 634 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { |
666 for (NodeIterator it(this); !it.done(); it.Advance()) { | 635 for (NodeIterator it(this); !it.done(); it.Advance()) { |
667 Node* node = it.node(); | 636 Node* node = it.node(); |
668 if (node->IsWeakRetainer()) { | 637 if (node->IsWeakRetainer()) { |
669 // Pending weak phantom handles die immediately. Everything else survives. | 638 // Pending weak phantom handles die immediately. Everything else survives. |
670 if (node->state() == Node::PENDING && | 639 if (node->state() == Node::PENDING && |
671 node->weakness_type() != NORMAL_WEAK && | |
672 node->weakness_type() != FINALIZER_WEAK) { | 640 node->weakness_type() != FINALIZER_WEAK) { |
673 node->CollectPhantomCallbackData(isolate(), | 641 node->CollectPhantomCallbackData(isolate(), |
674 &pending_phantom_callbacks_); | 642 &pending_phantom_callbacks_); |
675 } else { | 643 } else { |
676 v->VisitPointer(node->location()); | 644 v->VisitPointer(node->location()); |
677 } | 645 } |
678 } | 646 } |
679 } | 647 } |
680 } | 648 } |
681 | 649 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
723 | 691 |
724 | 692 |
725 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { | 693 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { |
726 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 694 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
727 Node* node = new_space_nodes_[i]; | 695 Node* node = new_space_nodes_[i]; |
728 DCHECK(node->is_in_new_space_list()); | 696 DCHECK(node->is_in_new_space_list()); |
729 if ((node->is_independent() || node->is_partially_dependent()) && | 697 if ((node->is_independent() || node->is_partially_dependent()) && |
730 node->IsWeakRetainer()) { | 698 node->IsWeakRetainer()) { |
731 // Pending weak phantom handles die immediately. Everything else survives. | 699 // Pending weak phantom handles die immediately. Everything else survives. |
732 if (node->state() == Node::PENDING && | 700 if (node->state() == Node::PENDING && |
733 node->weakness_type() != NORMAL_WEAK && | |
734 node->weakness_type() != FINALIZER_WEAK) { | 701 node->weakness_type() != FINALIZER_WEAK) { |
735 node->CollectPhantomCallbackData(isolate(), | 702 node->CollectPhantomCallbackData(isolate(), |
736 &pending_phantom_callbacks_); | 703 &pending_phantom_callbacks_); |
737 } else { | 704 } else { |
738 v->VisitPointer(node->location()); | 705 v->VisitPointer(node->location()); |
739 } | 706 } |
740 } | 707 } |
741 } | 708 } |
742 } | 709 } |
743 | 710 |
(...skipping 23 matching lines...) Expand all Loading... |
767 | 734 |
768 | 735 |
769 void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots(ObjectVisitor* v) { | 736 void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots(ObjectVisitor* v) { |
770 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 737 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
771 Node* node = new_space_nodes_[i]; | 738 Node* node = new_space_nodes_[i]; |
772 DCHECK(node->is_in_new_space_list()); | 739 DCHECK(node->is_in_new_space_list()); |
773 if ((node->is_independent() || !node->is_active()) && | 740 if ((node->is_independent() || !node->is_active()) && |
774 node->IsWeakRetainer()) { | 741 node->IsWeakRetainer()) { |
775 // Pending weak phantom handles die immediately. Everything else survives. | 742 // Pending weak phantom handles die immediately. Everything else survives. |
776 if (node->state() == Node::PENDING && | 743 if (node->state() == Node::PENDING && |
777 node->weakness_type() != NORMAL_WEAK && | |
778 node->weakness_type() != FINALIZER_WEAK) { | 744 node->weakness_type() != FINALIZER_WEAK) { |
779 node->CollectPhantomCallbackData(isolate(), | 745 node->CollectPhantomCallbackData(isolate(), |
780 &pending_phantom_callbacks_); | 746 &pending_phantom_callbacks_); |
781 } else { | 747 } else { |
782 v->VisitPointer(node->location()); | 748 v->VisitPointer(node->location()); |
783 } | 749 } |
784 } | 750 } |
785 } | 751 } |
786 } | 752 } |
787 | 753 |
(...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1502 blocks_[block][offset] = object; | 1468 blocks_[block][offset] = object; |
1503 if (isolate->heap()->InNewSpace(object)) { | 1469 if (isolate->heap()->InNewSpace(object)) { |
1504 new_space_indices_.Add(size_); | 1470 new_space_indices_.Add(size_); |
1505 } | 1471 } |
1506 *index = size_++; | 1472 *index = size_++; |
1507 } | 1473 } |
1508 | 1474 |
1509 | 1475 |
1510 } // namespace internal | 1476 } // namespace internal |
1511 } // namespace v8 | 1477 } // namespace v8 |
OLD | NEW |