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 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 if (tree_.FindGreatestLessThan(addr, &locator)) { | 226 if (tree_.FindGreatestLessThan(addr, &locator)) { |
227 // locator.key() <= addr. Need to check that addr is within entry. | 227 // locator.key() <= addr. Need to check that addr is within entry. |
228 const CodeEntryInfo& entry = locator.value(); | 228 const CodeEntryInfo& entry = locator.value(); |
229 if (addr < (locator.key() + entry.size)) | 229 if (addr < (locator.key() + entry.size)) |
230 return entry.entry; | 230 return entry.entry; |
231 } | 231 } |
232 return NULL; | 232 return NULL; |
233 } | 233 } |
234 | 234 |
235 | 235 |
236 ProfileGenerator::ProfileGenerator() | 236 CpuProfilesCollection::CpuProfilesCollection() |
237 : resource_names_(StringsMatch) { | 237 : function_and_resource_names_(StringsMatch) { |
238 } | 238 } |
239 | 239 |
240 | 240 |
241 static void CodeEntriesDeleter(CodeEntry** entry_ptr) { | 241 static void DeleteArgsCountName(char** name_ptr) { |
| 242 DeleteArray(*name_ptr); |
| 243 } |
| 244 |
| 245 |
| 246 static void DeleteCodeEntry(CodeEntry** entry_ptr) { |
242 delete *entry_ptr; | 247 delete *entry_ptr; |
243 } | 248 } |
244 | 249 |
245 | 250 static void DeleteCpuProfile(CpuProfile** profile_ptr) { |
246 ProfileGenerator::~ProfileGenerator() { | 251 delete *profile_ptr; |
247 for (HashMap::Entry* p = resource_names_.Start(); | |
248 p != NULL; | |
249 p = resource_names_.Next(p)) { | |
250 DeleteArray(reinterpret_cast<const char*>(p->value)); | |
251 } | |
252 | |
253 code_entries_.Iterate(CodeEntriesDeleter); | |
254 } | 252 } |
255 | 253 |
256 | 254 |
257 CodeEntry* ProfileGenerator::NewCodeEntry( | 255 CpuProfilesCollection::~CpuProfilesCollection() { |
258 Logger::LogEventsAndTags tag, | 256 profiles_.Iterate(DeleteCpuProfile); |
259 String* name, | 257 code_entries_.Iterate(DeleteCodeEntry); |
260 String* resource_name, int line_number) { | 258 args_count_names_.Iterate(DeleteArgsCountName); |
261 const char* cached_resource_name = NULL; | 259 for (HashMap::Entry* p = function_and_resource_names_.Start(); |
262 if (resource_name->IsString()) { | 260 p != NULL; |
263 // As we copy contents of resource names, and usually they are repeated, | 261 p = function_and_resource_names_.Next(p)) { |
264 // we cache names by string hashcode. | 262 DeleteArray(reinterpret_cast<const char*>(p->value)); |
265 HashMap::Entry* cache_entry = | |
266 resource_names_.Lookup(resource_name, | |
267 StringEntryHash(resource_name), | |
268 true); | |
269 if (cache_entry->value == NULL) { | |
270 // New entry added. | |
271 cache_entry->value = | |
272 resource_name->ToCString(DISALLOW_NULLS, | |
273 ROBUST_STRING_TRAVERSAL).Detach(); | |
274 } | |
275 cached_resource_name = reinterpret_cast<const char*>(cache_entry->value); | |
276 } | 263 } |
| 264 } |
277 | 265 |
278 CodeEntry* entry = new ManagedNameCodeEntry(tag, | 266 |
279 name, | 267 void CpuProfilesCollection::AddProfile(unsigned uid) { |
280 cached_resource_name, | 268 profiles_.Add(new CpuProfile()); |
281 line_number); | 269 } |
| 270 |
| 271 |
| 272 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, |
| 273 String* name, |
| 274 String* resource_name, |
| 275 int line_number) { |
| 276 CodeEntry* entry = new CodeEntry(tag, |
| 277 GetName(name), |
| 278 GetName(resource_name), |
| 279 line_number); |
282 code_entries_.Add(entry); | 280 code_entries_.Add(entry); |
283 return entry; | 281 return entry; |
284 } | 282 } |
285 | 283 |
286 | 284 |
287 CodeEntry* ProfileGenerator::NewCodeEntry( | 285 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, |
288 Logger::LogEventsAndTags tag, | 286 const char* name) { |
289 const char* name) { | 287 CodeEntry* entry = new CodeEntry(tag, name, "", 0); |
290 CodeEntry* entry = new StaticNameCodeEntry(tag, name); | |
291 code_entries_.Add(entry); | 288 code_entries_.Add(entry); |
292 return entry; | 289 return entry; |
293 } | 290 } |
294 | 291 |
| 292 |
| 293 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, |
| 294 int args_count) { |
| 295 CodeEntry* entry = new CodeEntry(tag, GetName(args_count), "", 0); |
| 296 code_entries_.Add(entry); |
| 297 return entry; |
| 298 } |
| 299 |
| 300 |
| 301 const char* CpuProfilesCollection::GetName(String* name) { |
| 302 if (name->IsString()) { |
| 303 char* c_name = |
| 304 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(); |
| 305 HashMap::Entry* cache_entry = |
| 306 function_and_resource_names_.Lookup(c_name, |
| 307 name->Hash(), |
| 308 true); |
| 309 if (cache_entry->value == NULL) { |
| 310 // New entry added. |
| 311 cache_entry->value = c_name; |
| 312 } else { |
| 313 DeleteArray(c_name); |
| 314 } |
| 315 return reinterpret_cast<const char*>(cache_entry->value); |
| 316 } else { |
| 317 return ""; |
| 318 } |
| 319 } |
| 320 |
| 321 |
| 322 const char* CpuProfilesCollection::GetName(int args_count) { |
| 323 ASSERT(args_count >= 0); |
| 324 if (args_count_names_.length() <= args_count) { |
| 325 args_count_names_.AddBlock( |
| 326 NULL, args_count - args_count_names_.length() + 1); |
| 327 } |
| 328 if (args_count_names_[args_count] == NULL) { |
| 329 const int kMaximumNameLength = 32; |
| 330 char* name = NewArray<char>(kMaximumNameLength); |
| 331 OS::SNPrintF(Vector<char>(name, kMaximumNameLength), |
| 332 "args_count: %d", args_count); |
| 333 args_count_names_[args_count] = name; |
| 334 } |
| 335 return args_count_names_[args_count]; |
| 336 } |
| 337 |
| 338 |
| 339 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles) |
| 340 : profiles_(profiles) { |
| 341 } |
| 342 |
| 343 |
| 344 void ProfileGenerator::RecordTickSample(const TickSample& sample) { |
| 345 // Allocate space for stack frames + pc + function. |
| 346 ScopedVector<CodeEntry*> entries(sample.frames_count + 2); |
| 347 CodeEntry** entry = entries.start(); |
| 348 *entry++ = code_map_.FindEntry(sample.pc); |
| 349 |
| 350 if (sample.function != NULL) { |
| 351 *entry = code_map_.FindEntry(sample.function); |
| 352 if (*entry != NULL && !(*entry)->is_js_function()) { |
| 353 *entry = NULL; |
| 354 } else { |
| 355 CodeEntry* pc_entry = *entries.start(); |
| 356 if (pc_entry == NULL || pc_entry->is_js_function()) |
| 357 *entry = NULL; |
| 358 } |
| 359 entry++; |
| 360 } else { |
| 361 *entry++ = NULL; |
| 362 } |
| 363 |
| 364 for (const Address *stack_pos = sample.stack, |
| 365 *stack_end = stack_pos + sample.frames_count; |
| 366 stack_pos != stack_end; |
| 367 ++stack_pos) { |
| 368 *entry++ = code_map_.FindEntry(*stack_pos); |
| 369 } |
| 370 |
| 371 profile()->AddPath(entries); |
| 372 } |
| 373 |
| 374 |
295 } } // namespace v8::internal | 375 } } // namespace v8::internal |
OLD | NEW |