| 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 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1347 | 1349 |
| 1348 isolate_->global_handles()->IdentifyNewSpaceWeakIndependentHandles( | 1350 isolate_->global_handles()->IdentifyNewSpaceWeakIndependentHandles( |
| 1349 &IsUnscavengedHeapObject); | 1351 &IsUnscavengedHeapObject); |
| 1350 isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots( | 1352 isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots( |
| 1351 &scavenge_visitor); | 1353 &scavenge_visitor); |
| 1352 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); | 1354 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); |
| 1353 | 1355 |
| 1354 UpdateNewSpaceReferencesInExternalStringTable( | 1356 UpdateNewSpaceReferencesInExternalStringTable( |
| 1355 &UpdateNewSpaceReferenceInExternalStringTableEntry); | 1357 &UpdateNewSpaceReferenceInExternalStringTableEntry); |
| 1356 | 1358 |
| 1359 error_object_list_.UpdateReferencesInNewSpace(this); |
| 1360 |
| 1357 promotion_queue_.Destroy(); | 1361 promotion_queue_.Destroy(); |
| 1358 | 1362 |
| 1359 LiveObjectList::UpdateReferencesForScavengeGC(); | 1363 LiveObjectList::UpdateReferencesForScavengeGC(); |
| 1360 if (!FLAG_watch_ic_patching) { | 1364 if (!FLAG_watch_ic_patching) { |
| 1361 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); | 1365 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); |
| 1362 } | 1366 } |
| 1363 incremental_marking()->UpdateMarkingDequeAfterScavenge(); | 1367 incremental_marking()->UpdateMarkingDequeAfterScavenge(); |
| 1364 | 1368 |
| 1365 ScavengeWeakObjectRetainer weak_object_retainer(this); | 1369 ScavengeWeakObjectRetainer weak_object_retainer(this); |
| 1366 ProcessWeakReferences(&weak_object_retainer); | 1370 ProcessWeakReferences(&weak_object_retainer); |
| (...skipping 4496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5863 } | 5867 } |
| 5864 | 5868 |
| 5865 | 5869 |
| 5866 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { | 5870 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { |
| 5867 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); | 5871 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); |
| 5868 v->Synchronize(VisitorSynchronization::kSymbolTable); | 5872 v->Synchronize(VisitorSynchronization::kSymbolTable); |
| 5869 if (mode != VISIT_ALL_IN_SCAVENGE && | 5873 if (mode != VISIT_ALL_IN_SCAVENGE && |
| 5870 mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { | 5874 mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { |
| 5871 // Scavenge collections have special processing for this. | 5875 // Scavenge collections have special processing for this. |
| 5872 external_string_table_.Iterate(v); | 5876 external_string_table_.Iterate(v); |
| 5877 error_object_list_.Iterate(v); |
| 5873 } | 5878 } |
| 5874 v->Synchronize(VisitorSynchronization::kExternalStringsTable); | 5879 v->Synchronize(VisitorSynchronization::kExternalStringsTable); |
| 5875 } | 5880 } |
| 5876 | 5881 |
| 5877 | 5882 |
| 5878 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { | 5883 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { |
| 5879 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); | 5884 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); |
| 5880 v->Synchronize(VisitorSynchronization::kStrongRootList); | 5885 v->Synchronize(VisitorSynchronization::kStrongRootList); |
| 5881 | 5886 |
| 5882 v->VisitPointer(BitCast<Object**>(&hidden_symbol_)); | 5887 v->VisitPointer(BitCast<Object**>(&hidden_symbol_)); |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6236 PrintF("min_in_mutator=%d ", get_min_in_mutator()); | 6241 PrintF("min_in_mutator=%d ", get_min_in_mutator()); |
| 6237 PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", | 6242 PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", |
| 6238 get_max_alive_after_gc()); | 6243 get_max_alive_after_gc()); |
| 6239 PrintF("\n\n"); | 6244 PrintF("\n\n"); |
| 6240 } | 6245 } |
| 6241 | 6246 |
| 6242 isolate_->global_handles()->TearDown(); | 6247 isolate_->global_handles()->TearDown(); |
| 6243 | 6248 |
| 6244 external_string_table_.TearDown(); | 6249 external_string_table_.TearDown(); |
| 6245 | 6250 |
| 6251 error_object_list_.TearDown(); |
| 6252 |
| 6246 new_space_.TearDown(); | 6253 new_space_.TearDown(); |
| 6247 | 6254 |
| 6248 if (old_pointer_space_ != NULL) { | 6255 if (old_pointer_space_ != NULL) { |
| 6249 old_pointer_space_->TearDown(); | 6256 old_pointer_space_->TearDown(); |
| 6250 delete old_pointer_space_; | 6257 delete old_pointer_space_; |
| 6251 old_pointer_space_ = NULL; | 6258 old_pointer_space_ = NULL; |
| 6252 } | 6259 } |
| 6253 | 6260 |
| 6254 if (old_data_space_ != NULL) { | 6261 if (old_data_space_ != NULL) { |
| 6255 old_data_space_->TearDown(); | 6262 old_data_space_->TearDown(); |
| (...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7142 if (new_space_strings_[i] == heap_->the_hole_value()) { | 7149 if (new_space_strings_[i] == heap_->the_hole_value()) { |
| 7143 continue; | 7150 continue; |
| 7144 } | 7151 } |
| 7145 if (heap_->InNewSpace(new_space_strings_[i])) { | 7152 if (heap_->InNewSpace(new_space_strings_[i])) { |
| 7146 new_space_strings_[last++] = new_space_strings_[i]; | 7153 new_space_strings_[last++] = new_space_strings_[i]; |
| 7147 } else { | 7154 } else { |
| 7148 old_space_strings_.Add(new_space_strings_[i]); | 7155 old_space_strings_.Add(new_space_strings_[i]); |
| 7149 } | 7156 } |
| 7150 } | 7157 } |
| 7151 new_space_strings_.Rewind(last); | 7158 new_space_strings_.Rewind(last); |
| 7159 new_space_strings_.Trim(); |
| 7160 |
| 7152 last = 0; | 7161 last = 0; |
| 7153 for (int i = 0; i < old_space_strings_.length(); ++i) { | 7162 for (int i = 0; i < old_space_strings_.length(); ++i) { |
| 7154 if (old_space_strings_[i] == heap_->the_hole_value()) { | 7163 if (old_space_strings_[i] == heap_->the_hole_value()) { |
| 7155 continue; | 7164 continue; |
| 7156 } | 7165 } |
| 7157 ASSERT(!heap_->InNewSpace(old_space_strings_[i])); | 7166 ASSERT(!heap_->InNewSpace(old_space_strings_[i])); |
| 7158 old_space_strings_[last++] = old_space_strings_[i]; | 7167 old_space_strings_[last++] = old_space_strings_[i]; |
| 7159 } | 7168 } |
| 7160 old_space_strings_.Rewind(last); | 7169 old_space_strings_.Rewind(last); |
| 7170 old_space_strings_.Trim(); |
| 7161 #ifdef VERIFY_HEAP | 7171 #ifdef VERIFY_HEAP |
| 7162 if (FLAG_verify_heap) { | 7172 if (FLAG_verify_heap) { |
| 7163 Verify(); | 7173 Verify(); |
| 7164 } | 7174 } |
| 7165 #endif | 7175 #endif |
| 7166 } | 7176 } |
| 7167 | 7177 |
| 7168 | 7178 |
| 7169 void ExternalStringTable::TearDown() { | 7179 void ExternalStringTable::TearDown() { |
| 7170 new_space_strings_.Free(); | 7180 new_space_strings_.Free(); |
| 7171 old_space_strings_.Free(); | 7181 old_space_strings_.Free(); |
| 7172 } | 7182 } |
| 7173 | 7183 |
| 7174 | 7184 |
| 7185 // Update all references. |
| 7186 void ErrorObjectList::UpdateReferences() { |
| 7187 for (int i = 0; i < list_.length(); i++) { |
| 7188 HeapObject* object = HeapObject::cast(list_[i]); |
| 7189 MapWord first_word = object->map_word(); |
| 7190 if (first_word.IsForwardingAddress()) { |
| 7191 list_[i] = first_word.ToForwardingAddress(); |
| 7192 } |
| 7193 } |
| 7194 } |
| 7195 |
| 7196 |
| 7197 // Unforwarded objects in new space are dead and removed from the list. |
| 7198 void ErrorObjectList::UpdateReferencesInNewSpace(Heap* heap) { |
| 7199 if (!nested_) { |
| 7200 int write_index = 0; |
| 7201 for (int i = 0; i < list_.length(); i++) { |
| 7202 MapWord first_word = HeapObject::cast(list_[i])->map_word(); |
| 7203 if (first_word.IsForwardingAddress()) { |
| 7204 list_[write_index++] = first_word.ToForwardingAddress(); |
| 7205 } |
| 7206 } |
| 7207 list_.Rewind(write_index); |
| 7208 } else { |
| 7209 // If a GC is triggered during DeferredFormatStackTrace, we do not move |
| 7210 // objects in the list, just remove dead ones, as to not confuse the |
| 7211 // loop in DeferredFormatStackTrace. |
| 7212 for (int i = 0; i < list_.length(); i++) { |
| 7213 MapWord first_word = HeapObject::cast(list_[i])->map_word(); |
| 7214 list_[i] = first_word.IsForwardingAddress() |
| 7215 ? first_word.ToForwardingAddress() |
| 7216 : heap->the_hole_value(); |
| 7217 } |
| 7218 } |
| 7219 } |
| 7220 |
| 7221 |
| 7222 void ErrorObjectList::DeferredFormatStackTrace(Isolate* isolate) { |
| 7223 // If formatting the stack trace causes a GC, this method will be |
| 7224 // recursively called. In that case, skip the recursive call, since |
| 7225 // the loop modifies the list while iterating over it. |
| 7226 if (nested_) return; |
| 7227 nested_ = true; |
| 7228 HandleScope scope(isolate); |
| 7229 Handle<String> stack_key = isolate->factory()->stack_symbol(); |
| 7230 int write_index = 0; |
| 7231 int budget = kBudgetPerGC; |
| 7232 for (int i = 0; i < list_.length(); i++) { |
| 7233 Object* object = list_[i]; |
| 7234 // Skip possible holes in the list. |
| 7235 if (object->IsTheHole()) continue; |
| 7236 if (isolate->heap()->InNewSpace(object) || budget == 0) { |
| 7237 list_[write_index++] = object; |
| 7238 continue; |
| 7239 } |
| 7240 |
| 7241 // Fire the stack property getter, if it is the original marked getter. |
| 7242 LookupResult lookup(isolate); |
| 7243 JSObject::cast(object)->LocalLookupRealNamedProperty(*stack_key, &lookup); |
| 7244 if (!lookup.IsFound() || lookup.type() != CALLBACKS) continue; |
| 7245 Object* callback = lookup.GetCallbackObject(); |
| 7246 if (!callback->IsAccessorPair()) continue; |
| 7247 Object* getter_obj = AccessorPair::cast(callback)->getter(); |
| 7248 if (!getter_obj->IsJSFunction()) continue; |
| 7249 JSFunction* getter_fun = JSFunction::cast(getter_obj); |
| 7250 String* key = isolate->heap()->hidden_stack_trace_symbol(); |
| 7251 if (key != getter_fun->GetHiddenProperty(key)) continue; |
| 7252 bool has_exception = false; |
| 7253 Execution::Call(Handle<Object>(getter_fun, isolate), |
| 7254 Handle<Object>(object, isolate), |
| 7255 0, |
| 7256 NULL, |
| 7257 &has_exception); |
| 7258 ASSERT(!has_exception); |
| 7259 budget--; |
| 7260 } |
| 7261 list_.Rewind(write_index); |
| 7262 list_.Trim(); |
| 7263 nested_ = false; |
| 7264 } |
| 7265 |
| 7266 |
| 7267 void ErrorObjectList::RemoveUnmarked(Heap* heap) { |
| 7268 for (int i = 0; i < list_.length(); i++) { |
| 7269 HeapObject* object = HeapObject::cast(list_[i]); |
| 7270 if (!Marking::MarkBitFrom(object).Get()) { |
| 7271 list_[i] = heap->the_hole_value(); |
| 7272 } |
| 7273 } |
| 7274 } |
| 7275 |
| 7276 |
| 7277 void ErrorObjectList::TearDown() { |
| 7278 list_.Free(); |
| 7279 } |
| 7280 |
| 7281 |
| 7175 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { | 7282 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { |
| 7176 chunk->set_next_chunk(chunks_queued_for_free_); | 7283 chunk->set_next_chunk(chunks_queued_for_free_); |
| 7177 chunks_queued_for_free_ = chunk; | 7284 chunks_queued_for_free_ = chunk; |
| 7178 } | 7285 } |
| 7179 | 7286 |
| 7180 | 7287 |
| 7181 void Heap::FreeQueuedChunks() { | 7288 void Heap::FreeQueuedChunks() { |
| 7182 if (chunks_queued_for_free_ == NULL) return; | 7289 if (chunks_queued_for_free_ == NULL) return; |
| 7183 MemoryChunk* next; | 7290 MemoryChunk* next; |
| 7184 MemoryChunk* chunk; | 7291 MemoryChunk* chunk; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7293 static_cast<int>(object_sizes_last_time_[index])); | 7400 static_cast<int>(object_sizes_last_time_[index])); |
| 7294 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) | 7401 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) |
| 7295 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 7402 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
| 7296 | 7403 |
| 7297 memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 7404 memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
| 7298 memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 7405 memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
| 7299 ClearObjectStats(); | 7406 ClearObjectStats(); |
| 7300 } | 7407 } |
| 7301 | 7408 |
| 7302 } } // namespace v8::internal | 7409 } } // namespace v8::internal |
| OLD | NEW |