| 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 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 | 98 |
| 99 void Initialize(int index, Node** first_free) { | 99 void Initialize(int index, Node** first_free) { |
| 100 index_ = static_cast<uint8_t>(index); | 100 index_ = static_cast<uint8_t>(index); |
| 101 ASSERT(static_cast<int>(index_) == index); | 101 ASSERT(static_cast<int>(index_) == index); |
| 102 set_state(FREE); | 102 set_state(FREE); |
| 103 set_in_new_space_list(false); | 103 set_in_new_space_list(false); |
| 104 parameter_or_next_free_.next_free = *first_free; | 104 parameter_or_next_free_.next_free = *first_free; |
| 105 *first_free = this; | 105 *first_free = this; |
| 106 } | 106 } |
| 107 | 107 |
| 108 void Acquire(Object* object, GlobalHandles* global_handles) { | 108 void Acquire(Object* object) { |
| 109 ASSERT(state() == FREE); | 109 ASSERT(state() == FREE); |
| 110 object_ = object; | 110 object_ = object; |
| 111 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 111 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
| 112 set_independent(false); | 112 set_independent(false); |
| 113 set_partially_dependent(false); | 113 set_partially_dependent(false); |
| 114 set_state(NORMAL); | 114 set_state(NORMAL); |
| 115 parameter_or_next_free_.parameter = NULL; | 115 parameter_or_next_free_.parameter = NULL; |
| 116 near_death_callback_ = NULL; | 116 near_death_callback_ = NULL; |
| 117 IncreaseBlockUses(global_handles); | 117 IncreaseBlockUses(); |
| 118 } | 118 } |
| 119 | 119 |
| 120 void Release(GlobalHandles* global_handles) { | 120 void Release() { |
| 121 ASSERT(state() != FREE); | 121 ASSERT(state() != FREE); |
| 122 set_state(FREE); | 122 set_state(FREE); |
| 123 #ifdef ENABLE_EXTRA_CHECKS | 123 #ifdef ENABLE_EXTRA_CHECKS |
| 124 // Zap the values for eager trapping. | 124 // Zap the values for eager trapping. |
| 125 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 125 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
| 126 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 126 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
| 127 set_independent(false); | 127 set_independent(false); |
| 128 set_partially_dependent(false); | 128 set_partially_dependent(false); |
| 129 near_death_callback_ = NULL; | 129 near_death_callback_ = NULL; |
| 130 #endif | 130 #endif |
| 131 parameter_or_next_free_.next_free = global_handles->first_free_; | 131 DecreaseBlockUses(); |
| 132 global_handles->first_free_ = this; | |
| 133 DecreaseBlockUses(global_handles); | |
| 134 } | 132 } |
| 135 | 133 |
| 136 // Object slot accessors. | 134 // Object slot accessors. |
| 137 Object* object() const { return object_; } | 135 Object* object() const { return object_; } |
| 138 Object** location() { return &object_; } | 136 Object** location() { return &object_; } |
| 139 Handle<Object> handle() { return Handle<Object>(location()); } | 137 Handle<Object> handle() { return Handle<Object>(location()); } |
| 140 | 138 |
| 141 // Wrapper class ID accessors. | 139 // Wrapper class ID accessors. |
| 142 bool has_wrapper_class_id() const { | 140 bool has_wrapper_class_id() const { |
| 143 return class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId; | 141 return class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId; |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 near_death_callback_ = near_death_callback; | 247 near_death_callback_ = near_death_callback; |
| 250 } | 248 } |
| 251 } | 249 } |
| 252 | 250 |
| 253 void ClearWeakness(GlobalHandles* global_handles) { | 251 void ClearWeakness(GlobalHandles* global_handles) { |
| 254 ASSERT(state() != FREE); | 252 ASSERT(state() != FREE); |
| 255 set_state(NORMAL); | 253 set_state(NORMAL); |
| 256 set_parameter(NULL); | 254 set_parameter(NULL); |
| 257 } | 255 } |
| 258 | 256 |
| 259 bool PostGarbageCollectionProcessing(Isolate* isolate, | 257 bool PostGarbageCollectionProcessing(Isolate* isolate) { |
| 260 GlobalHandles* global_handles) { | |
| 261 if (state() != Node::PENDING) return false; | 258 if (state() != Node::PENDING) return false; |
| 262 if (near_death_callback_ == NULL) { | 259 if (near_death_callback_ == NULL) { |
| 263 Release(global_handles); | 260 Release(); |
| 264 return false; | 261 return false; |
| 265 } | 262 } |
| 266 void* par = parameter(); | 263 void* par = parameter(); |
| 267 set_state(NEAR_DEATH); | 264 set_state(NEAR_DEATH); |
| 268 set_parameter(NULL); | 265 set_parameter(NULL); |
| 269 | 266 |
| 270 v8::Persistent<v8::Value> object = ToApi<v8::Value>(handle()); | 267 v8::Persistent<v8::Value> object = ToApi<v8::Value>(handle()); |
| 271 { | 268 { |
| 272 // Check that we are not passing a finalized external string to | 269 // Check that we are not passing a finalized external string to |
| 273 // the callback. | 270 // the callback. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 292 } | 289 } |
| 293 } | 290 } |
| 294 // Absence of explicit cleanup or revival of weak handle | 291 // Absence of explicit cleanup or revival of weak handle |
| 295 // in most of the cases would lead to memory leak. | 292 // in most of the cases would lead to memory leak. |
| 296 ASSERT(state() != NEAR_DEATH); | 293 ASSERT(state() != NEAR_DEATH); |
| 297 return true; | 294 return true; |
| 298 } | 295 } |
| 299 | 296 |
| 300 private: | 297 private: |
| 301 inline NodeBlock* FindBlock(); | 298 inline NodeBlock* FindBlock(); |
| 302 inline void IncreaseBlockUses(GlobalHandles* global_handles); | 299 inline void IncreaseBlockUses(); |
| 303 inline void DecreaseBlockUses(GlobalHandles* global_handles); | 300 inline void DecreaseBlockUses(); |
| 304 | 301 |
| 305 // Storage for object pointer. | 302 // Storage for object pointer. |
| 306 // Placed first to avoid offset computation. | 303 // Placed first to avoid offset computation. |
| 307 Object* object_; | 304 Object* object_; |
| 308 | 305 |
| 309 // Next word stores class_id, index, state, and independent. | 306 // Next word stores class_id, index, state, and independent. |
| 310 // Note: the most aligned fields should go first. | 307 // Note: the most aligned fields should go first. |
| 311 | 308 |
| 312 // Wrapper class ID. | 309 // Wrapper class ID. |
| 313 uint16_t class_id_; | 310 uint16_t class_id_; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 336 } parameter_or_next_free_; | 333 } parameter_or_next_free_; |
| 337 | 334 |
| 338 DISALLOW_COPY_AND_ASSIGN(Node); | 335 DISALLOW_COPY_AND_ASSIGN(Node); |
| 339 }; | 336 }; |
| 340 | 337 |
| 341 | 338 |
| 342 class GlobalHandles::NodeBlock { | 339 class GlobalHandles::NodeBlock { |
| 343 public: | 340 public: |
| 344 static const int kSize = 256; | 341 static const int kSize = 256; |
| 345 | 342 |
| 346 explicit NodeBlock(NodeBlock* next) | 343 explicit NodeBlock(GlobalHandles* global_handles, NodeBlock* next) |
| 347 : next_(next), used_nodes_(0), next_used_(NULL), prev_used_(NULL) {} | 344 : next_(next), |
| 345 used_nodes_(0), |
| 346 next_used_(NULL), |
| 347 prev_used_(NULL), |
| 348 global_handles_(global_handles) {} |
| 348 | 349 |
| 349 void PutNodesOnFreeList(Node** first_free) { | 350 void PutNodesOnFreeList(Node** first_free) { |
| 350 for (int i = kSize - 1; i >= 0; --i) { | 351 for (int i = kSize - 1; i >= 0; --i) { |
| 351 nodes_[i].Initialize(i, first_free); | 352 nodes_[i].Initialize(i, first_free); |
| 352 } | 353 } |
| 353 } | 354 } |
| 354 | 355 |
| 355 Node* node_at(int index) { | 356 Node* node_at(int index) { |
| 356 ASSERT(0 <= index && index < kSize); | 357 ASSERT(0 <= index && index < kSize); |
| 357 return &nodes_[index]; | 358 return &nodes_[index]; |
| 358 } | 359 } |
| 359 | 360 |
| 360 void IncreaseUses(GlobalHandles* global_handles) { | 361 void IncreaseUses() { |
| 361 ASSERT(used_nodes_ < kSize); | 362 ASSERT(used_nodes_ < kSize); |
| 362 if (used_nodes_++ == 0) { | 363 if (used_nodes_++ == 0) { |
| 363 NodeBlock* old_first = global_handles->first_used_block_; | 364 NodeBlock* old_first = global_handles_->first_used_block_; |
| 364 global_handles->first_used_block_ = this; | 365 global_handles_->first_used_block_ = this; |
| 365 next_used_ = old_first; | 366 next_used_ = old_first; |
| 366 prev_used_ = NULL; | 367 prev_used_ = NULL; |
| 367 if (old_first == NULL) return; | 368 if (old_first == NULL) return; |
| 368 old_first->prev_used_ = this; | 369 old_first->prev_used_ = this; |
| 369 } | 370 } |
| 370 } | 371 } |
| 371 | 372 |
| 372 void DecreaseUses(GlobalHandles* global_handles) { | 373 void DecreaseUses() { |
| 373 ASSERT(used_nodes_ > 0); | 374 ASSERT(used_nodes_ > 0); |
| 374 if (--used_nodes_ == 0) { | 375 if (--used_nodes_ == 0) { |
| 375 if (next_used_ != NULL) next_used_->prev_used_ = prev_used_; | 376 if (next_used_ != NULL) next_used_->prev_used_ = prev_used_; |
| 376 if (prev_used_ != NULL) prev_used_->next_used_ = next_used_; | 377 if (prev_used_ != NULL) prev_used_->next_used_ = next_used_; |
| 377 if (this == global_handles->first_used_block_) { | 378 if (this == global_handles_->first_used_block_) { |
| 378 global_handles->first_used_block_ = next_used_; | 379 global_handles_->first_used_block_ = next_used_; |
| 379 } | 380 } |
| 380 } | 381 } |
| 381 } | 382 } |
| 382 | 383 |
| 384 GlobalHandles* global_handles() { return global_handles_; } |
| 385 |
| 383 // Next block in the list of all blocks. | 386 // Next block in the list of all blocks. |
| 384 NodeBlock* next() const { return next_; } | 387 NodeBlock* next() const { return next_; } |
| 385 | 388 |
| 386 // Next/previous block in the list of blocks with used nodes. | 389 // Next/previous block in the list of blocks with used nodes. |
| 387 NodeBlock* next_used() const { return next_used_; } | 390 NodeBlock* next_used() const { return next_used_; } |
| 388 NodeBlock* prev_used() const { return prev_used_; } | 391 NodeBlock* prev_used() const { return prev_used_; } |
| 389 | 392 |
| 390 private: | 393 private: |
| 391 Node nodes_[kSize]; | 394 Node nodes_[kSize]; |
| 392 NodeBlock* const next_; | 395 NodeBlock* const next_; |
| 393 int used_nodes_; | 396 int used_nodes_; |
| 394 NodeBlock* next_used_; | 397 NodeBlock* next_used_; |
| 395 NodeBlock* prev_used_; | 398 NodeBlock* prev_used_; |
| 399 GlobalHandles* global_handles_; |
| 396 }; | 400 }; |
| 397 | 401 |
| 398 | 402 |
| 399 GlobalHandles::NodeBlock* GlobalHandles::Node::FindBlock() { | 403 GlobalHandles::NodeBlock* GlobalHandles::Node::FindBlock() { |
| 400 intptr_t ptr = reinterpret_cast<intptr_t>(this); | 404 intptr_t ptr = reinterpret_cast<intptr_t>(this); |
| 401 ptr = ptr - index_ * sizeof(Node); | 405 ptr = ptr - index_ * sizeof(Node); |
| 402 NodeBlock* block = reinterpret_cast<NodeBlock*>(ptr); | 406 NodeBlock* block = reinterpret_cast<NodeBlock*>(ptr); |
| 403 ASSERT(block->node_at(index_) == this); | 407 ASSERT(block->node_at(index_) == this); |
| 404 return block; | 408 return block; |
| 405 } | 409 } |
| 406 | 410 |
| 407 | 411 |
| 408 void GlobalHandles::Node::IncreaseBlockUses(GlobalHandles* global_handles) { | 412 void GlobalHandles::Node::IncreaseBlockUses() { |
| 409 FindBlock()->IncreaseUses(global_handles); | 413 NodeBlock* node_block = FindBlock(); |
| 414 node_block->IncreaseUses(); |
| 415 GlobalHandles* global_handles = node_block->global_handles(); |
| 416 global_handles->isolate()->counters()->global_handles()->Increment(); |
| 417 global_handles->number_of_global_handles_++; |
| 410 } | 418 } |
| 411 | 419 |
| 412 | 420 |
| 413 void GlobalHandles::Node::DecreaseBlockUses(GlobalHandles* global_handles) { | 421 void GlobalHandles::Node::DecreaseBlockUses() { |
| 414 FindBlock()->DecreaseUses(global_handles); | 422 NodeBlock* node_block = FindBlock(); |
| 423 GlobalHandles* global_handles = node_block->global_handles(); |
| 424 parameter_or_next_free_.next_free = global_handles->first_free_; |
| 425 global_handles->first_free_ = this; |
| 426 node_block->DecreaseUses(); |
| 427 global_handles->isolate()->counters()->global_handles()->Decrement(); |
| 428 global_handles->number_of_global_handles_--; |
| 415 } | 429 } |
| 416 | 430 |
| 417 | 431 |
| 418 class GlobalHandles::NodeIterator { | 432 class GlobalHandles::NodeIterator { |
| 419 public: | 433 public: |
| 420 explicit NodeIterator(GlobalHandles* global_handles) | 434 explicit NodeIterator(GlobalHandles* global_handles) |
| 421 : block_(global_handles->first_used_block_), | 435 : block_(global_handles->first_used_block_), |
| 422 index_(0) {} | 436 index_(0) {} |
| 423 | 437 |
| 424 bool done() const { return block_ == NULL; } | 438 bool done() const { return block_ == NULL; } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 while (block != NULL) { | 472 while (block != NULL) { |
| 459 NodeBlock* tmp = block->next(); | 473 NodeBlock* tmp = block->next(); |
| 460 delete block; | 474 delete block; |
| 461 block = tmp; | 475 block = tmp; |
| 462 } | 476 } |
| 463 first_block_ = NULL; | 477 first_block_ = NULL; |
| 464 } | 478 } |
| 465 | 479 |
| 466 | 480 |
| 467 Handle<Object> GlobalHandles::Create(Object* value) { | 481 Handle<Object> GlobalHandles::Create(Object* value) { |
| 468 isolate_->counters()->global_handles()->Increment(); | |
| 469 number_of_global_handles_++; | |
| 470 if (first_free_ == NULL) { | 482 if (first_free_ == NULL) { |
| 471 first_block_ = new NodeBlock(first_block_); | 483 first_block_ = new NodeBlock(this, first_block_); |
| 472 first_block_->PutNodesOnFreeList(&first_free_); | 484 first_block_->PutNodesOnFreeList(&first_free_); |
| 473 } | 485 } |
| 474 ASSERT(first_free_ != NULL); | 486 ASSERT(first_free_ != NULL); |
| 475 // Take the first node in the free list. | 487 // Take the first node in the free list. |
| 476 Node* result = first_free_; | 488 Node* result = first_free_; |
| 477 first_free_ = result->next_free(); | 489 first_free_ = result->next_free(); |
| 478 result->Acquire(value, this); | 490 result->Acquire(value); |
| 479 if (isolate_->heap()->InNewSpace(value) && | 491 if (isolate_->heap()->InNewSpace(value) && |
| 480 !result->is_in_new_space_list()) { | 492 !result->is_in_new_space_list()) { |
| 481 new_space_nodes_.Add(result); | 493 new_space_nodes_.Add(result); |
| 482 result->set_in_new_space_list(true); | 494 result->set_in_new_space_list(true); |
| 483 } | 495 } |
| 484 return result->handle(); | 496 return result->handle(); |
| 485 } | 497 } |
| 486 | 498 |
| 487 | 499 |
| 488 void GlobalHandles::Destroy(Object** location) { | 500 void GlobalHandles::Destroy(Object** location) { |
| 489 isolate_->counters()->global_handles()->Decrement(); | 501 if (location != NULL) Node::FromLocation(location)->Release(); |
| 490 number_of_global_handles_--; | |
| 491 if (location == NULL) return; | |
| 492 Node::FromLocation(location)->Release(this); | |
| 493 } | 502 } |
| 494 | 503 |
| 495 | 504 |
| 496 void GlobalHandles::MakeWeak(Object** location, | 505 void GlobalHandles::MakeWeak(Object** location, |
| 497 void* parameter, | 506 void* parameter, |
| 498 RevivableCallback weak_reference_callback, | 507 RevivableCallback weak_reference_callback, |
| 499 NearDeathCallback near_death_callback) { | 508 NearDeathCallback near_death_callback) { |
| 500 ASSERT((weak_reference_callback == NULL) != (near_death_callback == NULL)); | 509 ASSERT((weak_reference_callback == NULL) != (near_death_callback == NULL)); |
| 501 Node::FromLocation(location)->MakeWeak(this, | 510 Node::FromLocation(location)->MakeWeak(this, |
| 502 parameter, | 511 parameter, |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 655 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
| 647 Node* node = new_space_nodes_[i]; | 656 Node* node = new_space_nodes_[i]; |
| 648 ASSERT(node->is_in_new_space_list()); | 657 ASSERT(node->is_in_new_space_list()); |
| 649 // Skip dependent handles. Their weak callbacks might expect to be | 658 // Skip dependent handles. Their weak callbacks might expect to be |
| 650 // called between two global garbage collection callbacks which | 659 // called between two global garbage collection callbacks which |
| 651 // are not called for minor collections. | 660 // are not called for minor collections. |
| 652 if (!node->is_independent() && !node->is_partially_dependent()) { | 661 if (!node->is_independent() && !node->is_partially_dependent()) { |
| 653 continue; | 662 continue; |
| 654 } | 663 } |
| 655 node->clear_partially_dependent(); | 664 node->clear_partially_dependent(); |
| 656 if (node->PostGarbageCollectionProcessing(isolate_, this)) { | 665 if (node->PostGarbageCollectionProcessing(isolate_)) { |
| 657 if (initial_post_gc_processing_count != post_gc_processing_count_) { | 666 if (initial_post_gc_processing_count != post_gc_processing_count_) { |
| 658 // Weak callback triggered another GC and another round of | 667 // Weak callback triggered another GC and another round of |
| 659 // PostGarbageCollection processing. The current node might | 668 // PostGarbageCollection processing. The current node might |
| 660 // have been deleted in that round, so we need to bail out (or | 669 // have been deleted in that round, so we need to bail out (or |
| 661 // restart the processing). | 670 // restart the processing). |
| 662 return next_gc_likely_to_collect_more; | 671 return next_gc_likely_to_collect_more; |
| 663 } | 672 } |
| 664 } | 673 } |
| 665 if (!node->IsRetainer()) { | 674 if (!node->IsRetainer()) { |
| 666 next_gc_likely_to_collect_more = true; | 675 next_gc_likely_to_collect_more = true; |
| 667 } | 676 } |
| 668 } | 677 } |
| 669 } else { | 678 } else { |
| 670 for (NodeIterator it(this); !it.done(); it.Advance()) { | 679 for (NodeIterator it(this); !it.done(); it.Advance()) { |
| 671 it.node()->clear_partially_dependent(); | 680 it.node()->clear_partially_dependent(); |
| 672 if (it.node()->PostGarbageCollectionProcessing(isolate_, this)) { | 681 if (it.node()->PostGarbageCollectionProcessing(isolate_)) { |
| 673 if (initial_post_gc_processing_count != post_gc_processing_count_) { | 682 if (initial_post_gc_processing_count != post_gc_processing_count_) { |
| 674 // See the comment above. | 683 // See the comment above. |
| 675 return next_gc_likely_to_collect_more; | 684 return next_gc_likely_to_collect_more; |
| 676 } | 685 } |
| 677 } | 686 } |
| 678 if (!it.node()->IsRetainer()) { | 687 if (!it.node()->IsRetainer()) { |
| 679 next_gc_likely_to_collect_more = true; | 688 next_gc_likely_to_collect_more = true; |
| 680 } | 689 } |
| 681 } | 690 } |
| 682 } | 691 } |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1012 } | 1021 } |
| 1013 } | 1022 } |
| 1014 object_group_connections_.Clear(); | 1023 object_group_connections_.Clear(); |
| 1015 object_group_connections_.Initialize(kObjectGroupConnectionsCapacity); | 1024 object_group_connections_.Initialize(kObjectGroupConnectionsCapacity); |
| 1016 retainer_infos_.Clear(); | 1025 retainer_infos_.Clear(); |
| 1017 implicit_ref_connections_.Clear(); | 1026 implicit_ref_connections_.Clear(); |
| 1018 } | 1027 } |
| 1019 | 1028 |
| 1020 | 1029 |
| 1021 } } // namespace v8::internal | 1030 } } // namespace v8::internal |
| OLD | NEW |