Chromium Code Reviews| 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 |