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 : #include "src/ast/ast-value-factory.h"
29 :
30 : #include "src/api.h"
31 : #include "src/char-predicates-inl.h"
32 : #include "src/objects-inl.h"
33 : #include "src/objects.h"
34 : #include "src/string-hasher.h"
35 : #include "src/utils-inl.h"
36 :
37 : namespace v8 {
38 : namespace internal {
39 :
40 : namespace {
41 :
42 : // For using StringToArrayIndex.
43 : class OneByteStringStream {
44 : public:
45 : explicit OneByteStringStream(Vector<const byte> lb) :
46 29 : literal_bytes_(lb), pos_(0) {}
47 :
48 266 : bool HasMore() { return pos_ < literal_bytes_.length(); }
49 532 : uint16_t GetNext() { return literal_bytes_[pos_++]; }
50 :
51 : private:
52 : Vector<const byte> literal_bytes_;
53 : int pos_;
54 : };
55 :
56 : } // namespace
57 :
58 0 : class AstRawStringInternalizationKey : public StringTableKey {
59 : public:
60 31140861 : explicit AstRawStringInternalizationKey(const AstRawString* string)
61 31140861 : : StringTableKey(string->hash_field()), string_(string) {}
62 :
63 77668284 : bool IsMatch(Object* other) override {
64 77668284 : if (string_->is_one_byte())
65 77642790 : return String::cast(other)->IsOneByteEqualTo(string_->literal_bytes_);
66 : return String::cast(other)->IsTwoByteEqualTo(
67 25494 : Vector<const uint16_t>::cast(string_->literal_bytes_));
68 : }
69 :
70 10625258 : Handle<String> AsHandle(Isolate* isolate) override {
71 10646262 : if (string_->is_one_byte())
72 : return isolate->factory()->NewOneByteInternalizedString(
73 10604254 : string_->literal_bytes_, string_->hash_field());
74 : return isolate->factory()->NewTwoByteInternalizedString(
75 : Vector<const uint16_t>::cast(string_->literal_bytes_),
76 21004 : string_->hash_field());
77 : }
78 :
79 : private:
80 : const AstRawString* string_;
81 : };
82 :
83 31140861 : void AstRawString::Internalize(Isolate* isolate) {
84 : DCHECK(!has_string_);
85 62281722 : if (literal_bytes_.length() == 0) {
86 : set_string(isolate->factory()->empty_string());
87 : } else {
88 : AstRawStringInternalizationKey key(this);
89 31140861 : set_string(StringTable::LookupKey(isolate, &key));
90 : }
91 31140860 : }
92 :
93 12036075 : bool AstRawString::AsArrayIndex(uint32_t* index) const {
94 : // The StringHasher will set up the hash in such a way that we can use it to
95 : // figure out whether the string is convertible to an array index.
96 12036075 : if ((hash_field_ & Name::kIsNotArrayIndexMask) != 0) return false;
97 1580847 : if (length() <= Name::kMaxCachedArrayIndexLength) {
98 1580818 : *index = Name::ArrayIndexValueBits::decode(hash_field_);
99 : } else {
100 : OneByteStringStream stream(literal_bytes_);
101 29 : CHECK(StringToArrayIndex(&stream, index));
102 : }
103 : return true;
104 : }
105 :
106 127208 : bool AstRawString::IsOneByteEqualTo(const char* data) const {
107 127208 : if (!is_one_byte()) return false;
108 :
109 280765 : size_t length = static_cast<size_t>(literal_bytes_.length());
110 127208 : if (length != strlen(data)) return false;
111 :
112 : return 0 == strncmp(reinterpret_cast<const char*>(literal_bytes_.start()),
113 26349 : data, length);
114 : }
115 :
116 1782837 : uint16_t AstRawString::FirstCharacter() const {
117 1782837 : if (is_one_byte()) return literal_bytes_[0];
118 : const uint16_t* c = reinterpret_cast<const uint16_t*>(literal_bytes_.start());
119 7 : return *c;
120 : }
121 :
122 70733134 : bool AstRawString::Compare(void* a, void* b) {
123 : const AstRawString* lhs = static_cast<AstRawString*>(a);
124 : const AstRawString* rhs = static_cast<AstRawString*>(b);
125 : DCHECK_EQ(lhs->Hash(), rhs->Hash());
126 :
127 70733134 : if (lhs->length() != rhs->length()) return false;
128 : const unsigned char* l = lhs->raw_data();
129 : const unsigned char* r = rhs->raw_data();
130 70733116 : size_t length = rhs->length();
131 70733116 : if (lhs->is_one_byte()) {
132 70718478 : if (rhs->is_one_byte()) {
133 : return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
134 : reinterpret_cast<const uint8_t*>(r),
135 70718471 : length) == 0;
136 : } else {
137 : return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
138 : reinterpret_cast<const uint16_t*>(r),
139 7 : length) == 0;
140 : }
141 : } else {
142 14638 : if (rhs->is_one_byte()) {
143 : return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
144 : reinterpret_cast<const uint8_t*>(r),
145 0 : length) == 0;
146 : } else {
147 : return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
148 : reinterpret_cast<const uint16_t*>(r),
149 14638 : length) == 0;
150 : }
151 : }
152 : }
153 :
154 11348808 : void AstConsString::Internalize(Isolate* isolate) {
155 11348808 : if (IsEmpty()) {
156 : set_string(isolate->factory()->empty_string());
157 11348808 : return;
158 : }
159 : // AstRawStrings are internalized before AstConsStrings, so
160 : // AstRawString::string() will just work.
161 5457219 : Handle<String> tmp(segment_.string->string());
162 9156773 : for (AstConsString::Segment* current = segment_.next; current != nullptr;
163 : current = current->next) {
164 : tmp = isolate->factory()
165 3699554 : ->NewConsString(current->string->string(), tmp)
166 7399108 : .ToHandleChecked();
167 : }
168 : set_string(tmp);
169 : }
170 :
171 4164121 : AstValue::AstValue(double n) : next_(nullptr) {
172 : int int_value;
173 4164121 : if (DoubleToSmiInteger(n, &int_value)) {
174 2740808 : type_ = SMI;
175 2740808 : smi_ = int_value;
176 : } else {
177 1423313 : type_ = NUMBER;
178 1423313 : number_ = n;
179 : }
180 4164121 : }
181 :
182 2546009 : bool AstValue::ToUint32(uint32_t* value) const {
183 2546009 : if (IsSmi()) {
184 913629 : int num = smi_;
185 913629 : if (num < 0) return false;
186 913629 : *value = static_cast<uint32_t>(num);
187 913629 : return true;
188 : }
189 1632380 : if (IsHeapNumber()) {
190 34 : return DoubleToUint32IfEqualToSelf(number_, value);
191 : }
192 : return false;
193 : }
194 :
195 8972171 : bool AstValue::IsPropertyName() const {
196 8972171 : if (type_ == STRING) {
197 : uint32_t index;
198 8660792 : return !string_->AsArrayIndex(&index);
199 : }
200 : return false;
201 : }
202 :
203 :
204 60216 : bool AstValue::BooleanValue() const {
205 60216 : switch (type_) {
206 : case STRING:
207 : DCHECK_NOT_NULL(string_);
208 862 : return !string_->IsEmpty();
209 : case SYMBOL:
210 0 : UNREACHABLE();
211 : break;
212 : case NUMBER:
213 165 : return DoubleToBoolean(number_);
214 : case SMI:
215 48614 : return smi_ != 0;
216 : case BIGINT: {
217 14 : size_t length = strlen(bigint_buffer_);
218 : DCHECK_GT(length, 0);
219 14 : if (length == 1 && bigint_buffer_[0] == '0') return false;
220 : // Skip over any radix prefix; BigInts with length > 1 only
221 : // begin with zero if they include a radix.
222 47 : for (size_t i = (bigint_buffer_[0] == '0') ? 2 : 0; i < length; ++i) {
223 41 : if (bigint_buffer_[i] != '0') return true;
224 : }
225 : return false;
226 : }
227 : case BOOLEAN:
228 10956 : return bool_;
229 : case NULL_TYPE:
230 : return false;
231 : case THE_HOLE:
232 0 : UNREACHABLE();
233 : break;
234 : case UNDEFINED:
235 : return false;
236 : }
237 0 : UNREACHABLE();
238 : }
239 :
240 :
241 32991347 : void AstValue::Internalize(Isolate* isolate) {
242 32991347 : switch (type_) {
243 : case STRING:
244 : DCHECK_NOT_NULL(string_);
245 : // Strings are already internalized.
246 : DCHECK(!string_->string().is_null());
247 : break;
248 : case SYMBOL:
249 2038 : switch (symbol_) {
250 : case AstSymbol::kHomeObjectSymbol:
251 : set_value(isolate->factory()->home_object_symbol());
252 2038 : break;
253 : }
254 : break;
255 : case NUMBER:
256 1422338 : set_value(isolate->factory()->NewNumber(number_, TENURED));
257 : break;
258 : case SMI:
259 12228488 : set_value(handle(Smi::FromInt(smi_), isolate));
260 12228488 : break;
261 : case BIGINT:
262 : // TODO(adamk): Don't check-fail on conversion failure; instead
263 : // check for errors during parsing and throw at that point.
264 50 : set_value(BigIntLiteral(isolate, bigint_buffer_).ToHandleChecked());
265 25 : break;
266 : case BOOLEAN:
267 251795 : if (bool_) {
268 : set_value(isolate->factory()->true_value());
269 : } else {
270 : set_value(isolate->factory()->false_value());
271 : }
272 : break;
273 : case NULL_TYPE:
274 : set_value(isolate->factory()->null_value());
275 101245 : break;
276 : case THE_HOLE:
277 : set_value(isolate->factory()->the_hole_value());
278 5887 : break;
279 : case UNDEFINED:
280 : set_value(isolate->factory()->undefined_value());
281 180751 : break;
282 : }
283 32991347 : }
284 :
285 54999 : AstStringConstants::AstStringConstants(Isolate* isolate, uint32_t hash_seed)
286 : : zone_(isolate->allocator(), ZONE_NAME),
287 : string_table_(AstRawString::Compare),
288 109998 : hash_seed_(hash_seed) {
289 : DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
290 : #define F(name, str) \
291 : { \
292 : const char* data = str; \
293 : Vector<const uint8_t> literal(reinterpret_cast<const uint8_t*>(data), \
294 : static_cast<int>(strlen(data))); \
295 : uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>( \
296 : literal.start(), literal.length(), hash_seed_); \
297 : name##_string_ = new (&zone_) AstRawString(true, literal, hash_field); \
298 : /* The Handle returned by the factory is located on the roots */ \
299 : /* array, not on the temporary HandleScope, so this is safe. */ \
300 : name##_string_->set_string(isolate->factory()->name##_string()); \
301 : base::HashMap::Entry* entry = \
302 : string_table_.InsertNew(name##_string_, name##_string_->Hash()); \
303 : DCHECK_NULL(entry->value); \
304 : entry->value = reinterpret_cast<void*>(1); \
305 : }
306 6819876 : AST_STRING_CONSTANTS(F)
307 : #undef F
308 54999 : }
309 :
310 115714208 : AstRawString* AstValueFactory::GetOneByteStringInternal(
311 : Vector<const uint8_t> literal) {
312 136611502 : if (literal.length() == 1 && IsInRange(literal[0], 'a', 'z')) {
313 16677124 : int key = literal[0] - 'a';
314 16677124 : if (one_character_strings_[key] == nullptr) {
315 : uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>(
316 3256646 : literal.start(), literal.length(), hash_seed_);
317 3256646 : one_character_strings_[key] = GetString(hash_field, true, literal);
318 : }
319 16677124 : return one_character_strings_[key];
320 : }
321 : uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>(
322 99037084 : literal.start(), literal.length(), hash_seed_);
323 99037128 : return GetString(hash_field, true, literal);
324 : }
325 :
326 :
327 42432 : AstRawString* AstValueFactory::GetTwoByteStringInternal(
328 : Vector<const uint16_t> literal) {
329 : uint32_t hash_field = StringHasher::HashSequentialString<uint16_t>(
330 84864 : literal.start(), literal.length(), hash_seed_);
331 42432 : return GetString(hash_field, false, Vector<const byte>::cast(literal));
332 : }
333 :
334 :
335 697184 : const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
336 : AstRawString* result = nullptr;
337 : DisallowHeapAllocation no_gc;
338 697184 : String::FlatContent content = literal->GetFlatContent();
339 697184 : if (content.IsOneByte()) {
340 697177 : result = GetOneByteStringInternal(content.ToOneByteVector());
341 : } else {
342 : DCHECK(content.IsTwoByte());
343 7 : result = GetTwoByteStringInternal(content.ToUC16Vector());
344 : }
345 697184 : return result;
346 : }
347 :
348 12874356 : AstConsString* AstValueFactory::NewConsString() {
349 12874356 : AstConsString* new_string = new (zone_) AstConsString;
350 : DCHECK_NOT_NULL(new_string);
351 : AddConsString(new_string);
352 12874357 : return new_string;
353 : }
354 :
355 8034177 : AstConsString* AstValueFactory::NewConsString(const AstRawString* str) {
356 8034177 : return NewConsString()->AddString(zone_, str);
357 : }
358 :
359 25038 : AstConsString* AstValueFactory::NewConsString(const AstRawString* str1,
360 : const AstRawString* str2) {
361 25038 : return NewConsString()->AddString(zone_, str1)->AddString(zone_, str2);
362 : }
363 :
364 2997358 : void AstValueFactory::Internalize(Isolate* isolate) {
365 : // Strings need to be internalized before values, because values refer to
366 : // strings.
367 37135577 : for (AstRawString* current = strings_; current != nullptr;) {
368 : AstRawString* next = current->next();
369 31140859 : current->Internalize(isolate);
370 : current = next;
371 : }
372 :
373 : // AstConsStrings refer to AstRawStrings.
374 17343527 : for (AstConsString* current = cons_strings_; current != nullptr;) {
375 : AstConsString* next = current->next();
376 11348808 : current->Internalize(isolate);
377 : current = next;
378 : }
379 :
380 38986065 : for (AstValue* current = values_; current != nullptr;) {
381 : AstValue* next = current->next();
382 32991347 : current->Internalize(isolate);
383 : current = next;
384 : }
385 : ResetStrings();
386 2997359 : values_ = nullptr;
387 2997359 : }
388 :
389 :
390 20058082 : const AstValue* AstValueFactory::NewString(const AstRawString* string) {
391 20058082 : AstValue* value = new (zone_) AstValue(string);
392 20058072 : CHECK_NOT_NULL(string);
393 20058072 : return AddValue(value);
394 : }
395 :
396 2814 : const AstValue* AstValueFactory::NewSymbol(AstSymbol symbol) {
397 2814 : AstValue* value = new (zone_) AstValue(symbol);
398 2814 : return AddValue(value);
399 : }
400 :
401 4164121 : const AstValue* AstValueFactory::NewNumber(double number) {
402 8328242 : AstValue* value = new (zone_) AstValue(number);
403 4164121 : return AddValue(value);
404 : }
405 :
406 20530753 : const AstValue* AstValueFactory::NewSmi(uint32_t number) {
407 20530753 : bool cacheable_smi = number <= kMaxCachedSmi;
408 20530753 : if (cacheable_smi && smis_[number] != nullptr) return smis_[number];
409 :
410 20089986 : AstValue* value = new (zone_) AstValue(AstValue::SMI, number);
411 10044993 : if (cacheable_smi) smis_[number] = value;
412 10044993 : return AddValue(value);
413 : }
414 :
415 39 : const AstValue* AstValueFactory::NewBigInt(const char* number) {
416 39 : AstValue* value = new (zone_) AstValue(number);
417 39 : return AddValue(value);
418 : }
419 :
420 : #define GENERATE_VALUE_GETTER(value, initializer) \
421 : if (!value) { \
422 : value = AddValue(new (zone_) AstValue(initializer)); \
423 : } \
424 : return value;
425 :
426 969530 : const AstValue* AstValueFactory::NewBoolean(bool b) {
427 969530 : if (b) {
428 592151 : GENERATE_VALUE_GETTER(true_value_, true);
429 : } else {
430 753199 : GENERATE_VALUE_GETTER(false_value_, false);
431 : }
432 : }
433 :
434 :
435 455723 : const AstValue* AstValueFactory::NewNull() {
436 681171 : GENERATE_VALUE_GETTER(null_value_, AstValue::NULL_TYPE);
437 : }
438 :
439 :
440 667296 : const AstValue* AstValueFactory::NewUndefined() {
441 987792 : GENERATE_VALUE_GETTER(undefined_value_, AstValue::UNDEFINED);
442 : }
443 :
444 :
445 1173912 : const AstValue* AstValueFactory::NewTheHole() {
446 1187269 : GENERATE_VALUE_GETTER(the_hole_value_, AstValue::THE_HOLE);
447 : }
448 :
449 :
450 : #undef GENERATE_VALUE_GETTER
451 :
452 102336193 : AstRawString* AstValueFactory::GetString(uint32_t hash_field, bool is_one_byte,
453 : Vector<const byte> literal_bytes) {
454 : // literal_bytes here points to whatever the user passed, and this is OK
455 : // because we use vector_compare (which checks the contents) to compare
456 : // against the AstRawStrings which are in the string_table_. We should not
457 : // return this AstRawString.
458 : AstRawString key(is_one_byte, literal_bytes, hash_field);
459 204672482 : base::HashMap::Entry* entry = string_table_.LookupOrInsert(&key, key.Hash());
460 102336289 : if (entry->value == nullptr) {
461 : // Copy literal contents for later comparison.
462 32175351 : int length = literal_bytes.length();
463 32175351 : byte* new_literal_bytes = zone_->NewArray<byte>(length);
464 32175350 : memcpy(new_literal_bytes, literal_bytes.start(), length);
465 : AstRawString* new_string = new (zone_) AstRawString(
466 32175350 : is_one_byte, Vector<const byte>(new_literal_bytes, length), hash_field);
467 32175330 : CHECK_NOT_NULL(new_string);
468 : AddString(new_string);
469 32175330 : entry->key = new_string;
470 32175330 : entry->value = reinterpret_cast<void*>(1);
471 : }
472 102336268 : return reinterpret_cast<AstRawString*>(entry->key);
473 : }
474 :
475 : } // namespace internal
476 : } // namespace v8
|