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