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
StringsMatch(void * key1,void * key2)15 bool StringsStorage::StringsMatch(void* key1, void* key2) {
16 return strcmp(reinterpret_cast<char*>(key1), reinterpret_cast<char*>(key2)) ==
17 0;
18 }
19
20
StringsStorage(Heap * heap)21 StringsStorage::StringsStorage(Heap* heap)
22 : hash_seed_(heap->HashSeed()), names_(StringsMatch) {}
23
24
~StringsStorage()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
GetCopy(const char * src)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
GetFormatted(const char * format,...)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
AddOrDisposeString(char * str,int len)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
GetVFormatted(const char * format,va_list args)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
GetName(Name * name)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
GetName(int index)95 const char* StringsStorage::GetName(int index) {
96 return GetFormatted("%d", index);
97 }
98
99
GetFunctionName(Name * name)100 const char* StringsStorage::GetFunctionName(Name* name) {
101 return GetName(name);
102 }
103
104
GetFunctionName(const char * name)105 const char* StringsStorage::GetFunctionName(const char* name) {
106 return GetCopy(name);
107 }
108
109
GetUsedMemorySize() const110 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
GetEntry(const char * str,int len)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