Index: src/global-handles.cc |
=================================================================== |
--- src/global-handles.cc (revision 2724) |
+++ src/global-handles.cc (working copy) |
@@ -144,8 +144,8 @@ |
// Returns the callback for this weak handle. |
WeakReferenceCallback callback() { return callback_; } |
- void PostGarbageCollectionProcessing() { |
- if (state_ != Node::PENDING) return; |
+ bool PostGarbageCollectionProcessing() { |
+ if (state_ != Node::PENDING) return false; |
LOG(HandleEvent("GlobalHandle::Processing", handle().location())); |
void* par = parameter(); |
state_ = NEAR_DEATH; |
@@ -153,18 +153,19 @@ |
// The callback function is resolved as late as possible to preserve old |
// behavior. |
WeakReferenceCallback func = callback(); |
- if (func != NULL) { |
- v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); |
- { |
- // Forbid reuse of destroyed nodes as they might be already deallocated. |
- // It's fine though to reuse nodes that were destroyed in weak callback |
- // as those cannot be deallocated until we are back from the callback. |
- set_first_free(NULL); |
- // Leaving V8. |
- VMState state(EXTERNAL); |
- func(object, par); |
- } |
+ if (func == NULL) return false; |
+ |
+ v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); |
+ { |
+ // Forbid reuse of destroyed nodes as they might be already deallocated. |
+ // It's fine though to reuse nodes that were destroyed in weak callback |
+ // as those cannot be deallocated until we are back from the callback. |
+ set_first_free(NULL); |
+ // Leaving V8. |
+ VMState state(EXTERNAL); |
+ func(object, par); |
} |
+ return true; |
} |
// Place the handle address first to avoid offset computation. |
@@ -275,15 +276,25 @@ |
} |
+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
|
+ |
void GlobalHandles::PostGarbageCollectionProcessing() { |
// Process weak global handle callbacks. This must be done after the |
// GC is completely done, because the callbacks may invoke arbitrary |
// API functions. |
// At the same time deallocate all DESTROYED nodes |
ASSERT(Heap::gc_state() == Heap::NOT_IN_GC); |
+ const int local_time_stamp = ++time_stamp; |
Node** p = &head_; |
while (*p != NULL) { |
- (*p)->PostGarbageCollectionProcessing(); |
+ if ((*p)->PostGarbageCollectionProcessing()) { |
+ if (local_time_stamp != time_stamp) { |
+ // 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
|
+ // we can do is either to restart PostGarbageCollectionProcessing |
+ // 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.
|
+ break; |
+ } |
+ } |
if ((*p)->state_ == Node::DESTROYED) { |
// Delete the link. |
Node* node = *p; |