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 |