OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 30 matching lines...) Expand all Loading... |
41 } | 41 } |
42 | 42 |
43 | 43 |
44 class GlobalHandles::Node : public Malloced { | 44 class GlobalHandles::Node : public Malloced { |
45 public: | 45 public: |
46 | 46 |
47 void Initialize(Object* object) { | 47 void Initialize(Object* object) { |
48 // Set the initial value of the handle. | 48 // Set the initial value of the handle. |
49 object_ = object; | 49 object_ = object; |
50 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 50 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
| 51 independent_ = false; |
51 state_ = NORMAL; | 52 state_ = NORMAL; |
52 parameter_or_next_free_.parameter = NULL; | 53 parameter_or_next_free_.parameter = NULL; |
53 callback_ = NULL; | 54 callback_ = NULL; |
54 } | 55 } |
55 | 56 |
56 Node() { | 57 Node() { |
57 state_ = DESTROYED; | 58 state_ = DESTROYED; |
58 } | 59 } |
59 | 60 |
60 explicit Node(Object* object) { | 61 explicit Node(Object* object) { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 if (state_ == WEAK || IsNearDeath()) { | 132 if (state_ == WEAK || IsNearDeath()) { |
132 global_handles->number_of_weak_handles_--; | 133 global_handles->number_of_weak_handles_--; |
133 if (object_->IsJSGlobalObject()) { | 134 if (object_->IsJSGlobalObject()) { |
134 global_handles->number_of_global_object_weak_handles_--; | 135 global_handles->number_of_global_object_weak_handles_--; |
135 } | 136 } |
136 } | 137 } |
137 state_ = NORMAL; | 138 state_ = NORMAL; |
138 set_parameter(NULL); | 139 set_parameter(NULL); |
139 } | 140 } |
140 | 141 |
| 142 void MarkIndependent(GlobalHandles* global_handles) { |
| 143 LOG(global_handles->isolate(), |
| 144 HandleEvent("GlobalHandle::MarkIndependent", handle().location())); |
| 145 ASSERT(state_ != DESTROYED); |
| 146 independent_ = true; |
| 147 } |
| 148 |
141 bool IsNearDeath() { | 149 bool IsNearDeath() { |
142 // Check for PENDING to ensure correct answer when processing callbacks. | 150 // Check for PENDING to ensure correct answer when processing callbacks. |
143 return state_ == PENDING || state_ == NEAR_DEATH; | 151 return state_ == PENDING || state_ == NEAR_DEATH; |
144 } | 152 } |
145 | 153 |
146 bool IsWeak() { | 154 bool IsWeak() { |
147 return state_ == WEAK; | 155 return state_ == WEAK; |
148 } | 156 } |
149 | 157 |
150 bool CanBeRetainer() { | 158 bool CanBeRetainer() { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED } | 223 // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED } |
216 enum State { | 224 enum State { |
217 NORMAL, // Normal global handle. | 225 NORMAL, // Normal global handle. |
218 WEAK, // Flagged as weak but not yet finalized. | 226 WEAK, // Flagged as weak but not yet finalized. |
219 PENDING, // Has been recognized as only reachable by weak handles. | 227 PENDING, // Has been recognized as only reachable by weak handles. |
220 NEAR_DEATH, // Callback has informed the handle is near death. | 228 NEAR_DEATH, // Callback has informed the handle is near death. |
221 DESTROYED | 229 DESTROYED |
222 }; | 230 }; |
223 State state_ : 4; // Need one more bit for MSVC as it treats enums as signed. | 231 State state_ : 4; // Need one more bit for MSVC as it treats enums as signed. |
224 | 232 |
| 233 bool independent_ : 1; |
| 234 |
225 private: | 235 private: |
226 // Handle specific callback. | 236 // Handle specific callback. |
227 WeakReferenceCallback callback_; | 237 WeakReferenceCallback callback_; |
228 // Provided data for callback. In DESTROYED state, this is used for | 238 // Provided data for callback. In DESTROYED state, this is used for |
229 // the free list link. | 239 // the free list link. |
230 union { | 240 union { |
231 void* parameter; | 241 void* parameter; |
232 Node* next_free; | 242 Node* next_free; |
233 } parameter_or_next_free_; | 243 } parameter_or_next_free_; |
234 | 244 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 ASSERT(callback != NULL); | 367 ASSERT(callback != NULL); |
358 Node::FromLocation(location)->MakeWeak(this, parameter, callback); | 368 Node::FromLocation(location)->MakeWeak(this, parameter, callback); |
359 } | 369 } |
360 | 370 |
361 | 371 |
362 void GlobalHandles::ClearWeakness(Object** location) { | 372 void GlobalHandles::ClearWeakness(Object** location) { |
363 Node::FromLocation(location)->ClearWeakness(this); | 373 Node::FromLocation(location)->ClearWeakness(this); |
364 } | 374 } |
365 | 375 |
366 | 376 |
| 377 void GlobalHandles::MarkIndependent(Object** location) { |
| 378 Node::FromLocation(location)->MarkIndependent(this); |
| 379 } |
| 380 |
| 381 |
367 bool GlobalHandles::IsNearDeath(Object** location) { | 382 bool GlobalHandles::IsNearDeath(Object** location) { |
368 return Node::FromLocation(location)->IsNearDeath(); | 383 return Node::FromLocation(location)->IsNearDeath(); |
369 } | 384 } |
370 | 385 |
371 | 386 |
372 bool GlobalHandles::IsWeak(Object** location) { | 387 bool GlobalHandles::IsWeak(Object** location) { |
373 return Node::FromLocation(location)->IsWeak(); | 388 return Node::FromLocation(location)->IsWeak(); |
374 } | 389 } |
375 | 390 |
376 | 391 |
377 void GlobalHandles::SetWrapperClassId(Object** location, uint16_t class_id) { | 392 void GlobalHandles::SetWrapperClassId(Object** location, uint16_t class_id) { |
378 Node::FromLocation(location)->SetWrapperClassId(class_id); | 393 Node::FromLocation(location)->SetWrapperClassId(class_id); |
379 } | 394 } |
380 | 395 |
381 | 396 |
382 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { | 397 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { |
383 // Traversal of GC roots in the global handle list that are marked as | 398 // Traversal of GC roots in the global handle list that are marked as |
384 // WEAK or PENDING. | 399 // WEAK, PENDING or NEAR_DEATH. |
385 for (Node* current = head_; current != NULL; current = current->next()) { | 400 for (Node* current = head_; current != NULL; current = current->next()) { |
386 if (current->state_ == Node::WEAK | 401 if (current->state_ == Node::WEAK |
387 || current->state_ == Node::PENDING | 402 || current->state_ == Node::PENDING |
388 || current->state_ == Node::NEAR_DEATH) { | 403 || current->state_ == Node::NEAR_DEATH) { |
389 v->VisitPointer(¤t->object_); | 404 v->VisitPointer(¤t->object_); |
390 } | 405 } |
391 } | 406 } |
392 } | 407 } |
393 | 408 |
394 | 409 |
| 410 void GlobalHandles::IterateWeakIndependentRoots(ObjectVisitor* v) { |
| 411 // Traversal of GC roots in the global handle list that are independent |
| 412 // and marked as WEAK, PENDING or NEAR_DEATH. |
| 413 for (Node* current = head_; current != NULL; current = current->next()) { |
| 414 if (!current->independent_) continue; |
| 415 if (current->state_ == Node::WEAK |
| 416 || current->state_ == Node::PENDING |
| 417 || current->state_ == Node::NEAR_DEATH) { |
| 418 v->VisitPointer(¤t->object_); |
| 419 } |
| 420 } |
| 421 } |
| 422 |
| 423 |
395 void GlobalHandles::IterateWeakRoots(WeakReferenceGuest f, | 424 void GlobalHandles::IterateWeakRoots(WeakReferenceGuest f, |
396 WeakReferenceCallback callback) { | 425 WeakReferenceCallback callback) { |
397 for (Node* current = head_; current != NULL; current = current->next()) { | 426 for (Node* current = head_; current != NULL; current = current->next()) { |
398 if (current->IsWeak() && current->callback() == callback) { | 427 if (current->IsWeak() && current->callback() == callback) { |
399 f(current->object_, current->parameter()); | 428 f(current->object_, current->parameter()); |
400 } | 429 } |
401 } | 430 } |
402 } | 431 } |
403 | 432 |
404 | 433 |
405 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { | 434 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { |
406 for (Node* current = head_; current != NULL; current = current->next()) { | 435 for (Node* current = head_; current != NULL; current = current->next()) { |
407 if (current->state_ == Node::WEAK) { | 436 if (current->state_ == Node::WEAK) { |
408 if (f(¤t->object_)) { | 437 if (f(¤t->object_)) { |
409 current->state_ = Node::PENDING; | 438 current->state_ = Node::PENDING; |
410 LOG(isolate_, | 439 LOG(isolate_, |
411 HandleEvent("GlobalHandle::Pending", current->handle().location())); | 440 HandleEvent("GlobalHandle::Pending", current->handle().location())); |
412 } | 441 } |
413 } | 442 } |
414 } | 443 } |
415 } | 444 } |
416 | 445 |
417 | 446 |
418 bool GlobalHandles::PostGarbageCollectionProcessing() { | 447 void GlobalHandles::IdentifyWeakIndependentHandles(WeakSlotCallbackWithHeap f) { |
| 448 for (Node* current = head_; current != NULL; current = current->next()) { |
| 449 if (current->state_ == Node::WEAK && current->independent_) { |
| 450 if (f(isolate_->heap(), ¤t->object_)) { |
| 451 current->state_ = Node::PENDING; |
| 452 LOG(isolate_, |
| 453 HandleEvent("GlobalHandle::Pending", current->handle().location())); |
| 454 } |
| 455 } |
| 456 } |
| 457 } |
| 458 |
| 459 |
| 460 bool GlobalHandles::PostGarbageCollectionProcessing( |
| 461 GarbageCollector collector) { |
419 // Process weak global handle callbacks. This must be done after the | 462 // Process weak global handle callbacks. This must be done after the |
420 // GC is completely done, because the callbacks may invoke arbitrary | 463 // GC is completely done, because the callbacks may invoke arbitrary |
421 // API functions. | 464 // API functions. |
422 // At the same time deallocate all DESTROYED nodes. | 465 // At the same time deallocate all DESTROYED nodes. |
423 ASSERT(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); | 466 ASSERT(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); |
424 const int initial_post_gc_processing_count = ++post_gc_processing_count_; | 467 const int initial_post_gc_processing_count = ++post_gc_processing_count_; |
425 bool next_gc_likely_to_collect_more = false; | 468 bool next_gc_likely_to_collect_more = false; |
426 Node** p = &head_; | 469 Node** p = &head_; |
427 while (*p != NULL) { | 470 while (*p != NULL) { |
| 471 // Skip dependent handles. Their weak callbacks might expect to be |
| 472 // called between two global garbage collection callbacks which |
| 473 // are not called for minor collections. |
| 474 if (collector == SCAVENGER && !(*p)->independent_) { |
| 475 p = (*p)->next_addr(); |
| 476 continue; |
| 477 } |
| 478 |
428 if ((*p)->PostGarbageCollectionProcessing(isolate_, this)) { | 479 if ((*p)->PostGarbageCollectionProcessing(isolate_, this)) { |
429 if (initial_post_gc_processing_count != post_gc_processing_count_) { | 480 if (initial_post_gc_processing_count != post_gc_processing_count_) { |
430 // Weak callback triggered another GC and another round of | 481 // Weak callback triggered another GC and another round of |
431 // PostGarbageCollection processing. The current node might | 482 // PostGarbageCollection processing. The current node might |
432 // have been deleted in that round, so we need to bail out (or | 483 // have been deleted in that round, so we need to bail out (or |
433 // restart the processing). | 484 // restart the processing). |
434 break; | 485 break; |
435 } | 486 } |
436 } | 487 } |
437 if ((*p)->state_ == Node::DESTROYED) { | 488 if ((*p)->state_ == Node::DESTROYED) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 | 520 |
470 void GlobalHandles::IterateAllRoots(ObjectVisitor* v) { | 521 void GlobalHandles::IterateAllRoots(ObjectVisitor* v) { |
471 for (Node* current = head_; current != NULL; current = current->next()) { | 522 for (Node* current = head_; current != NULL; current = current->next()) { |
472 if (current->state_ != Node::DESTROYED) { | 523 if (current->state_ != Node::DESTROYED) { |
473 v->VisitPointer(¤t->object_); | 524 v->VisitPointer(¤t->object_); |
474 } | 525 } |
475 } | 526 } |
476 } | 527 } |
477 | 528 |
478 | 529 |
| 530 void GlobalHandles::IterateStrongAndDependentRoots(ObjectVisitor* v) { |
| 531 for (Node* current = head_; current != NULL; current = current->next()) { |
| 532 if ((current->independent_ && current->state_ == Node::NORMAL) || |
| 533 (!current->independent_ && current->state_ != Node::DESTROYED)) { |
| 534 v->VisitPointer(¤t->object_); |
| 535 } |
| 536 } |
| 537 } |
| 538 |
| 539 |
479 void GlobalHandles::IterateAllRootsWithClassIds(ObjectVisitor* v) { | 540 void GlobalHandles::IterateAllRootsWithClassIds(ObjectVisitor* v) { |
480 for (Node* current = head_; current != NULL; current = current->next()) { | 541 for (Node* current = head_; current != NULL; current = current->next()) { |
481 if (current->class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId && | 542 if (current->class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId && |
482 current->CanBeRetainer()) { | 543 current->CanBeRetainer()) { |
483 v->VisitEmbedderReference(¤t->object_, current->class_id_); | 544 v->VisitEmbedderReference(¤t->object_, current->class_id_); |
484 } | 545 } |
485 } | 546 } |
486 } | 547 } |
487 | 548 |
488 | 549 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
584 | 645 |
585 void GlobalHandles::RemoveImplicitRefGroups() { | 646 void GlobalHandles::RemoveImplicitRefGroups() { |
586 for (int i = 0; i < implicit_ref_groups_.length(); i++) { | 647 for (int i = 0; i < implicit_ref_groups_.length(); i++) { |
587 implicit_ref_groups_.at(i)->Dispose(); | 648 implicit_ref_groups_.at(i)->Dispose(); |
588 } | 649 } |
589 implicit_ref_groups_.Clear(); | 650 implicit_ref_groups_.Clear(); |
590 } | 651 } |
591 | 652 |
592 | 653 |
593 } } // namespace v8::internal | 654 } } // namespace v8::internal |
OLD | NEW |