| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/api.h" | 8 #include "src/api.h" |
| 9 #include "src/base/once.h" | 9 #include "src/base/once.h" |
| 10 #include "src/base/utils/random-number-generator.h" | 10 #include "src/base/utils/random-number-generator.h" |
| (...skipping 5937 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5948 // determining the source for leaks of global objects. | 5948 // determining the source for leaks of global objects. |
| 5949 void Heap::TracePathToGlobal() { | 5949 void Heap::TracePathToGlobal() { |
| 5950 PathTracer tracer(PathTracer::kAnyGlobalObject, | 5950 PathTracer tracer(PathTracer::kAnyGlobalObject, |
| 5951 PathTracer::FIND_ALL, | 5951 PathTracer::FIND_ALL, |
| 5952 VISIT_ALL); | 5952 VISIT_ALL); |
| 5953 IterateRoots(&tracer, VISIT_ONLY_STRONG); | 5953 IterateRoots(&tracer, VISIT_ONLY_STRONG); |
| 5954 } | 5954 } |
| 5955 #endif | 5955 #endif |
| 5956 | 5956 |
| 5957 | 5957 |
| 5958 static intptr_t CountTotalHolesSize(Heap* heap) { | |
| 5959 intptr_t holes_size = 0; | |
| 5960 OldSpaces spaces(heap); | |
| 5961 for (OldSpace* space = spaces.next(); | |
| 5962 space != NULL; | |
| 5963 space = spaces.next()) { | |
| 5964 holes_size += space->Waste() + space->Available(); | |
| 5965 } | |
| 5966 return holes_size; | |
| 5967 } | |
| 5968 | |
| 5969 | |
| 5970 void Heap::UpdateCumulativeGCStatistics(double duration, | 5958 void Heap::UpdateCumulativeGCStatistics(double duration, |
| 5971 double spent_in_mutator, | 5959 double spent_in_mutator, |
| 5972 double marking_time) { | 5960 double marking_time) { |
| 5973 if (FLAG_print_cumulative_gc_stat) { | 5961 if (FLAG_print_cumulative_gc_stat) { |
| 5974 total_gc_time_ms_ += duration; | 5962 total_gc_time_ms_ += duration; |
| 5975 max_gc_pause_ = Max(max_gc_pause_, duration); | 5963 max_gc_pause_ = Max(max_gc_pause_, duration); |
| 5976 max_alive_after_gc_ = Max(max_alive_after_gc_, SizeOfObjects()); | 5964 max_alive_after_gc_ = Max(max_alive_after_gc_, SizeOfObjects()); |
| 5977 min_in_mutator_ = Min(min_in_mutator_, spent_in_mutator); | 5965 min_in_mutator_ = Min(min_in_mutator_, spent_in_mutator); |
| 5978 } else if (FLAG_trace_gc_verbose) { | 5966 } else if (FLAG_trace_gc_verbose) { |
| 5979 total_gc_time_ms_ += duration; | 5967 total_gc_time_ms_ += duration; |
| 5980 } | 5968 } |
| 5981 | 5969 |
| 5982 marking_time_ += marking_time; | 5970 marking_time_ += marking_time; |
| 5983 } | 5971 } |
| 5984 | 5972 |
| 5985 | 5973 |
| 5986 GCTracer::Event::Event(Type type, const char* gc_reason, | |
| 5987 const char* collector_reason) | |
| 5988 : type(type), | |
| 5989 gc_reason(gc_reason), | |
| 5990 collector_reason(collector_reason), | |
| 5991 start_time(0.0), | |
| 5992 end_time(0.0), | |
| 5993 start_object_size(0), | |
| 5994 end_object_size(0), | |
| 5995 start_memory_size(0), | |
| 5996 end_memory_size(0), | |
| 5997 start_holes_size(0), | |
| 5998 end_holes_size(0), | |
| 5999 incremental_marking_steps(0), | |
| 6000 incremental_marking_duration(0.0) { | |
| 6001 for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) { | |
| 6002 scopes[i] = 0; | |
| 6003 } | |
| 6004 } | |
| 6005 | |
| 6006 | |
| 6007 const char* GCTracer::Event::TypeName(bool short_name) const { | |
| 6008 switch (type) { | |
| 6009 case SCAVENGER: | |
| 6010 if (short_name) { | |
| 6011 return "s"; | |
| 6012 } else { | |
| 6013 return "Scavenge"; | |
| 6014 } | |
| 6015 case MARK_COMPACTOR: | |
| 6016 if (short_name) { | |
| 6017 return "ms"; | |
| 6018 } else { | |
| 6019 return "Mark-sweep"; | |
| 6020 } | |
| 6021 case START: | |
| 6022 if (short_name) { | |
| 6023 return "st"; | |
| 6024 } else { | |
| 6025 return "Start"; | |
| 6026 } | |
| 6027 } | |
| 6028 return "Unknown Event Type"; | |
| 6029 } | |
| 6030 | |
| 6031 | |
| 6032 GCTracer::GCTracer(Heap* heap) | |
| 6033 : heap_(heap), | |
| 6034 incremental_marking_steps_(0), | |
| 6035 incremental_marking_duration_(0.0), | |
| 6036 longest_incremental_marking_step_(0.0) { | |
| 6037 current_ = Event(Event::START, NULL, NULL); | |
| 6038 current_.end_time = base::OS::TimeCurrentMillis(); | |
| 6039 previous_ = previous_mark_compactor_event_ = current_; | |
| 6040 } | |
| 6041 | |
| 6042 | |
| 6043 void GCTracer::Start(GarbageCollector collector, const char* gc_reason, | |
| 6044 const char* collector_reason) { | |
| 6045 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; | |
| 6046 | |
| 6047 previous_ = current_; | |
| 6048 if (current_.type == Event::MARK_COMPACTOR) | |
| 6049 previous_mark_compactor_event_ = current_; | |
| 6050 | |
| 6051 if (collector == SCAVENGER) { | |
| 6052 current_ = Event(Event::SCAVENGER, gc_reason, collector_reason); | |
| 6053 } else { | |
| 6054 current_ = Event(Event::MARK_COMPACTOR, gc_reason, collector_reason); | |
| 6055 } | |
| 6056 | |
| 6057 current_.start_time = base::OS::TimeCurrentMillis(); | |
| 6058 current_.start_object_size = heap_->SizeOfObjects(); | |
| 6059 current_.start_memory_size = heap_->isolate()->memory_allocator()->Size(); | |
| 6060 current_.start_holes_size = CountTotalHolesSize(heap_); | |
| 6061 | |
| 6062 current_.incremental_marking_steps = incremental_marking_steps_; | |
| 6063 current_.incremental_marking_duration = incremental_marking_duration_; | |
| 6064 current_.longest_incremental_marking_step = longest_incremental_marking_step_; | |
| 6065 | |
| 6066 for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) { | |
| 6067 current_.scopes[i] = 0; | |
| 6068 } | |
| 6069 } | |
| 6070 | |
| 6071 | |
| 6072 void GCTracer::Stop() { | |
| 6073 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; | |
| 6074 | |
| 6075 current_.end_time = base::OS::TimeCurrentMillis(); | |
| 6076 current_.end_object_size = heap_->SizeOfObjects(); | |
| 6077 current_.end_memory_size = heap_->isolate()->memory_allocator()->Size(); | |
| 6078 current_.end_holes_size = CountTotalHolesSize(heap_); | |
| 6079 | |
| 6080 if (current_.type == Event::SCAVENGER) { | |
| 6081 scavenger_events_.push_front(current_); | |
| 6082 } else { | |
| 6083 mark_compactor_events_.push_front(current_); | |
| 6084 } | |
| 6085 | |
| 6086 if (current_.type == Event::MARK_COMPACTOR) | |
| 6087 longest_incremental_marking_step_ = 0.0; | |
| 6088 | |
| 6089 double duration = current_.end_time - current_.start_time; | |
| 6090 double spent_in_mutator = Max(current_.start_time - previous_.end_time, 0.0); | |
| 6091 | |
| 6092 heap_->UpdateCumulativeGCStatistics(duration, spent_in_mutator, | |
| 6093 current_.scopes[Scope::MC_MARK]); | |
| 6094 | |
| 6095 if (current_.type == Event::SCAVENGER && FLAG_trace_gc_ignore_scavenger) | |
| 6096 return; | |
| 6097 | |
| 6098 if (FLAG_trace_gc) { | |
| 6099 if (FLAG_trace_gc_nvp) | |
| 6100 PrintNVP(); | |
| 6101 else | |
| 6102 Print(); | |
| 6103 | |
| 6104 heap_->PrintShortHeapStatistics(); | |
| 6105 } | |
| 6106 } | |
| 6107 | |
| 6108 | |
| 6109 void GCTracer::AddIncrementalMarkingStep(double duration) { | |
| 6110 incremental_marking_steps_++; | |
| 6111 incremental_marking_duration_ += duration; | |
| 6112 longest_incremental_marking_step_ = | |
| 6113 Max(longest_incremental_marking_step_, duration); | |
| 6114 } | |
| 6115 | |
| 6116 | |
| 6117 void GCTracer::Print() const { | |
| 6118 PrintPID("%8.0f ms: ", heap_->isolate()->time_millis_since_init()); | |
| 6119 | |
| 6120 PrintF("%s %.1f (%.1f) -> %.1f (%.1f) MB, ", current_.TypeName(false), | |
| 6121 static_cast<double>(current_.start_object_size) / MB, | |
| 6122 static_cast<double>(current_.start_memory_size) / MB, | |
| 6123 static_cast<double>(current_.end_object_size) / MB, | |
| 6124 static_cast<double>(current_.end_memory_size) / MB); | |
| 6125 | |
| 6126 int external_time = static_cast<int>(current_.scopes[Scope::EXTERNAL]); | |
| 6127 if (external_time > 0) PrintF("%d / ", external_time); | |
| 6128 | |
| 6129 double duration = current_.end_time - current_.start_time; | |
| 6130 PrintF("%.1f ms", duration); | |
| 6131 if (current_.type == Event::SCAVENGER) { | |
| 6132 int steps = current_.incremental_marking_steps - | |
| 6133 previous_.incremental_marking_steps; | |
| 6134 if (steps > 0) { | |
| 6135 PrintF(" (+ %.1f ms in %d steps since last GC)", | |
| 6136 current_.incremental_marking_duration - | |
| 6137 previous_.incremental_marking_duration, | |
| 6138 steps); | |
| 6139 } | |
| 6140 } else { | |
| 6141 int steps = current_.incremental_marking_steps - | |
| 6142 previous_mark_compactor_event_.incremental_marking_steps; | |
| 6143 if (steps > 0) { | |
| 6144 PrintF( | |
| 6145 " (+ %.1f ms in %d steps since start of marking, " | |
| 6146 "biggest step %.1f ms)", | |
| 6147 current_.incremental_marking_duration - | |
| 6148 previous_mark_compactor_event_.incremental_marking_duration, | |
| 6149 steps, current_.longest_incremental_marking_step); | |
| 6150 } | |
| 6151 } | |
| 6152 | |
| 6153 if (current_.gc_reason != NULL) { | |
| 6154 PrintF(" [%s]", current_.gc_reason); | |
| 6155 } | |
| 6156 | |
| 6157 if (current_.collector_reason != NULL) { | |
| 6158 PrintF(" [%s]", current_.collector_reason); | |
| 6159 } | |
| 6160 | |
| 6161 PrintF(".\n"); | |
| 6162 } | |
| 6163 | |
| 6164 | |
| 6165 void GCTracer::PrintNVP() const { | |
| 6166 PrintPID("%8.0f ms: ", heap_->isolate()->time_millis_since_init()); | |
| 6167 | |
| 6168 double duration = current_.end_time - current_.start_time; | |
| 6169 double spent_in_mutator = current_.start_time - previous_.end_time; | |
| 6170 | |
| 6171 PrintF("pause=%.1f ", duration); | |
| 6172 PrintF("mutator=%.1f ", spent_in_mutator); | |
| 6173 PrintF("gc=%s ", current_.TypeName(true)); | |
| 6174 | |
| 6175 PrintF("external=%.1f ", current_.scopes[Scope::EXTERNAL]); | |
| 6176 PrintF("mark=%.1f ", current_.scopes[Scope::MC_MARK]); | |
| 6177 PrintF("sweep=%.2f ", current_.scopes[Scope::MC_SWEEP]); | |
| 6178 PrintF("sweepns=%.2f ", current_.scopes[Scope::MC_SWEEP_NEWSPACE]); | |
| 6179 PrintF("sweepos=%.2f ", current_.scopes[Scope::MC_SWEEP_OLDSPACE]); | |
| 6180 PrintF("sweepcode=%.2f ", current_.scopes[Scope::MC_SWEEP_CODE]); | |
| 6181 PrintF("sweepcell=%.2f ", current_.scopes[Scope::MC_SWEEP_CELL]); | |
| 6182 PrintF("sweepmap=%.2f ", current_.scopes[Scope::MC_SWEEP_MAP]); | |
| 6183 PrintF("evacuate=%.1f ", current_.scopes[Scope::MC_EVACUATE_PAGES]); | |
| 6184 PrintF("new_new=%.1f ", | |
| 6185 current_.scopes[Scope::MC_UPDATE_NEW_TO_NEW_POINTERS]); | |
| 6186 PrintF("root_new=%.1f ", | |
| 6187 current_.scopes[Scope::MC_UPDATE_ROOT_TO_NEW_POINTERS]); | |
| 6188 PrintF("old_new=%.1f ", | |
| 6189 current_.scopes[Scope::MC_UPDATE_OLD_TO_NEW_POINTERS]); | |
| 6190 PrintF("compaction_ptrs=%.1f ", | |
| 6191 current_.scopes[Scope::MC_UPDATE_POINTERS_TO_EVACUATED]); | |
| 6192 PrintF("intracompaction_ptrs=%.1f ", | |
| 6193 current_.scopes[Scope::MC_UPDATE_POINTERS_BETWEEN_EVACUATED]); | |
| 6194 PrintF("misc_compaction=%.1f ", | |
| 6195 current_.scopes[Scope::MC_UPDATE_MISC_POINTERS]); | |
| 6196 PrintF("weakcollection_process=%.1f ", | |
| 6197 current_.scopes[Scope::MC_WEAKCOLLECTION_PROCESS]); | |
| 6198 PrintF("weakcollection_clear=%.1f ", | |
| 6199 current_.scopes[Scope::MC_WEAKCOLLECTION_CLEAR]); | |
| 6200 | |
| 6201 PrintF("total_size_before=%" V8_PTR_PREFIX "d ", current_.start_object_size); | |
| 6202 PrintF("total_size_after=%" V8_PTR_PREFIX "d ", current_.end_object_size); | |
| 6203 PrintF("holes_size_before=%" V8_PTR_PREFIX "d ", current_.start_holes_size); | |
| 6204 PrintF("holes_size_after=%" V8_PTR_PREFIX "d ", current_.end_holes_size); | |
| 6205 | |
| 6206 intptr_t allocated_since_last_gc = | |
| 6207 current_.start_object_size - previous_.end_object_size; | |
| 6208 PrintF("allocated=%" V8_PTR_PREFIX "d ", allocated_since_last_gc); | |
| 6209 PrintF("promoted=%" V8_PTR_PREFIX "d ", heap_->promoted_objects_size_); | |
| 6210 PrintF("semi_space_copied=%" V8_PTR_PREFIX "d ", | |
| 6211 heap_->semi_space_copied_object_size_); | |
| 6212 PrintF("nodes_died_in_new=%d ", heap_->nodes_died_in_new_space_); | |
| 6213 PrintF("nodes_copied_in_new=%d ", heap_->nodes_copied_in_new_space_); | |
| 6214 PrintF("nodes_promoted=%d ", heap_->nodes_promoted_); | |
| 6215 PrintF("promotion_rate=%.1f%% ", heap_->promotion_rate_); | |
| 6216 PrintF("semi_space_copy_rate=%.1f%% ", heap_->semi_space_copied_rate_); | |
| 6217 | |
| 6218 if (current_.type == Event::SCAVENGER) { | |
| 6219 PrintF("stepscount=%d ", current_.incremental_marking_steps - | |
| 6220 previous_.incremental_marking_steps); | |
| 6221 PrintF("stepstook=%.1f ", current_.incremental_marking_duration - | |
| 6222 previous_.incremental_marking_duration); | |
| 6223 } else { | |
| 6224 PrintF("stepscount=%d ", | |
| 6225 current_.incremental_marking_steps - | |
| 6226 previous_mark_compactor_event_.incremental_marking_steps); | |
| 6227 PrintF("stepstook=%.1f ", | |
| 6228 current_.incremental_marking_duration - | |
| 6229 previous_mark_compactor_event_.incremental_marking_duration); | |
| 6230 PrintF("longeststep=%.1f ", current_.longest_incremental_marking_step); | |
| 6231 } | |
| 6232 | |
| 6233 PrintF("\n"); | |
| 6234 } | |
| 6235 | |
| 6236 | |
| 6237 int KeyedLookupCache::Hash(Handle<Map> map, Handle<Name> name) { | 5974 int KeyedLookupCache::Hash(Handle<Map> map, Handle<Name> name) { |
| 6238 DisallowHeapAllocation no_gc; | 5975 DisallowHeapAllocation no_gc; |
| 6239 // Uses only lower 32 bits if pointers are larger. | 5976 // Uses only lower 32 bits if pointers are larger. |
| 6240 uintptr_t addr_hash = | 5977 uintptr_t addr_hash = |
| 6241 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(*map)) >> kMapHashShift; | 5978 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(*map)) >> kMapHashShift; |
| 6242 return static_cast<uint32_t>((addr_hash ^ name->Hash()) & kCapacityMask); | 5979 return static_cast<uint32_t>((addr_hash ^ name->Hash()) & kCapacityMask); |
| 6243 } | 5980 } |
| 6244 | 5981 |
| 6245 | 5982 |
| 6246 int KeyedLookupCache::Lookup(Handle<Map> map, Handle<Name> name) { | 5983 int KeyedLookupCache::Lookup(Handle<Map> map, Handle<Name> name) { |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6493 static_cast<int>(object_sizes_last_time_[index])); | 6230 static_cast<int>(object_sizes_last_time_[index])); |
| 6494 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 6231 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) |
| 6495 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 6232 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
| 6496 | 6233 |
| 6497 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 6234 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
| 6498 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 6235 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
| 6499 ClearObjectStats(); | 6236 ClearObjectStats(); |
| 6500 } | 6237 } |
| 6501 | 6238 |
| 6502 } } // namespace v8::internal | 6239 } } // namespace v8::internal |
| OLD | NEW |