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

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

Issue 15648008: de-isolate Persistent::Dispose (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 7 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
« include/v8.h ('K') | « src/global-handles.h ('k') | no next file » | 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 // 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
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
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
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
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
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
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
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
OLDNEW
« include/v8.h ('K') | « src/global-handles.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698