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