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 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 return p; | 257 return p; |
258 } | 258 } |
259 | 259 |
260 void CollectPhantomCallbackData( | 260 void CollectPhantomCallbackData( |
261 Isolate* isolate, | 261 Isolate* isolate, |
262 List<PendingPhantomCallback>* pending_phantom_callbacks) { | 262 List<PendingPhantomCallback>* pending_phantom_callbacks) { |
263 if (state() != PENDING) return; | 263 if (state() != PENDING) return; |
264 if (weak_callback_ != NULL) { | 264 if (weak_callback_ != NULL) { |
265 if (weakness_type() == NORMAL_WEAK) return; | 265 if (weakness_type() == NORMAL_WEAK) return; |
266 | 266 |
267 v8::Isolate* api_isolate = reinterpret_cast<v8::Isolate*>(isolate); | |
268 | |
269 DCHECK(weakness_type() == PHANTOM_WEAK || | 267 DCHECK(weakness_type() == PHANTOM_WEAK || |
270 weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS); | 268 weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS); |
271 | 269 |
272 Object* internal_field0 = nullptr; | 270 void* internal_fields[v8::kInternalFieldsInWeakCallback] = {nullptr, |
273 Object* internal_field1 = nullptr; | 271 nullptr}; |
274 if (weakness_type() != PHANTOM_WEAK) { | 272 if (weakness_type() != PHANTOM_WEAK && object()->IsJSObject()) { |
275 if (object()->IsJSObject()) { | 273 auto jsobject = JSObject::cast(object()); |
276 JSObject* jsobject = JSObject::cast(object()); | 274 int field_count = jsobject->GetInternalFieldCount(); |
277 int field_count = jsobject->GetInternalFieldCount(); | 275 for (int i = 0; i < v8::kInternalFieldsInWeakCallback; ++i) { |
278 if (field_count > 0) { | 276 if (field_count == i) break; |
279 internal_field0 = jsobject->GetInternalField(0); | 277 auto field = jsobject->GetInternalField(i); |
280 if (!internal_field0->IsSmi()) internal_field0 = nullptr; | 278 if (field->IsSmi()) internal_fields[i] = field; |
281 } | |
282 if (field_count > 1) { | |
283 internal_field1 = jsobject->GetInternalField(1); | |
284 if (!internal_field1->IsSmi()) internal_field1 = nullptr; | |
285 } | |
286 } | 279 } |
287 } | 280 } |
288 | 281 |
289 // Zap with harmless value. | 282 // Zap with something dangerous. |
290 *location() = Smi::FromInt(0); | 283 *location() = reinterpret_cast<Object*>(0x6057ca11); |
| 284 |
291 typedef v8::WeakCallbackInfo<void> Data; | 285 typedef v8::WeakCallbackInfo<void> Data; |
292 | 286 auto callback = reinterpret_cast<Data::Callback>(weak_callback_); |
293 Data data(api_isolate, parameter(), internal_field0, internal_field1); | |
294 Data::Callback callback = | |
295 reinterpret_cast<Data::Callback>(weak_callback_); | |
296 | |
297 pending_phantom_callbacks->Add( | 287 pending_phantom_callbacks->Add( |
298 PendingPhantomCallback(this, data, callback)); | 288 PendingPhantomCallback(this, callback, parameter(), internal_fields)); |
299 DCHECK(IsInUse()); | 289 DCHECK(IsInUse()); |
300 set_state(NEAR_DEATH); | 290 set_state(NEAR_DEATH); |
301 } | 291 } |
302 } | 292 } |
303 | 293 |
304 bool PostGarbageCollectionProcessing(Isolate* isolate) { | 294 bool PostGarbageCollectionProcessing(Isolate* isolate) { |
305 // Handles only weak handles (not phantom) that are dying. | 295 // Handles only weak handles (not phantom) that are dying. |
306 if (state() != Node::PENDING) return false; | 296 if (state() != Node::PENDING) return false; |
307 if (weak_callback_ == NULL) { | 297 if (weak_callback_ == NULL) { |
308 Release(); | 298 Release(); |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
831 node->set_in_new_space_list(false); | 821 node->set_in_new_space_list(false); |
832 isolate_->heap()->IncrementNodesDiedInNewSpace(); | 822 isolate_->heap()->IncrementNodesDiedInNewSpace(); |
833 } | 823 } |
834 } | 824 } |
835 new_space_nodes_.Rewind(last); | 825 new_space_nodes_.Rewind(last); |
836 } | 826 } |
837 | 827 |
838 | 828 |
839 int GlobalHandles::DispatchPendingPhantomCallbacks() { | 829 int GlobalHandles::DispatchPendingPhantomCallbacks() { |
840 int freed_nodes = 0; | 830 int freed_nodes = 0; |
| 831 { |
| 832 // The initial pass callbacks must simply clear the nodes. |
| 833 for (auto i = pending_phantom_callbacks_.begin(); |
| 834 i != pending_phantom_callbacks_.end(); ++i) { |
| 835 auto callback = i; |
| 836 // Skip callbacks that have already been processed once. |
| 837 if (callback->node() == nullptr) continue; |
| 838 callback->Invoke(isolate()); |
| 839 freed_nodes++; |
| 840 } |
| 841 } |
| 842 // The second pass empties the list. |
841 while (pending_phantom_callbacks_.length() != 0) { | 843 while (pending_phantom_callbacks_.length() != 0) { |
842 PendingPhantomCallback callback = pending_phantom_callbacks_.RemoveLast(); | 844 auto callback = pending_phantom_callbacks_.RemoveLast(); |
843 DCHECK(callback.node()->IsInUse()); | 845 DCHECK(callback.node() == nullptr); |
844 callback.invoke(); | 846 // No second pass callback required. |
845 DCHECK(!callback.node()->IsInUse()); | 847 if (callback.callback() == nullptr) continue; |
846 freed_nodes++; | 848 // Fire second pass callback. |
| 849 callback.Invoke(isolate()); |
847 } | 850 } |
848 return freed_nodes; | 851 return freed_nodes; |
849 } | 852 } |
850 | 853 |
851 | 854 |
| 855 void GlobalHandles::PendingPhantomCallback::Invoke(Isolate* isolate) { |
| 856 Data::Callback* callback_addr = nullptr; |
| 857 if (node_ != nullptr) { |
| 858 // Initialize for first pass callback. |
| 859 DCHECK(node_->state() == Node::NEAR_DEATH); |
| 860 callback_addr = &callback_; |
| 861 } |
| 862 Data data(reinterpret_cast<v8::Isolate*>(isolate), parameter_, |
| 863 internal_fields_, callback_addr); |
| 864 Data::Callback callback = callback_; |
| 865 callback_ = nullptr; |
| 866 callback(data); |
| 867 if (node_ != nullptr) { |
| 868 // Transition to second pass state. |
| 869 DCHECK(node_->state() == Node::FREE); |
| 870 node_ = nullptr; |
| 871 } |
| 872 } |
| 873 |
| 874 |
852 int GlobalHandles::PostGarbageCollectionProcessing(GarbageCollector collector) { | 875 int GlobalHandles::PostGarbageCollectionProcessing(GarbageCollector collector) { |
853 // Process weak global handle callbacks. This must be done after the | 876 // Process weak global handle callbacks. This must be done after the |
854 // GC is completely done, because the callbacks may invoke arbitrary | 877 // GC is completely done, because the callbacks may invoke arbitrary |
855 // API functions. | 878 // API functions. |
856 DCHECK(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); | 879 DCHECK(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); |
857 const int initial_post_gc_processing_count = ++post_gc_processing_count_; | 880 const int initial_post_gc_processing_count = ++post_gc_processing_count_; |
858 int freed_nodes = 0; | 881 int freed_nodes = 0; |
859 freed_nodes += DispatchPendingPhantomCallbacks(); | 882 freed_nodes += DispatchPendingPhantomCallbacks(); |
860 if (initial_post_gc_processing_count != post_gc_processing_count_) { | 883 if (initial_post_gc_processing_count != post_gc_processing_count_) { |
861 // If the callbacks caused a nested GC, then return. See comment in | 884 // If the callbacks caused a nested GC, then return. See comment in |
(...skipping 10 matching lines...) Expand all Loading... |
872 // PostScavengeProcessing. | 895 // PostScavengeProcessing. |
873 return freed_nodes; | 896 return freed_nodes; |
874 } | 897 } |
875 if (initial_post_gc_processing_count == post_gc_processing_count_) { | 898 if (initial_post_gc_processing_count == post_gc_processing_count_) { |
876 UpdateListOfNewSpaceNodes(); | 899 UpdateListOfNewSpaceNodes(); |
877 } | 900 } |
878 return freed_nodes; | 901 return freed_nodes; |
879 } | 902 } |
880 | 903 |
881 | 904 |
882 void GlobalHandles::PendingPhantomCallback::invoke() { | |
883 if (node_->state() == Node::FREE) return; | |
884 DCHECK(node_->state() == Node::NEAR_DEATH); | |
885 callback_(data_); | |
886 if (node_->state() != Node::FREE) node_->Release(); | |
887 } | |
888 | |
889 | |
890 void GlobalHandles::IterateStrongRoots(ObjectVisitor* v) { | 905 void GlobalHandles::IterateStrongRoots(ObjectVisitor* v) { |
891 for (NodeIterator it(this); !it.done(); it.Advance()) { | 906 for (NodeIterator it(this); !it.done(); it.Advance()) { |
892 if (it.node()->IsStrongRetainer()) { | 907 if (it.node()->IsStrongRetainer()) { |
893 v->VisitPointer(it.node()->location()); | 908 v->VisitPointer(it.node()->location()); |
894 } | 909 } |
895 } | 910 } |
896 } | 911 } |
897 | 912 |
898 | 913 |
899 void GlobalHandles::IterateAllRoots(ObjectVisitor* v) { | 914 void GlobalHandles::IterateAllRoots(ObjectVisitor* v) { |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1244 DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); | 1259 DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); |
1245 blocks_[block][offset] = object; | 1260 blocks_[block][offset] = object; |
1246 if (isolate->heap()->InNewSpace(object)) { | 1261 if (isolate->heap()->InNewSpace(object)) { |
1247 new_space_indices_.Add(size_); | 1262 new_space_indices_.Add(size_); |
1248 } | 1263 } |
1249 *index = size_++; | 1264 *index = size_++; |
1250 } | 1265 } |
1251 | 1266 |
1252 | 1267 |
1253 } } // namespace v8::internal | 1268 } } // namespace v8::internal |
OLD | NEW |