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

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

Issue 649563006: Introduce phantom weak handles in the API and use them internally for debug info (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Actually make available through the API and fix scavenge Created 6 years, 2 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 | Annotate | Revision Log
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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 flags_ = IsPartiallyDependent::update(flags_, v); 139 flags_ = IsPartiallyDependent::update(flags_, v);
140 } 140 }
141 141
142 bool is_in_new_space_list() { 142 bool is_in_new_space_list() {
143 return IsInNewSpaceList::decode(flags_); 143 return IsInNewSpaceList::decode(flags_);
144 } 144 }
145 void set_in_new_space_list(bool v) { 145 void set_in_new_space_list(bool v) {
146 flags_ = IsInNewSpaceList::update(flags_, v); 146 flags_ = IsInNewSpaceList::update(flags_, v);
147 } 147 }
148 148
149 bool is_zapped_during_weak_callback() {
150 return IsZappedDuringWeakCallback::decode(flags_);
151 }
152 void set_is_zapped_during_weak_callback(bool v) {
153 flags_ = IsZappedDuringWeakCallback::update(flags_, v);
154 }
155
149 bool IsNearDeath() const { 156 bool IsNearDeath() const {
150 // Check for PENDING to ensure correct answer when processing callbacks. 157 // Check for PENDING to ensure correct answer when processing callbacks.
151 return state() == PENDING || state() == NEAR_DEATH; 158 return state() == PENDING || state() == NEAR_DEATH;
152 } 159 }
153 160
154 bool IsWeak() const { return state() == WEAK; } 161 bool IsWeak() const { return state() == WEAK; }
155 162
156 bool IsRetainer() const { return state() != FREE; } 163 bool IsRetainer() const { return state() != FREE; }
157 164
158 bool IsStrongRetainer() const { return state() == NORMAL; } 165 bool IsStrongRetainer() const { return state() == NORMAL; }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 // Accessors for next free node in the free list. 204 // Accessors for next free node in the free list.
198 Node* next_free() { 205 Node* next_free() {
199 DCHECK(state() == FREE); 206 DCHECK(state() == FREE);
200 return parameter_or_next_free_.next_free; 207 return parameter_or_next_free_.next_free;
201 } 208 }
202 void set_next_free(Node* value) { 209 void set_next_free(Node* value) {
203 DCHECK(state() == FREE); 210 DCHECK(state() == FREE);
204 parameter_or_next_free_.next_free = value; 211 parameter_or_next_free_.next_free = value;
205 } 212 }
206 213
207 void MakeWeak(void* parameter, WeakCallback weak_callback) { 214 void MakeWeak(void* parameter, WeakCallback weak_callback,
215 bool is_zapped_during_weak_callback = false) {
208 DCHECK(weak_callback != NULL); 216 DCHECK(weak_callback != NULL);
209 DCHECK(state() != FREE); 217 DCHECK(state() != FREE);
210 CHECK(object_ != NULL); 218 CHECK(object_ != NULL);
211 set_state(WEAK); 219 set_state(WEAK);
212 set_parameter(parameter); 220 set_parameter(parameter);
221 set_is_zapped_during_weak_callback(is_zapped_during_weak_callback);
213 weak_callback_ = weak_callback; 222 weak_callback_ = weak_callback;
214 } 223 }
215 224
216 void* ClearWeakness() { 225 void* ClearWeakness() {
217 DCHECK(state() != FREE); 226 DCHECK(state() != FREE);
218 void* p = parameter(); 227 void* p = parameter();
219 set_state(NORMAL); 228 set_state(NORMAL);
220 set_parameter(NULL); 229 set_parameter(NULL);
221 return p; 230 return p;
222 } 231 }
223 232
224 bool PostGarbageCollectionProcessing(Isolate* isolate) { 233 bool PostGarbageCollectionProcessing(Isolate* isolate) {
225 if (state() != Node::PENDING) return false; 234 if (state() != Node::PENDING) return false;
226 if (weak_callback_ == NULL) { 235 if (weak_callback_ == NULL) {
227 Release(); 236 Release();
228 return false; 237 return false;
229 } 238 }
230 void* par = parameter(); 239 void* param = parameter();
231 set_state(NEAR_DEATH); 240 set_state(NEAR_DEATH);
232 set_parameter(NULL); 241 set_parameter(NULL);
233 242
234 Object** object = location(); 243 Object** object = location();
235 { 244 {
236 // Check that we are not passing a finalized external string to 245 // Check that we are not passing a finalized external string to
237 // the callback. 246 // the callback.
238 DCHECK(!object_->IsExternalOneByteString() || 247 DCHECK(!object_->IsExternalOneByteString() ||
239 ExternalOneByteString::cast(object_)->resource() != NULL); 248 ExternalOneByteString::cast(object_)->resource() != NULL);
240 DCHECK(!object_->IsExternalTwoByteString() || 249 DCHECK(!object_->IsExternalTwoByteString() ||
241 ExternalTwoByteString::cast(object_)->resource() != NULL); 250 ExternalTwoByteString::cast(object_)->resource() != NULL);
242 // Leaving V8. 251 // Leaving V8.
243 VMState<EXTERNAL> state(isolate); 252 VMState<EXTERNAL> state(isolate);
244 HandleScope handle_scope(isolate); 253 HandleScope handle_scope(isolate);
245 Handle<Object> handle(*object, isolate); 254 Handle<Object> handle(*object, isolate);
255 if (is_zapped_during_weak_callback()) {
256 DCHECK(*handle == Smi::FromInt(kPhantomReferenceZap));
jochen (gone - plz use gerrit) 2014/10/20 14:11:46 should we set handle to a null-handle here?
Erik Corry 2014/10/20 14:25:32 I think that's not so useful. The callback then d
jochen (gone - plz use gerrit) 2014/10/20 14:29:03 but the address of the handle is completely new, i
Erik Corry 2014/10/22 13:21:00 We could replace Handle<Object> handle(*object, i
257 }
246 v8::WeakCallbackData<v8::Value, void> data( 258 v8::WeakCallbackData<v8::Value, void> data(
247 reinterpret_cast<v8::Isolate*>(isolate), 259 reinterpret_cast<v8::Isolate*>(isolate), v8::Utils::ToLocal(handle),
248 v8::Utils::ToLocal(handle), 260 param);
249 par);
250 weak_callback_(data); 261 weak_callback_(data);
251 } 262 }
252 // Absence of explicit cleanup or revival of weak handle 263 // Absence of explicit cleanup or revival of weak handle
253 // in most of the cases would lead to memory leak. 264 // in most of the cases would lead to memory leak.
254 CHECK(state() != NEAR_DEATH); 265 CHECK(state() != NEAR_DEATH);
255 return true; 266 return true;
256 } 267 }
257 268
258 inline GlobalHandles* GetGlobalHandles(); 269 inline GlobalHandles* GetGlobalHandles();
259 270
(...skipping 10 matching lines...) Expand all
270 // Note: the most aligned fields should go first. 281 // Note: the most aligned fields should go first.
271 282
272 // Wrapper class ID. 283 // Wrapper class ID.
273 uint16_t class_id_; 284 uint16_t class_id_;
274 285
275 // Index in the containing handle block. 286 // Index in the containing handle block.
276 uint8_t index_; 287 uint8_t index_;
277 288
278 // This stores three flags (independent, partially_dependent and 289 // This stores three flags (independent, partially_dependent and
279 // in_new_space_list) and a State. 290 // in_new_space_list) and a State.
280 class NodeState: public BitField<State, 0, 4> {}; 291 class NodeState : public BitField<State, 0, 4> {};
281 class IsIndependent: public BitField<bool, 4, 1> {}; 292 class IsIndependent : public BitField<bool, 4, 1> {};
282 class IsPartiallyDependent: public BitField<bool, 5, 1> {}; 293 class IsPartiallyDependent : public BitField<bool, 5, 1> {};
283 class IsInNewSpaceList: public BitField<bool, 6, 1> {}; 294 class IsInNewSpaceList : public BitField<bool, 6, 1> {};
295 class IsZappedDuringWeakCallback : public BitField<bool, 7, 1> {};
284 296
285 uint8_t flags_; 297 uint8_t flags_;
286 298
287 // Handle specific callback - might be a weak reference in disguise. 299 // Handle specific callback - might be a weak reference in disguise.
288 WeakCallback weak_callback_; 300 WeakCallback weak_callback_;
289 301
290 // Provided data for callback. In FREE state, this is used for 302 // Provided data for callback. In FREE state, this is used for
291 // the free list link. 303 // the free list link.
292 union { 304 union {
293 void* parameter; 305 void* parameter;
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 DCHECK(location != NULL); 480 DCHECK(location != NULL);
469 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location); 481 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location);
470 } 482 }
471 483
472 484
473 void GlobalHandles::Destroy(Object** location) { 485 void GlobalHandles::Destroy(Object** location) {
474 if (location != NULL) Node::FromLocation(location)->Release(); 486 if (location != NULL) Node::FromLocation(location)->Release();
475 } 487 }
476 488
477 489
478 void GlobalHandles::MakeWeak(Object** location, 490 void GlobalHandles::MakeWeak(Object** location, void* parameter,
479 void* parameter, 491 WeakCallback weak_callback, PhantomState phantom) {
480 WeakCallback weak_callback) { 492 Node::FromLocation(location)
481 Node::FromLocation(location)->MakeWeak(parameter, weak_callback); 493 ->MakeWeak(parameter, weak_callback, phantom == Phantom);
482 } 494 }
483 495
484 496
485 void* GlobalHandles::ClearWeakness(Object** location) { 497 void* GlobalHandles::ClearWeakness(Object** location) {
486 return Node::FromLocation(location)->ClearWeakness(); 498 return Node::FromLocation(location)->ClearWeakness();
487 } 499 }
488 500
489 501
490 void GlobalHandles::MarkIndependent(Object** location) { 502 void GlobalHandles::MarkIndependent(Object** location) {
491 Node::FromLocation(location)->MarkIndependent(); 503 Node::FromLocation(location)->MarkIndependent();
(...skipping 15 matching lines...) Expand all
507 } 519 }
508 520
509 521
510 bool GlobalHandles::IsWeak(Object** location) { 522 bool GlobalHandles::IsWeak(Object** location) {
511 return Node::FromLocation(location)->IsWeak(); 523 return Node::FromLocation(location)->IsWeak();
512 } 524 }
513 525
514 526
515 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { 527 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) {
516 for (NodeIterator it(this); !it.done(); it.Advance()) { 528 for (NodeIterator it(this); !it.done(); it.Advance()) {
517 if (it.node()->IsWeakRetainer()) v->VisitPointer(it.node()->location()); 529 Node* node = it.node();
530 if (node->IsWeakRetainer()) {
531 if (node->state() == Node::PENDING &&
532 node->is_zapped_during_weak_callback()) {
533 *(node->location()) = Smi::FromInt(kPhantomReferenceZap);
534 } else {
535 v->VisitPointer(node->location());
536 }
537 }
518 } 538 }
519 } 539 }
520 540
521 541
522 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { 542 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) {
523 for (NodeIterator it(this); !it.done(); it.Advance()) { 543 for (NodeIterator it(this); !it.done(); it.Advance()) {
524 if (it.node()->IsWeak() && f(it.node()->location())) { 544 if (it.node()->IsWeak() && f(it.node()->location())) {
525 it.node()->MarkPending(); 545 it.node()->MarkPending();
526 } 546 }
527 } 547 }
(...skipping 24 matching lines...) Expand all
552 } 572 }
553 } 573 }
554 574
555 575
556 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { 576 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) {
557 for (int i = 0; i < new_space_nodes_.length(); ++i) { 577 for (int i = 0; i < new_space_nodes_.length(); ++i) {
558 Node* node = new_space_nodes_[i]; 578 Node* node = new_space_nodes_[i];
559 DCHECK(node->is_in_new_space_list()); 579 DCHECK(node->is_in_new_space_list());
560 if ((node->is_independent() || node->is_partially_dependent()) && 580 if ((node->is_independent() || node->is_partially_dependent()) &&
561 node->IsWeakRetainer()) { 581 node->IsWeakRetainer()) {
562 v->VisitPointer(node->location()); 582 if (node->is_zapped_during_weak_callback()) {
583 *(node->location()) = Smi::FromInt(kPhantomReferenceZap);
584 } else {
585 v->VisitPointer(node->location());
586 }
563 } 587 }
564 } 588 }
565 } 589 }
566 590
567 591
568 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, 592 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v,
569 WeakSlotCallbackWithHeap can_skip) { 593 WeakSlotCallbackWithHeap can_skip) {
570 ComputeObjectGroupsAndImplicitReferences(); 594 ComputeObjectGroupsAndImplicitReferences();
571 int last = 0; 595 int last = 0;
572 bool any_group_was_visited = false; 596 bool any_group_was_visited = false;
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after
1047 DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); 1071 DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]);
1048 blocks_[block][offset] = object; 1072 blocks_[block][offset] = object;
1049 if (isolate->heap()->InNewSpace(object)) { 1073 if (isolate->heap()->InNewSpace(object)) {
1050 new_space_indices_.Add(size_); 1074 new_space_indices_.Add(size_);
1051 } 1075 }
1052 *index = size_++; 1076 *index = size_++;
1053 } 1077 }
1054 1078
1055 1079
1056 } } // namespace v8::internal 1080 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698