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 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 137 parameter_or_next_free_.parameter = parameter; | 137 parameter_or_next_free_.parameter = parameter; |
| 138 } | 138 } |
| 139 void* parameter() { | 139 void* parameter() { |
| 140 ASSERT(state_ != DESTROYED); | 140 ASSERT(state_ != DESTROYED); |
| 141 return parameter_or_next_free_.parameter; | 141 return parameter_or_next_free_.parameter; |
| 142 } | 142 } |
| 143 | 143 |
| 144 // Returns the callback for this weak handle. | 144 // Returns the callback for this weak handle. |
| 145 WeakReferenceCallback callback() { return callback_; } | 145 WeakReferenceCallback callback() { return callback_; } |
| 146 | 146 |
| 147 void PostGarbageCollectionProcessing() { | 147 bool PostGarbageCollectionProcessing() { |
| 148 if (state_ != Node::PENDING) return; | 148 if (state_ != Node::PENDING) return false; |
| 149 LOG(HandleEvent("GlobalHandle::Processing", handle().location())); | 149 LOG(HandleEvent("GlobalHandle::Processing", handle().location())); |
| 150 void* par = parameter(); | 150 void* par = parameter(); |
| 151 state_ = NEAR_DEATH; | 151 state_ = NEAR_DEATH; |
| 152 set_parameter(NULL); | 152 set_parameter(NULL); |
| 153 // The callback function is resolved as late as possible to preserve old | 153 // The callback function is resolved as late as possible to preserve old |
| 154 // behavior. | 154 // behavior. |
| 155 WeakReferenceCallback func = callback(); | 155 WeakReferenceCallback func = callback(); |
| 156 if (func != NULL) { | 156 if (func == NULL) return false; |
| 157 v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); | 157 |
| 158 { | 158 v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); |
| 159 // Forbid reuse of destroyed nodes as they might be already deallocated. | 159 { |
| 160 // It's fine though to reuse nodes that were destroyed in weak callback | 160 // Forbid reuse of destroyed nodes as they might be already deallocated. |
| 161 // as those cannot be deallocated until we are back from the callback. | 161 // It's fine though to reuse nodes that were destroyed in weak callback |
| 162 set_first_free(NULL); | 162 // as those cannot be deallocated until we are back from the callback. |
| 163 // Leaving V8. | 163 set_first_free(NULL); |
| 164 VMState state(EXTERNAL); | 164 // Leaving V8. |
| 165 func(object, par); | 165 VMState state(EXTERNAL); |
| 166 } | 166 func(object, par); |
| 167 } | 167 } |
| 168 return true; | |
| 168 } | 169 } |
| 169 | 170 |
| 170 // Place the handle address first to avoid offset computation. | 171 // Place the handle address first to avoid offset computation. |
| 171 Object* object_; // Storage for object pointer. | 172 Object* object_; // Storage for object pointer. |
| 172 | 173 |
| 173 // Transition diagram: | 174 // Transition diagram: |
| 174 // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED } | 175 // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED } |
| 175 enum State { | 176 enum State { |
| 176 NORMAL, // Normal global handle. | 177 NORMAL, // Normal global handle. |
| 177 WEAK, // Flagged as weak but not yet finalized. | 178 WEAK, // Flagged as weak but not yet finalized. |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 if (current->state_ == Node::WEAK) { | 269 if (current->state_ == Node::WEAK) { |
| 269 if (f(¤t->object_)) { | 270 if (f(¤t->object_)) { |
| 270 current->state_ = Node::PENDING; | 271 current->state_ = Node::PENDING; |
| 271 LOG(HandleEvent("GlobalHandle::Pending", current->handle().location())); | 272 LOG(HandleEvent("GlobalHandle::Pending", current->handle().location())); |
| 272 } | 273 } |
| 273 } | 274 } |
| 274 } | 275 } |
| 275 } | 276 } |
| 276 | 277 |
| 277 | 278 |
| 279 int time_stamp = 0; | |
|
Mads Ager (chromium)
2009/08/21 05:58:16
You could expose Heap::mc_count() instead of intro
Mads Ager (chromium)
2009/08/21 06:09:28
Talking to Kasper, maybe it would be better to use
| |
| 280 | |
| 278 void GlobalHandles::PostGarbageCollectionProcessing() { | 281 void GlobalHandles::PostGarbageCollectionProcessing() { |
| 279 // Process weak global handle callbacks. This must be done after the | 282 // Process weak global handle callbacks. This must be done after the |
| 280 // GC is completely done, because the callbacks may invoke arbitrary | 283 // GC is completely done, because the callbacks may invoke arbitrary |
| 281 // API functions. | 284 // API functions. |
| 282 // At the same time deallocate all DESTROYED nodes | 285 // At the same time deallocate all DESTROYED nodes |
| 283 ASSERT(Heap::gc_state() == Heap::NOT_IN_GC); | 286 ASSERT(Heap::gc_state() == Heap::NOT_IN_GC); |
| 287 const int local_time_stamp = ++time_stamp; | |
| 284 Node** p = &head_; | 288 Node** p = &head_; |
| 285 while (*p != NULL) { | 289 while (*p != NULL) { |
| 286 (*p)->PostGarbageCollectionProcessing(); | 290 if ((*p)->PostGarbageCollectionProcessing()) { |
| 291 if (local_time_stamp != time_stamp) { | |
| 292 // Weak callback triggered another GC, the only safe thing | |
|
Mads Ager (chromium)
2009/08/21 05:58:16
Could you describe in the comment why it is unsafe
| |
| 293 // we can do is either to restart PostGarbageCollectionProcessing | |
| 294 // or abort it, let's abort as it's simpler :) | |
|
Mads Ager (chromium)
2009/08/21 05:58:16
Terminate comment with '.' and remove the smiley.
| |
| 295 break; | |
| 296 } | |
| 297 } | |
| 287 if ((*p)->state_ == Node::DESTROYED) { | 298 if ((*p)->state_ == Node::DESTROYED) { |
| 288 // Delete the link. | 299 // Delete the link. |
| 289 Node* node = *p; | 300 Node* node = *p; |
| 290 *p = node->next(); // Update the link. | 301 *p = node->next(); // Update the link. |
| 291 delete node; | 302 delete node; |
| 292 } else { | 303 } else { |
| 293 p = (*p)->next_addr(); | 304 p = (*p)->next_addr(); |
| 294 } | 305 } |
| 295 } | 306 } |
| 296 set_first_free(NULL); | 307 set_first_free(NULL); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 379 void GlobalHandles::RemoveObjectGroups() { | 390 void GlobalHandles::RemoveObjectGroups() { |
| 380 List<ObjectGroup*>* object_groups = ObjectGroups(); | 391 List<ObjectGroup*>* object_groups = ObjectGroups(); |
| 381 for (int i = 0; i< object_groups->length(); i++) { | 392 for (int i = 0; i< object_groups->length(); i++) { |
| 382 delete object_groups->at(i); | 393 delete object_groups->at(i); |
| 383 } | 394 } |
| 384 object_groups->Clear(); | 395 object_groups->Clear(); |
| 385 } | 396 } |
| 386 | 397 |
| 387 | 398 |
| 388 } } // namespace v8::internal | 399 } } // namespace v8::internal |
| OLD | NEW |