| 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 |