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 
     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