| Index: src/profile-generator.cc | 
| diff --git a/src/profile-generator.cc b/src/profile-generator.cc | 
| index 5c64d362c36268e5951d5ab2f43f15e5e0d9836f..9d7c3461cd3eaa790de955389d94f97bd5a77fb8 100644 | 
| --- a/src/profile-generator.cc | 
| +++ b/src/profile-generator.cc | 
| @@ -233,63 +233,143 @@ CodeEntry* CodeMap::FindEntry(Address addr) { | 
| } | 
|  | 
|  | 
| -ProfileGenerator::ProfileGenerator() | 
| -    : resource_names_(StringsMatch) { | 
| +CpuProfilesCollection::CpuProfilesCollection() | 
| +    : function_and_resource_names_(StringsMatch) { | 
| } | 
|  | 
|  | 
| -static void CodeEntriesDeleter(CodeEntry** entry_ptr) { | 
| +static void DeleteArgsCountName(char** name_ptr) { | 
| +  DeleteArray(*name_ptr); | 
| +} | 
| + | 
| + | 
| +static void DeleteCodeEntry(CodeEntry** entry_ptr) { | 
| delete *entry_ptr; | 
| } | 
|  | 
| +static void DeleteCpuProfile(CpuProfile** profile_ptr) { | 
| +  delete *profile_ptr; | 
| +} | 
| + | 
|  | 
| -ProfileGenerator::~ProfileGenerator() { | 
| -  for (HashMap::Entry* p = resource_names_.Start(); | 
| +CpuProfilesCollection::~CpuProfilesCollection() { | 
| +  profiles_.Iterate(DeleteCpuProfile); | 
| +  code_entries_.Iterate(DeleteCodeEntry); | 
| +  args_count_names_.Iterate(DeleteArgsCountName); | 
| +  for (HashMap::Entry* p = function_and_resource_names_.Start(); | 
| p != NULL; | 
| -       p = resource_names_.Next(p)) { | 
| +       p = function_and_resource_names_.Next(p)) { | 
| DeleteArray(reinterpret_cast<const char*>(p->value)); | 
| } | 
| +} | 
|  | 
| -  code_entries_.Iterate(CodeEntriesDeleter); | 
| + | 
| +void CpuProfilesCollection::AddProfile(unsigned uid) { | 
| +  profiles_.Add(new CpuProfile()); | 
| +} | 
| + | 
| + | 
| +CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, | 
| +                                               String* name, | 
| +                                               String* resource_name, | 
| +                                               int line_number) { | 
| +  CodeEntry* entry = new CodeEntry(tag, | 
| +                                   GetName(name), | 
| +                                   GetName(resource_name), | 
| +                                   line_number); | 
| +  code_entries_.Add(entry); | 
| +  return entry; | 
| +} | 
| + | 
| + | 
| +CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, | 
| +                                               const char* name) { | 
| +  CodeEntry* entry = new CodeEntry(tag, name, "", 0); | 
| +  code_entries_.Add(entry); | 
| +  return entry; | 
| +} | 
| + | 
| + | 
| +CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, | 
| +                                               int args_count) { | 
| +  CodeEntry* entry = new CodeEntry(tag, GetName(args_count), "", 0); | 
| +  code_entries_.Add(entry); | 
| +  return entry; | 
| } | 
|  | 
|  | 
| -CodeEntry* ProfileGenerator::NewCodeEntry( | 
| -    Logger::LogEventsAndTags tag, | 
| -    String* name, | 
| -    String* resource_name, int line_number) { | 
| -  const char* cached_resource_name = NULL; | 
| -  if (resource_name->IsString()) { | 
| -    // As we copy contents of resource names, and usually they are repeated, | 
| -    // we cache names by string hashcode. | 
| +const char* CpuProfilesCollection::GetName(String* name) { | 
| +  if (name->IsString()) { | 
| +    char* c_name = | 
| +        name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(); | 
| HashMap::Entry* cache_entry = | 
| -        resource_names_.Lookup(resource_name, | 
| -                               StringEntryHash(resource_name), | 
| -                               true); | 
| +        function_and_resource_names_.Lookup(c_name, | 
| +                                            name->Hash(), | 
| +                                            true); | 
| if (cache_entry->value == NULL) { | 
| // New entry added. | 
| -      cache_entry->value = | 
| -          resource_name->ToCString(DISALLOW_NULLS, | 
| -                                   ROBUST_STRING_TRAVERSAL).Detach(); | 
| +      cache_entry->value = c_name; | 
| +    } else { | 
| +      DeleteArray(c_name); | 
| } | 
| -    cached_resource_name = reinterpret_cast<const char*>(cache_entry->value); | 
| +    return reinterpret_cast<const char*>(cache_entry->value); | 
| +  } else { | 
| +    return ""; | 
| } | 
| +} | 
|  | 
| -  CodeEntry* entry = new ManagedNameCodeEntry(tag, | 
| -                                              name, | 
| -                                              cached_resource_name, | 
| -                                              line_number); | 
| -  code_entries_.Add(entry); | 
| -  return entry; | 
| + | 
| +const char* CpuProfilesCollection::GetName(int args_count) { | 
| +  ASSERT(args_count >= 0); | 
| +  if (args_count_names_.length() <= args_count) { | 
| +    args_count_names_.AddBlock( | 
| +        NULL, args_count - args_count_names_.length() + 1); | 
| +  } | 
| +  if (args_count_names_[args_count] == NULL) { | 
| +    const int kMaximumNameLength = 32; | 
| +    char* name = NewArray<char>(kMaximumNameLength); | 
| +    OS::SNPrintF(Vector<char>(name, kMaximumNameLength), | 
| +                 "args_count: %d", args_count); | 
| +    args_count_names_[args_count] = name; | 
| +  } | 
| +  return args_count_names_[args_count]; | 
| } | 
|  | 
|  | 
| -CodeEntry* ProfileGenerator::NewCodeEntry( | 
| -    Logger::LogEventsAndTags tag, | 
| -    const char* name) { | 
| -  CodeEntry* entry = new StaticNameCodeEntry(tag, name); | 
| -  code_entries_.Add(entry); | 
| -  return entry; | 
| +ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles) | 
| +    : profiles_(profiles) { | 
| } | 
|  | 
| + | 
| +void ProfileGenerator::RecordTickSample(const TickSample& sample) { | 
| +  // Allocate space for stack frames + pc + function. | 
| +  ScopedVector<CodeEntry*> entries(sample.frames_count + 2); | 
| +  CodeEntry** entry = entries.start(); | 
| +  *entry++ = code_map_.FindEntry(sample.pc); | 
| + | 
| +  if (sample.function != NULL) { | 
| +    *entry = code_map_.FindEntry(sample.function); | 
| +    if (*entry != NULL && !(*entry)->is_js_function()) { | 
| +      *entry = NULL; | 
| +    } else { | 
| +      CodeEntry* pc_entry = *entries.start(); | 
| +      if (pc_entry == NULL || pc_entry->is_js_function()) | 
| +        *entry = NULL; | 
| +    } | 
| +    entry++; | 
| +  } else { | 
| +    *entry++ = NULL; | 
| +  } | 
| + | 
| +  for (const Address *stack_pos = sample.stack, | 
| +         *stack_end = stack_pos + sample.frames_count; | 
| +       stack_pos != stack_end; | 
| +       ++stack_pos) { | 
| +    *entry++ = code_map_.FindEntry(*stack_pos); | 
| +  } | 
| + | 
| +  profile()->AddPath(entries); | 
| +} | 
| + | 
| + | 
| } }  // namespace v8::internal | 
|  |