Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1135)

Side by Side Diff: src/global-handles.cc

Issue 998253006: two pass phantom collection (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix debugger Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/global-handles.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/global-handles.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698