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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
310 object_groups_(4) { | 320 object_groups_(4) { |
311 } | 321 } |
312 | 322 |
313 | 323 |
314 GlobalHandles::~GlobalHandles() { | 324 GlobalHandles::~GlobalHandles() { |
315 delete pool_; | 325 delete pool_; |
316 pool_ = 0; | 326 pool_ = 0; |
317 } | 327 } |
318 | 328 |
319 | 329 |
320 Handle<Object> GlobalHandles::Create(Object* value) { | 330 Handle<Object> GlobalHandles::Create(Object* value) { |
antonm
2011/05/16 14:13:19
I think you should reset independent flag here.
Vyacheslav Egorov (Chromium)
2011/05/16 14:55:34
It's done by result->Initialize(value) below. Am I
antonm
2011/05/16 15:20:44
Sorry, missed this one.
On 2011/05/16 14:55:34, V
| |
321 isolate_->counters()->global_handles()->Increment(); | 331 isolate_->counters()->global_handles()->Increment(); |
322 Node* result; | 332 Node* result; |
323 if (first_free()) { | 333 if (first_free()) { |
324 // Take the first node in the free list. | 334 // Take the first node in the free list. |
325 result = first_free(); | 335 result = first_free(); |
326 set_first_free(result->next_free()); | 336 set_first_free(result->next_free()); |
327 } else if (first_deallocated()) { | 337 } else if (first_deallocated()) { |
328 // Next try deallocated list | 338 // Next try deallocated list |
329 result = first_deallocated(); | 339 result = first_deallocated(); |
330 set_first_deallocated(result->next_free()); | 340 set_first_deallocated(result->next_free()); |
(...skipping 26 matching lines...) Expand all 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 or PENDING. |
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 marked as | |
412 // WEAK or PENDING. | |
antonm
2011/05/16 14:13:19
comment is wrong.
Vyacheslav Egorov (Chromium)
2011/05/16 14:55:34
Thanks! Will fix.
| |
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 |
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 | |
418 bool GlobalHandles::PostGarbageCollectionProcessing() { | 460 bool GlobalHandles::PostGarbageCollectionProcessing() { |
419 // Process weak global handle callbacks. This must be done after the | 461 // Process weak global handle callbacks. This must be done after the |
420 // GC is completely done, because the callbacks may invoke arbitrary | 462 // GC is completely done, because the callbacks may invoke arbitrary |
421 // API functions. | 463 // API functions. |
422 // At the same time deallocate all DESTROYED nodes. | 464 // At the same time deallocate all DESTROYED nodes. |
423 ASSERT(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); | 465 ASSERT(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); |
424 const int initial_post_gc_processing_count = ++post_gc_processing_count_; | 466 const int initial_post_gc_processing_count = ++post_gc_processing_count_; |
425 bool next_gc_likely_to_collect_more = false; | 467 bool next_gc_likely_to_collect_more = false; |
426 Node** p = &head_; | 468 Node** p = &head_; |
427 while (*p != NULL) { | 469 while (*p != NULL) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
469 | 511 |
470 void GlobalHandles::IterateAllRoots(ObjectVisitor* v) { | 512 void GlobalHandles::IterateAllRoots(ObjectVisitor* v) { |
471 for (Node* current = head_; current != NULL; current = current->next()) { | 513 for (Node* current = head_; current != NULL; current = current->next()) { |
472 if (current->state_ != Node::DESTROYED) { | 514 if (current->state_ != Node::DESTROYED) { |
473 v->VisitPointer(¤t->object_); | 515 v->VisitPointer(¤t->object_); |
474 } | 516 } |
475 } | 517 } |
476 } | 518 } |
477 | 519 |
478 | 520 |
521 void GlobalHandles::IterateStrongAndDependentRoots(ObjectVisitor* v) { | |
522 for (Node* current = head_; current != NULL; current = current->next()) { | |
523 if ((current->independent_ && current->state_ == Node::NORMAL) || | |
524 (!current->independent_ && current->state_ != Node::DESTROYED)) { | |
525 v->VisitPointer(¤t->object_); | |
526 } | |
527 } | |
528 } | |
529 | |
530 | |
479 void GlobalHandles::IterateAllRootsWithClassIds(ObjectVisitor* v) { | 531 void GlobalHandles::IterateAllRootsWithClassIds(ObjectVisitor* v) { |
480 for (Node* current = head_; current != NULL; current = current->next()) { | 532 for (Node* current = head_; current != NULL; current = current->next()) { |
481 if (current->class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId && | 533 if (current->class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId && |
482 current->CanBeRetainer()) { | 534 current->CanBeRetainer()) { |
483 v->VisitEmbedderReference(¤t->object_, current->class_id_); | 535 v->VisitEmbedderReference(¤t->object_, current->class_id_); |
484 } | 536 } |
485 } | 537 } |
486 } | 538 } |
487 | 539 |
488 | 540 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
584 | 636 |
585 void GlobalHandles::RemoveImplicitRefGroups() { | 637 void GlobalHandles::RemoveImplicitRefGroups() { |
586 for (int i = 0; i < implicit_ref_groups_.length(); i++) { | 638 for (int i = 0; i < implicit_ref_groups_.length(); i++) { |
587 implicit_ref_groups_.at(i)->Dispose(); | 639 implicit_ref_groups_.at(i)->Dispose(); |
588 } | 640 } |
589 implicit_ref_groups_.Clear(); | 641 implicit_ref_groups_.Clear(); |
590 } | 642 } |
591 | 643 |
592 | 644 |
593 } } // namespace v8::internal | 645 } } // namespace v8::internal |
OLD | NEW |