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/allocation.h"
10 #include "src/objects-inl.h"
11
12 namespace v8 {
13 namespace internal {
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
StringsStorage()20 StringsStorage::StringsStorage() : names_(StringsMatch) {}
21
~StringsStorage()22 StringsStorage::~StringsStorage() {
23 for (base::HashMap::Entry* p = names_.Start(); p != nullptr;
24 p = names_.Next(p)) {
25 DeleteArray(reinterpret_cast<const char*>(p->value));
26 }
27 }
28
GetCopy(const char * src)29 const char* StringsStorage::GetCopy(const char* src) {
30 int len = static_cast<int>(strlen(src));
31 base::HashMap::Entry* entry = GetEntry(src, len);
32 if (entry->value == nullptr) {
33 Vector<char> dst = Vector<char>::New(len + 1);
34 StrNCpy(dst, src, len);
35 dst[len] = '\0';
36 entry->key = dst.start();
37 entry->value = entry->key;
38 }
39 return reinterpret_cast<const char*>(entry->value);
40 }
41
GetFormatted(const char * format,...)42 const char* StringsStorage::GetFormatted(const char* format, ...) {
43 va_list args;
44 va_start(args, format);
45 const char* result = GetVFormatted(format, args);
46 va_end(args);
47 return result;
48 }
49
AddOrDisposeString(char * str,int len)50 const char* StringsStorage::AddOrDisposeString(char* str, int len) {
51 base::HashMap::Entry* entry = GetEntry(str, len);
52 if (entry->value == nullptr) {
53 // New entry added.
54 entry->key = str;
55 entry->value = str;
56 } else {
57 DeleteArray(str);
58 }
59 return reinterpret_cast<const char*>(entry->value);
60 }
61
GetVFormatted(const char * format,va_list args)62 const char* StringsStorage::GetVFormatted(const char* format, va_list args) {
63 Vector<char> str = Vector<char>::New(1024);
64 int len = VSNPrintF(str, format, args);
65 if (len == -1) {
66 DeleteArray(str.start());
67 return GetCopy(format);
68 }
69 return AddOrDisposeString(str.start(), len);
70 }
71
GetName(Name * name)72 const char* StringsStorage::GetName(Name* name) {
73 if (name->IsString()) {
74 String* str = String::cast(name);
75 int length = Min(FLAG_heap_snapshot_string_limit, str->length());
76 int actual_length = 0;
77 std::unique_ptr<char[]> data = str->ToCString(
78 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL, 0, length, &actual_length);
79 return AddOrDisposeString(data.release(), actual_length);
80 } else if (name->IsSymbol()) {
81 return "<symbol>";
82 }
83 return "";
84 }
85
GetName(int index)86 const char* StringsStorage::GetName(int index) {
87 return GetFormatted("%d", index);
88 }
89
GetConsName(const char * prefix,Name * name)90 const char* StringsStorage::GetConsName(const char* prefix, Name* name) {
91 if (name->IsString()) {
92 String* str = String::cast(name);
93 int length = Min(FLAG_heap_snapshot_string_limit, str->length());
94 int actual_length = 0;
95 std::unique_ptr<char[]> data = str->ToCString(
96 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL, 0, length, &actual_length);
97
98 int cons_length = actual_length + static_cast<int>(strlen(prefix)) + 1;
99 char* cons_result = NewArray<char>(cons_length);
100 snprintf(cons_result, cons_length, "%s%s", prefix, data.get());
101
102 return AddOrDisposeString(cons_result, cons_length);
103 } else if (name->IsSymbol()) {
104 return "<symbol>";
105 }
106 return "";
107 }
108
GetEntry(const char * str,int len)109 base::HashMap::Entry* StringsStorage::GetEntry(const char* str, int len) {
110 uint32_t hash = StringHasher::HashSequentialString(str, len, kZeroHashSeed);
111 return names_.LookupOrInsert(const_cast<char*>(str), hash);
112 }
113
114 } // namespace internal
115 } // namespace v8
116