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/objects.h"
32 #include "src/utils.h"
33 
34 namespace v8 {
35 namespace internal {
36 
37 namespace {
38 
39 // For using StringToArrayIndex.
40 class OneByteStringStream {
41  public:
OneByteStringStream(Vector<const byte> lb)42   explicit OneByteStringStream(Vector<const byte> lb) :
43       literal_bytes_(lb), pos_(0) {}
44 
HasMore()45   bool HasMore() { return pos_ < literal_bytes_.length(); }
GetNext()46   uint16_t GetNext() { return literal_bytes_[pos_++]; }
47 
48  private:
49   Vector<const byte> literal_bytes_;
50   int pos_;
51 };
52 
53 }  // namespace
54 
55 class AstRawStringInternalizationKey : public HashTableKey {
56  public:
AstRawStringInternalizationKey(const AstRawString * string)57   explicit AstRawStringInternalizationKey(const AstRawString* string)
58       : string_(string) {}
59 
IsMatch(Object * other)60   bool IsMatch(Object* other) override {
61     if (string_->is_one_byte())
62       return String::cast(other)->IsOneByteEqualTo(string_->literal_bytes_);
63     return String::cast(other)->IsTwoByteEqualTo(
64         Vector<const uint16_t>::cast(string_->literal_bytes_));
65   }
66 
Hash()67   uint32_t Hash() override { return string_->hash() >> Name::kHashShift; }
68 
HashForObject(Object * key)69   uint32_t HashForObject(Object* key) override {
70     return String::cast(key)->Hash();
71   }
72 
AsHandle(Isolate * isolate)73   Handle<Object> AsHandle(Isolate* isolate) override {
74     if (string_->is_one_byte())
75       return isolate->factory()->NewOneByteInternalizedString(
76           string_->literal_bytes_, string_->hash());
77     return isolate->factory()->NewTwoByteInternalizedString(
78         Vector<const uint16_t>::cast(string_->literal_bytes_), string_->hash());
79   }
80 
81  private:
82   const AstRawString* string_;
83 };
84 
length() const85 int AstString::length() const {
86   if (IsRawStringBits::decode(bit_field_)) {
87     return reinterpret_cast<const AstRawString*>(this)->length();
88   }
89   return reinterpret_cast<const AstConsString*>(this)->length();
90 }
91 
Internalize(Isolate * isolate)92 void AstString::Internalize(Isolate* isolate) {
93   if (IsRawStringBits::decode(bit_field_)) {
94     return reinterpret_cast<AstRawString*>(this)->Internalize(isolate);
95   }
96   return reinterpret_cast<AstConsString*>(this)->Internalize(isolate);
97 }
98 
Internalize(Isolate * isolate)99 void AstRawString::Internalize(Isolate* isolate) {
100   if (literal_bytes_.length() == 0) {
101     set_string(isolate->factory()->empty_string());
102   } else {
103     AstRawStringInternalizationKey key(this);
104     set_string(StringTable::LookupKey(isolate, &key));
105   }
106 }
107 
AsArrayIndex(uint32_t * index) const108 bool AstRawString::AsArrayIndex(uint32_t* index) const {
109   // The StringHasher will set up the hash in such a way that we can use it to
110   // figure out whether the string is convertible to an array index.
111   if ((hash_ & Name::kIsNotArrayIndexMask) != 0) return false;
112   if (length() <= Name::kMaxCachedArrayIndexLength) {
113     *index = Name::ArrayIndexValueBits::decode(hash_);
114   } else {
115     OneByteStringStream stream(literal_bytes_);
116     CHECK(StringToArrayIndex(&stream, index));
117   }
118   return true;
119 }
120 
IsOneByteEqualTo(const char * data) const121 bool AstRawString::IsOneByteEqualTo(const char* data) const {
122   int length = static_cast<int>(strlen(data));
123   if (is_one_byte() && literal_bytes_.length() == length) {
124     const char* token = reinterpret_cast<const char*>(literal_bytes_.start());
125     return !strncmp(token, data, length);
126   }
127   return false;
128 }
129 
130 
Internalize(Isolate * isolate)131 void AstConsString::Internalize(Isolate* isolate) {
132   // AstRawStrings are internalized before AstConsStrings so left and right are
133   // already internalized.
134   set_string(isolate->factory()
135                  ->NewConsString(left_->string(), right_->string())
136                  .ToHandleChecked());
137 }
138 
IsPropertyName() const139 bool AstValue::IsPropertyName() const {
140   if (type_ == STRING) {
141     uint32_t index;
142     return !string_->AsArrayIndex(&index);
143   }
144   return false;
145 }
146 
147 
BooleanValue() const148 bool AstValue::BooleanValue() const {
149   switch (type_) {
150     case STRING:
151       DCHECK(string_ != NULL);
152       return !string_->IsEmpty();
153     case SYMBOL:
154       UNREACHABLE();
155       break;
156     case NUMBER_WITH_DOT:
157     case NUMBER:
158       return DoubleToBoolean(number_);
159     case SMI_WITH_DOT:
160     case SMI:
161       return smi_ != 0;
162     case BOOLEAN:
163       return bool_;
164     case NULL_TYPE:
165       return false;
166     case THE_HOLE:
167       UNREACHABLE();
168       break;
169     case UNDEFINED:
170       return false;
171   }
172   UNREACHABLE();
173   return false;
174 }
175 
176 
Internalize(Isolate * isolate)177 void AstValue::Internalize(Isolate* isolate) {
178   switch (type_) {
179     case STRING:
180       DCHECK_NOT_NULL(string_);
181       // Strings are already internalized.
182       DCHECK(!string_->string().is_null());
183       break;
184     case SYMBOL:
185       if (symbol_name_[0] == 'i') {
186         DCHECK_EQ(0, strcmp(symbol_name_, "iterator_symbol"));
187         set_value(isolate->factory()->iterator_symbol());
188       } else if (strcmp(symbol_name_, "hasInstance_symbol") == 0) {
189         set_value(isolate->factory()->has_instance_symbol());
190       } else {
191         DCHECK_EQ(0, strcmp(symbol_name_, "home_object_symbol"));
192         set_value(isolate->factory()->home_object_symbol());
193       }
194       break;
195     case NUMBER_WITH_DOT:
196     case NUMBER:
197       set_value(isolate->factory()->NewNumber(number_, TENURED));
198       break;
199     case SMI_WITH_DOT:
200     case SMI:
201       set_value(handle(Smi::FromInt(smi_), isolate));
202       break;
203     case BOOLEAN:
204       if (bool_) {
205         set_value(isolate->factory()->true_value());
206       } else {
207         set_value(isolate->factory()->false_value());
208       }
209       break;
210     case NULL_TYPE:
211       set_value(isolate->factory()->null_value());
212       break;
213     case THE_HOLE:
214       set_value(isolate->factory()->the_hole_value());
215       break;
216     case UNDEFINED:
217       set_value(isolate->factory()->undefined_value());
218       break;
219   }
220 }
221 
222 
GetOneByteStringInternal(Vector<const uint8_t> literal)223 AstRawString* AstValueFactory::GetOneByteStringInternal(
224     Vector<const uint8_t> literal) {
225   uint32_t hash = StringHasher::HashSequentialString<uint8_t>(
226       literal.start(), literal.length(), hash_seed_);
227   return GetString(hash, true, literal);
228 }
229 
230 
GetTwoByteStringInternal(Vector<const uint16_t> literal)231 AstRawString* AstValueFactory::GetTwoByteStringInternal(
232     Vector<const uint16_t> literal) {
233   uint32_t hash = StringHasher::HashSequentialString<uint16_t>(
234       literal.start(), literal.length(), hash_seed_);
235   return GetString(hash, false, Vector<const byte>::cast(literal));
236 }
237 
238 
GetString(Handle<String> literal)239 const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
240   AstRawString* result = NULL;
241   DisallowHeapAllocation no_gc;
242   String::FlatContent content = literal->GetFlatContent();
243   if (content.IsOneByte()) {
244     result = GetOneByteStringInternal(content.ToOneByteVector());
245   } else {
246     DCHECK(content.IsTwoByte());
247     result = GetTwoByteStringInternal(content.ToUC16Vector());
248   }
249   return result;
250 }
251 
252 
NewConsString(const AstString * left,const AstString * right)253 const AstConsString* AstValueFactory::NewConsString(
254     const AstString* left, const AstString* right) {
255   // This Vector will be valid as long as the Collector is alive (meaning that
256   // the AstRawString will not be moved).
257   AstConsString* new_string = new (zone_) AstConsString(left, right);
258   CHECK(new_string != nullptr);
259   AddString(new_string);
260   return new_string;
261 }
262 
ConcatStrings(const AstRawString * left,const AstRawString * right)263 const AstRawString* AstValueFactory::ConcatStrings(const AstRawString* left,
264                                                    const AstRawString* right) {
265   int left_length = left->length();
266   int right_length = right->length();
267   const unsigned char* left_data = left->raw_data();
268   const unsigned char* right_data = right->raw_data();
269   if (left->is_one_byte() && right->is_one_byte()) {
270     uint8_t* buffer = zone_->NewArray<uint8_t>(left_length + right_length);
271     memcpy(buffer, left_data, left_length);
272     memcpy(buffer + left_length, right_data, right_length);
273     Vector<const uint8_t> literal(buffer, left_length + right_length);
274     return GetOneByteStringInternal(literal);
275   } else {
276     uint16_t* buffer = zone_->NewArray<uint16_t>(left_length + right_length);
277     if (left->is_one_byte()) {
278       for (int i = 0; i < left_length; ++i) {
279         buffer[i] = left_data[i];
280       }
281     } else {
282       memcpy(buffer, left_data, 2 * left_length);
283     }
284     if (right->is_one_byte()) {
285       for (int i = 0; i < right_length; ++i) {
286         buffer[i + left_length] = right_data[i];
287       }
288     } else {
289       memcpy(buffer + left_length, right_data, 2 * right_length);
290     }
291     Vector<const uint16_t> literal(buffer, left_length + right_length);
292     return GetTwoByteStringInternal(literal);
293   }
294 }
295 
Internalize(Isolate * isolate)296 void AstValueFactory::Internalize(Isolate* isolate) {
297   // Strings need to be internalized before values, because values refer to
298   // strings.
299   for (AstString* current = strings_; current != nullptr;) {
300     AstString* next = current->next();
301     current->Internalize(isolate);
302     current = next;
303   }
304 
305   for (AstValue* current = values_; current != nullptr;) {
306     AstValue* next = current->next();
307     current->Internalize(isolate);
308     current = next;
309   }
310   ResetStrings();
311   values_ = nullptr;
312 }
313 
314 
NewString(const AstRawString * string)315 const AstValue* AstValueFactory::NewString(const AstRawString* string) {
316   AstValue* value = new (zone_) AstValue(string);
317   CHECK_NOT_NULL(string);
318   return AddValue(value);
319 }
320 
321 
NewSymbol(const char * name)322 const AstValue* AstValueFactory::NewSymbol(const char* name) {
323   AstValue* value = new (zone_) AstValue(name);
324   return AddValue(value);
325 }
326 
327 
NewNumber(double number,bool with_dot)328 const AstValue* AstValueFactory::NewNumber(double number, bool with_dot) {
329   AstValue* value = new (zone_) AstValue(number, with_dot);
330   return AddValue(value);
331 }
332 
NewSmi(uint32_t number)333 const AstValue* AstValueFactory::NewSmi(uint32_t number) {
334   bool cacheable_smi = number <= kMaxCachedSmi;
335   if (cacheable_smi && smis_[number] != nullptr) return smis_[number];
336 
337   AstValue* value = new (zone_) AstValue(AstValue::SMI, number);
338   if (cacheable_smi) smis_[number] = value;
339   return AddValue(value);
340 }
341 
342 #define GENERATE_VALUE_GETTER(value, initializer)        \
343   if (!value) {                                          \
344     value = AddValue(new (zone_) AstValue(initializer)); \
345   }                                                      \
346   return value;
347 
NewBoolean(bool b)348 const AstValue* AstValueFactory::NewBoolean(bool b) {
349   if (b) {
350     GENERATE_VALUE_GETTER(true_value_, true);
351   } else {
352     GENERATE_VALUE_GETTER(false_value_, false);
353   }
354 }
355 
356 
NewNull()357 const AstValue* AstValueFactory::NewNull() {
358   GENERATE_VALUE_GETTER(null_value_, AstValue::NULL_TYPE);
359 }
360 
361 
NewUndefined()362 const AstValue* AstValueFactory::NewUndefined() {
363   GENERATE_VALUE_GETTER(undefined_value_, AstValue::UNDEFINED);
364 }
365 
366 
NewTheHole()367 const AstValue* AstValueFactory::NewTheHole() {
368   GENERATE_VALUE_GETTER(the_hole_value_, AstValue::THE_HOLE);
369 }
370 
371 
372 #undef GENERATE_VALUE_GETTER
373 
GetString(uint32_t hash,bool is_one_byte,Vector<const byte> literal_bytes)374 AstRawString* AstValueFactory::GetString(uint32_t hash, bool is_one_byte,
375                                          Vector<const byte> literal_bytes) {
376   // literal_bytes here points to whatever the user passed, and this is OK
377   // because we use vector_compare (which checks the contents) to compare
378   // against the AstRawStrings which are in the string_table_. We should not
379   // return this AstRawString.
380   AstRawString key(is_one_byte, literal_bytes, hash);
381   base::HashMap::Entry* entry = string_table_.LookupOrInsert(&key, hash);
382   if (entry->value == NULL) {
383     // Copy literal contents for later comparison.
384     int length = literal_bytes.length();
385     byte* new_literal_bytes = zone_->NewArray<byte>(length);
386     memcpy(new_literal_bytes, literal_bytes.start(), length);
387     AstRawString* new_string = new (zone_) AstRawString(
388         is_one_byte, Vector<const byte>(new_literal_bytes, length), hash);
389     CHECK_NOT_NULL(new_string);
390     AddString(new_string);
391     entry->key = new_string;
392     entry->value = reinterpret_cast<void*>(1);
393   }
394   return reinterpret_cast<AstRawString*>(entry->key);
395 }
396 
397 
AstRawStringCompare(void * a,void * b)398 bool AstValueFactory::AstRawStringCompare(void* a, void* b) {
399   const AstRawString* lhs = static_cast<AstRawString*>(a);
400   const AstRawString* rhs = static_cast<AstRawString*>(b);
401   DCHECK_EQ(lhs->hash(), rhs->hash());
402   if (lhs->length() != rhs->length()) return false;
403   const unsigned char* l = lhs->raw_data();
404   const unsigned char* r = rhs->raw_data();
405   size_t length = rhs->length();
406   if (lhs->is_one_byte()) {
407     if (rhs->is_one_byte()) {
408       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
409                                   reinterpret_cast<const uint8_t*>(r),
410                                   length) == 0;
411     } else {
412       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
413                                   reinterpret_cast<const uint16_t*>(r),
414                                   length) == 0;
415     }
416   } else {
417     if (rhs->is_one_byte()) {
418       return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
419                                   reinterpret_cast<const uint8_t*>(r),
420                                   length) == 0;
421     } else {
422       return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
423                                   reinterpret_cast<const uint16_t*>(r),
424                                   length) == 0;
425     }
426   }
427 }
428 }  // namespace internal
429 }  // namespace v8
430