| 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 |