| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 23 matching lines...) Expand all Loading... |
| 34 #include "sampler.h" | 34 #include "sampler.h" |
| 35 #include "global-handles.h" | 35 #include "global-handles.h" |
| 36 #include "scopeinfo.h" | 36 #include "scopeinfo.h" |
| 37 #include "unicode.h" | 37 #include "unicode.h" |
| 38 #include "zone-inl.h" | 38 #include "zone-inl.h" |
| 39 | 39 |
| 40 namespace v8 { | 40 namespace v8 { |
| 41 namespace internal { | 41 namespace internal { |
| 42 | 42 |
| 43 | 43 |
| 44 bool StringsStorage::StringsMatch(void* key1, void* key2) { |
| 45 return strcmp(reinterpret_cast<char*>(key1), |
| 46 reinterpret_cast<char*>(key2)) == 0; |
| 47 } |
| 48 |
| 49 |
| 44 StringsStorage::StringsStorage(Heap* heap) | 50 StringsStorage::StringsStorage(Heap* heap) |
| 45 : hash_seed_(heap->HashSeed()), names_(StringsMatch) { | 51 : hash_seed_(heap->HashSeed()), names_(StringsMatch) { |
| 46 } | 52 } |
| 47 | 53 |
| 48 | 54 |
| 49 StringsStorage::~StringsStorage() { | 55 StringsStorage::~StringsStorage() { |
| 50 for (HashMap::Entry* p = names_.Start(); | 56 for (HashMap::Entry* p = names_.Start(); |
| 51 p != NULL; | 57 p != NULL; |
| 52 p = names_.Next(p)) { | 58 p = names_.Next(p)) { |
| 53 DeleteArray(reinterpret_cast<const char*>(p->value)); | 59 DeleteArray(reinterpret_cast<const char*>(p->value)); |
| 54 } | 60 } |
| 55 } | 61 } |
| 56 | 62 |
| 57 | 63 |
| 58 const char* StringsStorage::GetCopy(const char* src) { | 64 const char* StringsStorage::GetCopy(const char* src) { |
| 59 int len = static_cast<int>(strlen(src)); | 65 int len = static_cast<int>(strlen(src)); |
| 60 Vector<char> dst = Vector<char>::New(len + 1); | 66 HashMap::Entry* entry = GetEntry(src, len); |
| 61 OS::StrNCpy(dst, src, len); | 67 if (entry->value == NULL) { |
| 62 dst[len] = '\0'; | 68 Vector<char> dst = Vector<char>::New(len + 1); |
| 63 uint32_t hash = | 69 OS::StrNCpy(dst, src, len); |
| 64 StringHasher::HashSequentialString(dst.start(), len, hash_seed_); | 70 dst[len] = '\0'; |
| 65 return AddOrDisposeString(dst.start(), hash); | 71 entry->key = dst.start(); |
| 72 entry->value = entry->key; |
| 73 } |
| 74 return reinterpret_cast<const char*>(entry->value); |
| 66 } | 75 } |
| 67 | 76 |
| 68 | 77 |
| 69 const char* StringsStorage::GetFormatted(const char* format, ...) { | 78 const char* StringsStorage::GetFormatted(const char* format, ...) { |
| 70 va_list args; | 79 va_list args; |
| 71 va_start(args, format); | 80 va_start(args, format); |
| 72 const char* result = GetVFormatted(format, args); | 81 const char* result = GetVFormatted(format, args); |
| 73 va_end(args); | 82 va_end(args); |
| 74 return result; | 83 return result; |
| 75 } | 84 } |
| 76 | 85 |
| 77 | 86 |
| 78 const char* StringsStorage::AddOrDisposeString(char* str, uint32_t hash) { | 87 const char* StringsStorage::AddOrDisposeString(char* str, int len) { |
| 79 HashMap::Entry* cache_entry = names_.Lookup(str, hash, true); | 88 HashMap::Entry* entry = GetEntry(str, len); |
| 80 if (cache_entry->value == NULL) { | 89 if (entry->value == NULL) { |
| 81 // New entry added. | 90 // New entry added. |
| 82 cache_entry->value = str; | 91 entry->key = str; |
| 92 entry->value = str; |
| 83 } else { | 93 } else { |
| 84 DeleteArray(str); | 94 DeleteArray(str); |
| 85 } | 95 } |
| 86 return reinterpret_cast<const char*>(cache_entry->value); | 96 return reinterpret_cast<const char*>(entry->value); |
| 87 } | 97 } |
| 88 | 98 |
| 89 | 99 |
| 90 const char* StringsStorage::GetVFormatted(const char* format, va_list args) { | 100 const char* StringsStorage::GetVFormatted(const char* format, va_list args) { |
| 91 Vector<char> str = Vector<char>::New(1024); | 101 Vector<char> str = Vector<char>::New(1024); |
| 92 int len = OS::VSNPrintF(str, format, args); | 102 int len = OS::VSNPrintF(str, format, args); |
| 93 if (len == -1) { | 103 if (len == -1) { |
| 94 DeleteArray(str.start()); | 104 DeleteArray(str.start()); |
| 95 return format; | 105 return GetCopy(format); |
| 96 } | 106 } |
| 97 uint32_t hash = StringHasher::HashSequentialString( | 107 return AddOrDisposeString(str.start(), len); |
| 98 str.start(), len, hash_seed_); | |
| 99 return AddOrDisposeString(str.start(), hash); | |
| 100 } | 108 } |
| 101 | 109 |
| 102 | 110 |
| 103 const char* StringsStorage::GetName(Name* name) { | 111 const char* StringsStorage::GetName(Name* name) { |
| 104 if (name->IsString()) { | 112 if (name->IsString()) { |
| 105 String* str = String::cast(name); | 113 String* str = String::cast(name); |
| 106 int length = Min(kMaxNameSize, str->length()); | 114 int length = Min(kMaxNameSize, str->length()); |
| 115 int actual_length = 0; |
| 107 SmartArrayPointer<char> data = | 116 SmartArrayPointer<char> data = |
| 108 str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL, 0, length); | 117 str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL, 0, length, |
| 109 uint32_t hash = StringHasher::HashSequentialString( | 118 &actual_length); |
| 110 *data, length, name->GetHeap()->HashSeed()); | 119 return AddOrDisposeString(data.Detach(), actual_length); |
| 111 return AddOrDisposeString(data.Detach(), hash); | |
| 112 } else if (name->IsSymbol()) { | 120 } else if (name->IsSymbol()) { |
| 113 return "<symbol>"; | 121 return "<symbol>"; |
| 114 } | 122 } |
| 115 return ""; | 123 return ""; |
| 116 } | 124 } |
| 117 | 125 |
| 118 | 126 |
| 119 const char* StringsStorage::GetName(int index) { | 127 const char* StringsStorage::GetName(int index) { |
| 120 return GetFormatted("%d", index); | 128 return GetFormatted("%d", index); |
| 121 } | 129 } |
| 122 | 130 |
| 123 | 131 |
| 132 const char* StringsStorage::GetFunctionName(Name* name) { |
| 133 return BeautifyFunctionName(GetName(name)); |
| 134 } |
| 135 |
| 136 |
| 137 const char* StringsStorage::GetFunctionName(const char* name) { |
| 138 return BeautifyFunctionName(GetCopy(name)); |
| 139 } |
| 140 |
| 141 |
| 142 const char* StringsStorage::BeautifyFunctionName(const char* name) { |
| 143 return (*name == 0) ? ProfileGenerator::kAnonymousFunctionName : name; |
| 144 } |
| 145 |
| 146 |
| 124 size_t StringsStorage::GetUsedMemorySize() const { | 147 size_t StringsStorage::GetUsedMemorySize() const { |
| 125 size_t size = sizeof(*this); | 148 size_t size = sizeof(*this); |
| 126 size += sizeof(HashMap::Entry) * names_.capacity(); | 149 size += sizeof(HashMap::Entry) * names_.capacity(); |
| 127 for (HashMap::Entry* p = names_.Start(); p != NULL; p = names_.Next(p)) { | 150 for (HashMap::Entry* p = names_.Start(); p != NULL; p = names_.Next(p)) { |
| 128 size += strlen(reinterpret_cast<const char*>(p->value)) + 1; | 151 size += strlen(reinterpret_cast<const char*>(p->value)) + 1; |
| 129 } | 152 } |
| 130 return size; | 153 return size; |
| 131 } | 154 } |
| 132 | 155 |
| 133 | 156 |
| 157 HashMap::Entry* StringsStorage::GetEntry(const char* str, int len) { |
| 158 uint32_t hash = StringHasher::HashSequentialString(str, len, hash_seed_); |
| 159 return names_.Lookup(const_cast<char*>(str), hash, true); |
| 160 } |
| 161 |
| 162 |
| 134 const char* const CodeEntry::kEmptyNamePrefix = ""; | 163 const char* const CodeEntry::kEmptyNamePrefix = ""; |
| 135 const char* const CodeEntry::kEmptyResourceName = ""; | 164 const char* const CodeEntry::kEmptyResourceName = ""; |
| 136 const char* const CodeEntry::kEmptyBailoutReason = ""; | 165 const char* const CodeEntry::kEmptyBailoutReason = ""; |
| 137 | 166 |
| 138 | 167 |
| 139 CodeEntry::~CodeEntry() { | 168 CodeEntry::~CodeEntry() { |
| 140 delete no_frame_ranges_; | 169 delete no_frame_ranges_; |
| 141 } | 170 } |
| 142 | 171 |
| 143 | 172 |
| 144 void CodeEntry::CopyData(const CodeEntry& source) { | |
| 145 tag_ = source.tag_; | |
| 146 name_prefix_ = source.name_prefix_; | |
| 147 name_ = source.name_; | |
| 148 resource_name_ = source.resource_name_; | |
| 149 line_number_ = source.line_number_; | |
| 150 } | |
| 151 | |
| 152 | |
| 153 uint32_t CodeEntry::GetCallUid() const { | 173 uint32_t CodeEntry::GetCallUid() const { |
| 154 uint32_t hash = ComputeIntegerHash(tag_, v8::internal::kZeroHashSeed); | 174 uint32_t hash = ComputeIntegerHash(tag_, v8::internal::kZeroHashSeed); |
| 155 if (shared_id_ != 0) { | 175 if (shared_id_ != 0) { |
| 156 hash ^= ComputeIntegerHash(static_cast<uint32_t>(shared_id_), | 176 hash ^= ComputeIntegerHash(static_cast<uint32_t>(shared_id_), |
| 157 v8::internal::kZeroHashSeed); | 177 v8::internal::kZeroHashSeed); |
| 158 } else { | 178 } else { |
| 159 hash ^= ComputeIntegerHash( | 179 hash ^= ComputeIntegerHash( |
| 160 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_prefix_)), | 180 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_prefix_)), |
| 161 v8::internal::kZeroHashSeed); | 181 v8::internal::kZeroHashSeed); |
| 162 hash ^= ComputeIntegerHash( | 182 hash ^= ComputeIntegerHash( |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 539 } | 559 } |
| 540 current_profiles_semaphore_.Signal(); | 560 current_profiles_semaphore_.Signal(); |
| 541 } | 561 } |
| 542 | 562 |
| 543 | 563 |
| 544 CodeEntry* CpuProfilesCollection::NewCodeEntry( | 564 CodeEntry* CpuProfilesCollection::NewCodeEntry( |
| 545 Logger::LogEventsAndTags tag, | 565 Logger::LogEventsAndTags tag, |
| 546 const char* name, | 566 const char* name, |
| 547 const char* name_prefix, | 567 const char* name_prefix, |
| 548 const char* resource_name, | 568 const char* resource_name, |
| 549 int line_number) { | 569 int line_number, |
| 570 int column_number) { |
| 550 CodeEntry* code_entry = new CodeEntry(tag, | 571 CodeEntry* code_entry = new CodeEntry(tag, |
| 551 name, | 572 name, |
| 552 name_prefix, | 573 name_prefix, |
| 553 resource_name, | 574 resource_name, |
| 554 line_number); | 575 line_number, |
| 576 column_number); |
| 555 code_entries_.Add(code_entry); | 577 code_entries_.Add(code_entry); |
| 556 return code_entry; | 578 return code_entry; |
| 557 } | 579 } |
| 558 | 580 |
| 559 | 581 |
| 560 const char* const ProfileGenerator::kAnonymousFunctionName = | 582 const char* const ProfileGenerator::kAnonymousFunctionName = |
| 561 "(anonymous function)"; | 583 "(anonymous function)"; |
| 562 const char* const ProfileGenerator::kProgramEntryName = | 584 const char* const ProfileGenerator::kProgramEntryName = |
| 563 "(program)"; | 585 "(program)"; |
| 564 const char* const ProfileGenerator::kIdleEntryName = | 586 const char* const ProfileGenerator::kIdleEntryName = |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 // If no frames were symbolized, put the VM state entry in. | 675 // If no frames were symbolized, put the VM state entry in. |
| 654 if (no_symbolized_entries) { | 676 if (no_symbolized_entries) { |
| 655 *entry++ = EntryForVMState(sample.state); | 677 *entry++ = EntryForVMState(sample.state); |
| 656 } | 678 } |
| 657 } | 679 } |
| 658 | 680 |
| 659 profiles_->AddPathToCurrentProfiles(entries); | 681 profiles_->AddPathToCurrentProfiles(entries); |
| 660 } | 682 } |
| 661 | 683 |
| 662 | 684 |
| 685 CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) { |
| 686 switch (tag) { |
| 687 case GC: |
| 688 return gc_entry_; |
| 689 case JS: |
| 690 case COMPILER: |
| 691 // DOM events handlers are reported as OTHER / EXTERNAL entries. |
| 692 // To avoid confusing people, let's put all these entries into |
| 693 // one bucket. |
| 694 case OTHER: |
| 695 case EXTERNAL: |
| 696 return program_entry_; |
| 697 case IDLE: |
| 698 return idle_entry_; |
| 699 default: return NULL; |
| 700 } |
| 701 } |
| 702 |
| 663 } } // namespace v8::internal | 703 } } // namespace v8::internal |
| OLD | NEW |