fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 1 | // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 | // Redistribution and use in source and binary forms, with or without |
| 3 | // modification, are permitted provided that the following conditions are |
| 4 | // met: |
| 5 | // |
| 6 | // * Redistributions of source code must retain the above copyright |
| 7 | // notice, this list of conditions and the following disclaimer. |
| 8 | // * Redistributions in binary form must reproduce the above |
| 9 | // copyright notice, this list of conditions and the following |
| 10 | // disclaimer in the documentation and/or other materials provided |
| 11 | // with the distribution. |
| 12 | // * Neither the name of Google Inc. nor the names of its |
| 13 | // contributors may be used to endorse or promote products derived |
| 14 | // from this software without specific prior written permission. |
| 15 | // |
| 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | |
| 28 | #ifndef V8_PROFILE_GENERATOR_H_ |
| 29 | #define V8_PROFILE_GENERATOR_H_ |
| 30 | |
ricow@chromium.org | c9c8082 | 2010-04-21 08:22:37 +0000 | [diff] [blame] | 31 | #ifdef ENABLE_LOGGING_AND_PROFILING |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 32 | |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 33 | #include "hashmap.h" |
| 34 | |
| 35 | namespace v8 { |
| 36 | namespace internal { |
| 37 | |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 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 | |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 56 | class CodeEntry { |
| 57 | public: |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 58 | explicit INLINE(CodeEntry(int security_token_id)); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 59 | // CodeEntry doesn't own name strings, just references them. |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 60 | INLINE(CodeEntry(Logger::LogEventsAndTags tag, |
| 61 | const char* name_prefix, |
| 62 | const char* name, |
| 63 | const char* resource_name, |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 64 | int line_number, |
| 65 | int security_token_id)); |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 66 | |
ager@chromium.org | 357bf65 | 2010-04-12 11:30:10 +0000 | [diff] [blame] | 67 | INLINE(bool is_js_function() const) { return is_js_function_tag(tag_); } |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 68 | INLINE(const char* name_prefix() const) { return name_prefix_; } |
| 69 | INLINE(bool has_name_prefix() const) { return name_prefix_[0] != '\0'; } |
| 70 | INLINE(const char* name() const) { return name_; } |
| 71 | INLINE(const char* resource_name() const) { return resource_name_; } |
| 72 | INLINE(int line_number() const) { return line_number_; } |
ager@chromium.org | 357bf65 | 2010-04-12 11:30:10 +0000 | [diff] [blame] | 73 | INLINE(unsigned call_uid() const) { return call_uid_; } |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 74 | INLINE(int security_token_id() const) { return security_token_id_; } |
ager@chromium.org | 357bf65 | 2010-04-12 11:30:10 +0000 | [diff] [blame] | 75 | |
| 76 | INLINE(static bool is_js_function_tag(Logger::LogEventsAndTags tag)); |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 77 | |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 78 | void CopyData(const CodeEntry& source); |
| 79 | |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 80 | static const char* kEmptyNamePrefix; |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 81 | static const int kNoSecurityToken = -1; |
| 82 | static const int kInheritsSecurityToken = -2; |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 83 | |
| 84 | private: |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 85 | unsigned call_uid_; |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 86 | Logger::LogEventsAndTags tag_; |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 87 | const char* name_prefix_; |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 88 | const char* name_; |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 89 | const char* resource_name_; |
| 90 | int line_number_; |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 91 | int security_token_id_; |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 92 | |
ager@chromium.org | 357bf65 | 2010-04-12 11:30:10 +0000 | [diff] [blame] | 93 | static unsigned next_call_uid_; |
| 94 | |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 95 | DISALLOW_COPY_AND_ASSIGN(CodeEntry); |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 96 | }; |
| 97 | |
| 98 | |
ricow@chromium.org | c9c8082 | 2010-04-21 08:22:37 +0000 | [diff] [blame] | 99 | class ProfileTree; |
| 100 | |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 101 | class ProfileNode { |
| 102 | public: |
ricow@chromium.org | c9c8082 | 2010-04-21 08:22:37 +0000 | [diff] [blame] | 103 | INLINE(ProfileNode(ProfileTree* tree, CodeEntry* entry)); |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 104 | |
| 105 | ProfileNode* FindChild(CodeEntry* entry); |
| 106 | ProfileNode* FindOrAddChild(CodeEntry* entry); |
| 107 | INLINE(void IncrementSelfTicks()) { ++self_ticks_; } |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 108 | INLINE(void IncreaseSelfTicks(unsigned amount)) { self_ticks_ += amount; } |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 109 | INLINE(void IncreaseTotalTicks(unsigned amount)) { total_ticks_ += amount; } |
| 110 | |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 111 | INLINE(CodeEntry* entry() const) { return entry_; } |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 112 | INLINE(unsigned self_ticks() const) { return self_ticks_; } |
ricow@chromium.org | c9c8082 | 2010-04-21 08:22:37 +0000 | [diff] [blame] | 113 | INLINE(unsigned total_ticks() const) { return total_ticks_; } |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 114 | INLINE(const List<ProfileNode*>* children() const) { return &children_list_; } |
ricow@chromium.org | c9c8082 | 2010-04-21 08:22:37 +0000 | [diff] [blame] | 115 | double GetSelfMillis() const; |
| 116 | double GetTotalMillis() const; |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 117 | |
| 118 | void Print(int indent); |
| 119 | |
| 120 | private: |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 121 | INLINE(static bool CodeEntriesMatch(void* entry1, void* entry2)) { |
| 122 | return entry1 == entry2; |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 123 | } |
| 124 | |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 125 | INLINE(static uint32_t CodeEntryHash(CodeEntry* entry)) { |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 126 | return static_cast<int32_t>(reinterpret_cast<intptr_t>(entry)); |
| 127 | } |
| 128 | |
ricow@chromium.org | c9c8082 | 2010-04-21 08:22:37 +0000 | [diff] [blame] | 129 | ProfileTree* tree_; |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 130 | CodeEntry* entry_; |
| 131 | unsigned total_ticks_; |
| 132 | unsigned self_ticks_; |
| 133 | // CodeEntry* -> ProfileNode* |
| 134 | HashMap children_; |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 135 | List<ProfileNode*> children_list_; |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 136 | |
| 137 | DISALLOW_COPY_AND_ASSIGN(ProfileNode); |
| 138 | }; |
| 139 | |
| 140 | |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 141 | class ProfileTree { |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 142 | public: |
ager@chromium.org | 357bf65 | 2010-04-12 11:30:10 +0000 | [diff] [blame] | 143 | ProfileTree(); |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 144 | ~ProfileTree(); |
| 145 | |
| 146 | void AddPathFromEnd(const Vector<CodeEntry*>& path); |
| 147 | void AddPathFromStart(const Vector<CodeEntry*>& path); |
| 148 | void CalculateTotalTicks(); |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 149 | void FilteredClone(ProfileTree* src, int security_token_id); |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 150 | |
ricow@chromium.org | c9c8082 | 2010-04-21 08:22:37 +0000 | [diff] [blame] | 151 | double TicksToMillis(unsigned ticks) const { |
| 152 | return ticks * ms_to_ticks_scale_; |
| 153 | } |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 154 | ProfileNode* root() const { return root_; } |
ricow@chromium.org | c9c8082 | 2010-04-21 08:22:37 +0000 | [diff] [blame] | 155 | void SetTickRatePerMs(double ticks_per_ms); |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 156 | |
| 157 | void ShortPrint(); |
| 158 | void Print() { |
| 159 | root_->Print(0); |
| 160 | } |
| 161 | |
| 162 | private: |
| 163 | template <typename Callback> |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 164 | void TraverseDepthFirst(Callback* callback); |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 165 | |
ager@chromium.org | 357bf65 | 2010-04-12 11:30:10 +0000 | [diff] [blame] | 166 | CodeEntry root_entry_; |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 167 | ProfileNode* root_; |
ricow@chromium.org | c9c8082 | 2010-04-21 08:22:37 +0000 | [diff] [blame] | 168 | double ms_to_ticks_scale_; |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 169 | |
| 170 | DISALLOW_COPY_AND_ASSIGN(ProfileTree); |
| 171 | }; |
| 172 | |
| 173 | |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 174 | class CpuProfile { |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 175 | public: |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 176 | CpuProfile(const char* title, unsigned uid) |
| 177 | : title_(title), uid_(uid) { } |
| 178 | |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 179 | // Add pc -> ... -> main() call path to the profile. |
| 180 | void AddPath(const Vector<CodeEntry*>& path); |
| 181 | void CalculateTotalTicks(); |
ricow@chromium.org | c9c8082 | 2010-04-21 08:22:37 +0000 | [diff] [blame] | 182 | void SetActualSamplingRate(double actual_sampling_rate); |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 183 | CpuProfile* FilteredClone(int security_token_id); |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 184 | |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 185 | INLINE(const char* title() const) { return title_; } |
| 186 | INLINE(unsigned uid() const) { return uid_; } |
| 187 | INLINE(const ProfileTree* top_down() const) { return &top_down_; } |
| 188 | INLINE(const ProfileTree* bottom_up() const) { return &bottom_up_; } |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 189 | |
ricow@chromium.org | c9c8082 | 2010-04-21 08:22:37 +0000 | [diff] [blame] | 190 | void UpdateTicksScale(); |
| 191 | |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 192 | void ShortPrint(); |
| 193 | void Print(); |
| 194 | |
| 195 | private: |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 196 | const char* title_; |
| 197 | unsigned uid_; |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 198 | ProfileTree top_down_; |
| 199 | ProfileTree bottom_up_; |
| 200 | |
| 201 | DISALLOW_COPY_AND_ASSIGN(CpuProfile); |
| 202 | }; |
| 203 | |
| 204 | |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 205 | class CodeMap { |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 206 | public: |
| 207 | CodeMap() { } |
| 208 | INLINE(void AddCode(Address addr, CodeEntry* entry, unsigned size)); |
| 209 | INLINE(void MoveCode(Address from, Address to)); |
| 210 | INLINE(void DeleteCode(Address addr)); |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 211 | void AddAlias(Address start, CodeEntry* entry, Address code_start); |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 212 | CodeEntry* FindEntry(Address addr); |
| 213 | |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 214 | void Print(); |
| 215 | |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 216 | private: |
| 217 | struct CodeEntryInfo { |
| 218 | CodeEntryInfo(CodeEntry* an_entry, unsigned a_size) |
| 219 | : entry(an_entry), size(a_size) { } |
| 220 | CodeEntry* entry; |
| 221 | unsigned size; |
| 222 | }; |
| 223 | |
| 224 | struct CodeTreeConfig { |
| 225 | typedef Address Key; |
| 226 | typedef CodeEntryInfo Value; |
| 227 | static const Key kNoKey; |
| 228 | static const Value kNoValue; |
| 229 | static int Compare(const Key& a, const Key& b) { |
| 230 | return a < b ? -1 : (a > b ? 1 : 0); |
| 231 | } |
| 232 | }; |
| 233 | typedef SplayTree<CodeTreeConfig> CodeTree; |
| 234 | |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 235 | class CodeTreePrinter { |
| 236 | public: |
| 237 | void Call(const Address& key, const CodeEntryInfo& value); |
| 238 | }; |
| 239 | |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 240 | CodeTree tree_; |
| 241 | |
| 242 | DISALLOW_COPY_AND_ASSIGN(CodeMap); |
| 243 | }; |
| 244 | |
| 245 | |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 246 | class CpuProfilesCollection { |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 247 | public: |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 248 | CpuProfilesCollection(); |
| 249 | ~CpuProfilesCollection(); |
| 250 | |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 251 | bool StartProfiling(const char* title, unsigned uid); |
| 252 | bool StartProfiling(String* title, unsigned uid); |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 253 | CpuProfile* StopProfiling(int security_token_id, |
| 254 | const char* title, |
| 255 | double actual_sampling_rate); |
| 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); |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 261 | inline bool is_last_profile(); |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 262 | |
sgjesse@chromium.org | 82dbbab | 2010-06-02 08:57:44 +0000 | [diff] [blame^] | 263 | const char* GetName(String* name); |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 264 | CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, |
| 265 | String* name, String* resource_name, int line_number); |
| 266 | CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, const char* name); |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 267 | CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, |
| 268 | const char* name_prefix, String* name); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 269 | CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, int args_count); |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 270 | CodeEntry* NewCodeEntry(int security_token_id); |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 271 | |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 272 | // Called from profile generator thread. |
| 273 | void AddPathToCurrentProfiles(const Vector<CodeEntry*>& path); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 274 | |
| 275 | private: |
ager@chromium.org | 357bf65 | 2010-04-12 11:30:10 +0000 | [diff] [blame] | 276 | INLINE(const char* GetFunctionName(String* name)); |
| 277 | INLINE(const char* GetFunctionName(const char* name)); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 278 | const char* GetName(int args_count); |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 279 | List<CpuProfile*>* GetProfilesList(int security_token_id); |
| 280 | int TokenToIndex(int security_token_id); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 281 | |
| 282 | INLINE(static bool StringsMatch(void* key1, void* key2)) { |
| 283 | return strcmp(reinterpret_cast<char*>(key1), |
| 284 | reinterpret_cast<char*>(key2)) == 0; |
| 285 | } |
| 286 | |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 287 | INLINE(static bool UidsMatch(void* key1, void* key2)) { |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 288 | return key1 == key2; |
| 289 | } |
| 290 | |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 291 | // String::Hash -> const char* |
| 292 | HashMap function_and_resource_names_; |
| 293 | // args_count -> char* |
| 294 | List<char*> args_count_names_; |
| 295 | List<CodeEntry*> code_entries_; |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 296 | List<List<CpuProfile*>* > profiles_by_token_; |
| 297 | // uid -> index |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 298 | HashMap profiles_uids_; |
| 299 | |
| 300 | // Accessed by VM thread and profile generator thread. |
| 301 | List<CpuProfile*> current_profiles_; |
| 302 | Semaphore* current_profiles_semaphore_; |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 303 | |
| 304 | DISALLOW_COPY_AND_ASSIGN(CpuProfilesCollection); |
| 305 | }; |
| 306 | |
| 307 | |
ricow@chromium.org | c9c8082 | 2010-04-21 08:22:37 +0000 | [diff] [blame] | 308 | class SampleRateCalculator { |
| 309 | public: |
| 310 | SampleRateCalculator() |
| 311 | : result_(Logger::kSamplingIntervalMs * kResultScale), |
| 312 | ticks_per_ms_(Logger::kSamplingIntervalMs), |
| 313 | measurements_count_(0), |
| 314 | wall_time_query_countdown_(1) { |
| 315 | } |
| 316 | |
| 317 | double ticks_per_ms() { |
| 318 | return result_ / static_cast<double>(kResultScale); |
| 319 | } |
| 320 | void Tick(); |
| 321 | void UpdateMeasurements(double current_time); |
| 322 | |
| 323 | // Instead of querying current wall time each tick, |
| 324 | // we use this constant to control query intervals. |
| 325 | static const unsigned kWallTimeQueryIntervalMs = 100; |
| 326 | |
| 327 | private: |
| 328 | // As the result needs to be accessed from a different thread, we |
| 329 | // use type that guarantees atomic writes to memory. There should |
| 330 | // be <= 1000 ticks per second, thus storing a value of a 10 ** 5 |
| 331 | // order should provide enough precision while keeping away from a |
| 332 | // potential overflow. |
| 333 | static const int kResultScale = 100000; |
| 334 | |
| 335 | AtomicWord result_; |
| 336 | // All other fields are accessed only from the sampler thread. |
| 337 | double ticks_per_ms_; |
| 338 | unsigned measurements_count_; |
| 339 | unsigned wall_time_query_countdown_; |
| 340 | double last_wall_time_; |
| 341 | }; |
| 342 | |
| 343 | |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 344 | class ProfileGenerator { |
| 345 | public: |
| 346 | explicit ProfileGenerator(CpuProfilesCollection* profiles); |
| 347 | |
| 348 | INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, |
| 349 | String* name, |
| 350 | String* resource_name, |
| 351 | int line_number)) { |
| 352 | return profiles_->NewCodeEntry(tag, name, resource_name, line_number); |
| 353 | } |
| 354 | |
| 355 | INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, |
| 356 | const char* name)) { |
| 357 | return profiles_->NewCodeEntry(tag, name); |
| 358 | } |
| 359 | |
| 360 | INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 361 | const char* name_prefix, |
| 362 | String* name)) { |
| 363 | return profiles_->NewCodeEntry(tag, name_prefix, name); |
| 364 | } |
| 365 | |
| 366 | INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 367 | int args_count)) { |
| 368 | return profiles_->NewCodeEntry(tag, args_count); |
| 369 | } |
| 370 | |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 371 | INLINE(CodeEntry* NewCodeEntry(int security_token_id)) { |
| 372 | return profiles_->NewCodeEntry(security_token_id); |
| 373 | } |
| 374 | |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 375 | void RecordTickSample(const TickSample& sample); |
| 376 | |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 377 | INLINE(CodeMap* code_map()) { return &code_map_; } |
| 378 | |
ricow@chromium.org | c9c8082 | 2010-04-21 08:22:37 +0000 | [diff] [blame] | 379 | INLINE(void Tick()) { sample_rate_calc_.Tick(); } |
| 380 | INLINE(double actual_sampling_rate()) { |
| 381 | return sample_rate_calc_.ticks_per_ms(); |
| 382 | } |
| 383 | |
ager@chromium.org | 357bf65 | 2010-04-12 11:30:10 +0000 | [diff] [blame] | 384 | static const char* kAnonymousFunctionName; |
| 385 | static const char* kProgramEntryName; |
| 386 | static const char* kGarbageCollectorEntryName; |
| 387 | |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 388 | private: |
ager@chromium.org | 357bf65 | 2010-04-12 11:30:10 +0000 | [diff] [blame] | 389 | INLINE(CodeEntry* EntryForVMState(StateTag tag)); |
| 390 | |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 391 | CpuProfilesCollection* profiles_; |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 392 | CodeMap code_map_; |
ager@chromium.org | 357bf65 | 2010-04-12 11:30:10 +0000 | [diff] [blame] | 393 | CodeEntry* program_entry_; |
| 394 | CodeEntry* gc_entry_; |
ricow@chromium.org | c9c8082 | 2010-04-21 08:22:37 +0000 | [diff] [blame] | 395 | SampleRateCalculator sample_rate_calc_; |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 396 | |
| 397 | DISALLOW_COPY_AND_ASSIGN(ProfileGenerator); |
| 398 | }; |
| 399 | |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 400 | } } // namespace v8::internal |
| 401 | |
ricow@chromium.org | c9c8082 | 2010-04-21 08:22:37 +0000 | [diff] [blame] | 402 | #endif // ENABLE_LOGGING_AND_PROFILING |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 403 | |
fschneider@chromium.org | 086aac6 | 2010-03-17 13:18:24 +0000 | [diff] [blame] | 404 | #endif // V8_PROFILE_GENERATOR_H_ |