| 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 |