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 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1341 | 1343 |
1342 isolate_->global_handles()->IdentifyNewSpaceWeakIndependentHandles( | 1344 isolate_->global_handles()->IdentifyNewSpaceWeakIndependentHandles( |
1343 &IsUnscavengedHeapObject); | 1345 &IsUnscavengedHeapObject); |
1344 isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots( | 1346 isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots( |
1345 &scavenge_visitor); | 1347 &scavenge_visitor); |
1346 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); | 1348 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); |
1347 | 1349 |
1348 UpdateNewSpaceReferencesInExternalStringTable( | 1350 UpdateNewSpaceReferencesInExternalStringTable( |
1349 &UpdateNewSpaceReferenceInExternalStringTableEntry); | 1351 &UpdateNewSpaceReferenceInExternalStringTableEntry); |
1350 | 1352 |
1353 error_object_list_.UpdateReferencesInNewSpace(this); | |
1354 | |
1351 promotion_queue_.Destroy(); | 1355 promotion_queue_.Destroy(); |
1352 | 1356 |
1353 LiveObjectList::UpdateReferencesForScavengeGC(); | 1357 LiveObjectList::UpdateReferencesForScavengeGC(); |
1354 if (!FLAG_watch_ic_patching) { | 1358 if (!FLAG_watch_ic_patching) { |
1355 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); | 1359 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); |
1356 } | 1360 } |
1357 incremental_marking()->UpdateMarkingDequeAfterScavenge(); | 1361 incremental_marking()->UpdateMarkingDequeAfterScavenge(); |
1358 | 1362 |
1359 ScavengeWeakObjectRetainer weak_object_retainer(this); | 1363 ScavengeWeakObjectRetainer weak_object_retainer(this); |
1360 ProcessWeakReferences(&weak_object_retainer); | 1364 ProcessWeakReferences(&weak_object_retainer); |
(...skipping 4545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5906 } | 5910 } |
5907 | 5911 |
5908 | 5912 |
5909 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { | 5913 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { |
5910 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); | 5914 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); |
5911 v->Synchronize(VisitorSynchronization::kSymbolTable); | 5915 v->Synchronize(VisitorSynchronization::kSymbolTable); |
5912 if (mode != VISIT_ALL_IN_SCAVENGE && | 5916 if (mode != VISIT_ALL_IN_SCAVENGE && |
5913 mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { | 5917 mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { |
5914 // Scavenge collections have special processing for this. | 5918 // Scavenge collections have special processing for this. |
5915 external_string_table_.Iterate(v); | 5919 external_string_table_.Iterate(v); |
5920 error_object_list_.Iterate(v); | |
5916 } | 5921 } |
5917 v->Synchronize(VisitorSynchronization::kExternalStringsTable); | 5922 v->Synchronize(VisitorSynchronization::kExternalStringsTable); |
5918 } | 5923 } |
5919 | 5924 |
5920 | 5925 |
5921 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { | 5926 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { |
5922 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); | 5927 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); |
5923 v->Synchronize(VisitorSynchronization::kStrongRootList); | 5928 v->Synchronize(VisitorSynchronization::kStrongRootList); |
5924 | 5929 |
5925 v->VisitPointer(BitCast<Object**>(&hidden_symbol_)); | 5930 v->VisitPointer(BitCast<Object**>(&hidden_symbol_)); |
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6446 PrintF("min_in_mutator=%d ", get_min_in_mutator()); | 6451 PrintF("min_in_mutator=%d ", get_min_in_mutator()); |
6447 PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", | 6452 PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", |
6448 get_max_alive_after_gc()); | 6453 get_max_alive_after_gc()); |
6449 PrintF("\n\n"); | 6454 PrintF("\n\n"); |
6450 } | 6455 } |
6451 | 6456 |
6452 isolate_->global_handles()->TearDown(); | 6457 isolate_->global_handles()->TearDown(); |
6453 | 6458 |
6454 external_string_table_.TearDown(); | 6459 external_string_table_.TearDown(); |
6455 | 6460 |
6461 error_object_list_.TearDown(); | |
6462 | |
6456 new_space_.TearDown(); | 6463 new_space_.TearDown(); |
6457 | 6464 |
6458 if (old_pointer_space_ != NULL) { | 6465 if (old_pointer_space_ != NULL) { |
6459 old_pointer_space_->TearDown(); | 6466 old_pointer_space_->TearDown(); |
6460 delete old_pointer_space_; | 6467 delete old_pointer_space_; |
6461 old_pointer_space_ = NULL; | 6468 old_pointer_space_ = NULL; |
6462 } | 6469 } |
6463 | 6470 |
6464 if (old_data_space_ != NULL) { | 6471 if (old_data_space_ != NULL) { |
6465 old_data_space_->TearDown(); | 6472 old_data_space_->TearDown(); |
(...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7351 if (new_space_strings_[i] == heap_->the_hole_value()) { | 7358 if (new_space_strings_[i] == heap_->the_hole_value()) { |
7352 continue; | 7359 continue; |
7353 } | 7360 } |
7354 if (heap_->InNewSpace(new_space_strings_[i])) { | 7361 if (heap_->InNewSpace(new_space_strings_[i])) { |
7355 new_space_strings_[last++] = new_space_strings_[i]; | 7362 new_space_strings_[last++] = new_space_strings_[i]; |
7356 } else { | 7363 } else { |
7357 old_space_strings_.Add(new_space_strings_[i]); | 7364 old_space_strings_.Add(new_space_strings_[i]); |
7358 } | 7365 } |
7359 } | 7366 } |
7360 new_space_strings_.Rewind(last); | 7367 new_space_strings_.Rewind(last); |
7368 new_space_strings_.Trim(); | |
7369 | |
7361 last = 0; | 7370 last = 0; |
7362 for (int i = 0; i < old_space_strings_.length(); ++i) { | 7371 for (int i = 0; i < old_space_strings_.length(); ++i) { |
7363 if (old_space_strings_[i] == heap_->the_hole_value()) { | 7372 if (old_space_strings_[i] == heap_->the_hole_value()) { |
7364 continue; | 7373 continue; |
7365 } | 7374 } |
7366 ASSERT(!heap_->InNewSpace(old_space_strings_[i])); | 7375 ASSERT(!heap_->InNewSpace(old_space_strings_[i])); |
7367 old_space_strings_[last++] = old_space_strings_[i]; | 7376 old_space_strings_[last++] = old_space_strings_[i]; |
7368 } | 7377 } |
7369 old_space_strings_.Rewind(last); | 7378 old_space_strings_.Rewind(last); |
7379 old_space_strings_.Trim(); | |
7370 #ifdef VERIFY_HEAP | 7380 #ifdef VERIFY_HEAP |
7371 if (FLAG_verify_heap) { | 7381 if (FLAG_verify_heap) { |
7372 Verify(); | 7382 Verify(); |
7373 } | 7383 } |
7374 #endif | 7384 #endif |
7375 } | 7385 } |
7376 | 7386 |
7377 | 7387 |
7378 void ExternalStringTable::TearDown() { | 7388 void ExternalStringTable::TearDown() { |
7379 new_space_strings_.Free(); | 7389 new_space_strings_.Free(); |
7380 old_space_strings_.Free(); | 7390 old_space_strings_.Free(); |
7381 } | 7391 } |
7382 | 7392 |
7383 | 7393 |
7394 // Update all references. | |
7395 void ErrorObjectList::UpdateReferences() { | |
7396 for (int i = 0; i < list_.length(); i++) { | |
7397 HeapObject* object = HeapObject::cast(list_[i]); | |
7398 MapWord first_word = object->map_word(); | |
7399 if (first_word.IsForwardingAddress()) { | |
7400 list_[i] = first_word.ToForwardingAddress(); | |
7401 } | |
7402 } | |
7403 } | |
7404 | |
7405 | |
7406 // Unforwarded objects in new space are dead and removed from the list. | |
7407 void ErrorObjectList::UpdateReferencesInNewSpace(Heap* heap) { | |
7408 if (!nested_) { | |
7409 int write_index = 0; | |
7410 for (int i = 0; i < list_.length(); i++) { | |
7411 MapWord first_word = HeapObject::cast(list_[i])->map_word(); | |
7412 if (first_word.IsForwardingAddress()) { | |
7413 list_[write_index++] = first_word.ToForwardingAddress(); | |
7414 } | |
7415 } | |
7416 list_.Rewind(write_index); | |
7417 } else { | |
7418 // If a GC is triggered during DeferredFormatStackTrace, we do not move | |
7419 // objects in the list, just remove dead ones, as to not confuse the | |
7420 // loop in DeferredFormatStackTrace. | |
7421 for (int i = 0; i < list_.length(); i++) { | |
7422 MapWord first_word = HeapObject::cast(list_[i])->map_word(); | |
7423 list_[i] = first_word.IsForwardingAddress() | |
7424 ? first_word.ToForwardingAddress() | |
7425 : heap->the_hole_value(); | |
7426 } | |
7427 } | |
7428 } | |
7429 | |
7430 | |
7431 void ErrorObjectList::DeferredFormatStackTrace(Isolate* isolate) { | |
7432 // If formatting the stack trace causes a GC, this method will be | |
7433 // recursively called. In that case, skip the recursive call, since | |
7434 // the loop modifies the list while iterating over it. | |
7435 if (nested_) return; | |
7436 nested_ = true; | |
7437 HandleScope scope(isolate); | |
7438 Handle<String> stack_key = isolate->factory()->stack_symbol(); | |
7439 int write_index = 0; | |
7440 int budget = kBudgetPerGC; | |
7441 for (int i = 0; i < list_.length(); i++) { | |
7442 Object* object = list_[i]; | |
7443 // Skip possible holes in the list. | |
7444 if (object->IsTheHole()) continue; | |
7445 if (isolate->heap()->InNewSpace(object) || budget == 0) { | |
7446 list_[write_index++] = object; | |
7447 continue; | |
7448 } | |
7449 | |
7450 // Fire the stack property getter, if it is a getter defined in native code. | |
7451 LookupResult lookup(isolate); | |
7452 JSObject::cast(object)->LocalLookupRealNamedProperty(*stack_key, &lookup); | |
7453 if (!lookup.IsFound() || lookup.type() != CALLBACKS) continue; | |
7454 Object* callback = lookup.GetCallbackObject(); | |
7455 if (!callback->IsAccessorPair()) continue; | |
7456 Object* getter_obj = AccessorPair::cast(callback)->getter(); | |
7457 if (!getter_obj->IsJSFunction()) continue; | |
7458 JSFunction* getter_fun = JSFunction::cast(getter_obj); | |
7459 if (!getter_fun->shared()->native()) continue; | |
Vyacheslav Egorov (Google)
2012/11/20 17:30:42
I don't think this can guard you well enough. Here
| |
7460 bool has_exception = false; | |
7461 Execution::Call(Handle<Object>(getter_fun, isolate), | |
7462 Handle<Object>(object, isolate), | |
7463 0, | |
7464 NULL, | |
7465 &has_exception); | |
7466 ASSERT(!has_exception); | |
7467 budget--; | |
7468 } | |
7469 list_.Rewind(write_index); | |
7470 list_.Trim(); | |
7471 nested_ = false; | |
7472 } | |
7473 | |
7474 | |
7475 void ErrorObjectList::RemoveUnmarked(Heap* heap) { | |
7476 for (int i = 0; i < list_.length(); i++) { | |
7477 HeapObject* object = HeapObject::cast(list_[i]); | |
7478 if (!Marking::MarkBitFrom(object).Get()) { | |
7479 list_[i] = heap->the_hole_value(); | |
7480 } | |
7481 } | |
7482 } | |
7483 | |
7484 | |
7485 void ErrorObjectList::TearDown() { | |
7486 list_.Free(); | |
7487 } | |
7488 | |
7489 | |
7384 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { | 7490 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { |
7385 chunk->set_next_chunk(chunks_queued_for_free_); | 7491 chunk->set_next_chunk(chunks_queued_for_free_); |
7386 chunks_queued_for_free_ = chunk; | 7492 chunks_queued_for_free_ = chunk; |
7387 } | 7493 } |
7388 | 7494 |
7389 | 7495 |
7390 void Heap::FreeQueuedChunks() { | 7496 void Heap::FreeQueuedChunks() { |
7391 if (chunks_queued_for_free_ == NULL) return; | 7497 if (chunks_queued_for_free_ == NULL) return; |
7392 MemoryChunk* next; | 7498 MemoryChunk* next; |
7393 MemoryChunk* chunk; | 7499 MemoryChunk* chunk; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7502 static_cast<int>(object_sizes_last_time_[index])); | 7608 static_cast<int>(object_sizes_last_time_[index])); |
7503 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) | 7609 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) |
7504 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 7610 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
7505 | 7611 |
7506 memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 7612 memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
7507 memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 7613 memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
7508 ClearObjectStats(); | 7614 ClearObjectStats(); |
7509 } | 7615 } |
7510 | 7616 |
7511 } } // namespace v8::internal | 7617 } } // namespace v8::internal |
OLD | NEW |