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