Home | History | Annotate | Download | only in src
      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:
     41   explicit OneByteStringStream(Vector<const byte> lb) :
     42       literal_bytes_(lb), pos_(0) {}
     43 
     44   bool HasMore() { return pos_ < literal_bytes_.length(); }
     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:
     56   explicit AstRawStringInternalizationKey(const AstRawString* string)
     57       : string_(string) {}
     58 
     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 
     66   virtual uint32_t Hash() OVERRIDE {
     67     return string_->hash() >> Name::kHashShift;
     68   }
     69 
     70   virtual uint32_t HashForObject(Object* key) OVERRIDE {
     71     return String::cast(key)->Hash();
     72   }
     73 
     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 
     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 
     98 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 
    109 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 
    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 
    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 
    140 bool AstValue::IsPropertyName() const {
    141   if (type_ == STRING) {
    142     uint32_t index;
    143     return !string_->AsArrayIndex(&index);
    144   }
    145   return false;
    146 }
    147 
    148 
    149 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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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