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