Chromium Code Reviews| 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 21 matching lines...) Expand all Loading... | |
| 32 | 32 |
| 33 namespace v8 { | 33 namespace v8 { |
| 34 namespace internal { | 34 namespace internal { |
| 35 | 35 |
| 36 class GlobalHandles::Node : public Malloced { | 36 class GlobalHandles::Node : public Malloced { |
| 37 public: | 37 public: |
| 38 | 38 |
| 39 void Initialize(Object* object) { | 39 void Initialize(Object* object) { |
| 40 // Set the initial value of the handle. | 40 // Set the initial value of the handle. |
| 41 object_ = object; | 41 object_ = object; |
| 42 really_weak_ = false; | |
| 42 state_ = NORMAL; | 43 state_ = NORMAL; |
| 43 parameter_or_next_free_.parameter = NULL; | 44 parameter_or_next_free_.parameter = NULL; |
| 44 callback_ = NULL; | 45 callback_ = NULL; |
| 45 } | 46 } |
| 46 | 47 |
| 47 explicit Node(Object* object) { | 48 explicit Node(Object* object) { |
| 48 Initialize(object); | 49 Initialize(object); |
| 49 // Initialize link structure. | 50 // Initialize link structure. |
| 50 next_ = NULL; | 51 next_ = NULL; |
| 51 } | 52 } |
| 52 | 53 |
| 53 ~Node() { | 54 ~Node() { |
| 54 if (state_ != DESTROYED) Destroy(); | 55 if (state_ != DESTROYED) Destroy(); |
| 55 #ifdef DEBUG | 56 #ifdef DEBUG |
| 56 // Zap the values for eager trapping. | 57 // Zap the values for eager trapping. |
| 57 object_ = NULL; | 58 object_ = NULL; |
| 58 next_ = NULL; | 59 next_ = NULL; |
| 59 parameter_or_next_free_.next_free = NULL; | 60 parameter_or_next_free_.next_free = NULL; |
| 60 #endif | 61 #endif |
| 61 } | 62 } |
| 62 | 63 |
| 63 void Destroy() { | 64 void Destroy() { |
| 64 if (state_ == WEAK || IsNearDeath()) { | 65 if (state_ == WEAK || IsNearDeath()) { |
| 65 GlobalHandles::number_of_weak_handles_--; | 66 GlobalHandles::number_of_weak_handles_--; |
| 66 if (object_->IsJSGlobalObject()) { | |
| 67 GlobalHandles::number_of_global_object_weak_handles_--; | |
| 68 } | |
| 69 } | 67 } |
| 70 state_ = DESTROYED; | 68 state_ = DESTROYED; |
| 71 } | 69 } |
| 72 | 70 |
| 73 // Accessors for next_. | 71 // Accessors for next_. |
| 74 Node* next() { return next_; } | 72 Node* next() { return next_; } |
| 75 void set_next(Node* value) { next_ = value; } | 73 void set_next(Node* value) { next_ = value; } |
| 76 Node** next_addr() { return &next_; } | 74 Node** next_addr() { return &next_; } |
| 77 | 75 |
| 78 // Accessors for next free node in the free list. | 76 // Accessors for next free node in the free list. |
| 79 Node* next_free() { | 77 Node* next_free() { |
| 80 ASSERT(state_ == DESTROYED); | 78 ASSERT(state_ == DESTROYED); |
| 81 return parameter_or_next_free_.next_free; | 79 return parameter_or_next_free_.next_free; |
| 82 } | 80 } |
| 83 void set_next_free(Node* value) { | 81 void set_next_free(Node* value) { |
| 84 ASSERT(state_ == DESTROYED); | 82 ASSERT(state_ == DESTROYED); |
| 85 parameter_or_next_free_.next_free = value; | 83 parameter_or_next_free_.next_free = value; |
| 86 } | 84 } |
| 87 | 85 |
| 88 // Returns a link from the handle. | 86 // Returns a link from the handle. |
| 89 static Node* FromLocation(Object** location) { | 87 static Node* FromLocation(Object** location) { |
| 90 ASSERT(OFFSET_OF(Node, object_) == 0); | 88 ASSERT(OFFSET_OF(Node, object_) == 0); |
| 91 return reinterpret_cast<Node*>(location); | 89 return reinterpret_cast<Node*>(location); |
| 92 } | 90 } |
| 93 | 91 |
| 94 // Returns the handle. | 92 // Returns the handle. |
| 95 Handle<Object> handle() { return Handle<Object>(&object_); } | 93 Handle<Object> handle() { return Handle<Object>(&object_); } |
| 96 | 94 |
| 97 // Make this handle weak. | 95 // Make this handle weak. |
| 98 void MakeWeak(void* parameter, WeakReferenceCallback callback) { | 96 void MakeWeak(void* parameter, WeakReferenceCallback callback, |
|
Christian Plesner Hansen
2009/10/06 13:47:21
The 'callback' parameter should be moved to the ne
| |
| 97 bool really_weak) { | |
| 99 LOG(HandleEvent("GlobalHandle::MakeWeak", handle().location())); | 98 LOG(HandleEvent("GlobalHandle::MakeWeak", handle().location())); |
| 100 ASSERT(state_ != DESTROYED); | 99 ASSERT(state_ != DESTROYED); |
| 101 if (state_ != WEAK && !IsNearDeath()) { | 100 if (state_ != WEAK && !IsNearDeath()) { |
| 102 GlobalHandles::number_of_weak_handles_++; | 101 GlobalHandles::number_of_weak_handles_++; |
| 103 if (object_->IsJSGlobalObject()) { | |
| 104 GlobalHandles::number_of_global_object_weak_handles_++; | |
| 105 } | |
| 106 } | 102 } |
| 103 really_weak_ = really_weak; | |
| 107 state_ = WEAK; | 104 state_ = WEAK; |
| 108 set_parameter(parameter); | 105 set_parameter(parameter); |
| 109 callback_ = callback; | 106 callback_ = callback; |
| 110 } | 107 } |
| 111 | 108 |
| 112 void ClearWeakness() { | 109 void ClearWeakness() { |
| 113 LOG(HandleEvent("GlobalHandle::ClearWeakness", handle().location())); | 110 LOG(HandleEvent("GlobalHandle::ClearWeakness", handle().location())); |
| 114 ASSERT(state_ != DESTROYED); | 111 ASSERT(state_ != DESTROYED); |
| 115 if (state_ == WEAK || IsNearDeath()) { | 112 if (state_ == WEAK || IsNearDeath()) { |
| 113 // Can't clear weakness of near death really weak handle because | |
| 114 // the object may have been collected already. | |
| 115 ASSERT(!IsNearDeath() || !really_weak_); | |
|
Christian Plesner Hansen
2009/10/06 13:47:21
Are we sure this can't happen? Wouldn't it be saf
| |
| 116 GlobalHandles::number_of_weak_handles_--; | 116 GlobalHandles::number_of_weak_handles_--; |
| 117 if (object_->IsJSGlobalObject()) { | |
| 118 GlobalHandles::number_of_global_object_weak_handles_--; | |
| 119 } | |
| 120 } | 117 } |
| 118 really_weak_ = false; | |
| 121 state_ = NORMAL; | 119 state_ = NORMAL; |
| 122 set_parameter(NULL); | 120 set_parameter(NULL); |
| 123 } | 121 } |
| 124 | 122 |
| 125 bool IsNearDeath() { | 123 bool IsNearDeath() { |
| 126 // Check for PENDING to ensure correct answer when processing callbacks. | 124 // Check for PENDING to ensure correct answer when processing callbacks. |
| 127 return state_ == PENDING || state_ == NEAR_DEATH; | 125 return state_ == PENDING || state_ == NEAR_DEATH; |
| 128 } | 126 } |
| 129 | 127 |
| 130 bool IsWeak() { | 128 bool IsWeak() { |
| 131 return state_ == WEAK; | 129 return state_ == WEAK; |
| 132 } | 130 } |
| 133 | 131 |
| 132 bool IsReallyWeak() { | |
| 133 return really_weak_; | |
| 134 } | |
| 135 | |
| 134 // Returns the id for this weak handle. | 136 // Returns the id for this weak handle. |
| 135 void set_parameter(void* parameter) { | 137 void set_parameter(void* parameter) { |
| 136 ASSERT(state_ != DESTROYED); | 138 ASSERT(state_ != DESTROYED); |
| 137 parameter_or_next_free_.parameter = parameter; | 139 parameter_or_next_free_.parameter = parameter; |
| 138 } | 140 } |
| 139 void* parameter() { | 141 void* parameter() { |
| 140 ASSERT(state_ != DESTROYED); | 142 ASSERT(state_ != DESTROYED); |
| 141 return parameter_or_next_free_.parameter; | 143 return parameter_or_next_free_.parameter; |
| 142 } | 144 } |
| 143 | 145 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 164 // Leaving V8. | 166 // Leaving V8. |
| 165 VMState state(EXTERNAL); | 167 VMState state(EXTERNAL); |
| 166 func(object, par); | 168 func(object, par); |
| 167 } | 169 } |
| 168 return true; | 170 return true; |
| 169 } | 171 } |
| 170 | 172 |
| 171 // Place the handle address first to avoid offset computation. | 173 // Place the handle address first to avoid offset computation. |
| 172 Object* object_; // Storage for object pointer. | 174 Object* object_; // Storage for object pointer. |
| 173 | 175 |
| 176 bool really_weak_ : 1; | |
| 177 | |
| 174 // Transition diagram: | 178 // Transition diagram: |
| 175 // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED } | 179 // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED } |
| 176 enum State { | 180 enum State { |
| 177 NORMAL, // Normal global handle. | 181 NORMAL, // Normal global handle. |
| 178 WEAK, // Flagged as weak but not yet finalized. | 182 WEAK, // Flagged as weak but not yet finalized. |
| 179 PENDING, // Has been recognized as only reachable by weak handles. | 183 PENDING, // Has been recognized as only reachable by weak handles. |
| 180 NEAR_DEATH, // Callback has informed the handle is near death. | 184 NEAR_DEATH, // Callback has informed the handle is near death. |
| 181 DESTROYED | 185 DESTROYED |
| 182 }; | 186 }; |
| 183 State state_; | 187 State state_ : 3; |
| 184 | 188 |
| 185 private: | 189 private: |
| 186 // Handle specific callback. | 190 // Handle specific callback. |
| 187 WeakReferenceCallback callback_; | 191 WeakReferenceCallback callback_; |
| 188 // Provided data for callback. In DESTROYED state, this is used for | 192 // Provided data for callback. In DESTROYED state, this is used for |
| 189 // the free list link. | 193 // the free list link. |
| 190 union { | 194 union { |
| 191 void* parameter; | 195 void* parameter; |
| 192 Node* next_free; | 196 Node* next_free; |
| 193 } parameter_or_next_free_; | 197 } parameter_or_next_free_; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 node->Destroy(); | 229 node->Destroy(); |
| 226 // Link the destroyed. | 230 // Link the destroyed. |
| 227 node->set_next_free(first_free()); | 231 node->set_next_free(first_free()); |
| 228 set_first_free(node); | 232 set_first_free(node); |
| 229 } | 233 } |
| 230 | 234 |
| 231 | 235 |
| 232 void GlobalHandles::MakeWeak(Object** location, void* parameter, | 236 void GlobalHandles::MakeWeak(Object** location, void* parameter, |
| 233 WeakReferenceCallback callback) { | 237 WeakReferenceCallback callback) { |
| 234 ASSERT(callback != NULL); | 238 ASSERT(callback != NULL); |
| 235 Node::FromLocation(location)->MakeWeak(parameter, callback); | 239 Node::FromLocation(location)->MakeWeak(parameter, callback, false); |
| 236 } | 240 } |
| 237 | 241 |
| 238 | 242 |
| 243 void GlobalHandles::MakeReallyWeak(Object** location, void* parameter, | |
| 244 WeakReferenceCallback callback) { | |
| 245 ASSERT(callback != NULL); | |
| 246 Node::FromLocation(location)->MakeWeak(parameter, callback, true); | |
| 247 } | |
| 248 | |
| 249 | |
| 239 void GlobalHandles::ClearWeakness(Object** location) { | 250 void GlobalHandles::ClearWeakness(Object** location) { |
| 240 Node::FromLocation(location)->ClearWeakness(); | 251 Node::FromLocation(location)->ClearWeakness(); |
| 241 } | 252 } |
| 242 | 253 |
| 243 | 254 |
| 244 bool GlobalHandles::IsNearDeath(Object** location) { | 255 bool GlobalHandles::IsNearDeath(Object** location) { |
| 245 return Node::FromLocation(location)->IsNearDeath(); | 256 return Node::FromLocation(location)->IsNearDeath(); |
| 246 } | 257 } |
| 247 | 258 |
| 248 | 259 |
| 249 bool GlobalHandles::IsWeak(Object** location) { | 260 bool GlobalHandles::IsWeak(Object** location) { |
| 250 return Node::FromLocation(location)->IsWeak(); | 261 return Node::FromLocation(location)->IsWeak(); |
| 251 } | 262 } |
| 252 | 263 |
| 253 | 264 |
| 265 bool GlobalHandles::IsReallyWeak(Object** location) { | |
| 266 return Node::FromLocation(location)->IsReallyWeak(); | |
| 267 } | |
| 268 | |
| 269 | |
| 254 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { | 270 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { |
| 255 // Traversal of GC roots in the global handle list that are marked as | 271 // Traversal of GC roots in the global handle list that are marked as |
| 256 // WEAK or PENDING. | 272 // WEAK or PENDING. |
| 257 for (Node* current = head_; current != NULL; current = current->next()) { | 273 for (Node* current = head_; current != NULL; current = current->next()) { |
| 258 if (current->state_ == Node::WEAK | 274 if (current->state_ == Node::WEAK || |
| 259 || current->state_ == Node::PENDING | 275 (!current->really_weak_ && |
| 260 || current->state_ == Node::NEAR_DEATH) { | 276 (current->state_ == Node::PENDING || |
| 277 current->state_ == Node::NEAR_DEATH))) { | |
| 261 v->VisitPointer(¤t->object_); | 278 v->VisitPointer(¤t->object_); |
| 262 } | 279 } |
| 263 } | 280 } |
| 264 } | 281 } |
| 265 | 282 |
| 266 | 283 |
| 267 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { | 284 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { |
| 268 for (Node* current = head_; current != NULL; current = current->next()) { | 285 for (Node* current = head_; current != NULL; current = current->next()) { |
| 269 if (current->state_ == Node::WEAK) { | 286 if (current->state_ == Node::WEAK) { |
| 270 if (f(¤t->object_)) { | 287 if (f(¤t->object_)) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 303 delete node; | 320 delete node; |
| 304 } else { | 321 } else { |
| 305 p = (*p)->next_addr(); | 322 p = (*p)->next_addr(); |
| 306 } | 323 } |
| 307 } | 324 } |
| 308 set_first_free(NULL); | 325 set_first_free(NULL); |
| 309 } | 326 } |
| 310 | 327 |
| 311 | 328 |
| 312 void GlobalHandles::IterateRoots(ObjectVisitor* v) { | 329 void GlobalHandles::IterateRoots(ObjectVisitor* v) { |
| 313 // Traversal of global handles marked as NORMAL or NEAR_DEATH. | 330 // Traversal of global handles marked as NORMAL. |
| 314 for (Node* current = head_; current != NULL; current = current->next()) { | 331 for (Node* current = head_; current != NULL; current = current->next()) { |
| 315 if (current->state_ == Node::NORMAL) { | 332 if (current->state_ == Node::NORMAL) { |
| 316 v->VisitPointer(¤t->object_); | 333 v->VisitPointer(¤t->object_); |
| 317 } | 334 } |
| 318 } | 335 } |
| 319 } | 336 } |
| 320 | 337 |
| 321 void GlobalHandles::TearDown() { | 338 void GlobalHandles::TearDown() { |
| 322 // Delete all the nodes in the linked list. | 339 // Delete all the nodes in the linked list. |
| 323 Node* current = head_; | 340 Node* current = head_; |
| 324 while (current != NULL) { | 341 while (current != NULL) { |
| 325 Node* n = current; | 342 Node* n = current; |
| 326 current = current->next(); | 343 current = current->next(); |
| 327 delete n; | 344 delete n; |
| 328 } | 345 } |
| 329 // Reset the head and free_list. | 346 // Reset the head and free_list. |
| 330 set_head(NULL); | 347 set_head(NULL); |
| 331 set_first_free(NULL); | 348 set_first_free(NULL); |
| 332 } | 349 } |
| 333 | 350 |
| 334 | 351 |
| 335 int GlobalHandles::number_of_weak_handles_ = 0; | 352 int GlobalHandles::number_of_weak_handles_ = 0; |
| 336 int GlobalHandles::number_of_global_object_weak_handles_ = 0; | |
| 337 | 353 |
| 338 GlobalHandles::Node* GlobalHandles::head_ = NULL; | 354 GlobalHandles::Node* GlobalHandles::head_ = NULL; |
| 339 GlobalHandles::Node* GlobalHandles::first_free_ = NULL; | 355 GlobalHandles::Node* GlobalHandles::first_free_ = NULL; |
| 340 | 356 |
| 341 #ifdef DEBUG | 357 #ifdef DEBUG |
| 342 | 358 |
| 343 void GlobalHandles::PrintStats() { | 359 void GlobalHandles::PrintStats() { |
| 344 int total = 0; | 360 int total = 0; |
| 345 int weak = 0; | 361 int weak = 0; |
| 346 int pending = 0; | 362 int pending = 0; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 373 } | 389 } |
| 374 | 390 |
| 375 #endif | 391 #endif |
| 376 | 392 |
| 377 List<ObjectGroup*>* GlobalHandles::ObjectGroups() { | 393 List<ObjectGroup*>* GlobalHandles::ObjectGroups() { |
| 378 // Lazily initialize the list to avoid startup time static constructors. | 394 // Lazily initialize the list to avoid startup time static constructors. |
| 379 static List<ObjectGroup*> groups(4); | 395 static List<ObjectGroup*> groups(4); |
| 380 return &groups; | 396 return &groups; |
| 381 } | 397 } |
| 382 | 398 |
| 399 | |
| 383 void GlobalHandles::AddGroup(Object*** handles, size_t length) { | 400 void GlobalHandles::AddGroup(Object*** handles, size_t length) { |
| 384 ObjectGroup* new_entry = new ObjectGroup(length); | 401 ObjectGroup* new_entry = new ObjectGroup(length); |
| 385 for (size_t i = 0; i < length; ++i) | 402 for (size_t i = 0; i < length; ++i) |
| 386 new_entry->objects_.Add(handles[i]); | 403 new_entry->objects_.Add(handles[i]); |
| 387 ObjectGroups()->Add(new_entry); | 404 ObjectGroups()->Add(new_entry); |
| 388 } | 405 } |
| 389 | 406 |
| 390 | 407 |
| 391 void GlobalHandles::RemoveObjectGroups() { | 408 void GlobalHandles::RemoveObjectGroups() { |
| 392 List<ObjectGroup*>* object_groups = ObjectGroups(); | 409 List<ObjectGroup*>* object_groups = ObjectGroups(); |
| 393 for (int i = 0; i< object_groups->length(); i++) { | 410 for (int i = 0; i < object_groups->length(); ++i) { |
|
Christian Plesner Hansen
2009/10/06 13:47:21
Changing from i++ to ++i shouldn't make any differ
| |
| 394 delete object_groups->at(i); | 411 delete object_groups->at(i); |
| 395 } | 412 } |
| 396 object_groups->Clear(); | 413 object_groups->Clear(); |
| 397 } | 414 } |
| 398 | 415 |
| 399 | 416 |
| 400 } } // namespace v8::internal | 417 } } // namespace v8::internal |
| OLD | NEW |