Index: src/api.cc |
diff --git a/src/api.cc b/src/api.cc |
index e3596bef7a2f06e65e3383946d8f459aaf6f7046..376b29616b8b59fa02d391e153c680ed618ed062 100644 |
--- a/src/api.cc |
+++ b/src/api.cc |
@@ -6385,12 +6385,28 @@ char* HandleScopeImplementer::RestoreThread(char* storage) { |
void HandleScopeImplementer::IterateThis(ObjectVisitor* v) { |
+#ifdef DEBUG |
+ bool found_block_before_deferred = false; |
+#endif |
// Iterate over all handles in the blocks except for the last. |
for (int i = blocks()->length() - 2; i >= 0; --i) { |
Object** block = blocks()->at(i); |
- v->VisitPointers(block, &block[kHandleBlockSize]); |
+ if (last_handle_before_deferred_block_ != NULL && |
+ (last_handle_before_deferred_block_ < &block[kHandleBlockSize]) && |
+ (last_handle_before_deferred_block_ >= block)) { |
+ v->VisitPointers(block, last_handle_before_deferred_block_); |
+ ASSERT(!found_block_before_deferred); |
+#ifdef DEBUG |
+ found_block_before_deferred = true; |
+#endif |
+ } else { |
+ v->VisitPointers(block, &block[kHandleBlockSize]); |
+ } |
} |
+ ASSERT(last_handle_before_deferred_block_ == NULL || |
+ found_block_before_deferred); |
+ |
// Iterate over live handles in the last block (if any). |
if (!blocks()->is_empty()) { |
v->VisitPointers(blocks()->last(), handle_scope_data_.next); |
@@ -6400,6 +6416,12 @@ void HandleScopeImplementer::IterateThis(ObjectVisitor* v) { |
Object** start = reinterpret_cast<Object**>(&saved_contexts_.first()); |
v->VisitPointers(start, start + saved_contexts_.length()); |
} |
+ |
+ for (DeferredHandles* deferred = deferred_handles_head_; |
+ deferred != NULL; |
+ deferred = deferred->next_) { |
+ deferred->Iterate(v); |
+ } |
} |
@@ -6418,4 +6440,75 @@ char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) { |
return storage + ArchiveSpacePerThread(); |
} |
+ |
+DeferredHandles* HandleScopeImplementer::Detach(Object** prev_limit) { |
+ DeferredHandles* deferred = new DeferredHandles( |
+ deferred_handles_head_, isolate()->handle_scope_data()->next, this); |
+ |
+ while (!blocks_.is_empty()) { |
+ Object** block_start = blocks_.last(); |
+ Object** block_limit = &block_start[kHandleBlockSize]; |
+ // We should not need to check for NoHandleAllocation here. Assert |
+ // this. |
+ ASSERT(prev_limit == block_limit || |
+ !(block_start <= prev_limit && prev_limit <= block_limit)); |
+ if (prev_limit == block_limit) break; |
+ deferred->blocks_.Add(blocks_.last()); |
+ blocks_.RemoveLast(); |
+ } |
+ |
+ ASSERT(!blocks_.is_empty() && prev_limit != NULL); |
+ deferred_handles_head_ = deferred; |
+ ASSERT(last_handle_before_deferred_block_ != NULL); |
+ last_handle_before_deferred_block_ = NULL; |
+ return deferred; |
+} |
+ |
+ |
+void HandleScopeImplementer::DestroyDeferredHandles(DeferredHandles* deferred) { |
+ if (deferred_handles_head_ == deferred) { |
+ deferred_handles_head_ = deferred_handles_head_->next_; |
+ } |
+ if (deferred->next_ != NULL) { |
+ deferred->next_->previous_ = deferred->previous_; |
+ } |
+ if (deferred->previous_ != NULL) { |
+ deferred->previous_->next_ = deferred->next_; |
+ } |
+ for (int i = 0; i < deferred->blocks_.length(); i++) { |
+#ifdef DEBUG |
+ HandleScope::ZapRange(deferred->blocks_[i], |
+ &deferred->blocks_[i][kHandleBlockSize]); |
+#endif |
+ if (spare_ != NULL) DeleteArray(spare_); |
+ spare_ = deferred->blocks_[i]; |
+ } |
+} |
+ |
+ |
+void HandleScopeImplementer::BeginDeferredScope() { |
+ ASSERT(last_handle_before_deferred_block_ == NULL); |
+ last_handle_before_deferred_block_ = isolate()->handle_scope_data()->next; |
+} |
+ |
+ |
+DeferredHandles::~DeferredHandles() { |
+ impl_->DestroyDeferredHandles(this); |
+} |
+ |
+ |
+void DeferredHandles::Iterate(ObjectVisitor* v) { |
+ ASSERT(!blocks_.is_empty()); |
+ |
+ for (int i = 0; i < (blocks_.length() - 1); i++) { |
+ v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]); |
+ } |
+ |
+ ASSERT((last_block_limit_ >= blocks_.last()) && |
+ (last_block_limit_ < &(blocks_.last())[kHandleBlockSize])); |
+ |
+ v->VisitPointers(blocks_.last(), last_block_limit_); |
+} |
+ |
+ |
} } // namespace v8::internal |