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 : bool IsEmpty() const { return literal_bytes_.length() == 0; }
50 : int length() const {
51 : return is_one_byte() ? literal_bytes_.length()
52 158293451 : : 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 : int byte_length() const { return literal_bytes_.length(); }
63 : const unsigned char* raw_data() const {
64 : return literal_bytes_.start();
65 : }
66 :
67 : // For storing AstRawStrings in a hash map.
68 : uint32_t hash_field() const { return hash_field_; }
69 226657273 : 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 28585369 : 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 108942105 : 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 29165528 : return &next_;
98 : }
99 :
100 : void set_string(Handle<String> string) {
101 : DCHECK(!string.is_null());
102 : DCHECK(!has_string_);
103 29340393 : 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 7767750 : AstConsString* AddString(Zone* zone, const AstRawString* s) {
130 7767750 : if (s->IsEmpty()) return this;
131 4497867 : 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 : Segment* tmp = new (zone->New(sizeof(Segment))) Segment;
135 370510 : *tmp = segment_;
136 370510 : segment_.next = tmp;
137 : }
138 4497877 : segment_.string = s;
139 4497877 : 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 5687405 : return Handle<String>(string_);
153 : }
154 :
155 : std::forward_list<const AstRawString*> ToRawStrings() const;
156 :
157 : private:
158 : friend class AstValueFactory;
159 :
160 10376882 : AstConsString() : next_(nullptr), segment_({nullptr, nullptr}) {}
161 :
162 : AstConsString* next() const { return next_; }
163 10376882 : 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 8525360 : 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 32391 : 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(computed, "<computed>") \
206 : F(constructor, "constructor") \
207 : F(default, "default") \
208 : F(done, "done") \
209 : F(dot, ".") \
210 : F(dot_default, ".default") \
211 : F(dot_for, ".for") \
212 : F(dot_generator_object, ".generator_object") \
213 : F(dot_iterator, ".iterator") \
214 : F(dot_promise, ".promise") \
215 : F(dot_result, ".result") \
216 : F(dot_switch_tag, ".switch_tag") \
217 : F(dot_catch, ".catch") \
218 : F(empty, "") \
219 : F(eval, "eval") \
220 : F(from, "from") \
221 : F(function, "function") \
222 : F(get, "get") \
223 : F(get_space, "get ") \
224 : F(length, "length") \
225 : F(let, "let") \
226 : F(meta, "meta") \
227 : F(name, "name") \
228 : F(native, "native") \
229 : F(new_target, ".new.target") \
230 : F(next, "next") \
231 : F(number, "number") \
232 : F(object, "object") \
233 : F(of, "of") \
234 : F(private_constructor, "#constructor") \
235 : F(proto, "__proto__") \
236 : F(prototype, "prototype") \
237 : F(return, "return") \
238 : F(set, "set") \
239 : F(set_space, "set ") \
240 : F(string, "string") \
241 : F(symbol, "symbol") \
242 : F(target, "target") \
243 : F(this, "this") \
244 : F(this_function, ".this_function") \
245 : F(throw, "throw") \
246 : F(undefined, "undefined") \
247 : F(value, "value")
248 :
249 61519 : class AstStringConstants final {
250 : public:
251 : AstStringConstants(Isolate* isolate, uint64_t hash_seed);
252 :
253 : #define F(name, str) \
254 : const AstRawString* name##_string() const { return name##_string_; }
255 : AST_STRING_CONSTANTS(F)
256 : #undef F
257 :
258 : uint64_t hash_seed() const { return hash_seed_; }
259 : const base::CustomMatcherHashMap* string_table() const {
260 2979713 : return &string_table_;
261 : }
262 :
263 : private:
264 : Zone zone_;
265 : base::CustomMatcherHashMap string_table_;
266 : uint64_t hash_seed_;
267 :
268 : #define F(name, str) AstRawString* name##_string_;
269 : AST_STRING_CONSTANTS(F)
270 : #undef F
271 :
272 : DISALLOW_COPY_AND_ASSIGN(AstStringConstants);
273 : };
274 :
275 2979702 : class AstValueFactory {
276 : public:
277 2979713 : AstValueFactory(Zone* zone, const AstStringConstants* string_constants,
278 : uint64_t hash_seed)
279 : : string_table_(string_constants->string_table()),
280 : strings_(nullptr),
281 : strings_end_(&strings_),
282 : cons_strings_(nullptr),
283 : cons_strings_end_(&cons_strings_),
284 : string_constants_(string_constants),
285 : empty_cons_string_(nullptr),
286 : zone_(zone),
287 2979708 : hash_seed_(hash_seed) {
288 : DCHECK_EQ(hash_seed, string_constants->hash_seed());
289 2979708 : std::fill(one_character_strings_,
290 : one_character_strings_ + arraysize(one_character_strings_),
291 : nullptr);
292 2979708 : empty_cons_string_ = NewConsString();
293 2979710 : }
294 :
295 : Zone* zone() const { return zone_; }
296 :
297 : const AstRawString* GetOneByteString(Vector<const uint8_t> literal) {
298 90824190 : return GetOneByteStringInternal(literal);
299 : }
300 78071 : const AstRawString* GetOneByteString(const char* string) {
301 78071 : return GetOneByteString(Vector<const uint8_t>(
302 78071 : reinterpret_cast<const uint8_t*>(string), StrLength(string)));
303 : }
304 : const AstRawString* GetTwoByteString(Vector<const uint16_t> literal) {
305 77271 : return GetTwoByteStringInternal(literal);
306 : }
307 : const AstRawString* GetString(Handle<String> literal);
308 :
309 : // Clones an AstRawString from another ast value factory, adding it to this
310 : // factory and returning the clone.
311 : const AstRawString* CloneFromOtherFactory(const AstRawString* raw_string);
312 :
313 : V8_EXPORT_PRIVATE AstConsString* NewConsString();
314 : V8_EXPORT_PRIVATE AstConsString* NewConsString(const AstRawString* str);
315 : V8_EXPORT_PRIVATE AstConsString* NewConsString(const AstRawString* str1,
316 : const AstRawString* str2);
317 :
318 : V8_EXPORT_PRIVATE void Internalize(Isolate* isolate);
319 :
320 : #define F(name, str) \
321 : const AstRawString* name##_string() const { \
322 : return string_constants_->name##_string(); \
323 : }
324 : AST_STRING_CONSTANTS(F)
325 : #undef F
326 : const AstConsString* empty_cons_string() const { return empty_cons_string_; }
327 :
328 : private:
329 : AstRawString* AddString(AstRawString* string) {
330 29165528 : *strings_end_ = string;
331 29165528 : strings_end_ = string->next_location();
332 : return string;
333 : }
334 : AstConsString* AddConsString(AstConsString* string) {
335 10376882 : *cons_strings_end_ = string;
336 10376882 : cons_strings_end_ = string->next_location();
337 : return string;
338 : }
339 : void ResetStrings() {
340 3792035 : strings_ = nullptr;
341 3792035 : strings_end_ = &strings_;
342 3792035 : cons_strings_ = nullptr;
343 3792035 : cons_strings_end_ = &cons_strings_;
344 : }
345 : V8_EXPORT_PRIVATE AstRawString* GetOneByteStringInternal(
346 : Vector<const uint8_t> literal);
347 : AstRawString* GetTwoByteStringInternal(Vector<const uint16_t> literal);
348 : AstRawString* GetString(uint32_t hash, bool is_one_byte,
349 : Vector<const byte> literal_bytes);
350 :
351 : // All strings are copied here, one after another (no zeroes inbetween).
352 : base::CustomMatcherHashMap string_table_;
353 :
354 : // We need to keep track of strings_ in order since cons strings require their
355 : // members to be internalized first.
356 : AstRawString* strings_;
357 : AstRawString** strings_end_;
358 : AstConsString* cons_strings_;
359 : AstConsString** cons_strings_end_;
360 :
361 : // Holds constant string values which are shared across the isolate.
362 : const AstStringConstants* string_constants_;
363 : const AstConsString* empty_cons_string_;
364 :
365 : // Caches one character lowercase strings (for minified code).
366 : static const int kMaxOneCharStringValue = 128;
367 : AstRawString* one_character_strings_[kMaxOneCharStringValue];
368 :
369 : Zone* zone_;
370 :
371 : uint64_t hash_seed_;
372 : };
373 : } // namespace internal
374 : } // namespace v8
375 :
376 : #endif // V8_AST_AST_VALUE_FACTORY_H_
|