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
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.
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.
28 #include "src/ast-value-factory.h"
31 #include "src/objects.h"
38 // For using StringToArrayIndex.
39 class OneByteStringStream {
41 explicit OneByteStringStream(Vector<const byte> lb) :
42 literal_bytes_(lb), pos_(0) {}
44 bool HasMore() { return pos_ < literal_bytes_.length(); }
45 uint16_t GetNext() { return literal_bytes_[pos_++]; }
48 Vector<const byte> literal_bytes_;
54 class AstRawStringInternalizationKey : public HashTableKey {
56 explicit AstRawStringInternalizationKey(const AstRawString* string)
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_));
66 uint32_t Hash() override { return string_->hash() >> Name::kHashShift; }
68 uint32_t HashForObject(Object* key) override {
69 return String::cast(key)->Hash();
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());
81 const AstRawString* string_;
85 void AstRawString::Internalize(Isolate* isolate) {
86 if (!string_.is_null()) return;
87 if (literal_bytes_.length() == 0) {
88 string_ = isolate->factory()->empty_string();
90 AstRawStringInternalizationKey key(this);
91 string_ = StringTable::LookupKey(isolate, &key);
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)
102 OneByteStringStream stream(literal_bytes_);
103 return StringToArrayIndex(&stream, index);
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);
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())
126 bool AstValue::IsPropertyName() const {
127 if (type_ == STRING) {
129 return !string_->AsArrayIndex(&index);
135 bool AstValue::BooleanValue() const {
138 DCHECK(string_ != NULL);
139 return !string_->IsEmpty();
143 case NUMBER_WITH_DOT:
145 return DoubleToBoolean(number_);
163 void AstValue::Internalize(Isolate* isolate) {
166 DCHECK(string_ != NULL);
167 // Strings are already internalized.
168 DCHECK(!string_->string().is_null());
171 if (symbol_name_[0] == 'i') {
172 DCHECK_EQ(0, strcmp(symbol_name_, "iterator_symbol"));
173 value_ = isolate->factory()->iterator_symbol();
175 DCHECK_EQ(0, strcmp(symbol_name_, "home_object_symbol"));
176 value_ = isolate->factory()->home_object_symbol();
179 case NUMBER_WITH_DOT:
181 value_ = isolate->factory()->NewNumber(number_, TENURED);
184 value_ = handle(Smi::FromInt(smi_), isolate);
188 value_ = isolate->factory()->true_value();
190 value_ = isolate->factory()->false_value();
194 value_ = isolate->factory()->null_value();
197 value_ = isolate->factory()->the_hole_value();
200 value_ = isolate->factory()->undefined_value();
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);
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));
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_;
229 DisallowHeapAllocation no_gc;
230 String::FlatContent content = literal->GetFlatContent();
231 if (content.IsOneByte()) {
232 result = GetOneByteStringInternal(content.ToOneByteVector());
234 DCHECK(content.IsTwoByte());
235 result = GetTwoByteStringInternal(content.ToUC16Vector());
238 isolate_ = saved_isolate;
239 if (isolate_) result->Internalize(isolate_);
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);
251 new_string->Internalize(isolate_);
257 void AstValueFactory::Internalize(Isolate* isolate) {
259 // Everything is already internalized.
262 // Strings need to be internalized before values, because values refer to
264 for (int i = 0; i < strings_.length(); ++i) {
265 strings_[i]->Internalize(isolate);
267 for (int i = 0; i < values_.length(); ++i) {
268 values_[i]->Internalize(isolate);
274 const AstValue* AstValueFactory::NewString(const AstRawString* string) {
275 AstValue* value = new (zone_) AstValue(string);
276 DCHECK(string != NULL);
278 value->Internalize(isolate_);
285 const AstValue* AstValueFactory::NewSymbol(const char* name) {
286 AstValue* value = new (zone_) AstValue(name);
288 value->Internalize(isolate_);
295 const AstValue* AstValueFactory::NewNumber(double number, bool with_dot) {
296 AstValue* value = new (zone_) AstValue(number, with_dot);
298 value->Internalize(isolate_);
305 const AstValue* AstValueFactory::NewSmi(int number) {
307 new (zone_) AstValue(AstValue::SMI, number);
309 value->Internalize(isolate_);
316 #define GENERATE_VALUE_GETTER(value, initializer) \
318 value = new (zone_) AstValue(initializer); \
320 value->Internalize(isolate_); \
322 values_.Add(value); \
327 const AstValue* AstValueFactory::NewBoolean(bool b) {
329 GENERATE_VALUE_GETTER(true_value_, true);
331 GENERATE_VALUE_GETTER(false_value_, false);
336 const AstValue* AstValueFactory::NewNull() {
337 GENERATE_VALUE_GETTER(null_value_, AstValue::NULL_TYPE);
341 const AstValue* AstValueFactory::NewUndefined() {
342 GENERATE_VALUE_GETTER(undefined_value_, AstValue::UNDEFINED);
346 const AstValue* AstValueFactory::NewTheHole() {
347 GENERATE_VALUE_GETTER(the_hole_value_, AstValue::THE_HOLE);
351 #undef GENERATE_VALUE_GETTER
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);
371 new_string->Internalize(isolate_);
373 entry->value = reinterpret_cast<void*>(1);
375 return reinterpret_cast<AstRawString*>(entry->key);
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;
388 } // namespace internal