OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 #undef UPDATE_COUNTERS_FOR_SPACE | 543 #undef UPDATE_COUNTERS_FOR_SPACE |
544 #undef UPDATE_FRAGMENTATION_FOR_SPACE | 544 #undef UPDATE_FRAGMENTATION_FOR_SPACE |
545 #undef UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE | 545 #undef UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE |
546 | 546 |
547 #if defined(DEBUG) | 547 #if defined(DEBUG) |
548 ReportStatisticsAfterGC(); | 548 ReportStatisticsAfterGC(); |
549 #endif // DEBUG | 549 #endif // DEBUG |
550 #ifdef ENABLE_DEBUGGER_SUPPORT | 550 #ifdef ENABLE_DEBUGGER_SUPPORT |
551 isolate_->debug()->AfterGarbageCollection(); | 551 isolate_->debug()->AfterGarbageCollection(); |
552 #endif // ENABLE_DEBUGGER_SUPPORT | 552 #endif // ENABLE_DEBUGGER_SUPPORT |
| 553 |
| 554 error_object_list_.DeferredFormatStackTrace(isolate()); |
553 } | 555 } |
554 | 556 |
555 | 557 |
556 void Heap::CollectAllGarbage(int flags, const char* gc_reason) { | 558 void Heap::CollectAllGarbage(int flags, const char* gc_reason) { |
557 // Since we are ignoring the return value, the exact choice of space does | 559 // Since we are ignoring the return value, the exact choice of space does |
558 // not matter, so long as we do not specify NEW_SPACE, which would not | 560 // not matter, so long as we do not specify NEW_SPACE, which would not |
559 // cause a full GC. | 561 // cause a full GC. |
560 mark_compact_collector_.SetFlags(flags); | 562 mark_compact_collector_.SetFlags(flags); |
561 CollectGarbage(OLD_POINTER_SPACE, gc_reason); | 563 CollectGarbage(OLD_POINTER_SPACE, gc_reason); |
562 mark_compact_collector_.SetFlags(kNoGCFlags); | 564 mark_compact_collector_.SetFlags(kNoGCFlags); |
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1347 | 1349 |
1348 isolate_->global_handles()->IdentifyNewSpaceWeakIndependentHandles( | 1350 isolate_->global_handles()->IdentifyNewSpaceWeakIndependentHandles( |
1349 &IsUnscavengedHeapObject); | 1351 &IsUnscavengedHeapObject); |
1350 isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots( | 1352 isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots( |
1351 &scavenge_visitor); | 1353 &scavenge_visitor); |
1352 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); | 1354 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); |
1353 | 1355 |
1354 UpdateNewSpaceReferencesInExternalStringTable( | 1356 UpdateNewSpaceReferencesInExternalStringTable( |
1355 &UpdateNewSpaceReferenceInExternalStringTableEntry); | 1357 &UpdateNewSpaceReferenceInExternalStringTableEntry); |
1356 | 1358 |
| 1359 error_object_list_.UpdateReferencesInNewSpace(this); |
| 1360 |
1357 promotion_queue_.Destroy(); | 1361 promotion_queue_.Destroy(); |
1358 | 1362 |
1359 LiveObjectList::UpdateReferencesForScavengeGC(); | 1363 LiveObjectList::UpdateReferencesForScavengeGC(); |
1360 if (!FLAG_watch_ic_patching) { | 1364 if (!FLAG_watch_ic_patching) { |
1361 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); | 1365 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); |
1362 } | 1366 } |
1363 incremental_marking()->UpdateMarkingDequeAfterScavenge(); | 1367 incremental_marking()->UpdateMarkingDequeAfterScavenge(); |
1364 | 1368 |
1365 ScavengeWeakObjectRetainer weak_object_retainer(this); | 1369 ScavengeWeakObjectRetainer weak_object_retainer(this); |
1366 ProcessWeakReferences(&weak_object_retainer); | 1370 ProcessWeakReferences(&weak_object_retainer); |
(...skipping 4496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5863 } | 5867 } |
5864 | 5868 |
5865 | 5869 |
5866 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { | 5870 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { |
5867 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); | 5871 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); |
5868 v->Synchronize(VisitorSynchronization::kSymbolTable); | 5872 v->Synchronize(VisitorSynchronization::kSymbolTable); |
5869 if (mode != VISIT_ALL_IN_SCAVENGE && | 5873 if (mode != VISIT_ALL_IN_SCAVENGE && |
5870 mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { | 5874 mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { |
5871 // Scavenge collections have special processing for this. | 5875 // Scavenge collections have special processing for this. |
5872 external_string_table_.Iterate(v); | 5876 external_string_table_.Iterate(v); |
| 5877 error_object_list_.Iterate(v); |
5873 } | 5878 } |
5874 v->Synchronize(VisitorSynchronization::kExternalStringsTable); | 5879 v->Synchronize(VisitorSynchronization::kExternalStringsTable); |
5875 } | 5880 } |
5876 | 5881 |
5877 | 5882 |
5878 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { | 5883 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { |
5879 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); | 5884 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); |
5880 v->Synchronize(VisitorSynchronization::kStrongRootList); | 5885 v->Synchronize(VisitorSynchronization::kStrongRootList); |
5881 | 5886 |
5882 v->VisitPointer(BitCast<Object**>(&hidden_symbol_)); | 5887 v->VisitPointer(BitCast<Object**>(&hidden_symbol_)); |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6236 PrintF("min_in_mutator=%d ", get_min_in_mutator()); | 6241 PrintF("min_in_mutator=%d ", get_min_in_mutator()); |
6237 PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", | 6242 PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", |
6238 get_max_alive_after_gc()); | 6243 get_max_alive_after_gc()); |
6239 PrintF("\n\n"); | 6244 PrintF("\n\n"); |
6240 } | 6245 } |
6241 | 6246 |
6242 isolate_->global_handles()->TearDown(); | 6247 isolate_->global_handles()->TearDown(); |
6243 | 6248 |
6244 external_string_table_.TearDown(); | 6249 external_string_table_.TearDown(); |
6245 | 6250 |
| 6251 error_object_list_.TearDown(); |
| 6252 |
6246 new_space_.TearDown(); | 6253 new_space_.TearDown(); |
6247 | 6254 |
6248 if (old_pointer_space_ != NULL) { | 6255 if (old_pointer_space_ != NULL) { |
6249 old_pointer_space_->TearDown(); | 6256 old_pointer_space_->TearDown(); |
6250 delete old_pointer_space_; | 6257 delete old_pointer_space_; |
6251 old_pointer_space_ = NULL; | 6258 old_pointer_space_ = NULL; |
6252 } | 6259 } |
6253 | 6260 |
6254 if (old_data_space_ != NULL) { | 6261 if (old_data_space_ != NULL) { |
6255 old_data_space_->TearDown(); | 6262 old_data_space_->TearDown(); |
(...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7142 if (new_space_strings_[i] == heap_->the_hole_value()) { | 7149 if (new_space_strings_[i] == heap_->the_hole_value()) { |
7143 continue; | 7150 continue; |
7144 } | 7151 } |
7145 if (heap_->InNewSpace(new_space_strings_[i])) { | 7152 if (heap_->InNewSpace(new_space_strings_[i])) { |
7146 new_space_strings_[last++] = new_space_strings_[i]; | 7153 new_space_strings_[last++] = new_space_strings_[i]; |
7147 } else { | 7154 } else { |
7148 old_space_strings_.Add(new_space_strings_[i]); | 7155 old_space_strings_.Add(new_space_strings_[i]); |
7149 } | 7156 } |
7150 } | 7157 } |
7151 new_space_strings_.Rewind(last); | 7158 new_space_strings_.Rewind(last); |
| 7159 new_space_strings_.Trim(); |
| 7160 |
7152 last = 0; | 7161 last = 0; |
7153 for (int i = 0; i < old_space_strings_.length(); ++i) { | 7162 for (int i = 0; i < old_space_strings_.length(); ++i) { |
7154 if (old_space_strings_[i] == heap_->the_hole_value()) { | 7163 if (old_space_strings_[i] == heap_->the_hole_value()) { |
7155 continue; | 7164 continue; |
7156 } | 7165 } |
7157 ASSERT(!heap_->InNewSpace(old_space_strings_[i])); | 7166 ASSERT(!heap_->InNewSpace(old_space_strings_[i])); |
7158 old_space_strings_[last++] = old_space_strings_[i]; | 7167 old_space_strings_[last++] = old_space_strings_[i]; |
7159 } | 7168 } |
7160 old_space_strings_.Rewind(last); | 7169 old_space_strings_.Rewind(last); |
| 7170 old_space_strings_.Trim(); |
7161 #ifdef VERIFY_HEAP | 7171 #ifdef VERIFY_HEAP |
7162 if (FLAG_verify_heap) { | 7172 if (FLAG_verify_heap) { |
7163 Verify(); | 7173 Verify(); |
7164 } | 7174 } |
7165 #endif | 7175 #endif |
7166 } | 7176 } |
7167 | 7177 |
7168 | 7178 |
7169 void ExternalStringTable::TearDown() { | 7179 void ExternalStringTable::TearDown() { |
7170 new_space_strings_.Free(); | 7180 new_space_strings_.Free(); |
7171 old_space_strings_.Free(); | 7181 old_space_strings_.Free(); |
7172 } | 7182 } |
7173 | 7183 |
7174 | 7184 |
| 7185 // Update all references. |
| 7186 void ErrorObjectList::UpdateReferences() { |
| 7187 for (int i = 0; i < list_.length(); i++) { |
| 7188 HeapObject* object = HeapObject::cast(list_[i]); |
| 7189 MapWord first_word = object->map_word(); |
| 7190 if (first_word.IsForwardingAddress()) { |
| 7191 list_[i] = first_word.ToForwardingAddress(); |
| 7192 } |
| 7193 } |
| 7194 } |
| 7195 |
| 7196 |
| 7197 // Unforwarded objects in new space are dead and removed from the list. |
| 7198 void ErrorObjectList::UpdateReferencesInNewSpace(Heap* heap) { |
| 7199 if (!nested_) { |
| 7200 int write_index = 0; |
| 7201 for (int i = 0; i < list_.length(); i++) { |
| 7202 MapWord first_word = HeapObject::cast(list_[i])->map_word(); |
| 7203 if (first_word.IsForwardingAddress()) { |
| 7204 list_[write_index++] = first_word.ToForwardingAddress(); |
| 7205 } |
| 7206 } |
| 7207 list_.Rewind(write_index); |
| 7208 } else { |
| 7209 // If a GC is triggered during DeferredFormatStackTrace, we do not move |
| 7210 // objects in the list, just remove dead ones, as to not confuse the |
| 7211 // loop in DeferredFormatStackTrace. |
| 7212 for (int i = 0; i < list_.length(); i++) { |
| 7213 MapWord first_word = HeapObject::cast(list_[i])->map_word(); |
| 7214 list_[i] = first_word.IsForwardingAddress() |
| 7215 ? first_word.ToForwardingAddress() |
| 7216 : heap->the_hole_value(); |
| 7217 } |
| 7218 } |
| 7219 } |
| 7220 |
| 7221 |
| 7222 void ErrorObjectList::DeferredFormatStackTrace(Isolate* isolate) { |
| 7223 // If formatting the stack trace causes a GC, this method will be |
| 7224 // recursively called. In that case, skip the recursive call, since |
| 7225 // the loop modifies the list while iterating over it. |
| 7226 if (nested_) return; |
| 7227 nested_ = true; |
| 7228 HandleScope scope(isolate); |
| 7229 Handle<String> stack_key = isolate->factory()->stack_symbol(); |
| 7230 int write_index = 0; |
| 7231 int budget = kBudgetPerGC; |
| 7232 for (int i = 0; i < list_.length(); i++) { |
| 7233 Object* object = list_[i]; |
| 7234 // Skip possible holes in the list. |
| 7235 if (object->IsTheHole()) continue; |
| 7236 if (isolate->heap()->InNewSpace(object) || budget == 0) { |
| 7237 list_[write_index++] = object; |
| 7238 continue; |
| 7239 } |
| 7240 |
| 7241 // Fire the stack property getter, if it is the original marked getter. |
| 7242 LookupResult lookup(isolate); |
| 7243 JSObject::cast(object)->LocalLookupRealNamedProperty(*stack_key, &lookup); |
| 7244 if (!lookup.IsFound() || lookup.type() != CALLBACKS) continue; |
| 7245 Object* callback = lookup.GetCallbackObject(); |
| 7246 if (!callback->IsAccessorPair()) continue; |
| 7247 Object* getter_obj = AccessorPair::cast(callback)->getter(); |
| 7248 if (!getter_obj->IsJSFunction()) continue; |
| 7249 JSFunction* getter_fun = JSFunction::cast(getter_obj); |
| 7250 String* key = isolate->heap()->hidden_stack_trace_symbol(); |
| 7251 if (key != getter_fun->GetHiddenProperty(key)) continue; |
| 7252 bool has_exception = false; |
| 7253 Execution::Call(Handle<Object>(getter_fun, isolate), |
| 7254 Handle<Object>(object, isolate), |
| 7255 0, |
| 7256 NULL, |
| 7257 &has_exception); |
| 7258 ASSERT(!has_exception); |
| 7259 budget--; |
| 7260 } |
| 7261 list_.Rewind(write_index); |
| 7262 list_.Trim(); |
| 7263 nested_ = false; |
| 7264 } |
| 7265 |
| 7266 |
| 7267 void ErrorObjectList::RemoveUnmarked(Heap* heap) { |
| 7268 for (int i = 0; i < list_.length(); i++) { |
| 7269 HeapObject* object = HeapObject::cast(list_[i]); |
| 7270 if (!Marking::MarkBitFrom(object).Get()) { |
| 7271 list_[i] = heap->the_hole_value(); |
| 7272 } |
| 7273 } |
| 7274 } |
| 7275 |
| 7276 |
| 7277 void ErrorObjectList::TearDown() { |
| 7278 list_.Free(); |
| 7279 } |
| 7280 |
| 7281 |
7175 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { | 7282 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { |
7176 chunk->set_next_chunk(chunks_queued_for_free_); | 7283 chunk->set_next_chunk(chunks_queued_for_free_); |
7177 chunks_queued_for_free_ = chunk; | 7284 chunks_queued_for_free_ = chunk; |
7178 } | 7285 } |
7179 | 7286 |
7180 | 7287 |
7181 void Heap::FreeQueuedChunks() { | 7288 void Heap::FreeQueuedChunks() { |
7182 if (chunks_queued_for_free_ == NULL) return; | 7289 if (chunks_queued_for_free_ == NULL) return; |
7183 MemoryChunk* next; | 7290 MemoryChunk* next; |
7184 MemoryChunk* chunk; | 7291 MemoryChunk* chunk; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7293 static_cast<int>(object_sizes_last_time_[index])); | 7400 static_cast<int>(object_sizes_last_time_[index])); |
7294 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) | 7401 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) |
7295 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 7402 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
7296 | 7403 |
7297 memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 7404 memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
7298 memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 7405 memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
7299 ClearObjectStats(); | 7406 ClearObjectStats(); |
7300 } | 7407 } |
7301 | 7408 |
7302 } } // namespace v8::internal | 7409 } } // namespace v8::internal |
OLD | NEW |