1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/profiler/strings-storage.h" 6 7 #include <memory> 8 9 #include "src/objects-inl.h" 10 11 namespace v8 { 12 namespace internal { 13 14 15 bool StringsStorage::StringsMatch(void* key1, void* key2) { 16 return strcmp(reinterpret_cast<char*>(key1), reinterpret_cast<char*>(key2)) == 17 0; 18 } 19 20 21 StringsStorage::StringsStorage(Heap* heap) 22 : hash_seed_(heap->HashSeed()), names_(StringsMatch) {} 23 24 25 StringsStorage::~StringsStorage() { 26 for (base::HashMap::Entry* p = names_.Start(); p != NULL; 27 p = names_.Next(p)) { 28 DeleteArray(reinterpret_cast<const char*>(p->value)); 29 } 30 } 31 32 33 const char* StringsStorage::GetCopy(const char* src) { 34 int len = static_cast<int>(strlen(src)); 35 base::HashMap::Entry* entry = GetEntry(src, len); 36 if (entry->value == NULL) { 37 Vector<char> dst = Vector<char>::New(len + 1); 38 StrNCpy(dst, src, len); 39 dst[len] = '\0'; 40 entry->key = dst.start(); 41 entry->value = entry->key; 42 } 43 return reinterpret_cast<const char*>(entry->value); 44 } 45 46 47 const char* StringsStorage::GetFormatted(const char* format, ...) { 48 va_list args; 49 va_start(args, format); 50 const char* result = GetVFormatted(format, args); 51 va_end(args); 52 return result; 53 } 54 55 56 const char* StringsStorage::AddOrDisposeString(char* str, int len) { 57 base::HashMap::Entry* entry = GetEntry(str, len); 58 if (entry->value == NULL) { 59 // New entry added. 60 entry->key = str; 61 entry->value = str; 62 } else { 63 DeleteArray(str); 64 } 65 return reinterpret_cast<const char*>(entry->value); 66 } 67 68 69 const char* StringsStorage::GetVFormatted(const char* format, va_list args) { 70 Vector<char> str = Vector<char>::New(1024); 71 int len = VSNPrintF(str, format, args); 72 if (len == -1) { 73 DeleteArray(str.start()); 74 return GetCopy(format); 75 } 76 return AddOrDisposeString(str.start(), len); 77 } 78 79 80 const char* StringsStorage::GetName(Name* name) { 81 if (name->IsString()) { 82 String* str = String::cast(name); 83 int length = Min(kMaxNameSize, str->length()); 84 int actual_length = 0; 85 std::unique_ptr<char[]> data = str->ToCString( 86 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL, 0, length, &actual_length); 87 return AddOrDisposeString(data.release(), actual_length); 88 } else if (name->IsSymbol()) { 89 return "<symbol>"; 90 } 91 return ""; 92 } 93 94 95 const char* StringsStorage::GetName(int index) { 96 return GetFormatted("%d", index); 97 } 98 99 100 const char* StringsStorage::GetFunctionName(Name* name) { 101 return GetName(name); 102 } 103 104 105 const char* StringsStorage::GetFunctionName(const char* name) { 106 return GetCopy(name); 107 } 108 109 110 size_t StringsStorage::GetUsedMemorySize() const { 111 size_t size = sizeof(*this); 112 size += sizeof(base::HashMap::Entry) * names_.capacity(); 113 for (base::HashMap::Entry* p = names_.Start(); p != NULL; 114 p = names_.Next(p)) { 115 size += strlen(reinterpret_cast<const char*>(p->value)) + 1; 116 } 117 return size; 118 } 119 120 base::HashMap::Entry* StringsStorage::GetEntry(const char* str, int len) { 121 uint32_t hash = StringHasher::HashSequentialString(str, len, hash_seed_); 122 return names_.LookupOrInsert(const_cast<char*>(str), hash); 123 } 124 } // namespace internal 125 } // namespace v8 126