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

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

Issue 1064713005: collect phantom handle data before it gets overwritten (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: 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') | src/heap/heap.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 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 162
163 bool IsNearDeath() const { 163 bool IsNearDeath() const {
164 // Check for PENDING to ensure correct answer when processing callbacks. 164 // Check for PENDING to ensure correct answer when processing callbacks.
165 return state() == PENDING || state() == NEAR_DEATH; 165 return state() == PENDING || state() == NEAR_DEATH;
166 } 166 }
167 167
168 bool IsWeak() const { return state() == WEAK; } 168 bool IsWeak() const { return state() == WEAK; }
169 169
170 bool IsInUse() const { return state() != FREE; } 170 bool IsInUse() const { return state() != FREE; }
171 171
172 bool IsRetainer() const { return state() != FREE; } 172 bool IsRetainer() const {
173 return state() != FREE &&
174 !(state() == NEAR_DEATH && weakness_type() != NORMAL_WEAK);
Hannes Payer (out of office) 2015/04/13 11:50:45 please simplify this statement
dcarney 2015/04/13 12:27:05 this was the clearest version i could think of. wh
175 }
173 176
174 bool IsStrongRetainer() const { return state() == NORMAL; } 177 bool IsStrongRetainer() const { return state() == NORMAL; }
175 178
176 bool IsWeakRetainer() const { 179 bool IsWeakRetainer() const {
177 return state() == WEAK || state() == PENDING || state() == NEAR_DEATH; 180 return state() == WEAK || state() == PENDING ||
181 (state() == NEAR_DEATH && weakness_type() == NORMAL_WEAK);
178 } 182 }
179 183
180 void MarkPending() { 184 void MarkPending() {
181 DCHECK(state() == WEAK); 185 DCHECK(state() == WEAK);
182 set_state(PENDING); 186 set_state(PENDING);
183 } 187 }
184 188
185 // Independent flag accessors. 189 // Independent flag accessors.
186 void MarkIndependent() { 190 void MarkIndependent() {
187 DCHECK(IsInUse()); 191 DCHECK(IsInUse());
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 DCHECK(IsInUse()); 257 DCHECK(IsInUse());
254 void* p = parameter(); 258 void* p = parameter();
255 set_state(NORMAL); 259 set_state(NORMAL);
256 set_parameter(NULL); 260 set_parameter(NULL);
257 return p; 261 return p;
258 } 262 }
259 263
260 void CollectPhantomCallbackData( 264 void CollectPhantomCallbackData(
261 Isolate* isolate, 265 Isolate* isolate,
262 List<PendingPhantomCallback>* pending_phantom_callbacks) { 266 List<PendingPhantomCallback>* pending_phantom_callbacks) {
263 if (state() != PENDING) return; 267 DCHECK(weakness_type() == PHANTOM_WEAK ||
264 if (weak_callback_ != NULL) { 268 weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS);
265 if (weakness_type() == NORMAL_WEAK) return; 269 DCHECK(state() == PENDING);
266 270
267 DCHECK(weakness_type() == PHANTOM_WEAK || 271 void* internal_fields[v8::kInternalFieldsInWeakCallback] = {nullptr,
268 weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS); 272 nullptr};
273 if (weakness_type() != PHANTOM_WEAK && object()->IsJSObject()) {
274 auto jsobject = JSObject::cast(object());
275 int field_count = jsobject->GetInternalFieldCount();
276 for (int i = 0; i < v8::kInternalFieldsInWeakCallback; ++i) {
277 if (field_count == i) break;
278 auto field = jsobject->GetInternalField(i);
279 if (field->IsSmi()) internal_fields[i] = field;
280 }
281 }
269 282
270 void* internal_fields[v8::kInternalFieldsInWeakCallback] = {nullptr, 283 // Zap with something dangerous.
271 nullptr}; 284 *location() = reinterpret_cast<Object*>(0x6057ca11);
272 if (weakness_type() != PHANTOM_WEAK && object()->IsJSObject()) {
273 auto jsobject = JSObject::cast(object());
274 int field_count = jsobject->GetInternalFieldCount();
275 for (int i = 0; i < v8::kInternalFieldsInWeakCallback; ++i) {
276 if (field_count == i) break;
277 auto field = jsobject->GetInternalField(i);
278 if (field->IsSmi()) internal_fields[i] = field;
279 }
280 }
281 285
282 // Zap with something dangerous. 286 typedef v8::WeakCallbackInfo<void> Data;
283 *location() = reinterpret_cast<Object*>(0x6057ca11); 287 auto callback = reinterpret_cast<Data::Callback>(weak_callback_);
284 288 pending_phantom_callbacks->Add(
285 typedef v8::WeakCallbackInfo<void> Data; 289 PendingPhantomCallback(this, callback, parameter(), internal_fields));
286 auto callback = reinterpret_cast<Data::Callback>(weak_callback_); 290 DCHECK(IsInUse());
287 pending_phantom_callbacks->Add( 291 set_state(NEAR_DEATH);
288 PendingPhantomCallback(this, callback, parameter(), internal_fields));
289 DCHECK(IsInUse());
290 set_state(NEAR_DEATH);
291 }
292 } 292 }
293 293
294 bool PostGarbageCollectionProcessing(Isolate* isolate) { 294 bool PostGarbageCollectionProcessing(Isolate* isolate) {
295 // Handles only weak handles (not phantom) that are dying. 295 // Handles only weak handles (not phantom) that are dying.
296 if (state() != Node::PENDING) return false; 296 if (state() != Node::PENDING) return false;
297 if (weak_callback_ == NULL) { 297 if (weak_callback_ == NULL) {
298 Release(); 298 Release();
299 return false; 299 return false;
300 } 300 }
301 set_state(NEAR_DEATH); 301 set_state(NEAR_DEATH);
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 typedef v8::WeakCallbackInfo<void>::Callback GenericCallback; 555 typedef v8::WeakCallbackInfo<void>::Callback GenericCallback;
556 556
557 557
558 void GlobalHandles::MakeWeak(Object** location, void* parameter, 558 void GlobalHandles::MakeWeak(Object** location, void* parameter,
559 GenericCallback phantom_callback, 559 GenericCallback phantom_callback,
560 v8::WeakCallbackType type) { 560 v8::WeakCallbackType type) {
561 Node::FromLocation(location)->MakeWeak(parameter, phantom_callback, type); 561 Node::FromLocation(location)->MakeWeak(parameter, phantom_callback, type);
562 } 562 }
563 563
564 564
565 void GlobalHandles::CollectAllPhantomCallbackData() {
566 for (NodeIterator it(this); !it.done(); it.Advance()) {
567 Node* node = it.node();
568 node->CollectPhantomCallbackData(isolate(), &pending_phantom_callbacks_);
569 }
570 }
571
572
573 void GlobalHandles::CollectYoungPhantomCallbackData() {
574 for (int i = 0; i < new_space_nodes_.length(); ++i) {
575 Node* node = new_space_nodes_[i];
576 DCHECK(node->is_in_new_space_list());
577 node->CollectPhantomCallbackData(isolate(), &pending_phantom_callbacks_);
578 }
579 }
580
581
582 void* GlobalHandles::ClearWeakness(Object** location) { 565 void* GlobalHandles::ClearWeakness(Object** location) {
583 return Node::FromLocation(location)->ClearWeakness(); 566 return Node::FromLocation(location)->ClearWeakness();
584 } 567 }
585 568
586 569
587 void GlobalHandles::MarkIndependent(Object** location) { 570 void GlobalHandles::MarkIndependent(Object** location) {
588 Node::FromLocation(location)->MarkIndependent(); 571 Node::FromLocation(location)->MarkIndependent();
589 } 572 }
590 573
591 574
(...skipping 17 matching lines...) Expand all
609 } 592 }
610 593
611 594
612 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { 595 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) {
613 for (NodeIterator it(this); !it.done(); it.Advance()) { 596 for (NodeIterator it(this); !it.done(); it.Advance()) {
614 Node* node = it.node(); 597 Node* node = it.node();
615 if (node->IsWeakRetainer()) { 598 if (node->IsWeakRetainer()) {
616 // Weakness type can be normal or phantom, with or without internal 599 // Weakness type can be normal or phantom, with or without internal
617 // fields). For normal weakness we mark through the handle so that the 600 // fields). For normal weakness we mark through the handle so that the
618 // object and things reachable from it are available to the callback. 601 // object and things reachable from it are available to the callback.
619 //
620 // In the case of phantom with no internal fields, we can zap the object
621 // handle now and we won't need it, so we don't need to mark through it.
622 // In the internal fields case we will need the internal
623 // fields, so we can't zap the handle.
624 if (node->state() == Node::PENDING) { 602 if (node->state() == Node::PENDING) {
625 if (node->weakness_type() == PHANTOM_WEAK) { 603 if (node->weakness_type() == NORMAL_WEAK) {
626 *(node->location()) = Smi::FromInt(0);
627 } else if (node->weakness_type() == NORMAL_WEAK) {
628 v->VisitPointer(node->location()); 604 v->VisitPointer(node->location());
629 } else { 605 } else {
630 DCHECK(node->weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS); 606 node->CollectPhantomCallbackData(isolate(),
607 &pending_phantom_callbacks_);
631 } 608 }
632 } else { 609 } else {
633 // Node is not pending, so that means the object survived. We still 610 // Node is not pending, so that means the object survived. We still
634 // need to visit the pointer in case the object moved, eg. because of 611 // need to visit the pointer in case the object moved, eg. because of
635 // compaction. 612 // compaction.
636 v->VisitPointer(node->location()); 613 v->VisitPointer(node->location());
637 } 614 }
638 } 615 }
639 } 616 }
640 } 617 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
673 } 650 }
674 } 651 }
675 652
676 653
677 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { 654 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) {
678 for (int i = 0; i < new_space_nodes_.length(); ++i) { 655 for (int i = 0; i < new_space_nodes_.length(); ++i) {
679 Node* node = new_space_nodes_[i]; 656 Node* node = new_space_nodes_[i];
680 DCHECK(node->is_in_new_space_list()); 657 DCHECK(node->is_in_new_space_list());
681 if ((node->is_independent() || node->is_partially_dependent()) && 658 if ((node->is_independent() || node->is_partially_dependent()) &&
682 node->IsWeakRetainer()) { 659 node->IsWeakRetainer()) {
683 if (node->weakness_type() == PHANTOM_WEAK) { 660 if (node->weakness_type() == NORMAL_WEAK) {
684 *(node->location()) = Smi::FromInt(0);
685 } else if (node->weakness_type() == NORMAL_WEAK) {
686 v->VisitPointer(node->location()); 661 v->VisitPointer(node->location());
687 } else { 662 } else if (node->state() == Node::PENDING) {
688 DCHECK(node->weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS); 663 node->CollectPhantomCallbackData(isolate(),
689 // For this case we only need to trace if it's alive: The tracing of 664 &pending_phantom_callbacks_);
690 // something that is already alive is just to get the pointer updated
691 // to the new location of the object).
692 DCHECK(node->state() != Node::NEAR_DEATH);
693 if (node->state() != Node::PENDING) {
694 v->VisitPointer(node->location());
695 }
696 } 665 }
697 } 666 }
698 } 667 }
699 } 668 }
700 669
701 670
702 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, 671 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v,
703 WeakSlotCallbackWithHeap can_skip) { 672 WeakSlotCallbackWithHeap can_skip) {
704 ComputeObjectGroupsAndImplicitReferences(); 673 ComputeObjectGroupsAndImplicitReferences();
705 int last = 0; 674 int last = 0;
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after
1259 DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); 1228 DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]);
1260 blocks_[block][offset] = object; 1229 blocks_[block][offset] = object;
1261 if (isolate->heap()->InNewSpace(object)) { 1230 if (isolate->heap()->InNewSpace(object)) {
1262 new_space_indices_.Add(size_); 1231 new_space_indices_.Add(size_);
1263 } 1232 }
1264 *index = size_++; 1233 *index = size_++;
1265 } 1234 }
1266 1235
1267 1236
1268 } } // namespace v8::internal 1237 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/global-handles.h ('k') | src/heap/heap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698