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 23 matching lines...) Expand all Loading... |
34 | 34 |
35 namespace v8 { | 35 namespace v8 { |
36 namespace internal { | 36 namespace internal { |
37 | 37 |
38 class GlobalHandles::Node : public Malloced { | 38 class GlobalHandles::Node : public Malloced { |
39 public: | 39 public: |
40 | 40 |
41 void Initialize(Object* object) { | 41 void Initialize(Object* object) { |
42 // Set the initial value of the handle. | 42 // Set the initial value of the handle. |
43 object_ = object; | 43 object_ = object; |
| 44 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
44 state_ = NORMAL; | 45 state_ = NORMAL; |
45 parameter_or_next_free_.parameter = NULL; | 46 parameter_or_next_free_.parameter = NULL; |
46 callback_ = NULL; | 47 callback_ = NULL; |
47 } | 48 } |
48 | 49 |
49 Node() { | 50 Node() { |
50 state_ = DESTROYED; | 51 state_ = DESTROYED; |
51 } | 52 } |
52 | 53 |
53 explicit Node(Object* object) { | 54 explicit Node(Object* object) { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 | 131 |
131 bool IsNearDeath() { | 132 bool IsNearDeath() { |
132 // Check for PENDING to ensure correct answer when processing callbacks. | 133 // Check for PENDING to ensure correct answer when processing callbacks. |
133 return state_ == PENDING || state_ == NEAR_DEATH; | 134 return state_ == PENDING || state_ == NEAR_DEATH; |
134 } | 135 } |
135 | 136 |
136 bool IsWeak() { | 137 bool IsWeak() { |
137 return state_ == WEAK; | 138 return state_ == WEAK; |
138 } | 139 } |
139 | 140 |
| 141 bool CanBeRetainer() { |
| 142 return state_ != DESTROYED && state_ != NEAR_DEATH; |
| 143 } |
| 144 |
| 145 void SetWrapperClassId(uint16_t class_id) { |
| 146 class_id_ = class_id; |
| 147 } |
| 148 |
140 // Returns the id for this weak handle. | 149 // Returns the id for this weak handle. |
141 void set_parameter(void* parameter) { | 150 void set_parameter(void* parameter) { |
142 ASSERT(state_ != DESTROYED); | 151 ASSERT(state_ != DESTROYED); |
143 parameter_or_next_free_.parameter = parameter; | 152 parameter_or_next_free_.parameter = parameter; |
144 } | 153 } |
145 void* parameter() { | 154 void* parameter() { |
146 ASSERT(state_ != DESTROYED); | 155 ASSERT(state_ != DESTROYED); |
147 return parameter_or_next_free_.parameter; | 156 return parameter_or_next_free_.parameter; |
148 } | 157 } |
149 | 158 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 } | 192 } |
184 // Absense of explicit cleanup or revival of weak handle | 193 // Absense of explicit cleanup or revival of weak handle |
185 // in most of the cases would lead to memory leak. | 194 // in most of the cases would lead to memory leak. |
186 ASSERT(state_ != NEAR_DEATH); | 195 ASSERT(state_ != NEAR_DEATH); |
187 return true; | 196 return true; |
188 } | 197 } |
189 | 198 |
190 // Place the handle address first to avoid offset computation. | 199 // Place the handle address first to avoid offset computation. |
191 Object* object_; // Storage for object pointer. | 200 Object* object_; // Storage for object pointer. |
192 | 201 |
| 202 uint16_t class_id_; |
| 203 |
193 // Transition diagram: | 204 // Transition diagram: |
194 // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED } | 205 // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED } |
195 enum State { | 206 enum State { |
196 NORMAL, // Normal global handle. | 207 NORMAL, // Normal global handle. |
197 WEAK, // Flagged as weak but not yet finalized. | 208 WEAK, // Flagged as weak but not yet finalized. |
198 PENDING, // Has been recognized as only reachable by weak handles. | 209 PENDING, // Has been recognized as only reachable by weak handles. |
199 NEAR_DEATH, // Callback has informed the handle is near death. | 210 NEAR_DEATH, // Callback has informed the handle is near death. |
200 DESTROYED | 211 DESTROYED |
201 }; | 212 }; |
202 State state_; | 213 State state_ : 3; |
203 | 214 |
204 private: | 215 private: |
205 // Handle specific callback. | 216 // Handle specific callback. |
206 WeakReferenceCallback callback_; | 217 WeakReferenceCallback callback_; |
207 // Provided data for callback. In DESTROYED state, this is used for | 218 // Provided data for callback. In DESTROYED state, this is used for |
208 // the free list link. | 219 // the free list link. |
209 union { | 220 union { |
210 void* parameter; | 221 void* parameter; |
211 Node* next_free; | 222 Node* next_free; |
212 } parameter_or_next_free_; | 223 } parameter_or_next_free_; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 bool GlobalHandles::IsNearDeath(Object** location) { | 341 bool GlobalHandles::IsNearDeath(Object** location) { |
331 return Node::FromLocation(location)->IsNearDeath(); | 342 return Node::FromLocation(location)->IsNearDeath(); |
332 } | 343 } |
333 | 344 |
334 | 345 |
335 bool GlobalHandles::IsWeak(Object** location) { | 346 bool GlobalHandles::IsWeak(Object** location) { |
336 return Node::FromLocation(location)->IsWeak(); | 347 return Node::FromLocation(location)->IsWeak(); |
337 } | 348 } |
338 | 349 |
339 | 350 |
| 351 void GlobalHandles::SetWrapperClassId(Object** location, uint16_t class_id) { |
| 352 Node::FromLocation(location)->SetWrapperClassId(class_id); |
| 353 } |
| 354 |
| 355 |
340 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { | 356 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { |
341 // Traversal of GC roots in the global handle list that are marked as | 357 // Traversal of GC roots in the global handle list that are marked as |
342 // WEAK or PENDING. | 358 // WEAK or PENDING. |
343 for (Node* current = head_; current != NULL; current = current->next()) { | 359 for (Node* current = head_; current != NULL; current = current->next()) { |
344 if (current->state_ == Node::WEAK | 360 if (current->state_ == Node::WEAK |
345 || current->state_ == Node::PENDING | 361 || current->state_ == Node::PENDING |
346 || current->state_ == Node::NEAR_DEATH) { | 362 || current->state_ == Node::NEAR_DEATH) { |
347 v->VisitPointer(¤t->object_); | 363 v->VisitPointer(¤t->object_); |
348 } | 364 } |
349 } | 365 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 | 444 |
429 void GlobalHandles::IterateAllRoots(ObjectVisitor* v) { | 445 void GlobalHandles::IterateAllRoots(ObjectVisitor* v) { |
430 for (Node* current = head_; current != NULL; current = current->next()) { | 446 for (Node* current = head_; current != NULL; current = current->next()) { |
431 if (current->state_ != Node::DESTROYED) { | 447 if (current->state_ != Node::DESTROYED) { |
432 v->VisitPointer(¤t->object_); | 448 v->VisitPointer(¤t->object_); |
433 } | 449 } |
434 } | 450 } |
435 } | 451 } |
436 | 452 |
437 | 453 |
| 454 void GlobalHandles::IterateAllRootsWithClassIds(ObjectVisitor* v) { |
| 455 for (Node* current = head_; current != NULL; current = current->next()) { |
| 456 if (current->class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId && |
| 457 current->CanBeRetainer()) { |
| 458 v->VisitEmbedderReference(¤t->object_, current->class_id_); |
| 459 } |
| 460 } |
| 461 } |
| 462 |
| 463 |
438 void GlobalHandles::TearDown() { | 464 void GlobalHandles::TearDown() { |
439 // Reset all the lists. | 465 // Reset all the lists. |
440 set_head(NULL); | 466 set_head(NULL); |
441 set_first_free(NULL); | 467 set_first_free(NULL); |
442 set_first_deallocated(NULL); | 468 set_first_deallocated(NULL); |
443 pool_.Release(); | 469 pool_.Release(); |
444 } | 470 } |
445 | 471 |
446 | 472 |
447 int GlobalHandles::number_of_weak_handles_ = 0; | 473 int GlobalHandles::number_of_weak_handles_ = 0; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 } | 534 } |
509 | 535 |
510 #endif | 536 #endif |
511 | 537 |
512 List<ObjectGroup*>* GlobalHandles::ObjectGroups() { | 538 List<ObjectGroup*>* GlobalHandles::ObjectGroups() { |
513 // Lazily initialize the list to avoid startup time static constructors. | 539 // Lazily initialize the list to avoid startup time static constructors. |
514 static List<ObjectGroup*> groups(4); | 540 static List<ObjectGroup*> groups(4); |
515 return &groups; | 541 return &groups; |
516 } | 542 } |
517 | 543 |
518 void GlobalHandles::AddGroup(Object*** handles, size_t length) { | 544 void GlobalHandles::AddGroup(Object*** handles, |
519 ObjectGroup* new_entry = new ObjectGroup(length); | 545 size_t length, |
| 546 v8::RetainedObjectInfo* info) { |
| 547 ObjectGroup* new_entry = new ObjectGroup(length, info); |
520 for (size_t i = 0; i < length; ++i) | 548 for (size_t i = 0; i < length; ++i) |
521 new_entry->objects_.Add(handles[i]); | 549 new_entry->objects_.Add(handles[i]); |
522 ObjectGroups()->Add(new_entry); | 550 ObjectGroups()->Add(new_entry); |
523 } | 551 } |
524 | 552 |
525 | 553 |
526 void GlobalHandles::RemoveObjectGroups() { | 554 void GlobalHandles::RemoveObjectGroups() { |
527 List<ObjectGroup*>* object_groups = ObjectGroups(); | 555 List<ObjectGroup*>* object_groups = ObjectGroups(); |
528 for (int i = 0; i< object_groups->length(); i++) { | 556 for (int i = 0; i< object_groups->length(); i++) { |
529 delete object_groups->at(i); | 557 delete object_groups->at(i); |
530 } | 558 } |
531 object_groups->Clear(); | 559 object_groups->Clear(); |
532 } | 560 } |
533 | 561 |
534 } } // namespace v8::internal | 562 } } // namespace v8::internal |
OLD | NEW |