v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
strings-storage.cc
Go to the documentation of this file.
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
6
7#include <memory>
8
9#include "src/base/bits.h"
10#include "src/base/strings.h"
13
14namespace v8 {
15namespace internal {
16
17bool StringsStorage::StringsMatch(void* key1, void* key2) {
18 return strcmp(reinterpret_cast<char*>(key1), reinterpret_cast<char*>(key2)) ==
19 0;
20}
21
23
25 for (base::HashMap::Entry* p = names_.Start(); p != nullptr;
26 p = names_.Next(p)) {
27 DeleteArray(reinterpret_cast<const char*>(p->key));
28 }
29}
30
31const char* StringsStorage::GetCopy(const char* src) {
33 int len = static_cast<int>(strlen(src));
34 base::HashMap::Entry* entry = GetEntry(src, len);
35 if (entry->value == nullptr) {
37 base::StrNCpy(dst, src, len);
38 dst[len] = '\0';
39 entry->key = dst.begin();
40 string_size_ += len;
41 }
42 entry->value =
43 reinterpret_cast<void*>(reinterpret_cast<size_t>(entry->value) + 1);
44 return reinterpret_cast<const char*>(entry->key);
45}
46
47const 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
55const char* StringsStorage::AddOrDisposeString(char* str, size_t len) {
57 base::HashMap::Entry* entry = GetEntry(str, len);
58 if (entry->value == nullptr) {
59 // New entry added.
60 entry->key = str;
61 string_size_ += len;
62 } else {
63 DeleteArray(str);
64 }
65 entry->value =
66 reinterpret_cast<void*>(reinterpret_cast<size_t>(entry->value) + 1);
67 return reinterpret_cast<const char*>(entry->key);
68}
69
70const char* StringsStorage::GetVFormatted(const char* format, va_list args) {
72 int len = base::VSNPrintF(str, format, args);
73 if (len == -1) {
74 DeleteArray(str.begin());
75 return GetCopy(format);
76 }
77 return AddOrDisposeString(str.begin(), len);
78}
79
81 if (!IsString(sym->description())) {
82 return "<symbol>";
83 }
84 Tagged<String> description = Cast<String>(sym->description());
85 uint32_t length = std::min(v8_flags.heap_snapshot_string_limit.value(),
86 description->length());
87 size_t data_length = 0;
88 auto data = description->ToCString(0, length, &data_length);
89 if (sym->is_private_name()) {
90 return AddOrDisposeString(data.release(), data_length);
91 }
92 auto str_length = 8 + data_length + 1 + 1;
93 auto str_result = NewArray<char>(str_length);
94 snprintf(str_result, str_length, "<symbol %s>", data.get());
95 return AddOrDisposeString(str_result, str_length - 1);
96}
97
99 if (IsString(name)) {
100 Tagged<String> str = Cast<String>(name);
101 uint32_t length =
102 std::min(v8_flags.heap_snapshot_string_limit.value(), str->length());
103 size_t data_length = 0;
104 std::unique_ptr<char[]> data = str->ToCString(0, length, &data_length);
105 return AddOrDisposeString(data.release(), data_length);
106 } else if (IsSymbol(name)) {
107 return GetSymbol(Cast<Symbol>(name));
108 }
109 return "";
110}
111
112const char* StringsStorage::GetName(int index) {
113 return GetFormatted("%d", index);
114}
115
116const char* StringsStorage::GetConsName(const char* prefix, Tagged<Name> name) {
117 if (IsString(name)) {
118 Tagged<String> str = Cast<String>(name);
119 uint32_t length =
120 std::min(v8_flags.heap_snapshot_string_limit.value(), str->length());
121 size_t data_length = 0;
122 std::unique_ptr<char[]> data = str->ToCString(0, length, &data_length);
123
124 size_t cons_length = data_length + strlen(prefix) + 1;
125 char* cons_result = NewArray<char>(cons_length);
126 snprintf(cons_result, cons_length, "%s%s", prefix, data.get());
127
128 return AddOrDisposeString(cons_result, cons_length - 1);
129 } else if (IsSymbol(name)) {
130 return GetSymbol(Cast<Symbol>(name));
131 }
132 return "";
133}
134
135namespace {
136
137inline uint32_t ComputeStringHash(const char* str, size_t len) {
138 uint32_t raw_hash_field = base::bits::RotateLeft32(
139 StringHasher::HashSequentialString(str, base::checked_cast<uint32_t>(len),
141 2);
142 return Name::HashBits::decode(raw_hash_field);
143}
144
145} // namespace
146
147bool StringsStorage::Release(const char* str) {
148 base::MutexGuard guard(&mutex_);
149 size_t len = strlen(str);
150 uint32_t hash = ComputeStringHash(str, len);
151 base::HashMap::Entry* entry = names_.Lookup(const_cast<char*>(str), hash);
152
153 // If an entry wasn't found or the address of the found entry doesn't match
154 // the one passed in, this string wasn't managed by this StringsStorage
155 // instance (i.e. a constant). Ignore this.
156 if (!entry || entry->key != str) {
157 return false;
158 }
159
160 DCHECK(entry->value);
161 entry->value =
162 reinterpret_cast<void*>(reinterpret_cast<size_t>(entry->value) - 1);
163
164 if (entry->value == 0) {
165 string_size_ -= len;
166 names_.Remove(const_cast<char*>(str), hash);
167 DeleteArray(str);
168 }
169 return true;
170}
171
175
177 base::MutexGuard guard(&mutex_);
178 return string_size_;
179}
180
181base::HashMap::Entry* StringsStorage::GetEntry(const char* str, size_t len) {
182 uint32_t hash = ComputeStringHash(str, len);
183 return names_.LookupOrInsert(const_cast<char*>(str), hash);
184}
185
186} // namespace internal
187} // namespace v8
static constexpr T decode(U value)
Definition bit-field.h:66
Entry * Next(Entry *entry) const
Definition hashmap.h:345
uint32_t occupancy() const
Definition hashmap.h:111
Entry * LookupOrInsert(const Key &key, uint32_t hash)
Definition hashmap.h:223
Value Remove(const Key &key, uint32_t hash)
Definition hashmap.h:265
Entry * Lookup(const Key &key, uint32_t hash) const
Definition hashmap.h:214
static Vector< T > New(size_t length)
Definition vector.h:35
constexpr T * begin() const
Definition vector.h:96
static uint32_t HashSequentialString(const char_t *chars, uint32_t length, uint64_t seed)
const char * GetConsName(const char *prefix, Tagged< Name > name)
const char * GetSymbol(Tagged< Symbol > sym)
const char * GetCopy(const char *src)
base::CustomMatcherHashMap::Entry * GetEntry(const char *str, size_t len)
base::CustomMatcherHashMap names_
const char * GetName(Tagged< Name > name)
const char * GetVFormatted(const char *format, va_list args)
const char * AddOrDisposeString(char *str, size_t len)
static bool StringsMatch(void *key1, void *key2)
bool Release(const char *str)
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
StringsStorage * names_
ZoneVector< RpoNumber > & result
constexpr uint32_t RotateLeft32(uint32_t value, uint32_t shift)
Definition bits.h:279
void StrNCpy(base::Vector< char > dest, const char *src, size_t n)
Definition strings.cc:28
int VSNPrintF(Vector< char > str, const char *format, va_list args)
Definition strings.cc:16
void DeleteArray(T *array)
Definition allocation.h:63
static const uint64_t kZeroHashSeed
Definition utils.h:267
V8_EXPORT_PRIVATE FlagValues v8_flags
T * NewArray(size_t size)
Definition allocation.h:43
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
#define DCHECK(condition)
Definition logging.h:482