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()); | |
555 } | 553 } |
556 | 554 |
557 | 555 |
558 void Heap::CollectAllGarbage(int flags, const char* gc_reason) { | 556 void Heap::CollectAllGarbage(int flags, const char* gc_reason) { |
559 // Since we are ignoring the return value, the exact choice of space does | 557 // Since we are ignoring the return value, the exact choice of space does |
560 // not matter, so long as we do not specify NEW_SPACE, which would not | 558 // not matter, so long as we do not specify NEW_SPACE, which would not |
561 // cause a full GC. | 559 // cause a full GC. |
562 mark_compact_collector_.SetFlags(flags); | 560 mark_compact_collector_.SetFlags(flags); |
563 CollectGarbage(OLD_POINTER_SPACE, gc_reason); | 561 CollectGarbage(OLD_POINTER_SPACE, gc_reason); |
564 mark_compact_collector_.SetFlags(kNoGCFlags); | 562 mark_compact_collector_.SetFlags(kNoGCFlags); |
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1349 | 1347 |
1350 isolate_->global_handles()->IdentifyNewSpaceWeakIndependentHandles( | 1348 isolate_->global_handles()->IdentifyNewSpaceWeakIndependentHandles( |
1351 &IsUnscavengedHeapObject); | 1349 &IsUnscavengedHeapObject); |
1352 isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots( | 1350 isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots( |
1353 &scavenge_visitor); | 1351 &scavenge_visitor); |
1354 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); | 1352 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); |
1355 | 1353 |
1356 UpdateNewSpaceReferencesInExternalStringTable( | 1354 UpdateNewSpaceReferencesInExternalStringTable( |
1357 &UpdateNewSpaceReferenceInExternalStringTableEntry); | 1355 &UpdateNewSpaceReferenceInExternalStringTableEntry); |
1358 | 1356 |
1359 error_object_list_.UpdateReferencesInNewSpace(this); | |
1360 | |
1361 promotion_queue_.Destroy(); | 1357 promotion_queue_.Destroy(); |
1362 | 1358 |
1363 LiveObjectList::UpdateReferencesForScavengeGC(); | 1359 LiveObjectList::UpdateReferencesForScavengeGC(); |
1364 if (!FLAG_watch_ic_patching) { | 1360 if (!FLAG_watch_ic_patching) { |
1365 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); | 1361 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); |
1366 } | 1362 } |
1367 incremental_marking()->UpdateMarkingDequeAfterScavenge(); | 1363 incremental_marking()->UpdateMarkingDequeAfterScavenge(); |
1368 | 1364 |
1369 ScavengeWeakObjectRetainer weak_object_retainer(this); | 1365 ScavengeWeakObjectRetainer weak_object_retainer(this); |
1370 ProcessWeakReferences(&weak_object_retainer); | 1366 ProcessWeakReferences(&weak_object_retainer); |
(...skipping 4559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5930 } | 5926 } |
5931 | 5927 |
5932 | 5928 |
5933 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { | 5929 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { |
5934 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); | 5930 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); |
5935 v->Synchronize(VisitorSynchronization::kSymbolTable); | 5931 v->Synchronize(VisitorSynchronization::kSymbolTable); |
5936 if (mode != VISIT_ALL_IN_SCAVENGE && | 5932 if (mode != VISIT_ALL_IN_SCAVENGE && |
5937 mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { | 5933 mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { |
5938 // Scavenge collections have special processing for this. | 5934 // Scavenge collections have special processing for this. |
5939 external_string_table_.Iterate(v); | 5935 external_string_table_.Iterate(v); |
5940 error_object_list_.Iterate(v); | |
5941 } | 5936 } |
5942 v->Synchronize(VisitorSynchronization::kExternalStringsTable); | 5937 v->Synchronize(VisitorSynchronization::kExternalStringsTable); |
5943 } | 5938 } |
5944 | 5939 |
5945 | 5940 |
5946 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { | 5941 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { |
5947 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); | 5942 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); |
5948 v->Synchronize(VisitorSynchronization::kStrongRootList); | 5943 v->Synchronize(VisitorSynchronization::kStrongRootList); |
5949 | 5944 |
5950 v->VisitPointer(BitCast<Object**>(&hidden_symbol_)); | 5945 v->VisitPointer(BitCast<Object**>(&hidden_symbol_)); |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6304 PrintF("min_in_mutator=%d ", get_min_in_mutator()); | 6299 PrintF("min_in_mutator=%d ", get_min_in_mutator()); |
6305 PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", | 6300 PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", |
6306 get_max_alive_after_gc()); | 6301 get_max_alive_after_gc()); |
6307 PrintF("\n\n"); | 6302 PrintF("\n\n"); |
6308 } | 6303 } |
6309 | 6304 |
6310 isolate_->global_handles()->TearDown(); | 6305 isolate_->global_handles()->TearDown(); |
6311 | 6306 |
6312 external_string_table_.TearDown(); | 6307 external_string_table_.TearDown(); |
6313 | 6308 |
6314 error_object_list_.TearDown(); | |
6315 | |
6316 new_space_.TearDown(); | 6309 new_space_.TearDown(); |
6317 | 6310 |
6318 if (old_pointer_space_ != NULL) { | 6311 if (old_pointer_space_ != NULL) { |
6319 old_pointer_space_->TearDown(); | 6312 old_pointer_space_->TearDown(); |
6320 delete old_pointer_space_; | 6313 delete old_pointer_space_; |
6321 old_pointer_space_ = NULL; | 6314 old_pointer_space_ = NULL; |
6322 } | 6315 } |
6323 | 6316 |
6324 if (old_data_space_ != NULL) { | 6317 if (old_data_space_ != NULL) { |
6325 old_data_space_->TearDown(); | 6318 old_data_space_->TearDown(); |
(...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7212 if (new_space_strings_[i] == heap_->the_hole_value()) { | 7205 if (new_space_strings_[i] == heap_->the_hole_value()) { |
7213 continue; | 7206 continue; |
7214 } | 7207 } |
7215 if (heap_->InNewSpace(new_space_strings_[i])) { | 7208 if (heap_->InNewSpace(new_space_strings_[i])) { |
7216 new_space_strings_[last++] = new_space_strings_[i]; | 7209 new_space_strings_[last++] = new_space_strings_[i]; |
7217 } else { | 7210 } else { |
7218 old_space_strings_.Add(new_space_strings_[i]); | 7211 old_space_strings_.Add(new_space_strings_[i]); |
7219 } | 7212 } |
7220 } | 7213 } |
7221 new_space_strings_.Rewind(last); | 7214 new_space_strings_.Rewind(last); |
7222 new_space_strings_.Trim(); | |
7223 | |
7224 last = 0; | 7215 last = 0; |
7225 for (int i = 0; i < old_space_strings_.length(); ++i) { | 7216 for (int i = 0; i < old_space_strings_.length(); ++i) { |
7226 if (old_space_strings_[i] == heap_->the_hole_value()) { | 7217 if (old_space_strings_[i] == heap_->the_hole_value()) { |
7227 continue; | 7218 continue; |
7228 } | 7219 } |
7229 ASSERT(!heap_->InNewSpace(old_space_strings_[i])); | 7220 ASSERT(!heap_->InNewSpace(old_space_strings_[i])); |
7230 old_space_strings_[last++] = old_space_strings_[i]; | 7221 old_space_strings_[last++] = old_space_strings_[i]; |
7231 } | 7222 } |
7232 old_space_strings_.Rewind(last); | 7223 old_space_strings_.Rewind(last); |
7233 old_space_strings_.Trim(); | |
7234 #ifdef VERIFY_HEAP | 7224 #ifdef VERIFY_HEAP |
7235 if (FLAG_verify_heap) { | 7225 if (FLAG_verify_heap) { |
7236 Verify(); | 7226 Verify(); |
7237 } | 7227 } |
7238 #endif | 7228 #endif |
7239 } | 7229 } |
7240 | 7230 |
7241 | 7231 |
7242 void ExternalStringTable::TearDown() { | 7232 void ExternalStringTable::TearDown() { |
7243 new_space_strings_.Free(); | 7233 new_space_strings_.Free(); |
7244 old_space_strings_.Free(); | 7234 old_space_strings_.Free(); |
7245 } | 7235 } |
7246 | 7236 |
7247 | 7237 |
7248 // Update all references. | |
7249 void ErrorObjectList::UpdateReferences() { | |
7250 for (int i = 0; i < list_.length(); i++) { | |
7251 HeapObject* object = HeapObject::cast(list_[i]); | |
7252 MapWord first_word = object->map_word(); | |
7253 if (first_word.IsForwardingAddress()) { | |
7254 list_[i] = first_word.ToForwardingAddress(); | |
7255 } | |
7256 } | |
7257 } | |
7258 | |
7259 | |
7260 // Unforwarded objects in new space are dead and removed from the list. | |
7261 void ErrorObjectList::UpdateReferencesInNewSpace(Heap* heap) { | |
7262 if (!nested_) { | |
7263 int write_index = 0; | |
7264 for (int i = 0; i < list_.length(); i++) { | |
7265 MapWord first_word = HeapObject::cast(list_[i])->map_word(); | |
7266 if (first_word.IsForwardingAddress()) { | |
7267 list_[write_index++] = first_word.ToForwardingAddress(); | |
7268 } | |
7269 } | |
7270 list_.Rewind(write_index); | |
7271 } else { | |
7272 // If a GC is triggered during DeferredFormatStackTrace, we do not move | |
7273 // objects in the list, just remove dead ones, as to not confuse the | |
7274 // loop in DeferredFormatStackTrace. | |
7275 for (int i = 0; i < list_.length(); i++) { | |
7276 MapWord first_word = HeapObject::cast(list_[i])->map_word(); | |
7277 list_[i] = first_word.IsForwardingAddress() | |
7278 ? first_word.ToForwardingAddress() | |
7279 : heap->the_hole_value(); | |
7280 } | |
7281 } | |
7282 } | |
7283 | |
7284 | |
7285 void ErrorObjectList::DeferredFormatStackTrace(Isolate* isolate) { | |
7286 // If formatting the stack trace causes a GC, this method will be | |
7287 // recursively called. In that case, skip the recursive call, since | |
7288 // the loop modifies the list while iterating over it. | |
7289 if (nested_ || isolate->has_pending_exception()) return; | |
7290 nested_ = true; | |
7291 HandleScope scope(isolate); | |
7292 Handle<String> stack_key = isolate->factory()->stack_symbol(); | |
7293 int write_index = 0; | |
7294 int budget = kBudgetPerGC; | |
7295 for (int i = 0; i < list_.length(); i++) { | |
7296 Object* object = list_[i]; | |
7297 JSFunction* getter_fun; | |
7298 | |
7299 { AssertNoAllocation assert; | |
7300 // Skip possible holes in the list. | |
7301 if (object->IsTheHole()) continue; | |
7302 if (isolate->heap()->InNewSpace(object) || budget == 0) { | |
7303 list_[write_index++] = object; | |
7304 continue; | |
7305 } | |
7306 | |
7307 // Check whether the stack property is backed by the original getter. | |
7308 LookupResult lookup(isolate); | |
7309 JSObject::cast(object)->LocalLookupRealNamedProperty(*stack_key, &lookup); | |
7310 if (!lookup.IsFound() || lookup.type() != CALLBACKS) continue; | |
7311 Object* callback = lookup.GetCallbackObject(); | |
7312 if (!callback->IsAccessorPair()) continue; | |
7313 Object* getter_obj = AccessorPair::cast(callback)->getter(); | |
7314 if (!getter_obj->IsJSFunction()) continue; | |
7315 getter_fun = JSFunction::cast(getter_obj); | |
7316 String* key = isolate->heap()->hidden_stack_trace_symbol(); | |
7317 if (key != getter_fun->GetHiddenProperty(key)) continue; | |
7318 } | |
7319 | |
7320 budget--; | |
7321 HandleScope scope(isolate); | |
7322 bool has_exception = false; | |
7323 Handle<Object> object_handle(object, isolate); | |
7324 Handle<Object> getter_handle(getter_fun, isolate); | |
7325 Execution::Call(getter_handle, object_handle, 0, NULL, &has_exception); | |
7326 if (has_exception) { | |
7327 // Hit an exception (most likely a stack overflow). | |
7328 // Wrap up this pass and retry after another GC. | |
7329 isolate->clear_pending_exception(); | |
7330 // We use the handle since calling the getter might have caused a GC. | |
7331 list_[write_index++] = *object_handle; | |
7332 budget = 0; | |
7333 } | |
7334 } | |
7335 list_.Rewind(write_index); | |
7336 list_.Trim(); | |
7337 nested_ = false; | |
7338 } | |
7339 | |
7340 | |
7341 void ErrorObjectList::RemoveUnmarked(Heap* heap) { | |
7342 for (int i = 0; i < list_.length(); i++) { | |
7343 HeapObject* object = HeapObject::cast(list_[i]); | |
7344 if (!Marking::MarkBitFrom(object).Get()) { | |
7345 list_[i] = heap->the_hole_value(); | |
7346 } | |
7347 } | |
7348 } | |
7349 | |
7350 | |
7351 void ErrorObjectList::TearDown() { | |
7352 list_.Free(); | |
7353 } | |
7354 | |
7355 | |
7356 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { | 7238 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { |
7357 chunk->set_next_chunk(chunks_queued_for_free_); | 7239 chunk->set_next_chunk(chunks_queued_for_free_); |
7358 chunks_queued_for_free_ = chunk; | 7240 chunks_queued_for_free_ = chunk; |
7359 } | 7241 } |
7360 | 7242 |
7361 | 7243 |
7362 void Heap::FreeQueuedChunks() { | 7244 void Heap::FreeQueuedChunks() { |
7363 if (chunks_queued_for_free_ == NULL) return; | 7245 if (chunks_queued_for_free_ == NULL) return; |
7364 MemoryChunk* next; | 7246 MemoryChunk* next; |
7365 MemoryChunk* chunk; | 7247 MemoryChunk* chunk; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7474 static_cast<int>(object_sizes_last_time_[index])); | 7356 static_cast<int>(object_sizes_last_time_[index])); |
7475 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) | 7357 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) |
7476 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 7358 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
7477 | 7359 |
7478 memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 7360 memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
7479 memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 7361 memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
7480 ClearObjectStats(); | 7362 ClearObjectStats(); |
7481 } | 7363 } |
7482 | 7364 |
7483 } } // namespace v8::internal | 7365 } } // namespace v8::internal |
OLD | NEW |