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 34namespace v8 { 35namespace internal { 36 37namespace { 38 39// For using StringToArrayIndex. 40class 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 55class 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 86void 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 97bool 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 108bool 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 118void 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 127bool AstValue::IsPropertyName() const { 128 if (type_ == STRING) { 129 uint32_t index; 130 return !string_->AsArrayIndex(&index); 131 } 132 return false; 133} 134 135 136bool 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 164void 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 209AstRawString* 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 217AstRawString* 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 225const 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 247const 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 260void 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 277const 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 288const 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 298const 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 308const 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 330const 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 339const AstValue* AstValueFactory::NewNull() { 340 GENERATE_VALUE_GETTER(null_value_, AstValue::NULL_TYPE); 341} 342 343 344const AstValue* AstValueFactory::NewUndefined() { 345 GENERATE_VALUE_GETTER(undefined_value_, AstValue::UNDEFINED); 346} 347 348 349const AstValue* AstValueFactory::NewTheHole() { 350 GENERATE_VALUE_GETTER(the_hole_value_, AstValue::THE_HOLE); 351} 352 353 354#undef GENERATE_VALUE_GETTER 355 356AstRawString* 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 382bool 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