Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Unified Diff: src/heap.cc

Issue 11880018: Reland r13188, r13194, r13256 (Deferred formatting of error stack trace during GC). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/heap.h ('k') | src/heap-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/heap.cc
diff --git a/src/heap.cc b/src/heap.cc
index 013a18c3205903a13989b56016252a0142d2d3de..3ffcd1b0a4aba60434bddd6c3078a2f6d581d5fc 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -550,6 +550,8 @@ void Heap::GarbageCollectionEpilogue() {
#ifdef ENABLE_DEBUGGER_SUPPORT
isolate_->debug()->AfterGarbageCollection();
#endif // ENABLE_DEBUGGER_SUPPORT
+
+ error_object_list_.DeferredFormatStackTrace(isolate());
}
@@ -1377,6 +1379,8 @@ void Heap::Scavenge() {
UpdateNewSpaceReferencesInExternalStringTable(
&UpdateNewSpaceReferenceInExternalStringTableEntry);
+ error_object_list_.UpdateReferencesInNewSpace(this);
+
promotion_queue_.Destroy();
LiveObjectList::UpdateReferencesForScavengeGC();
@@ -5959,6 +5963,7 @@ void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) {
mode != VISIT_ALL_IN_SWEEP_NEWSPACE) {
// Scavenge collections have special processing for this.
external_string_table_.Iterate(v);
+ error_object_list_.Iterate(v);
}
v->Synchronize(VisitorSynchronization::kExternalStringsTable);
}
@@ -6332,6 +6337,8 @@ void Heap::TearDown() {
external_string_table_.TearDown();
+ error_object_list_.TearDown();
+
new_space_.TearDown();
if (old_pointer_space_ != NULL) {
@@ -7238,6 +7245,8 @@ void ExternalStringTable::CleanUp() {
}
}
new_space_strings_.Rewind(last);
+ new_space_strings_.Trim();
+
last = 0;
for (int i = 0; i < old_space_strings_.length(); ++i) {
if (old_space_strings_[i] == heap_->the_hole_value()) {
@@ -7247,6 +7256,7 @@ void ExternalStringTable::CleanUp() {
old_space_strings_[last++] = old_space_strings_[i];
}
old_space_strings_.Rewind(last);
+ old_space_strings_.Trim();
#ifdef VERIFY_HEAP
if (FLAG_verify_heap) {
Verify();
@@ -7261,6 +7271,116 @@ void ExternalStringTable::TearDown() {
}
+// Update all references.
+void ErrorObjectList::UpdateReferences() {
+ for (int i = 0; i < list_.length(); i++) {
+ HeapObject* object = HeapObject::cast(list_[i]);
+ MapWord first_word = object->map_word();
+ if (first_word.IsForwardingAddress()) {
+ list_[i] = first_word.ToForwardingAddress();
+ }
+ }
+}
+
+
+// Unforwarded objects in new space are dead and removed from the list.
+void ErrorObjectList::UpdateReferencesInNewSpace(Heap* heap) {
+ if (!nested_) {
+ int write_index = 0;
+ for (int i = 0; i < list_.length(); i++) {
+ MapWord first_word = HeapObject::cast(list_[i])->map_word();
+ if (first_word.IsForwardingAddress()) {
+ list_[write_index++] = first_word.ToForwardingAddress();
+ }
+ }
+ list_.Rewind(write_index);
+ } else {
+ // If a GC is triggered during DeferredFormatStackTrace, we do not move
+ // objects in the list, just remove dead ones, as to not confuse the
+ // loop in DeferredFormatStackTrace.
+ for (int i = 0; i < list_.length(); i++) {
+ MapWord first_word = HeapObject::cast(list_[i])->map_word();
+ list_[i] = first_word.IsForwardingAddress()
+ ? first_word.ToForwardingAddress()
+ : heap->the_hole_value();
+ }
+ }
+}
+
+
+void ErrorObjectList::DeferredFormatStackTrace(Isolate* isolate) {
+ // If formatting the stack trace causes a GC, this method will be
+ // recursively called. In that case, skip the recursive call, since
+ // the loop modifies the list while iterating over it.
+ if (nested_ || isolate->has_pending_exception()) return;
+ nested_ = true;
+ HandleScope scope(isolate);
+ Handle<String> stack_key = isolate->factory()->stack_symbol();
+ int write_index = 0;
+ int budget = kBudgetPerGC;
+ for (int i = 0; i < list_.length(); i++) {
+ Object* object = list_[i];
+ JSFunction* getter_fun;
+
+ { AssertNoAllocation assert;
+ // Skip possible holes in the list.
+ if (object->IsTheHole()) continue;
+ if (isolate->heap()->InNewSpace(object) || budget == 0) {
+ list_[write_index++] = object;
+ continue;
+ }
+
+ // Check whether the stack property is backed by the original getter.
+ LookupResult lookup(isolate);
+ JSObject::cast(object)->LocalLookupRealNamedProperty(*stack_key, &lookup);
+ if (!lookup.IsFound() || lookup.type() != CALLBACKS) continue;
+ Object* callback = lookup.GetCallbackObject();
+ if (!callback->IsAccessorPair()) continue;
+ Object* getter_obj = AccessorPair::cast(callback)->getter();
+ if (!getter_obj->IsJSFunction()) continue;
+ getter_fun = JSFunction::cast(getter_obj);
+ String* key = isolate->heap()->hidden_stack_trace_symbol();
+ if (key != getter_fun->GetHiddenProperty(key)) continue;
+ }
+
+ budget--;
+ HandleScope scope(isolate);
+ bool has_exception = false;
+ Handle<Map> map(HeapObject::cast(object)->map(), isolate);
+ Handle<Object> object_handle(object, isolate);
+ Handle<Object> getter_handle(getter_fun, isolate);
+ Execution::Call(getter_handle, object_handle, 0, NULL, &has_exception);
+ CHECK(*map == HeapObject::cast(*object_handle)->map());
+ if (has_exception) {
+ // Hit an exception (most likely a stack overflow).
+ // Wrap up this pass and retry after another GC.
+ isolate->clear_pending_exception();
+ // We use the handle since calling the getter might have caused a GC.
+ list_[write_index++] = *object_handle;
+ budget = 0;
+ }
+ }
+ list_.Rewind(write_index);
+ list_.Trim();
+ nested_ = false;
+}
+
+
+void ErrorObjectList::RemoveUnmarked(Heap* heap) {
+ for (int i = 0; i < list_.length(); i++) {
+ HeapObject* object = HeapObject::cast(list_[i]);
+ if (!Marking::MarkBitFrom(object).Get()) {
+ list_[i] = heap->the_hole_value();
+ }
+ }
+}
+
+
+void ErrorObjectList::TearDown() {
+ list_.Free();
+}
+
+
void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) {
chunk->set_next_chunk(chunks_queued_for_free_);
chunks_queued_for_free_ = chunk;
« no previous file with comments | « src/heap.h ('k') | src/heap-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698