Home | History | Annotate | Download | only in ast
      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 int AstString::length() const {
     86   if (IsRawStringBits::decode(bit_field_)) {
     87     return reinterpret_cast<const AstRawString*>(this)->length();
     88   }
     89   return reinterpret_cast<const AstConsString*>(this)->length();
     90 }
     91 
     92 void AstString::Internalize(Isolate* isolate) {
     93   if (IsRawStringBits::decode(bit_field_)) {
     94     return reinterpret_cast<AstRawString*>(this)->Internalize(isolate);
     95   }
     96   return reinterpret_cast<AstConsString*>(this)->Internalize(isolate);
     97 }
     98 
     99 void AstRawString::Internalize(Isolate* isolate) {
    100   if (literal_bytes_.length() == 0) {
    101     set_string(isolate->factory()->empty_string());
    102   } else {
    103     AstRawStringInternalizationKey key(this);
    104     set_string(StringTable::LookupKey(isolate, &key));
    105   }
    106 }
    107 
    108 bool AstRawString::AsArrayIndex(uint32_t* index) const {
    109   // The StringHasher will set up the hash in such a way that we can use it to
    110   // figure out whether the string is convertible to an array index.
    111   if ((hash_ & Name::kIsNotArrayIndexMask) != 0) return false;
    112   if (length() <= Name::kMaxCachedArrayIndexLength) {
    113     *index = Name::ArrayIndexValueBits::decode(hash_);
    114   } else {
    115     OneByteStringStream stream(literal_bytes_);
    116     CHECK(StringToArrayIndex(&stream, index));
    117   }
    118   return true;
    119 }
    120 
    121 bool AstRawString::IsOneByteEqualTo(const char* data) const {
    122   int length = static_cast<int>(strlen(data));
    123   if (is_one_byte() && literal_bytes_.length() == length) {
    124     const char* token = reinterpret_cast<const char*>(literal_bytes_.start());
    125     return !strncmp(token, data, length);
    126   }
    127   return false;
    128 }
    129 
    130 
    131 void AstConsString::Internalize(Isolate* isolate) {
    132   // AstRawStrings are internalized before AstConsStrings so left and right are
    133   // already internalized.
    134   set_string(isolate->factory()
    135                  ->NewConsString(left_->string(), right_->string())
    136                  .ToHandleChecked());
    137 }
    138 
    139 bool AstValue::IsPropertyName() const {
    140   if (type_ == STRING) {
    141     uint32_t index;
    142     return !string_->AsArrayIndex(&index);
    143   }
    144   return false;
    145 }
    146 
    147 
    148 bool AstValue::BooleanValue() const {
    149   switch (type_) {
    150     case STRING:
    151       DCHECK(string_ != NULL);
    152       return !string_->IsEmpty();
    153     case SYMBOL:
    154       UNREACHABLE();
    155       break;
    156     case NUMBER_WITH_DOT:
    157     case NUMBER:
    158       return DoubleToBoolean(number_);
    159     case SMI_WITH_DOT:
    160     case SMI:
    161       return smi_ != 0;
    162     case BOOLEAN:
    163       return bool_;
    164     case NULL_TYPE:
    165       return false;
    166     case THE_HOLE:
    167       UNREACHABLE();
    168       break;
    169     case UNDEFINED:
    170       return false;
    171   }
    172   UNREACHABLE();
    173   return false;
    174 }
    175 
    176 
    177 void AstValue::Internalize(Isolate* isolate) {
    178   switch (type_) {
    179     case STRING:
    180       DCHECK_NOT_NULL(string_);
    181       // Strings are already internalized.
    182       DCHECK(!string_->string().is_null());
    183       break;
    184     case SYMBOL:
    185       if (symbol_name_[0] == 'i') {
    186         DCHECK_EQ(0, strcmp(symbol_name_, "iterator_symbol"));
    187         set_value(isolate->factory()->iterator_symbol());
    188       } else if (strcmp(symbol_name_, "hasInstance_symbol") == 0) {
    189         set_value(isolate->factory()->has_instance_symbol());
    190       } else {
    191         DCHECK_EQ(0, strcmp(symbol_name_, "home_object_symbol"));
    192         set_value(isolate->factory()->home_object_symbol());
    193       }
    194       break;
    195     case NUMBER_WITH_DOT:
    196     case NUMBER:
    197       set_value(isolate->factory()->NewNumber(number_, TENURED));
    198       break;
    199     case SMI_WITH_DOT:
    200     case SMI:
    201       set_value(handle(Smi::FromInt(smi_), isolate));
    202       break;
    203     case BOOLEAN:
    204       if (bool_) {
    205         set_value(isolate->factory()->true_value());
    206       } else {
    207         set_value(isolate->factory()->false_value());
    208       }
    209       break;
    210     case NULL_TYPE:
    211       set_value(isolate->factory()->null_value());
    212       break;
    213     case THE_HOLE:
    214       set_value(isolate->factory()->the_hole_value());
    215       break;
    216     case UNDEFINED:
    217       set_value(isolate->factory()->undefined_value());
    218       break;
    219   }
    220 }
    221 
    222 
    223 AstRawString* AstValueFactory::GetOneByteStringInternal(
    224     Vector<const uint8_t> literal) {
    225   uint32_t hash = StringHasher::HashSequentialString<uint8_t>(
    226       literal.start(), literal.length(), hash_seed_);
    227   return GetString(hash, true, literal);
    228 }
    229 
    230 
    231 AstRawString* AstValueFactory::GetTwoByteStringInternal(
    232     Vector<const uint16_t> literal) {
    233   uint32_t hash = StringHasher::HashSequentialString<uint16_t>(
    234       literal.start(), literal.length(), hash_seed_);
    235   return GetString(hash, false, Vector<const byte>::cast(literal));
    236 }
    237 
    238 
    239 const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
    240   AstRawString* result = NULL;
    241   DisallowHeapAllocation no_gc;
    242   String::FlatContent content = literal->GetFlatContent();
    243   if (content.IsOneByte()) {
    244     result = GetOneByteStringInternal(content.ToOneByteVector());
    245   } else {
    246     DCHECK(content.IsTwoByte());
    247     result = GetTwoByteStringInternal(content.ToUC16Vector());
    248   }
    249   return result;
    250 }
    251 
    252 
    253 const AstConsString* AstValueFactory::NewConsString(
    254     const AstString* left, const AstString* right) {
    255   // This Vector will be valid as long as the Collector is alive (meaning that
    256   // the AstRawString will not be moved).
    257   AstConsString* new_string = new (zone_) AstConsString(left, right);
    258   CHECK(new_string != nullptr);
    259   AddString(new_string);
    260   return new_string;
    261 }
    262 
    263 const AstRawString* AstValueFactory::ConcatStrings(const AstRawString* left,
    264                                                    const AstRawString* right) {
    265   int left_length = left->length();
    266   int right_length = right->length();
    267   const unsigned char* left_data = left->raw_data();
    268   const unsigned char* right_data = right->raw_data();
    269   if (left->is_one_byte() && right->is_one_byte()) {
    270     uint8_t* buffer = zone_->NewArray<uint8_t>(left_length + right_length);
    271     memcpy(buffer, left_data, left_length);
    272     memcpy(buffer + left_length, right_data, right_length);
    273     Vector<const uint8_t> literal(buffer, left_length + right_length);
    274     return GetOneByteStringInternal(literal);
    275   } else {
    276     uint16_t* buffer = zone_->NewArray<uint16_t>(left_length + right_length);
    277     if (left->is_one_byte()) {
    278       for (int i = 0; i < left_length; ++i) {
    279         buffer[i] = left_data[i];
    280       }
    281     } else {
    282       memcpy(buffer, left_data, 2 * left_length);
    283     }
    284     if (right->is_one_byte()) {
    285       for (int i = 0; i < right_length; ++i) {
    286         buffer[i + left_length] = right_data[i];
    287       }
    288     } else {
    289       memcpy(buffer + left_length, right_data, 2 * right_length);
    290     }
    291     Vector<const uint16_t> literal(buffer, left_length + right_length);
    292     return GetTwoByteStringInternal(literal);
    293   }
    294 }
    295 
    296 void AstValueFactory::Internalize(Isolate* isolate) {
    297   // Strings need to be internalized before values, because values refer to
    298   // strings.
    299   for (AstString* current = strings_; current != nullptr;) {
    300     AstString* next = current->next();
    301     current->Internalize(isolate);
    302     current = next;
    303   }
    304 
    305   for (AstValue* current = values_; current != nullptr;) {
    306     AstValue* next = current->next();
    307     current->Internalize(isolate);
    308     current = next;
    309   }
    310   ResetStrings();
    311   values_ = nullptr;
    312 }
    313 
    314 
    315 const AstValue* AstValueFactory::NewString(const AstRawString* string) {
    316   AstValue* value = new (zone_) AstValue(string);
    317   CHECK_NOT_NULL(string);
    318   return AddValue(value);
    319 }
    320 
    321 
    322 const AstValue* AstValueFactory::NewSymbol(const char* name) {
    323   AstValue* value = new (zone_) AstValue(name);
    324   return AddValue(value);
    325 }
    326 
    327 
    328 const AstValue* AstValueFactory::NewNumber(double number, bool with_dot) {
    329   AstValue* value = new (zone_) AstValue(number, with_dot);
    330   return AddValue(value);
    331 }
    332 
    333 const AstValue* AstValueFactory::NewSmi(uint32_t number) {
    334   bool cacheable_smi = number <= kMaxCachedSmi;
    335   if (cacheable_smi && smis_[number] != nullptr) return smis_[number];
    336 
    337   AstValue* value = new (zone_) AstValue(AstValue::SMI, number);
    338   if (cacheable_smi) smis_[number] = value;
    339   return AddValue(value);
    340 }
    341 
    342 #define GENERATE_VALUE_GETTER(value, initializer)        \
    343   if (!value) {                                          \
    344     value = AddValue(new (zone_) AstValue(initializer)); \
    345   }                                                      \
    346   return value;
    347 
    348 const AstValue* AstValueFactory::NewBoolean(bool b) {
    349   if (b) {
    350     GENERATE_VALUE_GETTER(true_value_, true);
    351   } else {
    352     GENERATE_VALUE_GETTER(false_value_, false);
    353   }
    354 }
    355 
    356 
    357 const AstValue* AstValueFactory::NewNull() {
    358   GENERATE_VALUE_GETTER(null_value_, AstValue::NULL_TYPE);
    359 }
    360 
    361 
    362 const AstValue* AstValueFactory::NewUndefined() {
    363   GENERATE_VALUE_GETTER(undefined_value_, AstValue::UNDEFINED);
    364 }
    365 
    366 
    367 const AstValue* AstValueFactory::NewTheHole() {
    368   GENERATE_VALUE_GETTER(the_hole_value_, AstValue::THE_HOLE);
    369 }
    370 
    371 
    372 #undef GENERATE_VALUE_GETTER
    373 
    374 AstRawString* AstValueFactory::GetString(uint32_t hash, bool is_one_byte,
    375                                          Vector<const byte> literal_bytes) {
    376   // literal_bytes here points to whatever the user passed, and this is OK
    377   // because we use vector_compare (which checks the contents) to compare
    378   // against the AstRawStrings which are in the string_table_. We should not
    379   // return this AstRawString.
    380   AstRawString key(is_one_byte, literal_bytes, hash);
    381   base::HashMap::Entry* entry = string_table_.LookupOrInsert(&key, hash);
    382   if (entry->value == NULL) {
    383     // Copy literal contents for later comparison.
    384     int length = literal_bytes.length();
    385     byte* new_literal_bytes = zone_->NewArray<byte>(length);
    386     memcpy(new_literal_bytes, literal_bytes.start(), length);
    387     AstRawString* new_string = new (zone_) AstRawString(
    388         is_one_byte, Vector<const byte>(new_literal_bytes, length), hash);
    389     CHECK_NOT_NULL(new_string);
    390     AddString(new_string);
    391     entry->key = new_string;
    392     entry->value = reinterpret_cast<void*>(1);
    393   }
    394   return reinterpret_cast<AstRawString*>(entry->key);
    395 }
    396 
    397 
    398 bool AstValueFactory::AstRawStringCompare(void* a, void* b) {
    399   const AstRawString* lhs = static_cast<AstRawString*>(a);
    400   const AstRawString* rhs = static_cast<AstRawString*>(b);
    401   DCHECK_EQ(lhs->hash(), rhs->hash());
    402   if (lhs->length() != rhs->length()) return false;
    403   const unsigned char* l = lhs->raw_data();
    404   const unsigned char* r = rhs->raw_data();
    405   size_t length = rhs->length();
    406   if (lhs->is_one_byte()) {
    407     if (rhs->is_one_byte()) {
    408       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
    409                                   reinterpret_cast<const uint8_t*>(r),
    410                                   length) == 0;
    411     } else {
    412       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
    413                                   reinterpret_cast<const uint16_t*>(r),
    414                                   length) == 0;
    415     }
    416   } else {
    417     if (rhs->is_one_byte()) {
    418       return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
    419                                   reinterpret_cast<const uint8_t*>(r),
    420                                   length) == 0;
    421     } else {
    422       return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
    423                                   reinterpret_cast<const uint16_t*>(r),
    424                                   length) == 0;
    425     }
    426   }
    427 }
    428 }  // namespace internal
    429 }  // namespace v8
    430