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: 42 explicit OneByteStringStream(Vector<const byte> lb) : 43 literal_bytes_(lb), pos_(0) {} 44 45 bool HasMore() { return pos_ < literal_bytes_.length(); } 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: 57 explicit AstRawStringInternalizationKey(const AstRawString* string) 58 : string_(string) {} 59 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 67 uint32_t Hash() override { return string_->hash() >> Name::kHashShift; } 68 69 uint32_t HashForObject(Object* key) override { 70 return String::cast(key)->Hash(); 71 } 72 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 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 97 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 108 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 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 127 bool AstValue::IsPropertyName() const { 128 if (type_ == STRING) { 129 uint32_t index; 130 return !string_->AsArrayIndex(&index); 131 } 132 return false; 133 } 134 135 136 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 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 { 176 DCHECK_EQ(0, strcmp(symbol_name_, "home_object_symbol")); 177 value_ = isolate->factory()->home_object_symbol(); 178 } 179 break; 180 case NUMBER_WITH_DOT: 181 case NUMBER: 182 value_ = isolate->factory()->NewNumber(number_, TENURED); 183 break; 184 case SMI: 185 value_ = handle(Smi::FromInt(smi_), isolate); 186 break; 187 case BOOLEAN: 188 if (bool_) { 189 value_ = isolate->factory()->true_value(); 190 } else { 191 value_ = isolate->factory()->false_value(); 192 } 193 break; 194 case NULL_TYPE: 195 value_ = isolate->factory()->null_value(); 196 break; 197 case THE_HOLE: 198 value_ = isolate->factory()->the_hole_value(); 199 break; 200 case UNDEFINED: 201 value_ = isolate->factory()->undefined_value(); 202 break; 203 } 204 } 205 206 207 AstRawString* AstValueFactory::GetOneByteStringInternal( 208 Vector<const uint8_t> literal) { 209 uint32_t hash = StringHasher::HashSequentialString<uint8_t>( 210 literal.start(), literal.length(), hash_seed_); 211 return GetString(hash, true, literal); 212 } 213 214 215 AstRawString* AstValueFactory::GetTwoByteStringInternal( 216 Vector<const uint16_t> literal) { 217 uint32_t hash = StringHasher::HashSequentialString<uint16_t>( 218 literal.start(), literal.length(), hash_seed_); 219 return GetString(hash, false, Vector<const byte>::cast(literal)); 220 } 221 222 223 const AstRawString* AstValueFactory::GetString(Handle<String> literal) { 224 // For the FlatContent to stay valid, we shouldn't do any heap 225 // allocation. Make sure we won't try to internalize the string in GetString. 226 AstRawString* result = NULL; 227 Isolate* saved_isolate = isolate_; 228 isolate_ = NULL; 229 { 230 DisallowHeapAllocation no_gc; 231 String::FlatContent content = literal->GetFlatContent(); 232 if (content.IsOneByte()) { 233 result = GetOneByteStringInternal(content.ToOneByteVector()); 234 } else { 235 DCHECK(content.IsTwoByte()); 236 result = GetTwoByteStringInternal(content.ToUC16Vector()); 237 } 238 } 239 isolate_ = saved_isolate; 240 if (isolate_) result->Internalize(isolate_); 241 return result; 242 } 243 244 245 const AstConsString* AstValueFactory::NewConsString( 246 const AstString* left, const AstString* right) { 247 // This Vector will be valid as long as the Collector is alive (meaning that 248 // the AstRawString will not be moved). 249 AstConsString* new_string = new (zone_) AstConsString(left, right); 250 strings_.Add(new_string); 251 if (isolate_) { 252 new_string->Internalize(isolate_); 253 } 254 return new_string; 255 } 256 257 258 void AstValueFactory::Internalize(Isolate* isolate) { 259 if (isolate_) { 260 // Everything is already internalized. 261 return; 262 } 263 // Strings need to be internalized before values, because values refer to 264 // strings. 265 for (int i = 0; i < strings_.length(); ++i) { 266 strings_[i]->Internalize(isolate); 267 } 268 for (int i = 0; i < values_.length(); ++i) { 269 values_[i]->Internalize(isolate); 270 } 271 isolate_ = isolate; 272 } 273 274 275 const AstValue* AstValueFactory::NewString(const AstRawString* string) { 276 AstValue* value = new (zone_) AstValue(string); 277 DCHECK(string != NULL); 278 if (isolate_) { 279 value->Internalize(isolate_); 280 } 281 values_.Add(value); 282 return value; 283 } 284 285 286 const AstValue* AstValueFactory::NewSymbol(const char* name) { 287 AstValue* value = new (zone_) AstValue(name); 288 if (isolate_) { 289 value->Internalize(isolate_); 290 } 291 values_.Add(value); 292 return value; 293 } 294 295 296 const AstValue* AstValueFactory::NewNumber(double number, bool with_dot) { 297 AstValue* value = new (zone_) AstValue(number, with_dot); 298 if (isolate_) { 299 value->Internalize(isolate_); 300 } 301 values_.Add(value); 302 return value; 303 } 304 305 306 const AstValue* AstValueFactory::NewSmi(int number) { 307 AstValue* value = 308 new (zone_) AstValue(AstValue::SMI, number); 309 if (isolate_) { 310 value->Internalize(isolate_); 311 } 312 values_.Add(value); 313 return value; 314 } 315 316 317 #define GENERATE_VALUE_GETTER(value, initializer) \ 318 if (!value) { \ 319 value = new (zone_) AstValue(initializer); \ 320 if (isolate_) { \ 321 value->Internalize(isolate_); \ 322 } \ 323 values_.Add(value); \ 324 } \ 325 return value; 326 327 328 const AstValue* AstValueFactory::NewBoolean(bool b) { 329 if (b) { 330 GENERATE_VALUE_GETTER(true_value_, true); 331 } else { 332 GENERATE_VALUE_GETTER(false_value_, false); 333 } 334 } 335 336 337 const AstValue* AstValueFactory::NewNull() { 338 GENERATE_VALUE_GETTER(null_value_, AstValue::NULL_TYPE); 339 } 340 341 342 const AstValue* AstValueFactory::NewUndefined() { 343 GENERATE_VALUE_GETTER(undefined_value_, AstValue::UNDEFINED); 344 } 345 346 347 const AstValue* AstValueFactory::NewTheHole() { 348 GENERATE_VALUE_GETTER(the_hole_value_, AstValue::THE_HOLE); 349 } 350 351 352 #undef GENERATE_VALUE_GETTER 353 354 AstRawString* AstValueFactory::GetString(uint32_t hash, bool is_one_byte, 355 Vector<const byte> literal_bytes) { 356 // literal_bytes here points to whatever the user passed, and this is OK 357 // because we use vector_compare (which checks the contents) to compare 358 // against the AstRawStrings which are in the string_table_. We should not 359 // return this AstRawString. 360 AstRawString key(is_one_byte, literal_bytes, hash); 361 HashMap::Entry* entry = string_table_.LookupOrInsert(&key, hash); 362 if (entry->value == NULL) { 363 // Copy literal contents for later comparison. 364 int length = literal_bytes.length(); 365 byte* new_literal_bytes = zone_->NewArray<byte>(length); 366 memcpy(new_literal_bytes, literal_bytes.start(), length); 367 AstRawString* new_string = new (zone_) AstRawString( 368 is_one_byte, Vector<const byte>(new_literal_bytes, length), hash); 369 entry->key = new_string; 370 strings_.Add(new_string); 371 if (isolate_) { 372 new_string->Internalize(isolate_); 373 } 374 entry->value = reinterpret_cast<void*>(1); 375 } 376 return reinterpret_cast<AstRawString*>(entry->key); 377 } 378 379 380 bool AstValueFactory::AstRawStringCompare(void* a, void* b) { 381 const AstRawString* lhs = static_cast<AstRawString*>(a); 382 const AstRawString* rhs = static_cast<AstRawString*>(b); 383 if (lhs->length() != rhs->length()) return false; 384 if (lhs->hash() != rhs->hash()) return false; 385 const unsigned char* l = lhs->raw_data(); 386 const unsigned char* r = rhs->raw_data(); 387 size_t length = rhs->length(); 388 if (lhs->is_one_byte()) { 389 if (rhs->is_one_byte()) { 390 return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l), 391 reinterpret_cast<const uint8_t*>(r), 392 length) == 0; 393 } else { 394 return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l), 395 reinterpret_cast<const uint16_t*>(r), 396 length) == 0; 397 } 398 } else { 399 if (rhs->is_one_byte()) { 400 return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l), 401 reinterpret_cast<const uint8_t*>(r), 402 length) == 0; 403 } else { 404 return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l), 405 reinterpret_cast<const uint16_t*>(r), 406 length) == 0; 407 } 408 } 409 } 410 } // namespace internal 411 } // namespace v8 412