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