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/utils.h"
35 :
36 : namespace v8 {
37 : namespace internal {
38 :
39 : namespace {
40 :
41 : // For using StringToArrayIndex.
42 : class OneByteStringStream {
43 : public:
44 : explicit OneByteStringStream(Vector<const byte> lb) :
45 29 : literal_bytes_(lb), pos_(0) {}
46 :
47 274 : bool HasMore() { return pos_ < literal_bytes_.length(); }
48 548 : uint16_t GetNext() { return literal_bytes_[pos_++]; }
49 :
50 : private:
51 : Vector<const byte> literal_bytes_;
52 : int pos_;
53 : };
54 :
55 : } // namespace
56 :
57 0 : class AstRawStringInternalizationKey : public HashTableKey {
58 : public:
59 : explicit AstRawStringInternalizationKey(const AstRawString* string)
60 41368669 : : string_(string) {}
61 :
62 75215956 : bool IsMatch(Object* other) override {
63 75215956 : if (string_->is_one_byte())
64 75175209 : return String::cast(other)->IsOneByteEqualTo(string_->literal_bytes_);
65 : return String::cast(other)->IsTwoByteEqualTo(
66 81494 : Vector<const uint16_t>::cast(string_->literal_bytes_));
67 : }
68 :
69 52231736 : uint32_t Hash() override { return string_->hash() >> Name::kHashShift; }
70 :
71 6295068 : uint32_t HashForObject(Object* key) override {
72 6295068 : return String::cast(key)->Hash();
73 : }
74 :
75 10863122 : Handle<Object> AsHandle(Isolate* isolate) override {
76 10893561 : if (string_->is_one_byte())
77 : return isolate->factory()->NewOneByteInternalizedString(
78 10832683 : string_->literal_bytes_, string_->hash());
79 : return isolate->factory()->NewTwoByteInternalizedString(
80 60878 : Vector<const uint16_t>::cast(string_->literal_bytes_), string_->hash());
81 : }
82 :
83 : private:
84 : const AstRawString* string_;
85 : };
86 :
87 41368669 : void AstRawString::Internalize(Isolate* isolate) {
88 : DCHECK(!has_string_);
89 41368669 : if (literal_bytes_.length() == 0) {
90 : set_string(isolate->factory()->empty_string());
91 : } else {
92 : AstRawStringInternalizationKey key(this);
93 41368669 : set_string(StringTable::LookupKey(isolate, &key));
94 : }
95 41368658 : }
96 :
97 26240224 : bool AstRawString::AsArrayIndex(uint32_t* index) const {
98 : // The StringHasher will set up the hash in such a way that we can use it to
99 : // figure out whether the string is convertible to an array index.
100 26240224 : if ((hash_ & Name::kIsNotArrayIndexMask) != 0) return false;
101 817289 : if (length() <= Name::kMaxCachedArrayIndexLength) {
102 817260 : *index = Name::ArrayIndexValueBits::decode(hash_);
103 : } else {
104 : OneByteStringStream stream(literal_bytes_);
105 29 : CHECK(StringToArrayIndex(&stream, index));
106 : }
107 : return true;
108 : }
109 :
110 106756 : bool AstRawString::IsOneByteEqualTo(const char* data) const {
111 106756 : if (!is_one_byte()) return false;
112 :
113 140970 : size_t length = static_cast<size_t>(literal_bytes_.length());
114 106756 : if (length != strlen(data)) return false;
115 :
116 : return 0 == strncmp(reinterpret_cast<const char*>(literal_bytes_.start()),
117 34214 : data, length);
118 : }
119 :
120 2805033 : uint16_t AstRawString::FirstCharacter() const {
121 2805033 : if (is_one_byte()) return literal_bytes_[0];
122 : const uint16_t* c = reinterpret_cast<const uint16_t*>(literal_bytes_.start());
123 9 : return *c;
124 : }
125 :
126 85283477 : bool AstRawString::Compare(void* a, void* b) {
127 : const AstRawString* lhs = static_cast<AstRawString*>(a);
128 : const AstRawString* rhs = static_cast<AstRawString*>(b);
129 : DCHECK_EQ(lhs->hash(), rhs->hash());
130 :
131 85283477 : if (lhs->length() != rhs->length()) return false;
132 : const unsigned char* l = lhs->raw_data();
133 : const unsigned char* r = rhs->raw_data();
134 85283481 : size_t length = rhs->length();
135 85283481 : if (lhs->is_one_byte()) {
136 85258741 : if (rhs->is_one_byte()) {
137 : return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
138 : reinterpret_cast<const uint8_t*>(r),
139 85258732 : length) == 0;
140 : } else {
141 : return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
142 : reinterpret_cast<const uint16_t*>(r),
143 9 : length) == 0;
144 : }
145 : } else {
146 24740 : if (rhs->is_one_byte()) {
147 : return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
148 : reinterpret_cast<const uint8_t*>(r),
149 0 : length) == 0;
150 : } else {
151 : return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
152 : reinterpret_cast<const uint16_t*>(r),
153 24740 : length) == 0;
154 : }
155 : }
156 : }
157 :
158 17232962 : void AstConsString::Internalize(Isolate* isolate) {
159 17232962 : if (IsEmpty()) {
160 : set_string(isolate->factory()->empty_string());
161 17232962 : return;
162 : }
163 : // AstRawStrings are internalized before AstConsStrings, so
164 : // AstRawString::string() will just work.
165 7714830 : Handle<String> tmp(segment_.string->string());
166 13653820 : for (AstConsString::Segment* current = segment_.next; current != nullptr;
167 : current = current->next) {
168 : tmp = isolate->factory()
169 : ->NewConsString(current->string->string(), tmp)
170 11877980 : .ToHandleChecked();
171 : }
172 : set_string(tmp);
173 : }
174 :
175 22554063 : bool AstValue::IsPropertyName() const {
176 22554063 : if (type_ == STRING) {
177 : uint32_t index;
178 21831905 : return !string_->AsArrayIndex(&index);
179 : }
180 : return false;
181 : }
182 :
183 :
184 64079 : bool AstValue::BooleanValue() const {
185 64079 : switch (type_) {
186 : case STRING:
187 : DCHECK(string_ != NULL);
188 900 : return !string_->IsEmpty();
189 : case SYMBOL:
190 0 : UNREACHABLE();
191 : break;
192 : case NUMBER_WITH_DOT:
193 : case NUMBER:
194 213 : return DoubleToBoolean(number_);
195 : case SMI_WITH_DOT:
196 : case SMI:
197 45048 : return smi_ != 0;
198 : case BOOLEAN:
199 18328 : return bool_;
200 : case NULL_TYPE:
201 : return false;
202 : case THE_HOLE:
203 0 : UNREACHABLE();
204 : break;
205 : case UNDEFINED:
206 : return false;
207 : }
208 0 : UNREACHABLE();
209 : return false;
210 : }
211 :
212 :
213 57348830 : void AstValue::Internalize(Isolate* isolate) {
214 57348830 : switch (type_) {
215 : case STRING:
216 : DCHECK_NOT_NULL(string_);
217 : // Strings are already internalized.
218 : DCHECK(!string_->string().is_null());
219 : break;
220 : case SYMBOL:
221 6119 : switch (symbol_) {
222 : case AstSymbol::kHomeObjectSymbol:
223 : set_value(isolate->factory()->home_object_symbol());
224 6119 : break;
225 : }
226 : break;
227 : case NUMBER_WITH_DOT:
228 : case NUMBER:
229 2232106 : set_value(isolate->factory()->NewNumber(number_, TENURED));
230 : break;
231 : case SMI_WITH_DOT:
232 : case SMI:
233 16932749 : set_value(handle(Smi::FromInt(smi_), isolate));
234 16932750 : break;
235 : case BOOLEAN:
236 655471 : if (bool_) {
237 : set_value(isolate->factory()->true_value());
238 : } else {
239 : set_value(isolate->factory()->false_value());
240 : }
241 : break;
242 : case NULL_TYPE:
243 : set_value(isolate->factory()->null_value());
244 369867 : break;
245 : case THE_HOLE:
246 : set_value(isolate->factory()->the_hole_value());
247 13677 : break;
248 : case UNDEFINED:
249 : set_value(isolate->factory()->undefined_value());
250 500792 : break;
251 : }
252 57348831 : }
253 :
254 144921021 : AstRawString* AstValueFactory::GetOneByteStringInternal(
255 : Vector<const uint8_t> literal) {
256 175253589 : if (literal.length() == 1 && IsInRange(literal[0], 'a', 'z')) {
257 23752776 : int key = literal[0] - 'a';
258 23752776 : if (one_character_strings_[key] == nullptr) {
259 : uint32_t hash = StringHasher::HashSequentialString<uint8_t>(
260 4682170 : literal.start(), literal.length(), hash_seed_);
261 4682170 : one_character_strings_[key] = GetString(hash, true, literal);
262 : }
263 23752776 : return one_character_strings_[key];
264 : }
265 : uint32_t hash = StringHasher::HashSequentialString<uint8_t>(
266 121168245 : literal.start(), literal.length(), hash_seed_);
267 121168353 : return GetString(hash, true, literal);
268 : }
269 :
270 :
271 66200 : AstRawString* AstValueFactory::GetTwoByteStringInternal(
272 : Vector<const uint16_t> literal) {
273 : uint32_t hash = StringHasher::HashSequentialString<uint16_t>(
274 66200 : literal.start(), literal.length(), hash_seed_);
275 66200 : return GetString(hash, false, Vector<const byte>::cast(literal));
276 : }
277 :
278 :
279 1321921 : const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
280 : AstRawString* result = NULL;
281 : DisallowHeapAllocation no_gc;
282 1321921 : String::FlatContent content = literal->GetFlatContent();
283 1321921 : if (content.IsOneByte()) {
284 1321912 : result = GetOneByteStringInternal(content.ToOneByteVector());
285 : } else {
286 : DCHECK(content.IsTwoByte());
287 9 : result = GetTwoByteStringInternal(content.ToUC16Vector());
288 : }
289 1321920 : return result;
290 : }
291 :
292 17714993 : AstConsString* AstValueFactory::NewConsString() {
293 17714993 : AstConsString* new_string = new (zone_) AstConsString;
294 : DCHECK_NOT_NULL(new_string);
295 : AddConsString(new_string);
296 17714991 : return new_string;
297 : }
298 :
299 10861298 : AstConsString* AstValueFactory::NewConsString(const AstRawString* str) {
300 10861298 : return NewConsString()->AddString(zone_, str);
301 : }
302 :
303 30615 : AstConsString* AstValueFactory::NewConsString(const AstRawString* str1,
304 : const AstRawString* str2) {
305 30615 : return NewConsString()->AddString(zone_, str1)->AddString(zone_, str2);
306 : }
307 :
308 5591148 : void AstValueFactory::Internalize(Isolate* isolate) {
309 : // Strings need to be internalized before values, because values refer to
310 : // strings.
311 52550965 : for (AstRawString* current = strings_; current != nullptr;) {
312 : AstRawString* next = current->next();
313 41368670 : current->Internalize(isolate);
314 : current = next;
315 : }
316 :
317 : // AstConsStrings refer to AstRawStrings.
318 28415256 : for (AstConsString* current = cons_strings_; current != nullptr;) {
319 : AstConsString* next = current->next();
320 17232960 : current->Internalize(isolate);
321 : current = next;
322 : }
323 :
324 68531131 : for (AstValue* current = values_; current != nullptr;) {
325 : AstValue* next = current->next();
326 57348829 : current->Internalize(isolate);
327 : current = next;
328 : }
329 : ResetStrings();
330 5591153 : values_ = nullptr;
331 5591153 : }
332 :
333 :
334 36639069 : const AstValue* AstValueFactory::NewString(const AstRawString* string) {
335 36639069 : AstValue* value = new (zone_) AstValue(string);
336 36639061 : CHECK_NOT_NULL(string);
337 36639061 : return AddValue(value);
338 : }
339 :
340 6119 : const AstValue* AstValueFactory::NewSymbol(AstSymbol symbol) {
341 6119 : AstValue* value = new (zone_) AstValue(symbol);
342 6119 : return AddValue(value);
343 : }
344 :
345 :
346 5080760 : const AstValue* AstValueFactory::NewNumber(double number, bool with_dot) {
347 10161520 : AstValue* value = new (zone_) AstValue(number, with_dot);
348 5080760 : return AddValue(value);
349 : }
350 :
351 30000283 : const AstValue* AstValueFactory::NewSmi(uint32_t number) {
352 30000283 : bool cacheable_smi = number <= kMaxCachedSmi;
353 30000283 : if (cacheable_smi && smis_[number] != nullptr) return smis_[number];
354 :
355 28170273 : AstValue* value = new (zone_) AstValue(AstValue::SMI, number);
356 14085141 : if (cacheable_smi) smis_[number] = value;
357 14085141 : return AddValue(value);
358 : }
359 :
360 : #define GENERATE_VALUE_GETTER(value, initializer) \
361 : if (!value) { \
362 : value = AddValue(new (zone_) AstValue(initializer)); \
363 : } \
364 : return value;
365 :
366 1790872 : const AstValue* AstValueFactory::NewBoolean(bool b) {
367 1790872 : if (b) {
368 1107567 : GENERATE_VALUE_GETTER(true_value_, true);
369 : } else {
370 1338776 : GENERATE_VALUE_GETTER(false_value_, false);
371 : }
372 : }
373 :
374 :
375 1052943 : const AstValue* AstValueFactory::NewNull() {
376 1422810 : GENERATE_VALUE_GETTER(null_value_, AstValue::NULL_TYPE);
377 : }
378 :
379 :
380 1263283 : const AstValue* AstValueFactory::NewUndefined() {
381 1764075 : GENERATE_VALUE_GETTER(undefined_value_, AstValue::UNDEFINED);
382 : }
383 :
384 :
385 1437236 : const AstValue* AstValueFactory::NewTheHole() {
386 1450913 : GENERATE_VALUE_GETTER(the_hole_value_, AstValue::THE_HOLE);
387 : }
388 :
389 :
390 : #undef GENERATE_VALUE_GETTER
391 :
392 125916650 : AstRawString* AstValueFactory::GetString(uint32_t hash, bool is_one_byte,
393 : Vector<const byte> literal_bytes) {
394 : // literal_bytes here points to whatever the user passed, and this is OK
395 : // because we use vector_compare (which checks the contents) to compare
396 : // against the AstRawStrings which are in the string_table_. We should not
397 : // return this AstRawString.
398 : AstRawString key(is_one_byte, literal_bytes, hash);
399 251833498 : base::HashMap::Entry* entry = string_table_.LookupOrInsert(&key, hash);
400 125916848 : if (entry->value == nullptr) {
401 : // Copy literal contents for later comparison.
402 41441131 : int length = literal_bytes.length();
403 41441131 : byte* new_literal_bytes = zone_->NewArray<byte>(length);
404 41441133 : memcpy(new_literal_bytes, literal_bytes.start(), length);
405 : AstRawString* new_string = new (zone_) AstRawString(
406 41441133 : is_one_byte, Vector<const byte>(new_literal_bytes, length), hash);
407 41441090 : CHECK_NOT_NULL(new_string);
408 : AddString(new_string);
409 41441090 : entry->key = new_string;
410 41441090 : entry->value = reinterpret_cast<void*>(1);
411 : }
412 125916807 : return reinterpret_cast<AstRawString*>(entry->key);
413 : }
414 :
415 : } // namespace internal
416 : } // namespace v8
|