• 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-value-factory.h"
29 
30 #include "src/api.h"
31 #include "src/objects.h"
32 
33 namespace v8 {
34 namespace internal {
35 
36 namespace {
37 
38 // For using StringToArrayIndex.
39 class OneByteStringStream {
40  public:
OneByteStringStream(Vector<const byte> lb)41   explicit OneByteStringStream(Vector<const byte> lb) :
42       literal_bytes_(lb), pos_(0) {}
43 
HasMore()44   bool HasMore() { return pos_ < literal_bytes_.length(); }
GetNext()45   uint16_t GetNext() { return literal_bytes_[pos_++]; }
46 
47  private:
48   Vector<const byte> literal_bytes_;
49   int pos_;
50 };
51 
52 }
53 
54 class AstRawStringInternalizationKey : public HashTableKey {
55  public:
AstRawStringInternalizationKey(const AstRawString * string)56   explicit AstRawStringInternalizationKey(const AstRawString* string)
57       : string_(string) {}
58 
IsMatch(Object * other)59   virtual bool IsMatch(Object* other) OVERRIDE {
60     if (string_->is_one_byte_)
61       return String::cast(other)->IsOneByteEqualTo(string_->literal_bytes_);
62     return String::cast(other)->IsTwoByteEqualTo(
63         Vector<const uint16_t>::cast(string_->literal_bytes_));
64   }
65 
Hash()66   virtual uint32_t Hash() OVERRIDE {
67     return string_->hash() >> Name::kHashShift;
68   }
69 
HashForObject(Object * key)70   virtual uint32_t HashForObject(Object* key) OVERRIDE {
71     return String::cast(key)->Hash();
72   }
73 
AsHandle(Isolate * isolate)74   virtual Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
75     if (string_->is_one_byte_)
76       return isolate->factory()->NewOneByteInternalizedString(
77           string_->literal_bytes_, string_->hash());
78     return isolate->factory()->NewTwoByteInternalizedString(
79         Vector<const uint16_t>::cast(string_->literal_bytes_), string_->hash());
80   }
81 
82  private:
83   const AstRawString* string_;
84 };
85 
86 
Internalize(Isolate * isolate)87 void AstRawString::Internalize(Isolate* isolate) {
88   if (!string_.is_null()) return;
89   if (literal_bytes_.length() == 0) {
90     string_ = isolate->factory()->empty_string();
91   } else {
92     AstRawStringInternalizationKey key(this);
93     string_ = StringTable::LookupKey(isolate, &key);
94   }
95 }
96 
97 
AsArrayIndex(uint32_t * index) const98 bool AstRawString::AsArrayIndex(uint32_t* index) const {
99   if (!string_.is_null())
100     return string_->AsArrayIndex(index);
101   if (!is_one_byte_ || literal_bytes_.length() == 0 ||
102       literal_bytes_.length() > String::kMaxArrayIndexSize)
103     return false;
104   OneByteStringStream stream(literal_bytes_);
105   return StringToArrayIndex(&stream, index);
106 }
107 
108 
IsOneByteEqualTo(const char * data) const109 bool AstRawString::IsOneByteEqualTo(const char* data) const {
110   int length = static_cast<int>(strlen(data));
111   if (is_one_byte_ && literal_bytes_.length() == length) {
112     const char* token = reinterpret_cast<const char*>(literal_bytes_.start());
113     return !strncmp(token, data, length);
114   }
115   return false;
116 }
117 
118 
Compare(void * a,void * b)119 bool AstRawString::Compare(void* a, void* b) {
120   AstRawString* string1 = reinterpret_cast<AstRawString*>(a);
121   AstRawString* string2 = reinterpret_cast<AstRawString*>(b);
122   if (string1->is_one_byte_ != string2->is_one_byte_) return false;
123   if (string1->hash_ != string2->hash_) return false;
124   int length = string1->literal_bytes_.length();
125   if (string2->literal_bytes_.length() != length) return false;
126   return memcmp(string1->literal_bytes_.start(),
127                 string2->literal_bytes_.start(), length) == 0;
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   string_ = isolate->factory()
135                 ->NewConsString(left_->string(), right_->string())
136                 .ToHandleChecked();
137 }
138 
139 
IsPropertyName() const140 bool AstValue::IsPropertyName() const {
141   if (type_ == STRING) {
142     uint32_t index;
143     return !string_->AsArrayIndex(&index);
144   }
145   return false;
146 }
147 
148 
BooleanValue() const149 bool AstValue::BooleanValue() const {
150   switch (type_) {
151     case STRING:
152       DCHECK(string_ != NULL);
153       return !string_->IsEmpty();
154     case SYMBOL:
155       UNREACHABLE();
156       break;
157     case NUMBER:
158       return DoubleToBoolean(number_);
159     case SMI:
160       return smi_ != 0;
161     case STRING_ARRAY:
162       UNREACHABLE();
163       break;
164     case BOOLEAN:
165       return bool_;
166     case NULL_TYPE:
167       return false;
168     case THE_HOLE:
169       UNREACHABLE();
170       break;
171     case UNDEFINED:
172       return false;
173   }
174   UNREACHABLE();
175   return false;
176 }
177 
178 
Internalize(Isolate * isolate)179 void AstValue::Internalize(Isolate* isolate) {
180   switch (type_) {
181     case STRING:
182       DCHECK(string_ != NULL);
183       // Strings are already internalized.
184       DCHECK(!string_->string().is_null());
185       break;
186     case SYMBOL:
187       value_ = Object::GetProperty(
188                    isolate, handle(isolate->native_context()->builtins()),
189                    symbol_name_).ToHandleChecked();
190       break;
191     case NUMBER:
192       value_ = isolate->factory()->NewNumber(number_, TENURED);
193       break;
194     case SMI:
195       value_ = handle(Smi::FromInt(smi_), isolate);
196       break;
197     case BOOLEAN:
198       if (bool_) {
199         value_ = isolate->factory()->true_value();
200       } else {
201         value_ = isolate->factory()->false_value();
202       }
203       break;
204     case STRING_ARRAY: {
205       DCHECK(strings_ != NULL);
206       Factory* factory = isolate->factory();
207       int len = strings_->length();
208       Handle<FixedArray> elements = factory->NewFixedArray(len, TENURED);
209       for (int i = 0; i < len; i++) {
210         const AstRawString* string = (*strings_)[i];
211         Handle<Object> element = string->string();
212         // Strings are already internalized.
213         DCHECK(!element.is_null());
214         elements->set(i, *element);
215       }
216       value_ =
217           factory->NewJSArrayWithElements(elements, FAST_ELEMENTS, TENURED);
218       break;
219     }
220     case NULL_TYPE:
221       value_ = isolate->factory()->null_value();
222       break;
223     case THE_HOLE:
224       value_ = isolate->factory()->the_hole_value();
225       break;
226     case UNDEFINED:
227       value_ = isolate->factory()->undefined_value();
228       break;
229   }
230 }
231 
232 
GetOneByteString(Vector<const uint8_t> literal)233 const AstRawString* AstValueFactory::GetOneByteString(
234     Vector<const uint8_t> literal) {
235   uint32_t hash = StringHasher::HashSequentialString<uint8_t>(
236       literal.start(), literal.length(), hash_seed_);
237   return GetString(hash, true, literal);
238 }
239 
240 
GetTwoByteString(Vector<const uint16_t> literal)241 const AstRawString* AstValueFactory::GetTwoByteString(
242     Vector<const uint16_t> literal) {
243   uint32_t hash = StringHasher::HashSequentialString<uint16_t>(
244       literal.start(), literal.length(), hash_seed_);
245   return GetString(hash, false, Vector<const byte>::cast(literal));
246 }
247 
248 
GetString(Handle<String> literal)249 const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
250   DisallowHeapAllocation no_gc;
251   String::FlatContent content = literal->GetFlatContent();
252   if (content.IsOneByte()) {
253     return GetOneByteString(content.ToOneByteVector());
254   }
255   DCHECK(content.IsTwoByte());
256   return GetTwoByteString(content.ToUC16Vector());
257 }
258 
259 
NewConsString(const AstString * left,const AstString * right)260 const AstConsString* AstValueFactory::NewConsString(
261     const AstString* left, const AstString* right) {
262   // This Vector will be valid as long as the Collector is alive (meaning that
263   // the AstRawString will not be moved).
264   AstConsString* new_string = new (zone_) AstConsString(left, right);
265   strings_.Add(new_string);
266   if (isolate_) {
267     new_string->Internalize(isolate_);
268   }
269   return new_string;
270 }
271 
272 
Internalize(Isolate * isolate)273 void AstValueFactory::Internalize(Isolate* isolate) {
274   if (isolate_) {
275     // Everything is already internalized.
276     return;
277   }
278   // Strings need to be internalized before values, because values refer to
279   // strings.
280   for (int i = 0; i < strings_.length(); ++i) {
281     strings_[i]->Internalize(isolate);
282   }
283   for (int i = 0; i < values_.length(); ++i) {
284     values_[i]->Internalize(isolate);
285   }
286   isolate_ = isolate;
287 }
288 
289 
NewString(const AstRawString * string)290 const AstValue* AstValueFactory::NewString(const AstRawString* string) {
291   AstValue* value = new (zone_) AstValue(string);
292   DCHECK(string != NULL);
293   if (isolate_) {
294     value->Internalize(isolate_);
295   }
296   values_.Add(value);
297   return value;
298 }
299 
300 
NewSymbol(const char * name)301 const AstValue* AstValueFactory::NewSymbol(const char* name) {
302   AstValue* value = new (zone_) AstValue(name);
303   if (isolate_) {
304     value->Internalize(isolate_);
305   }
306   values_.Add(value);
307   return value;
308 }
309 
310 
NewNumber(double number)311 const AstValue* AstValueFactory::NewNumber(double number) {
312   AstValue* value = new (zone_) AstValue(number);
313   if (isolate_) {
314     value->Internalize(isolate_);
315   }
316   values_.Add(value);
317   return value;
318 }
319 
320 
NewSmi(int number)321 const AstValue* AstValueFactory::NewSmi(int number) {
322   AstValue* value =
323       new (zone_) AstValue(AstValue::SMI, number);
324   if (isolate_) {
325     value->Internalize(isolate_);
326   }
327   values_.Add(value);
328   return value;
329 }
330 
331 
NewBoolean(bool b)332 const AstValue* AstValueFactory::NewBoolean(bool b) {
333   AstValue* value = new (zone_) AstValue(b);
334   if (isolate_) {
335     value->Internalize(isolate_);
336   }
337   values_.Add(value);
338   return value;
339 }
340 
341 
NewStringList(ZoneList<const AstRawString * > * strings)342 const AstValue* AstValueFactory::NewStringList(
343     ZoneList<const AstRawString*>* strings) {
344   AstValue* value = new (zone_) AstValue(strings);
345   if (isolate_) {
346     value->Internalize(isolate_);
347   }
348   values_.Add(value);
349   return value;
350 }
351 
352 
NewNull()353 const AstValue* AstValueFactory::NewNull() {
354   AstValue* value = new (zone_) AstValue(AstValue::NULL_TYPE);
355   if (isolate_) {
356     value->Internalize(isolate_);
357   }
358   values_.Add(value);
359   return value;
360 }
361 
362 
NewUndefined()363 const AstValue* AstValueFactory::NewUndefined() {
364   AstValue* value = new (zone_) AstValue(AstValue::UNDEFINED);
365   if (isolate_) {
366     value->Internalize(isolate_);
367   }
368   values_.Add(value);
369   return value;
370 }
371 
372 
NewTheHole()373 const AstValue* AstValueFactory::NewTheHole() {
374   AstValue* value = new (zone_) AstValue(AstValue::THE_HOLE);
375   if (isolate_) {
376     value->Internalize(isolate_);
377   }
378   values_.Add(value);
379   return value;
380 }
381 
382 
GetString(uint32_t hash,bool is_one_byte,Vector<const byte> literal_bytes)383 const AstRawString* AstValueFactory::GetString(
384     uint32_t hash, bool is_one_byte, Vector<const byte> literal_bytes) {
385   // literal_bytes here points to whatever the user passed, and this is OK
386   // because we use vector_compare (which checks the contents) to compare
387   // against the AstRawStrings which are in the string_table_. We should not
388   // return this AstRawString.
389   AstRawString key(is_one_byte, literal_bytes, hash);
390   HashMap::Entry* entry = string_table_.Lookup(&key, hash, true);
391   if (entry->value == NULL) {
392     // Copy literal contents for later comparison.
393     int length = literal_bytes.length();
394     byte* new_literal_bytes = zone_->NewArray<byte>(length);
395     memcpy(new_literal_bytes, literal_bytes.start(), length);
396     AstRawString* new_string = new (zone_) AstRawString(
397         is_one_byte, Vector<const byte>(new_literal_bytes, length), hash);
398     entry->key = new_string;
399     strings_.Add(new_string);
400     if (isolate_) {
401       new_string->Internalize(isolate_);
402     }
403     entry->value = reinterpret_cast<void*>(1);
404   }
405   return reinterpret_cast<AstRawString*>(entry->key);
406 }
407 
408 
409 } }  // namespace v8::internal
410