Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved.
2 : // Redistribution and use in source and binary forms, with or without
3 : // modification, are permitted provided that the following conditions are
4 : // met:
5 : //
6 : // * Redistributions of source code must retain the above copyright
7 : // notice, this list of conditions and the following disclaimer.
8 : // * Redistributions in binary form must reproduce the above
9 : // copyright notice, this list of conditions and the following
10 : // disclaimer in the documentation and/or other materials provided
11 : // with the distribution.
12 : // * Neither the name of Google Inc. nor the names of its
13 : // contributors may be used to endorse or promote products derived
14 : // from this software without specific prior written permission.
15 : //
16 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 :
28 : #ifndef V8_AST_AST_VALUE_FACTORY_H_
29 : #define V8_AST_AST_VALUE_FACTORY_H_
30 :
31 : #include <forward_list>
32 :
33 : #include "src/base/hashmap.h"
34 : #include "src/conversions.h"
35 : #include "src/globals.h"
36 : #include "src/heap/factory.h"
37 : #include "src/isolate.h"
38 :
39 : // Ast(Raw|Cons)String and AstValueFactory are for storing strings and
40 : // values independent of the V8 heap and internalizing them later. During
41 : // parsing, they are created and stored outside the heap, in AstValueFactory.
42 : // After parsing, the strings and values are internalized (moved into the V8
43 : // heap).
44 : namespace v8 {
45 : namespace internal {
46 :
47 : class AstRawString final : public ZoneObject {
48 : public:
49 27174350 : bool IsEmpty() const { return literal_bytes_.length() == 0; }
50 109897281 : int length() const {
51 164181376 : return is_one_byte() ? literal_bytes_.length()
52 164204647 : : literal_bytes_.length() / 2;
53 : }
54 : bool AsArrayIndex(uint32_t* index) const;
55 : bool IsOneByteEqualTo(const char* data) const;
56 : uint16_t FirstCharacter() const;
57 :
58 : void Internalize(Isolate* isolate);
59 :
60 : // Access the physical representation:
61 : bool is_one_byte() const { return is_one_byte_; }
62 595350 : int byte_length() const { return literal_bytes_.length(); }
63 : const unsigned char* raw_data() const {
64 55230964 : return literal_bytes_.start();
65 : }
66 :
67 : // For storing AstRawStrings in a hash map.
68 : uint32_t hash_field() const { return hash_field_; }
69 249811232 : uint32_t Hash() const { return hash_field_ >> Name::kHashShift; }
70 :
71 : // This function can be called after internalizing.
72 : V8_INLINE Handle<String> string() const {
73 : DCHECK_NOT_NULL(string_);
74 : DCHECK(has_string_);
75 : return Handle<String>(string_);
76 : }
77 :
78 : private:
79 : friend class AstRawStringInternalizationKey;
80 : friend class AstStringConstants;
81 : friend class AstValueFactory;
82 :
83 : // Members accessed only by the AstValueFactory & related classes:
84 : static bool Compare(void* a, void* b);
85 : AstRawString(bool is_one_byte, const Vector<const byte>& literal_bytes,
86 : uint32_t hash_field)
87 : : next_(nullptr),
88 : literal_bytes_(literal_bytes),
89 : hash_field_(hash_field),
90 117538782 : is_one_byte_(is_one_byte) {}
91 : AstRawString* next() {
92 : DCHECK(!has_string_);
93 : return next_;
94 : }
95 : AstRawString** next_location() {
96 : DCHECK(!has_string_);
97 : return &next_;
98 : }
99 :
100 : void set_string(Handle<String> string) {
101 : DCHECK(!string.is_null());
102 : DCHECK(!has_string_);
103 31072134 : string_ = string.location();
104 : #ifdef DEBUG
105 : has_string_ = true;
106 : #endif
107 : }
108 :
109 : // {string_} is stored as Address* instead of a Handle<String> so it can be
110 : // stored in a union with {next_}.
111 : union {
112 : AstRawString* next_;
113 : Address* string_;
114 : };
115 :
116 : Vector<const byte> literal_bytes_; // Memory owned by Zone.
117 : uint32_t hash_field_;
118 : bool is_one_byte_;
119 : #ifdef DEBUG
120 : // (Debug-only:) Verify the object life-cylce: Some functions may only be
121 : // called after internalization (that is, after a v8::internal::String has
122 : // been set); some only before.
123 : bool has_string_ = false;
124 : #endif
125 : };
126 :
127 : class AstConsString final : public ZoneObject {
128 : public:
129 12076907 : AstConsString* AddString(Zone* zone, const AstRawString* s) {
130 7692011 : if (s->IsEmpty()) return this;
131 4384896 : if (!IsEmpty()) {
132 : // We're putting the new string to the head of the list, meaning
133 : // the string segments will be in reverse order.
134 374276 : Segment* tmp = new (zone->New(sizeof(Segment))) Segment;
135 374227 : *tmp = segment_;
136 374227 : segment_.next = tmp;
137 : }
138 4384847 : segment_.string = s;
139 4384847 : return this;
140 : }
141 :
142 : bool IsEmpty() const {
143 : DCHECK_IMPLIES(segment_.string == nullptr, segment_.next == nullptr);
144 : DCHECK_IMPLIES(segment_.string != nullptr, !segment_.string->IsEmpty());
145 : return segment_.string == nullptr;
146 : }
147 :
148 : void Internalize(Isolate* isolate);
149 :
150 : V8_INLINE Handle<String> string() const {
151 : DCHECK_NOT_NULL(string_);
152 : return Handle<String>(string_);
153 : }
154 :
155 : std::forward_list<const AstRawString*> ToRawStrings() const;
156 :
157 : private:
158 : friend class AstValueFactory;
159 :
160 10273612 : AstConsString() : next_(nullptr), segment_({nullptr, nullptr}) {}
161 :
162 : AstConsString* next() const { return next_; }
163 : AstConsString** next_location() { return &next_; }
164 :
165 : // {string_} is stored as Address* instead of a Handle<String> so it can be
166 : // stored in a union with {next_}.
167 8470449 : void set_string(Handle<String> string) { string_ = string.location(); }
168 : union {
169 : AstConsString* next_;
170 : Address* string_;
171 : };
172 :
173 : struct Segment {
174 : const AstRawString* string;
175 : AstConsString::Segment* next;
176 : };
177 : Segment segment_;
178 : };
179 :
180 : enum class AstSymbol : uint8_t { kHomeObjectSymbol };
181 :
182 : class AstBigInt {
183 : public:
184 : // |bigint| must be a NUL-terminated string of ASCII characters
185 : // representing a BigInt (suitable for passing to BigIntLiteral()
186 : // from conversions.h).
187 10 : explicit AstBigInt(const char* bigint) : bigint_(bigint) {}
188 :
189 32246 : const char* c_str() const { return bigint_; }
190 :
191 : private:
192 : const char* bigint_;
193 : };
194 :
195 : // For generating constants.
196 : #define AST_STRING_CONSTANTS(F) \
197 : F(anonymous, "anonymous") \
198 : F(anonymous_function, "(anonymous function)") \
199 : F(arguments, "arguments") \
200 : F(as, "as") \
201 : F(async, "async") \
202 : F(await, "await") \
203 : F(bigint, "bigint") \
204 : F(boolean, "boolean") \
205 : F(constructor, "constructor") \
206 : F(default, "default") \
207 : F(done, "done") \
208 : F(dot, ".") \
209 : F(dot_for, ".for") \
210 : F(dot_generator_object, ".generator_object") \
211 : F(dot_iterator, ".iterator") \
212 : F(dot_promise, ".promise") \
213 : F(dot_result, ".result") \
214 : F(dot_switch_tag, ".switch_tag") \
215 : F(dot_catch, ".catch") \
216 : F(empty, "") \
217 : F(eval, "eval") \
218 : F(from, "from") \
219 : F(function, "function") \
220 : F(get, "get") \
221 : F(get_space, "get ") \
222 : F(length, "length") \
223 : F(let, "let") \
224 : F(meta, "meta") \
225 : F(name, "name") \
226 : F(native, "native") \
227 : F(new_target, ".new.target") \
228 : F(next, "next") \
229 : F(number, "number") \
230 : F(object, "object") \
231 : F(of, "of") \
232 : F(private_constructor, "#constructor") \
233 : F(proto, "__proto__") \
234 : F(prototype, "prototype") \
235 : F(return, "return") \
236 : F(set, "set") \
237 : F(set_space, "set ") \
238 : F(star_default_star, "*default*") \
239 : F(string, "string") \
240 : F(symbol, "symbol") \
241 : F(target, "target") \
242 : F(this, "this") \
243 : F(this_function, ".this_function") \
244 : F(throw, "throw") \
245 : F(undefined, "undefined") \
246 : F(value, "value")
247 :
248 62868 : class AstStringConstants final {
249 : public:
250 : AstStringConstants(Isolate* isolate, uint64_t hash_seed);
251 :
252 : #define F(name, str) \
253 : const AstRawString* name##_string() const { return name##_string_; }
254 : AST_STRING_CONSTANTS(F)
255 : #undef F
256 :
257 : uint64_t hash_seed() const { return hash_seed_; }
258 : const base::CustomMatcherHashMap* string_table() const {
259 : return &string_table_;
260 : }
261 :
262 : private:
263 : Zone zone_;
264 : base::CustomMatcherHashMap string_table_;
265 : uint64_t hash_seed_;
266 :
267 : #define F(name, str) AstRawString* name##_string_;
268 : AST_STRING_CONSTANTS(F)
269 : #undef F
270 :
271 : DISALLOW_COPY_AND_ASSIGN(AstStringConstants);
272 : };
273 :
274 : class AstValueFactory {
275 : public:
276 2955957 : AstValueFactory(Zone* zone, const AstStringConstants* string_constants,
277 : uint64_t hash_seed)
278 : : string_table_(string_constants->string_table()),
279 : strings_(nullptr),
280 : strings_end_(&strings_),
281 : cons_strings_(nullptr),
282 : cons_strings_end_(&cons_strings_),
283 : string_constants_(string_constants),
284 : empty_cons_string_(nullptr),
285 : zone_(zone),
286 5911933 : hash_seed_(hash_seed) {
287 : DCHECK_EQ(hash_seed, string_constants->hash_seed());
288 : std::fill(one_character_strings_,
289 : one_character_strings_ + arraysize(one_character_strings_),
290 2955976 : nullptr);
291 2955976 : empty_cons_string_ = NewConsString();
292 2955979 : }
293 :
294 : Zone* zone() const { return zone_; }
295 :
296 : const AstRawString* GetOneByteString(Vector<const uint8_t> literal) {
297 99044574 : return GetOneByteStringInternal(literal);
298 : }
299 77952 : const AstRawString* GetOneByteString(const char* string) {
300 : return GetOneByteString(Vector<const uint8_t>(
301 155907 : reinterpret_cast<const uint8_t*>(string), StrLength(string)));
302 : }
303 : const AstRawString* GetTwoByteString(Vector<const uint16_t> literal) {
304 77462 : return GetTwoByteStringInternal(literal);
305 : }
306 : const AstRawString* GetString(Handle<String> literal);
307 :
308 : // Clones an AstRawString from another ast value factory, adding it to this
309 : // factory and returning the clone.
310 : const AstRawString* CloneFromOtherFactory(const AstRawString* raw_string);
311 :
312 : V8_EXPORT_PRIVATE AstConsString* NewConsString();
313 : V8_EXPORT_PRIVATE AstConsString* NewConsString(const AstRawString* str);
314 : V8_EXPORT_PRIVATE AstConsString* NewConsString(const AstRawString* str1,
315 : const AstRawString* str2);
316 :
317 : V8_EXPORT_PRIVATE void Internalize(Isolate* isolate);
318 :
319 : #define F(name, str) \
320 : const AstRawString* name##_string() const { \
321 : return string_constants_->name##_string(); \
322 : }
323 344926465 : AST_STRING_CONSTANTS(F)
324 : #undef F
325 : const AstConsString* empty_cons_string() const { return empty_cons_string_; }
326 :
327 : private:
328 : AstRawString* AddString(AstRawString* string) {
329 31713756 : *strings_end_ = string;
330 31713756 : strings_end_ = string->next_location();
331 : return string;
332 : }
333 : AstConsString* AddConsString(AstConsString* string) {
334 10273612 : *cons_strings_end_ = string;
335 10273612 : cons_strings_end_ = string->next_location();
336 : return string;
337 : }
338 : void ResetStrings() {
339 3784935 : strings_ = nullptr;
340 3784935 : strings_end_ = &strings_;
341 3784935 : cons_strings_ = nullptr;
342 3784935 : cons_strings_end_ = &cons_strings_;
343 : }
344 : V8_EXPORT_PRIVATE AstRawString* GetOneByteStringInternal(
345 : Vector<const uint8_t> literal);
346 : AstRawString* GetTwoByteStringInternal(Vector<const uint16_t> literal);
347 : AstRawString* GetString(uint32_t hash, bool is_one_byte,
348 : Vector<const byte> literal_bytes);
349 :
350 : // All strings are copied here, one after another (no zeroes inbetween).
351 : base::CustomMatcherHashMap string_table_;
352 :
353 : // We need to keep track of strings_ in order since cons strings require their
354 : // members to be internalized first.
355 : AstRawString* strings_;
356 : AstRawString** strings_end_;
357 : AstConsString* cons_strings_;
358 : AstConsString** cons_strings_end_;
359 :
360 : // Holds constant string values which are shared across the isolate.
361 : const AstStringConstants* string_constants_;
362 : const AstConsString* empty_cons_string_;
363 :
364 : // Caches one character lowercase strings (for minified code).
365 : static const int kMaxOneCharStringValue = 128;
366 : AstRawString* one_character_strings_[kMaxOneCharStringValue];
367 :
368 : Zone* zone_;
369 :
370 : uint64_t hash_seed_;
371 : };
372 : } // namespace internal
373 : } // namespace v8
374 :
375 : #endif // V8_AST_AST_VALUE_FACTORY_H_
|