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 807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1370 | 1372 |
1371 isolate_->global_handles()->IdentifyNewSpaceWeakIndependentHandles( | 1373 isolate_->global_handles()->IdentifyNewSpaceWeakIndependentHandles( |
1372 &IsUnscavengedHeapObject); | 1374 &IsUnscavengedHeapObject); |
1373 isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots( | 1375 isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots( |
1374 &scavenge_visitor); | 1376 &scavenge_visitor); |
1375 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); | 1377 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); |
1376 | 1378 |
1377 UpdateNewSpaceReferencesInExternalStringTable( | 1379 UpdateNewSpaceReferencesInExternalStringTable( |
1378 &UpdateNewSpaceReferenceInExternalStringTableEntry); | 1380 &UpdateNewSpaceReferenceInExternalStringTableEntry); |
1379 | 1381 |
| 1382 error_object_list_.UpdateReferencesInNewSpace(this); |
| 1383 |
1380 promotion_queue_.Destroy(); | 1384 promotion_queue_.Destroy(); |
1381 | 1385 |
1382 LiveObjectList::UpdateReferencesForScavengeGC(); | 1386 LiveObjectList::UpdateReferencesForScavengeGC(); |
1383 if (!FLAG_watch_ic_patching) { | 1387 if (!FLAG_watch_ic_patching) { |
1384 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); | 1388 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); |
1385 } | 1389 } |
1386 incremental_marking()->UpdateMarkingDequeAfterScavenge(); | 1390 incremental_marking()->UpdateMarkingDequeAfterScavenge(); |
1387 | 1391 |
1388 ScavengeWeakObjectRetainer weak_object_retainer(this); | 1392 ScavengeWeakObjectRetainer weak_object_retainer(this); |
1389 ProcessWeakReferences(&weak_object_retainer); | 1393 ProcessWeakReferences(&weak_object_retainer); |
(...skipping 4562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5952 } | 5956 } |
5953 | 5957 |
5954 | 5958 |
5955 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { | 5959 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { |
5956 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); | 5960 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); |
5957 v->Synchronize(VisitorSynchronization::kSymbolTable); | 5961 v->Synchronize(VisitorSynchronization::kSymbolTable); |
5958 if (mode != VISIT_ALL_IN_SCAVENGE && | 5962 if (mode != VISIT_ALL_IN_SCAVENGE && |
5959 mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { | 5963 mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { |
5960 // Scavenge collections have special processing for this. | 5964 // Scavenge collections have special processing for this. |
5961 external_string_table_.Iterate(v); | 5965 external_string_table_.Iterate(v); |
| 5966 error_object_list_.Iterate(v); |
5962 } | 5967 } |
5963 v->Synchronize(VisitorSynchronization::kExternalStringsTable); | 5968 v->Synchronize(VisitorSynchronization::kExternalStringsTable); |
5964 } | 5969 } |
5965 | 5970 |
5966 | 5971 |
5967 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { | 5972 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { |
5968 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); | 5973 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); |
5969 v->Synchronize(VisitorSynchronization::kStrongRootList); | 5974 v->Synchronize(VisitorSynchronization::kStrongRootList); |
5970 | 5975 |
5971 v->VisitPointer(BitCast<Object**>(&hidden_symbol_)); | 5976 v->VisitPointer(BitCast<Object**>(&hidden_symbol_)); |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6325 PrintF("min_in_mutator=%d ", get_min_in_mutator()); | 6330 PrintF("min_in_mutator=%d ", get_min_in_mutator()); |
6326 PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", | 6331 PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", |
6327 get_max_alive_after_gc()); | 6332 get_max_alive_after_gc()); |
6328 PrintF("\n\n"); | 6333 PrintF("\n\n"); |
6329 } | 6334 } |
6330 | 6335 |
6331 isolate_->global_handles()->TearDown(); | 6336 isolate_->global_handles()->TearDown(); |
6332 | 6337 |
6333 external_string_table_.TearDown(); | 6338 external_string_table_.TearDown(); |
6334 | 6339 |
| 6340 error_object_list_.TearDown(); |
| 6341 |
6335 new_space_.TearDown(); | 6342 new_space_.TearDown(); |
6336 | 6343 |
6337 if (old_pointer_space_ != NULL) { | 6344 if (old_pointer_space_ != NULL) { |
6338 old_pointer_space_->TearDown(); | 6345 old_pointer_space_->TearDown(); |
6339 delete old_pointer_space_; | 6346 delete old_pointer_space_; |
6340 old_pointer_space_ = NULL; | 6347 old_pointer_space_ = NULL; |
6341 } | 6348 } |
6342 | 6349 |
6343 if (old_data_space_ != NULL) { | 6350 if (old_data_space_ != NULL) { |
6344 old_data_space_->TearDown(); | 6351 old_data_space_->TearDown(); |
(...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7231 if (new_space_strings_[i] == heap_->the_hole_value()) { | 7238 if (new_space_strings_[i] == heap_->the_hole_value()) { |
7232 continue; | 7239 continue; |
7233 } | 7240 } |
7234 if (heap_->InNewSpace(new_space_strings_[i])) { | 7241 if (heap_->InNewSpace(new_space_strings_[i])) { |
7235 new_space_strings_[last++] = new_space_strings_[i]; | 7242 new_space_strings_[last++] = new_space_strings_[i]; |
7236 } else { | 7243 } else { |
7237 old_space_strings_.Add(new_space_strings_[i]); | 7244 old_space_strings_.Add(new_space_strings_[i]); |
7238 } | 7245 } |
7239 } | 7246 } |
7240 new_space_strings_.Rewind(last); | 7247 new_space_strings_.Rewind(last); |
| 7248 new_space_strings_.Trim(); |
| 7249 |
7241 last = 0; | 7250 last = 0; |
7242 for (int i = 0; i < old_space_strings_.length(); ++i) { | 7251 for (int i = 0; i < old_space_strings_.length(); ++i) { |
7243 if (old_space_strings_[i] == heap_->the_hole_value()) { | 7252 if (old_space_strings_[i] == heap_->the_hole_value()) { |
7244 continue; | 7253 continue; |
7245 } | 7254 } |
7246 ASSERT(!heap_->InNewSpace(old_space_strings_[i])); | 7255 ASSERT(!heap_->InNewSpace(old_space_strings_[i])); |
7247 old_space_strings_[last++] = old_space_strings_[i]; | 7256 old_space_strings_[last++] = old_space_strings_[i]; |
7248 } | 7257 } |
7249 old_space_strings_.Rewind(last); | 7258 old_space_strings_.Rewind(last); |
| 7259 old_space_strings_.Trim(); |
7250 #ifdef VERIFY_HEAP | 7260 #ifdef VERIFY_HEAP |
7251 if (FLAG_verify_heap) { | 7261 if (FLAG_verify_heap) { |
7252 Verify(); | 7262 Verify(); |
7253 } | 7263 } |
7254 #endif | 7264 #endif |
7255 } | 7265 } |
7256 | 7266 |
7257 | 7267 |
7258 void ExternalStringTable::TearDown() { | 7268 void ExternalStringTable::TearDown() { |
7259 new_space_strings_.Free(); | 7269 new_space_strings_.Free(); |
7260 old_space_strings_.Free(); | 7270 old_space_strings_.Free(); |
7261 } | 7271 } |
7262 | 7272 |
7263 | 7273 |
| 7274 // Update all references. |
| 7275 void ErrorObjectList::UpdateReferences() { |
| 7276 for (int i = 0; i < list_.length(); i++) { |
| 7277 HeapObject* object = HeapObject::cast(list_[i]); |
| 7278 MapWord first_word = object->map_word(); |
| 7279 if (first_word.IsForwardingAddress()) { |
| 7280 list_[i] = first_word.ToForwardingAddress(); |
| 7281 } |
| 7282 } |
| 7283 } |
| 7284 |
| 7285 |
| 7286 // Unforwarded objects in new space are dead and removed from the list. |
| 7287 void ErrorObjectList::UpdateReferencesInNewSpace(Heap* heap) { |
| 7288 if (!nested_) { |
| 7289 int write_index = 0; |
| 7290 for (int i = 0; i < list_.length(); i++) { |
| 7291 MapWord first_word = HeapObject::cast(list_[i])->map_word(); |
| 7292 if (first_word.IsForwardingAddress()) { |
| 7293 list_[write_index++] = first_word.ToForwardingAddress(); |
| 7294 } |
| 7295 } |
| 7296 list_.Rewind(write_index); |
| 7297 } else { |
| 7298 // If a GC is triggered during DeferredFormatStackTrace, we do not move |
| 7299 // objects in the list, just remove dead ones, as to not confuse the |
| 7300 // loop in DeferredFormatStackTrace. |
| 7301 for (int i = 0; i < list_.length(); i++) { |
| 7302 MapWord first_word = HeapObject::cast(list_[i])->map_word(); |
| 7303 list_[i] = first_word.IsForwardingAddress() |
| 7304 ? first_word.ToForwardingAddress() |
| 7305 : heap->the_hole_value(); |
| 7306 } |
| 7307 } |
| 7308 } |
| 7309 |
| 7310 |
| 7311 void ErrorObjectList::DeferredFormatStackTrace(Isolate* isolate) { |
| 7312 // If formatting the stack trace causes a GC, this method will be |
| 7313 // recursively called. In that case, skip the recursive call, since |
| 7314 // the loop modifies the list while iterating over it. |
| 7315 if (nested_ || isolate->has_pending_exception()) return; |
| 7316 nested_ = true; |
| 7317 HandleScope scope(isolate); |
| 7318 Handle<String> stack_key = isolate->factory()->stack_symbol(); |
| 7319 int write_index = 0; |
| 7320 int budget = kBudgetPerGC; |
| 7321 for (int i = 0; i < list_.length(); i++) { |
| 7322 Object* object = list_[i]; |
| 7323 JSFunction* getter_fun; |
| 7324 |
| 7325 { AssertNoAllocation assert; |
| 7326 // Skip possible holes in the list. |
| 7327 if (object->IsTheHole()) continue; |
| 7328 if (isolate->heap()->InNewSpace(object) || budget == 0) { |
| 7329 list_[write_index++] = object; |
| 7330 continue; |
| 7331 } |
| 7332 |
| 7333 // Check whether the stack property is backed by the original getter. |
| 7334 LookupResult lookup(isolate); |
| 7335 JSObject::cast(object)->LocalLookupRealNamedProperty(*stack_key, &lookup); |
| 7336 if (!lookup.IsFound() || lookup.type() != CALLBACKS) continue; |
| 7337 Object* callback = lookup.GetCallbackObject(); |
| 7338 if (!callback->IsAccessorPair()) continue; |
| 7339 Object* getter_obj = AccessorPair::cast(callback)->getter(); |
| 7340 if (!getter_obj->IsJSFunction()) continue; |
| 7341 getter_fun = JSFunction::cast(getter_obj); |
| 7342 String* key = isolate->heap()->hidden_stack_trace_symbol(); |
| 7343 if (key != getter_fun->GetHiddenProperty(key)) continue; |
| 7344 } |
| 7345 |
| 7346 budget--; |
| 7347 HandleScope scope(isolate); |
| 7348 bool has_exception = false; |
| 7349 Handle<Map> map(HeapObject::cast(object)->map(), isolate); |
| 7350 Handle<Object> object_handle(object, isolate); |
| 7351 Handle<Object> getter_handle(getter_fun, isolate); |
| 7352 Execution::Call(getter_handle, object_handle, 0, NULL, &has_exception); |
| 7353 CHECK(*map == HeapObject::cast(*object_handle)->map()); |
| 7354 if (has_exception) { |
| 7355 // Hit an exception (most likely a stack overflow). |
| 7356 // Wrap up this pass and retry after another GC. |
| 7357 isolate->clear_pending_exception(); |
| 7358 // We use the handle since calling the getter might have caused a GC. |
| 7359 list_[write_index++] = *object_handle; |
| 7360 budget = 0; |
| 7361 } |
| 7362 } |
| 7363 list_.Rewind(write_index); |
| 7364 list_.Trim(); |
| 7365 nested_ = false; |
| 7366 } |
| 7367 |
| 7368 |
| 7369 void ErrorObjectList::RemoveUnmarked(Heap* heap) { |
| 7370 for (int i = 0; i < list_.length(); i++) { |
| 7371 HeapObject* object = HeapObject::cast(list_[i]); |
| 7372 if (!Marking::MarkBitFrom(object).Get()) { |
| 7373 list_[i] = heap->the_hole_value(); |
| 7374 } |
| 7375 } |
| 7376 } |
| 7377 |
| 7378 |
| 7379 void ErrorObjectList::TearDown() { |
| 7380 list_.Free(); |
| 7381 } |
| 7382 |
| 7383 |
7264 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { | 7384 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { |
7265 chunk->set_next_chunk(chunks_queued_for_free_); | 7385 chunk->set_next_chunk(chunks_queued_for_free_); |
7266 chunks_queued_for_free_ = chunk; | 7386 chunks_queued_for_free_ = chunk; |
7267 } | 7387 } |
7268 | 7388 |
7269 | 7389 |
7270 void Heap::FreeQueuedChunks() { | 7390 void Heap::FreeQueuedChunks() { |
7271 if (chunks_queued_for_free_ == NULL) return; | 7391 if (chunks_queued_for_free_ == NULL) return; |
7272 MemoryChunk* next; | 7392 MemoryChunk* next; |
7273 MemoryChunk* chunk; | 7393 MemoryChunk* chunk; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7382 static_cast<int>(object_sizes_last_time_[index])); | 7502 static_cast<int>(object_sizes_last_time_[index])); |
7383 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) | 7503 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) |
7384 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 7504 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
7385 | 7505 |
7386 memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 7506 memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
7387 memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 7507 memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
7388 ClearObjectStats(); | 7508 ClearObjectStats(); |
7389 } | 7509 } |
7390 | 7510 |
7391 } } // namespace v8::internal | 7511 } } // namespace v8::internal |
OLD | NEW |