• 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/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 
85 
Internalize(Isolate * isolate)86 void AstRawString::Internalize(Isolate* isolate) {
87   if (!string_.is_null()) return;
88   if (literal_bytes_.length() == 0) {
89     string_ = isolate->factory()->empty_string();
90   } else {
91     AstRawStringInternalizationKey key(this);
92     string_ = StringTable::LookupKey(isolate, &key);
93   }
94 }
95 
96 
AsArrayIndex(uint32_t * index) const97 bool AstRawString::AsArrayIndex(uint32_t* index) const {
98   if (!string_.is_null())
99     return string_->AsArrayIndex(index);
100   if (!is_one_byte_ || literal_bytes_.length() == 0 ||
101       literal_bytes_.length() > String::kMaxArrayIndexSize)
102     return false;
103   OneByteStringStream stream(literal_bytes_);
104   return StringToArrayIndex(&stream, index);
105 }
106 
107 
IsOneByteEqualTo(const char * data) const108 bool AstRawString::IsOneByteEqualTo(const char* data) const {
109   int length = static_cast<int>(strlen(data));
110   if (is_one_byte_ && literal_bytes_.length() == length) {
111     const char* token = reinterpret_cast<const char*>(literal_bytes_.start());
112     return !strncmp(token, data, length);
113   }
114   return false;
115 }
116 
117 
Internalize(Isolate * isolate)118 void AstConsString::Internalize(Isolate* isolate) {
119   // AstRawStrings are internalized before AstConsStrings so left and right are
120   // already internalized.
121   string_ = isolate->factory()
122                 ->NewConsString(left_->string(), right_->string())
123                 .ToHandleChecked();
124 }
125 
126 
IsPropertyName() const127 bool AstValue::IsPropertyName() const {
128   if (type_ == STRING) {
129     uint32_t index;
130     return !string_->AsArrayIndex(&index);
131   }
132   return false;
133 }
134 
135 
BooleanValue() const136 bool AstValue::BooleanValue() const {
137   switch (type_) {
138     case STRING:
139       DCHECK(string_ != NULL);
140       return !string_->IsEmpty();
141     case SYMBOL:
142       UNREACHABLE();
143       break;
144     case NUMBER_WITH_DOT:
145     case NUMBER:
146       return DoubleToBoolean(number_);
147     case SMI:
148       return smi_ != 0;
149     case BOOLEAN:
150       return bool_;
151     case NULL_TYPE:
152       return false;
153     case THE_HOLE:
154       UNREACHABLE();
155       break;
156     case UNDEFINED:
157       return false;
158   }
159   UNREACHABLE();
160   return false;
161 }
162 
163 
Internalize(Isolate * isolate)164 void AstValue::Internalize(Isolate* isolate) {
165   switch (type_) {
166     case STRING:
167       DCHECK(string_ != NULL);
168       // Strings are already internalized.
169       DCHECK(!string_->string().is_null());
170       break;
171     case SYMBOL:
172       if (symbol_name_[0] == 'i') {
173         DCHECK_EQ(0, strcmp(symbol_name_, "iterator_symbol"));
174         value_ = isolate->factory()->iterator_symbol();
175       } else if (strcmp(symbol_name_, "hasInstance_symbol") == 0) {
176         value_ = isolate->factory()->has_instance_symbol();
177       } else {
178         DCHECK_EQ(0, strcmp(symbol_name_, "home_object_symbol"));
179         value_ = isolate->factory()->home_object_symbol();
180       }
181       break;
182     case NUMBER_WITH_DOT:
183     case NUMBER:
184       value_ = isolate->factory()->NewNumber(number_, TENURED);
185       break;
186     case SMI:
187       value_ = handle(Smi::FromInt(smi_), isolate);
188       break;
189     case BOOLEAN:
190       if (bool_) {
191         value_ = isolate->factory()->true_value();
192       } else {
193         value_ = isolate->factory()->false_value();
194       }
195       break;
196     case NULL_TYPE:
197       value_ = isolate->factory()->null_value();
198       break;
199     case THE_HOLE:
200       value_ = isolate->factory()->the_hole_value();
201       break;
202     case UNDEFINED:
203       value_ = isolate->factory()->undefined_value();
204       break;
205   }
206 }
207 
208 
GetOneByteStringInternal(Vector<const uint8_t> literal)209 AstRawString* AstValueFactory::GetOneByteStringInternal(
210     Vector<const uint8_t> literal) {
211   uint32_t hash = StringHasher::HashSequentialString<uint8_t>(
212       literal.start(), literal.length(), hash_seed_);
213   return GetString(hash, true, literal);
214 }
215 
216 
GetTwoByteStringInternal(Vector<const uint16_t> literal)217 AstRawString* AstValueFactory::GetTwoByteStringInternal(
218     Vector<const uint16_t> literal) {
219   uint32_t hash = StringHasher::HashSequentialString<uint16_t>(
220       literal.start(), literal.length(), hash_seed_);
221   return GetString(hash, false, Vector<const byte>::cast(literal));
222 }
223 
224 
GetString(Handle<String> literal)225 const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
226   // For the FlatContent to stay valid, we shouldn't do any heap
227   // allocation. Make sure we won't try to internalize the string in GetString.
228   AstRawString* result = NULL;
229   Isolate* saved_isolate = isolate_;
230   isolate_ = NULL;
231   {
232     DisallowHeapAllocation no_gc;
233     String::FlatContent content = literal->GetFlatContent();
234     if (content.IsOneByte()) {
235       result = GetOneByteStringInternal(content.ToOneByteVector());
236     } else {
237       DCHECK(content.IsTwoByte());
238       result = GetTwoByteStringInternal(content.ToUC16Vector());
239     }
240   }
241   isolate_ = saved_isolate;
242   if (isolate_) result->Internalize(isolate_);
243   return result;
244 }
245 
246 
NewConsString(const AstString * left,const AstString * right)247 const AstConsString* AstValueFactory::NewConsString(
248     const AstString* left, const AstString* right) {
249   // This Vector will be valid as long as the Collector is alive (meaning that
250   // the AstRawString will not be moved).
251   AstConsString* new_string = new (zone_) AstConsString(left, right);
252   strings_.Add(new_string);
253   if (isolate_) {
254     new_string->Internalize(isolate_);
255   }
256   return new_string;
257 }
258 
259 
Internalize(Isolate * isolate)260 void AstValueFactory::Internalize(Isolate* isolate) {
261   if (isolate_) {
262     // Everything is already internalized.
263     return;
264   }
265   // Strings need to be internalized before values, because values refer to
266   // strings.
267   for (int i = 0; i < strings_.length(); ++i) {
268     strings_[i]->Internalize(isolate);
269   }
270   for (int i = 0; i < values_.length(); ++i) {
271     values_[i]->Internalize(isolate);
272   }
273   isolate_ = isolate;
274 }
275 
276 
NewString(const AstRawString * string)277 const AstValue* AstValueFactory::NewString(const AstRawString* string) {
278   AstValue* value = new (zone_) AstValue(string);
279   DCHECK(string != NULL);
280   if (isolate_) {
281     value->Internalize(isolate_);
282   }
283   values_.Add(value);
284   return value;
285 }
286 
287 
NewSymbol(const char * name)288 const AstValue* AstValueFactory::NewSymbol(const char* name) {
289   AstValue* value = new (zone_) AstValue(name);
290   if (isolate_) {
291     value->Internalize(isolate_);
292   }
293   values_.Add(value);
294   return value;
295 }
296 
297 
NewNumber(double number,bool with_dot)298 const AstValue* AstValueFactory::NewNumber(double number, bool with_dot) {
299   AstValue* value = new (zone_) AstValue(number, with_dot);
300   if (isolate_) {
301     value->Internalize(isolate_);
302   }
303   values_.Add(value);
304   return value;
305 }
306 
307 
NewSmi(int number)308 const AstValue* AstValueFactory::NewSmi(int number) {
309   AstValue* value =
310       new (zone_) AstValue(AstValue::SMI, number);
311   if (isolate_) {
312     value->Internalize(isolate_);
313   }
314   values_.Add(value);
315   return value;
316 }
317 
318 
319 #define GENERATE_VALUE_GETTER(value, initializer) \
320   if (!value) {                                   \
321     value = new (zone_) AstValue(initializer);    \
322     if (isolate_) {                               \
323       value->Internalize(isolate_);               \
324     }                                             \
325     values_.Add(value);                           \
326   }                                               \
327   return value;
328 
329 
NewBoolean(bool b)330 const AstValue* AstValueFactory::NewBoolean(bool b) {
331   if (b) {
332     GENERATE_VALUE_GETTER(true_value_, true);
333   } else {
334     GENERATE_VALUE_GETTER(false_value_, false);
335   }
336 }
337 
338 
NewNull()339 const AstValue* AstValueFactory::NewNull() {
340   GENERATE_VALUE_GETTER(null_value_, AstValue::NULL_TYPE);
341 }
342 
343 
NewUndefined()344 const AstValue* AstValueFactory::NewUndefined() {
345   GENERATE_VALUE_GETTER(undefined_value_, AstValue::UNDEFINED);
346 }
347 
348 
NewTheHole()349 const AstValue* AstValueFactory::NewTheHole() {
350   GENERATE_VALUE_GETTER(the_hole_value_, AstValue::THE_HOLE);
351 }
352 
353 
354 #undef GENERATE_VALUE_GETTER
355 
GetString(uint32_t hash,bool is_one_byte,Vector<const byte> literal_bytes)356 AstRawString* AstValueFactory::GetString(uint32_t hash, bool is_one_byte,
357                                          Vector<const byte> literal_bytes) {
358   // literal_bytes here points to whatever the user passed, and this is OK
359   // because we use vector_compare (which checks the contents) to compare
360   // against the AstRawStrings which are in the string_table_. We should not
361   // return this AstRawString.
362   AstRawString key(is_one_byte, literal_bytes, hash);
363   base::HashMap::Entry* entry = string_table_.LookupOrInsert(&key, hash);
364   if (entry->value == NULL) {
365     // Copy literal contents for later comparison.
366     int length = literal_bytes.length();
367     byte* new_literal_bytes = zone_->NewArray<byte>(length);
368     memcpy(new_literal_bytes, literal_bytes.start(), length);
369     AstRawString* new_string = new (zone_) AstRawString(
370         is_one_byte, Vector<const byte>(new_literal_bytes, length), hash);
371     entry->key = new_string;
372     strings_.Add(new_string);
373     if (isolate_) {
374       new_string->Internalize(isolate_);
375     }
376     entry->value = reinterpret_cast<void*>(1);
377   }
378   return reinterpret_cast<AstRawString*>(entry->key);
379 }
380 
381 
AstRawStringCompare(void * a,void * b)382 bool AstValueFactory::AstRawStringCompare(void* a, void* b) {
383   const AstRawString* lhs = static_cast<AstRawString*>(a);
384   const AstRawString* rhs = static_cast<AstRawString*>(b);
385   if (lhs->length() != rhs->length()) return false;
386   if (lhs->hash() != rhs->hash()) return false;
387   const unsigned char* l = lhs->raw_data();
388   const unsigned char* r = rhs->raw_data();
389   size_t length = rhs->length();
390   if (lhs->is_one_byte()) {
391     if (rhs->is_one_byte()) {
392       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
393                                   reinterpret_cast<const uint8_t*>(r),
394                                   length) == 0;
395     } else {
396       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
397                                   reinterpret_cast<const uint16_t*>(r),
398                                   length) == 0;
399     }
400   } else {
401     if (rhs->is_one_byte()) {
402       return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
403                                   reinterpret_cast<const uint8_t*>(r),
404                                   length) == 0;
405     } else {
406       return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
407                                   reinterpret_cast<const uint16_t*>(r),
408                                   length) == 0;
409     }
410   }
411 }
412 }  // namespace internal
413 }  // namespace v8
414