| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 17 matching lines...) Expand all Loading... |
| 28 #ifndef V8_PROFILE_GENERATOR_H_ | 28 #ifndef V8_PROFILE_GENERATOR_H_ |
| 29 #define V8_PROFILE_GENERATOR_H_ | 29 #define V8_PROFILE_GENERATOR_H_ |
| 30 | 30 |
| 31 #ifdef ENABLE_LOGGING_AND_PROFILING | 31 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 32 | 32 |
| 33 #include "hashmap.h" | 33 #include "hashmap.h" |
| 34 | 34 |
| 35 namespace v8 { | 35 namespace v8 { |
| 36 namespace internal { | 36 namespace internal { |
| 37 | 37 |
| 38 class TokenEnumerator { |
| 39 public: |
| 40 TokenEnumerator(); |
| 41 ~TokenEnumerator(); |
| 42 int GetTokenId(Object* token); |
| 43 |
| 44 private: |
| 45 static void TokenRemovedCallback(v8::Persistent<v8::Value> handle, |
| 46 void* parameter); |
| 47 void TokenRemoved(Object** token_location); |
| 48 |
| 49 List<Object**> token_locations_; |
| 50 List<bool> token_removed_; |
| 51 |
| 52 friend class TokenEnumeratorTester; |
| 53 }; |
| 54 |
| 55 |
| 38 class CodeEntry { | 56 class CodeEntry { |
| 39 public: | 57 public: |
| 58 explicit INLINE(CodeEntry(int security_token_id)); |
| 40 // CodeEntry doesn't own name strings, just references them. | 59 // CodeEntry doesn't own name strings, just references them. |
| 41 INLINE(CodeEntry(Logger::LogEventsAndTags tag, | 60 INLINE(CodeEntry(Logger::LogEventsAndTags tag, |
| 42 const char* name_prefix, | 61 const char* name_prefix, |
| 43 const char* name, | 62 const char* name, |
| 44 const char* resource_name, | 63 const char* resource_name, |
| 45 int line_number)); | 64 int line_number, |
| 65 int security_token_id)); |
| 46 | 66 |
| 47 INLINE(bool is_js_function() const) { return is_js_function_tag(tag_); } | 67 INLINE(bool is_js_function() const) { return is_js_function_tag(tag_); } |
| 48 INLINE(const char* name_prefix() const) { return name_prefix_; } | 68 INLINE(const char* name_prefix() const) { return name_prefix_; } |
| 49 INLINE(bool has_name_prefix() const) { return name_prefix_[0] != '\0'; } | 69 INLINE(bool has_name_prefix() const) { return name_prefix_[0] != '\0'; } |
| 50 INLINE(const char* name() const) { return name_; } | 70 INLINE(const char* name() const) { return name_; } |
| 51 INLINE(const char* resource_name() const) { return resource_name_; } | 71 INLINE(const char* resource_name() const) { return resource_name_; } |
| 52 INLINE(int line_number() const) { return line_number_; } | 72 INLINE(int line_number() const) { return line_number_; } |
| 53 INLINE(unsigned call_uid() const) { return call_uid_; } | 73 INLINE(unsigned call_uid() const) { return call_uid_; } |
| 74 INLINE(int security_token_id() const) { return security_token_id_; } |
| 54 | 75 |
| 55 INLINE(static bool is_js_function_tag(Logger::LogEventsAndTags tag)); | 76 INLINE(static bool is_js_function_tag(Logger::LogEventsAndTags tag)); |
| 56 | 77 |
| 78 void CopyData(const CodeEntry& source); |
| 79 |
| 57 static const char* kEmptyNamePrefix; | 80 static const char* kEmptyNamePrefix; |
| 81 static const int kNoSecurityToken = -1; |
| 82 static const int kInheritsSecurityToken = -2; |
| 58 | 83 |
| 59 private: | 84 private: |
| 60 const unsigned call_uid_; | 85 unsigned call_uid_; |
| 61 Logger::LogEventsAndTags tag_; | 86 Logger::LogEventsAndTags tag_; |
| 62 const char* name_prefix_; | 87 const char* name_prefix_; |
| 63 const char* name_; | 88 const char* name_; |
| 64 const char* resource_name_; | 89 const char* resource_name_; |
| 65 int line_number_; | 90 int line_number_; |
| 91 int security_token_id_; |
| 66 | 92 |
| 67 static unsigned next_call_uid_; | 93 static unsigned next_call_uid_; |
| 68 | 94 |
| 69 DISALLOW_COPY_AND_ASSIGN(CodeEntry); | 95 DISALLOW_COPY_AND_ASSIGN(CodeEntry); |
| 70 }; | 96 }; |
| 71 | 97 |
| 72 | 98 |
| 73 class ProfileTree; | 99 class ProfileTree; |
| 74 | 100 |
| 75 class ProfileNode { | 101 class ProfileNode { |
| 76 public: | 102 public: |
| 77 INLINE(ProfileNode(ProfileTree* tree, CodeEntry* entry)); | 103 INLINE(ProfileNode(ProfileTree* tree, CodeEntry* entry)); |
| 78 | 104 |
| 79 ProfileNode* FindChild(CodeEntry* entry); | 105 ProfileNode* FindChild(CodeEntry* entry); |
| 80 ProfileNode* FindOrAddChild(CodeEntry* entry); | 106 ProfileNode* FindOrAddChild(CodeEntry* entry); |
| 81 INLINE(void IncrementSelfTicks()) { ++self_ticks_; } | 107 INLINE(void IncrementSelfTicks()) { ++self_ticks_; } |
| 108 INLINE(void IncreaseSelfTicks(unsigned amount)) { self_ticks_ += amount; } |
| 82 INLINE(void IncreaseTotalTicks(unsigned amount)) { total_ticks_ += amount; } | 109 INLINE(void IncreaseTotalTicks(unsigned amount)) { total_ticks_ += amount; } |
| 83 | 110 |
| 84 INLINE(CodeEntry* entry() const) { return entry_; } | 111 INLINE(CodeEntry* entry() const) { return entry_; } |
| 85 INLINE(unsigned self_ticks() const) { return self_ticks_; } | 112 INLINE(unsigned self_ticks() const) { return self_ticks_; } |
| 86 INLINE(unsigned total_ticks() const) { return total_ticks_; } | 113 INLINE(unsigned total_ticks() const) { return total_ticks_; } |
| 87 INLINE(const List<ProfileNode*>* children() const) { return &children_list_; } | 114 INLINE(const List<ProfileNode*>* children() const) { return &children_list_; } |
| 88 double GetSelfMillis() const; | 115 double GetSelfMillis() const; |
| 89 double GetTotalMillis() const; | 116 double GetTotalMillis() const; |
| 90 | 117 |
| 91 void Print(int indent); | 118 void Print(int indent); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 112 | 139 |
| 113 | 140 |
| 114 class ProfileTree { | 141 class ProfileTree { |
| 115 public: | 142 public: |
| 116 ProfileTree(); | 143 ProfileTree(); |
| 117 ~ProfileTree(); | 144 ~ProfileTree(); |
| 118 | 145 |
| 119 void AddPathFromEnd(const Vector<CodeEntry*>& path); | 146 void AddPathFromEnd(const Vector<CodeEntry*>& path); |
| 120 void AddPathFromStart(const Vector<CodeEntry*>& path); | 147 void AddPathFromStart(const Vector<CodeEntry*>& path); |
| 121 void CalculateTotalTicks(); | 148 void CalculateTotalTicks(); |
| 149 void FilteredClone(ProfileTree* src, int security_token_id); |
| 122 | 150 |
| 123 double TicksToMillis(unsigned ticks) const { | 151 double TicksToMillis(unsigned ticks) const { |
| 124 return ticks * ms_to_ticks_scale_; | 152 return ticks * ms_to_ticks_scale_; |
| 125 } | 153 } |
| 126 ProfileNode* root() const { return root_; } | 154 ProfileNode* root() const { return root_; } |
| 127 void SetTickRatePerMs(double ticks_per_ms); | 155 void SetTickRatePerMs(double ticks_per_ms); |
| 128 | 156 |
| 129 void ShortPrint(); | 157 void ShortPrint(); |
| 130 void Print() { | 158 void Print() { |
| 131 root_->Print(0); | 159 root_->Print(0); |
| 132 } | 160 } |
| 133 | 161 |
| 134 private: | 162 private: |
| 135 template <typename Callback> | 163 template <typename Callback> |
| 136 void TraverseDepthFirstPostOrder(Callback* callback); | 164 void TraverseDepthFirst(Callback* callback); |
| 137 | 165 |
| 138 CodeEntry root_entry_; | 166 CodeEntry root_entry_; |
| 139 ProfileNode* root_; | 167 ProfileNode* root_; |
| 140 double ms_to_ticks_scale_; | 168 double ms_to_ticks_scale_; |
| 141 | 169 |
| 142 DISALLOW_COPY_AND_ASSIGN(ProfileTree); | 170 DISALLOW_COPY_AND_ASSIGN(ProfileTree); |
| 143 }; | 171 }; |
| 144 | 172 |
| 145 | 173 |
| 146 class CpuProfile { | 174 class CpuProfile { |
| 147 public: | 175 public: |
| 148 CpuProfile(const char* title, unsigned uid) | 176 CpuProfile(const char* title, unsigned uid) |
| 149 : title_(title), uid_(uid) { } | 177 : title_(title), uid_(uid) { } |
| 150 | 178 |
| 151 // Add pc -> ... -> main() call path to the profile. | 179 // Add pc -> ... -> main() call path to the profile. |
| 152 void AddPath(const Vector<CodeEntry*>& path); | 180 void AddPath(const Vector<CodeEntry*>& path); |
| 153 void CalculateTotalTicks(); | 181 void CalculateTotalTicks(); |
| 154 void SetActualSamplingRate(double actual_sampling_rate); | 182 void SetActualSamplingRate(double actual_sampling_rate); |
| 183 CpuProfile* FilteredClone(int security_token_id); |
| 155 | 184 |
| 156 INLINE(const char* title() const) { return title_; } | 185 INLINE(const char* title() const) { return title_; } |
| 157 INLINE(unsigned uid() const) { return uid_; } | 186 INLINE(unsigned uid() const) { return uid_; } |
| 158 INLINE(const ProfileTree* top_down() const) { return &top_down_; } | 187 INLINE(const ProfileTree* top_down() const) { return &top_down_; } |
| 159 INLINE(const ProfileTree* bottom_up() const) { return &bottom_up_; } | 188 INLINE(const ProfileTree* bottom_up() const) { return &bottom_up_; } |
| 160 | 189 |
| 161 void UpdateTicksScale(); | 190 void UpdateTicksScale(); |
| 162 | 191 |
| 163 void ShortPrint(); | 192 void ShortPrint(); |
| 164 void Print(); | 193 void Print(); |
| 165 | 194 |
| 166 private: | 195 private: |
| 167 const char* title_; | 196 const char* title_; |
| 168 unsigned uid_; | 197 unsigned uid_; |
| 169 ProfileTree top_down_; | 198 ProfileTree top_down_; |
| 170 ProfileTree bottom_up_; | 199 ProfileTree bottom_up_; |
| 171 | 200 |
| 172 DISALLOW_COPY_AND_ASSIGN(CpuProfile); | 201 DISALLOW_COPY_AND_ASSIGN(CpuProfile); |
| 173 }; | 202 }; |
| 174 | 203 |
| 175 | 204 |
| 176 class CodeMap { | 205 class CodeMap { |
| 177 public: | 206 public: |
| 178 CodeMap() { } | 207 CodeMap() { } |
| 179 INLINE(void AddCode(Address addr, CodeEntry* entry, unsigned size)); | 208 INLINE(void AddCode(Address addr, CodeEntry* entry, unsigned size)); |
| 180 INLINE(void MoveCode(Address from, Address to)); | 209 INLINE(void MoveCode(Address from, Address to)); |
| 181 INLINE(void DeleteCode(Address addr)); | 210 INLINE(void DeleteCode(Address addr)); |
| 182 void AddAlias(Address alias, Address addr); | 211 void AddAlias(Address start, CodeEntry* entry, Address code_start); |
| 183 CodeEntry* FindEntry(Address addr); | 212 CodeEntry* FindEntry(Address addr); |
| 184 | 213 |
| 185 void Print(); | 214 void Print(); |
| 186 | 215 |
| 187 private: | 216 private: |
| 188 struct CodeEntryInfo { | 217 struct CodeEntryInfo { |
| 189 CodeEntryInfo(CodeEntry* an_entry, unsigned a_size) | 218 CodeEntryInfo(CodeEntry* an_entry, unsigned a_size) |
| 190 : entry(an_entry), size(a_size) { } | 219 : entry(an_entry), size(a_size) { } |
| 191 CodeEntry* entry; | 220 CodeEntry* entry; |
| 192 unsigned size; | 221 unsigned size; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 214 }; | 243 }; |
| 215 | 244 |
| 216 | 245 |
| 217 class CpuProfilesCollection { | 246 class CpuProfilesCollection { |
| 218 public: | 247 public: |
| 219 CpuProfilesCollection(); | 248 CpuProfilesCollection(); |
| 220 ~CpuProfilesCollection(); | 249 ~CpuProfilesCollection(); |
| 221 | 250 |
| 222 bool StartProfiling(const char* title, unsigned uid); | 251 bool StartProfiling(const char* title, unsigned uid); |
| 223 bool StartProfiling(String* title, unsigned uid); | 252 bool StartProfiling(String* title, unsigned uid); |
| 224 CpuProfile* StopProfiling(const char* title, double actual_sampling_rate); | 253 CpuProfile* StopProfiling(int security_token_id, |
| 225 CpuProfile* StopProfiling(String* title, double actual_sampling_rate); | 254 const char* title, |
| 226 INLINE(List<CpuProfile*>* profiles()) { return &profiles_; } | 255 double actual_sampling_rate); |
| 227 CpuProfile* GetProfile(unsigned uid); | 256 CpuProfile* StopProfiling(int security_token_id, |
| 257 String* title, |
| 258 double actual_sampling_rate); |
| 259 List<CpuProfile*>* Profiles(int security_token_id); |
| 260 CpuProfile* GetProfile(int security_token_id, unsigned uid); |
| 228 inline bool is_last_profile(); | 261 inline bool is_last_profile(); |
| 229 | 262 |
| 230 CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, | 263 CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, |
| 231 String* name, String* resource_name, int line_number); | 264 String* name, String* resource_name, int line_number); |
| 232 CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, const char* name); | 265 CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, const char* name); |
| 233 CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, | 266 CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, |
| 234 const char* name_prefix, String* name); | 267 const char* name_prefix, String* name); |
| 235 CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, int args_count); | 268 CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, int args_count); |
| 269 CodeEntry* NewCodeEntry(int security_token_id); |
| 236 | 270 |
| 237 // Called from profile generator thread. | 271 // Called from profile generator thread. |
| 238 void AddPathToCurrentProfiles(const Vector<CodeEntry*>& path); | 272 void AddPathToCurrentProfiles(const Vector<CodeEntry*>& path); |
| 239 | 273 |
| 240 private: | 274 private: |
| 241 INLINE(const char* GetFunctionName(String* name)); | 275 INLINE(const char* GetFunctionName(String* name)); |
| 242 INLINE(const char* GetFunctionName(const char* name)); | 276 INLINE(const char* GetFunctionName(const char* name)); |
| 243 const char* GetName(String* name); | 277 const char* GetName(String* name); |
| 244 const char* GetName(int args_count); | 278 const char* GetName(int args_count); |
| 279 List<CpuProfile*>* GetProfilesList(int security_token_id); |
| 280 int TokenToIndex(int security_token_id); |
| 245 | 281 |
| 246 INLINE(static bool StringsMatch(void* key1, void* key2)) { | 282 INLINE(static bool StringsMatch(void* key1, void* key2)) { |
| 247 return strcmp(reinterpret_cast<char*>(key1), | 283 return strcmp(reinterpret_cast<char*>(key1), |
| 248 reinterpret_cast<char*>(key2)) == 0; | 284 reinterpret_cast<char*>(key2)) == 0; |
| 249 } | 285 } |
| 250 | 286 |
| 251 INLINE(static bool CpuProfilesMatch(void* key1, void* key2)) { | 287 INLINE(static bool UidsMatch(void* key1, void* key2)) { |
| 252 return key1 == key2; | 288 return key1 == key2; |
| 253 } | 289 } |
| 254 | 290 |
| 255 // String::Hash -> const char* | 291 // String::Hash -> const char* |
| 256 HashMap function_and_resource_names_; | 292 HashMap function_and_resource_names_; |
| 257 // args_count -> char* | 293 // args_count -> char* |
| 258 List<char*> args_count_names_; | 294 List<char*> args_count_names_; |
| 259 List<CodeEntry*> code_entries_; | 295 List<CodeEntry*> code_entries_; |
| 260 List<CpuProfile*> profiles_; | 296 List<List<CpuProfile*>* > profiles_by_token_; |
| 261 // uid -> CpuProfile* | 297 // uid -> index |
| 262 HashMap profiles_uids_; | 298 HashMap profiles_uids_; |
| 263 | 299 |
| 264 // Accessed by VM thread and profile generator thread. | 300 // Accessed by VM thread and profile generator thread. |
| 265 List<CpuProfile*> current_profiles_; | 301 List<CpuProfile*> current_profiles_; |
| 266 Semaphore* current_profiles_semaphore_; | 302 Semaphore* current_profiles_semaphore_; |
| 267 | 303 |
| 268 DISALLOW_COPY_AND_ASSIGN(CpuProfilesCollection); | 304 DISALLOW_COPY_AND_ASSIGN(CpuProfilesCollection); |
| 269 }; | 305 }; |
| 270 | 306 |
| 271 | 307 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 const char* name_prefix, | 361 const char* name_prefix, |
| 326 String* name)) { | 362 String* name)) { |
| 327 return profiles_->NewCodeEntry(tag, name_prefix, name); | 363 return profiles_->NewCodeEntry(tag, name_prefix, name); |
| 328 } | 364 } |
| 329 | 365 |
| 330 INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, | 366 INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, |
| 331 int args_count)) { | 367 int args_count)) { |
| 332 return profiles_->NewCodeEntry(tag, args_count); | 368 return profiles_->NewCodeEntry(tag, args_count); |
| 333 } | 369 } |
| 334 | 370 |
| 371 INLINE(CodeEntry* NewCodeEntry(int security_token_id)) { |
| 372 return profiles_->NewCodeEntry(security_token_id); |
| 373 } |
| 374 |
| 335 void RecordTickSample(const TickSample& sample); | 375 void RecordTickSample(const TickSample& sample); |
| 336 | 376 |
| 337 INLINE(CodeMap* code_map()) { return &code_map_; } | 377 INLINE(CodeMap* code_map()) { return &code_map_; } |
| 338 | 378 |
| 339 INLINE(void Tick()) { sample_rate_calc_.Tick(); } | 379 INLINE(void Tick()) { sample_rate_calc_.Tick(); } |
| 340 INLINE(double actual_sampling_rate()) { | 380 INLINE(double actual_sampling_rate()) { |
| 341 return sample_rate_calc_.ticks_per_ms(); | 381 return sample_rate_calc_.ticks_per_ms(); |
| 342 } | 382 } |
| 343 | 383 |
| 344 static const char* kAnonymousFunctionName; | 384 static const char* kAnonymousFunctionName; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 355 SampleRateCalculator sample_rate_calc_; | 395 SampleRateCalculator sample_rate_calc_; |
| 356 | 396 |
| 357 DISALLOW_COPY_AND_ASSIGN(ProfileGenerator); | 397 DISALLOW_COPY_AND_ASSIGN(ProfileGenerator); |
| 358 }; | 398 }; |
| 359 | 399 |
| 360 } } // namespace v8::internal | 400 } } // namespace v8::internal |
| 361 | 401 |
| 362 #endif // ENABLE_LOGGING_AND_PROFILING | 402 #endif // ENABLE_LOGGING_AND_PROFILING |
| 363 | 403 |
| 364 #endif // V8_PROFILE_GENERATOR_H_ | 404 #endif // V8_PROFILE_GENERATOR_H_ |
| OLD | NEW |