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 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 
    209 AstRawString* 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 
    217 AstRawString* 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 
    225 const 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 
    247 const 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 
    260 void 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 
    277 const 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 
    288 const 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 
    298 const 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 
    308 const 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 
    330 const 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 
    339 const AstValue* AstValueFactory::NewNull() {
    340   GENERATE_VALUE_GETTER(null_value_, AstValue::NULL_TYPE);
    341 }
    342 
    343 
    344 const AstValue* AstValueFactory::NewUndefined() {
    345   GENERATE_VALUE_GETTER(undefined_value_, AstValue::UNDEFINED);
    346 }
    347 
    348 
    349 const AstValue* AstValueFactory::NewTheHole() {
    350   GENERATE_VALUE_GETTER(the_hole_value_, AstValue::THE_HOLE);
    351 }
    352 
    353 
    354 #undef GENERATE_VALUE_GETTER
    355 
    356 AstRawString* 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 
    382 bool 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