LCOV - code coverage report
Current view: top level - src/ast - ast-value-factory.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 139 144 96.5 %
Date: 2017-04-26 Functions: 29 31 93.5 %

          Line data    Source code
       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/char-predicates-inl.h"
      32             : #include "src/objects-inl.h"
      33             : #include "src/objects.h"
      34             : #include "src/utils.h"
      35             : 
      36             : namespace v8 {
      37             : namespace internal {
      38             : 
      39             : namespace {
      40             : 
      41             : // For using StringToArrayIndex.
      42             : class OneByteStringStream {
      43             :  public:
      44             :   explicit OneByteStringStream(Vector<const byte> lb) :
      45          29 :       literal_bytes_(lb), pos_(0) {}
      46             : 
      47         274 :   bool HasMore() { return pos_ < literal_bytes_.length(); }
      48         548 :   uint16_t GetNext() { return literal_bytes_[pos_++]; }
      49             : 
      50             :  private:
      51             :   Vector<const byte> literal_bytes_;
      52             :   int pos_;
      53             : };
      54             : 
      55             : }  // namespace
      56             : 
      57           0 : class AstRawStringInternalizationKey : public HashTableKey {
      58             :  public:
      59             :   explicit AstRawStringInternalizationKey(const AstRawString* string)
      60    41368669 :       : string_(string) {}
      61             : 
      62    75215956 :   bool IsMatch(Object* other) override {
      63    75215956 :     if (string_->is_one_byte())
      64    75175209 :       return String::cast(other)->IsOneByteEqualTo(string_->literal_bytes_);
      65             :     return String::cast(other)->IsTwoByteEqualTo(
      66       81494 :         Vector<const uint16_t>::cast(string_->literal_bytes_));
      67             :   }
      68             : 
      69    52231736 :   uint32_t Hash() override { return string_->hash() >> Name::kHashShift; }
      70             : 
      71     6295068 :   uint32_t HashForObject(Object* key) override {
      72     6295068 :     return String::cast(key)->Hash();
      73             :   }
      74             : 
      75    10863122 :   Handle<Object> AsHandle(Isolate* isolate) override {
      76    10893561 :     if (string_->is_one_byte())
      77             :       return isolate->factory()->NewOneByteInternalizedString(
      78    10832683 :           string_->literal_bytes_, string_->hash());
      79             :     return isolate->factory()->NewTwoByteInternalizedString(
      80       60878 :         Vector<const uint16_t>::cast(string_->literal_bytes_), string_->hash());
      81             :   }
      82             : 
      83             :  private:
      84             :   const AstRawString* string_;
      85             : };
      86             : 
      87    41368669 : void AstRawString::Internalize(Isolate* isolate) {
      88             :   DCHECK(!has_string_);
      89    41368669 :   if (literal_bytes_.length() == 0) {
      90             :     set_string(isolate->factory()->empty_string());
      91             :   } else {
      92             :     AstRawStringInternalizationKey key(this);
      93    41368669 :     set_string(StringTable::LookupKey(isolate, &key));
      94             :   }
      95    41368658 : }
      96             : 
      97    26240224 : bool AstRawString::AsArrayIndex(uint32_t* index) const {
      98             :   // The StringHasher will set up the hash in such a way that we can use it to
      99             :   // figure out whether the string is convertible to an array index.
     100    26240224 :   if ((hash_ & Name::kIsNotArrayIndexMask) != 0) return false;
     101      817289 :   if (length() <= Name::kMaxCachedArrayIndexLength) {
     102      817260 :     *index = Name::ArrayIndexValueBits::decode(hash_);
     103             :   } else {
     104             :     OneByteStringStream stream(literal_bytes_);
     105          29 :     CHECK(StringToArrayIndex(&stream, index));
     106             :   }
     107             :   return true;
     108             : }
     109             : 
     110      106756 : bool AstRawString::IsOneByteEqualTo(const char* data) const {
     111      106756 :   if (!is_one_byte()) return false;
     112             : 
     113      140970 :   size_t length = static_cast<size_t>(literal_bytes_.length());
     114      106756 :   if (length != strlen(data)) return false;
     115             : 
     116             :   return 0 == strncmp(reinterpret_cast<const char*>(literal_bytes_.start()),
     117       34214 :                       data, length);
     118             : }
     119             : 
     120     2805033 : uint16_t AstRawString::FirstCharacter() const {
     121     2805033 :   if (is_one_byte()) return literal_bytes_[0];
     122             :   const uint16_t* c = reinterpret_cast<const uint16_t*>(literal_bytes_.start());
     123           9 :   return *c;
     124             : }
     125             : 
     126    85283477 : bool AstRawString::Compare(void* a, void* b) {
     127             :   const AstRawString* lhs = static_cast<AstRawString*>(a);
     128             :   const AstRawString* rhs = static_cast<AstRawString*>(b);
     129             :   DCHECK_EQ(lhs->hash(), rhs->hash());
     130             : 
     131    85283477 :   if (lhs->length() != rhs->length()) return false;
     132             :   const unsigned char* l = lhs->raw_data();
     133             :   const unsigned char* r = rhs->raw_data();
     134    85283481 :   size_t length = rhs->length();
     135    85283481 :   if (lhs->is_one_byte()) {
     136    85258741 :     if (rhs->is_one_byte()) {
     137             :       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
     138             :                                   reinterpret_cast<const uint8_t*>(r),
     139    85258732 :                                   length) == 0;
     140             :     } else {
     141             :       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
     142             :                                   reinterpret_cast<const uint16_t*>(r),
     143           9 :                                   length) == 0;
     144             :     }
     145             :   } else {
     146       24740 :     if (rhs->is_one_byte()) {
     147             :       return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
     148             :                                   reinterpret_cast<const uint8_t*>(r),
     149           0 :                                   length) == 0;
     150             :     } else {
     151             :       return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
     152             :                                   reinterpret_cast<const uint16_t*>(r),
     153       24740 :                                   length) == 0;
     154             :     }
     155             :   }
     156             : }
     157             : 
     158    17232962 : void AstConsString::Internalize(Isolate* isolate) {
     159    17232962 :   if (IsEmpty()) {
     160             :     set_string(isolate->factory()->empty_string());
     161    17232962 :     return;
     162             :   }
     163             :   // AstRawStrings are internalized before AstConsStrings, so
     164             :   // AstRawString::string() will just work.
     165     7714830 :   Handle<String> tmp(segment_.string->string());
     166    13653820 :   for (AstConsString::Segment* current = segment_.next; current != nullptr;
     167             :        current = current->next) {
     168             :     tmp = isolate->factory()
     169             :               ->NewConsString(current->string->string(), tmp)
     170    11877980 :               .ToHandleChecked();
     171             :   }
     172             :   set_string(tmp);
     173             : }
     174             : 
     175    22554063 : bool AstValue::IsPropertyName() const {
     176    22554063 :   if (type_ == STRING) {
     177             :     uint32_t index;
     178    21831905 :     return !string_->AsArrayIndex(&index);
     179             :   }
     180             :   return false;
     181             : }
     182             : 
     183             : 
     184       64079 : bool AstValue::BooleanValue() const {
     185       64079 :   switch (type_) {
     186             :     case STRING:
     187             :       DCHECK(string_ != NULL);
     188         900 :       return !string_->IsEmpty();
     189             :     case SYMBOL:
     190           0 :       UNREACHABLE();
     191             :       break;
     192             :     case NUMBER_WITH_DOT:
     193             :     case NUMBER:
     194         213 :       return DoubleToBoolean(number_);
     195             :     case SMI_WITH_DOT:
     196             :     case SMI:
     197       45048 :       return smi_ != 0;
     198             :     case BOOLEAN:
     199       18328 :       return bool_;
     200             :     case NULL_TYPE:
     201             :       return false;
     202             :     case THE_HOLE:
     203           0 :       UNREACHABLE();
     204             :       break;
     205             :     case UNDEFINED:
     206             :       return false;
     207             :   }
     208           0 :   UNREACHABLE();
     209             :   return false;
     210             : }
     211             : 
     212             : 
     213    57348830 : void AstValue::Internalize(Isolate* isolate) {
     214    57348830 :   switch (type_) {
     215             :     case STRING:
     216             :       DCHECK_NOT_NULL(string_);
     217             :       // Strings are already internalized.
     218             :       DCHECK(!string_->string().is_null());
     219             :       break;
     220             :     case SYMBOL:
     221        6119 :       switch (symbol_) {
     222             :         case AstSymbol::kHomeObjectSymbol:
     223             :           set_value(isolate->factory()->home_object_symbol());
     224        6119 :           break;
     225             :       }
     226             :       break;
     227             :     case NUMBER_WITH_DOT:
     228             :     case NUMBER:
     229     2232106 :       set_value(isolate->factory()->NewNumber(number_, TENURED));
     230             :       break;
     231             :     case SMI_WITH_DOT:
     232             :     case SMI:
     233    16932749 :       set_value(handle(Smi::FromInt(smi_), isolate));
     234    16932750 :       break;
     235             :     case BOOLEAN:
     236      655471 :       if (bool_) {
     237             :         set_value(isolate->factory()->true_value());
     238             :       } else {
     239             :         set_value(isolate->factory()->false_value());
     240             :       }
     241             :       break;
     242             :     case NULL_TYPE:
     243             :       set_value(isolate->factory()->null_value());
     244      369867 :       break;
     245             :     case THE_HOLE:
     246             :       set_value(isolate->factory()->the_hole_value());
     247       13677 :       break;
     248             :     case UNDEFINED:
     249             :       set_value(isolate->factory()->undefined_value());
     250      500792 :       break;
     251             :   }
     252    57348831 : }
     253             : 
     254   144921021 : AstRawString* AstValueFactory::GetOneByteStringInternal(
     255             :     Vector<const uint8_t> literal) {
     256   175253589 :   if (literal.length() == 1 && IsInRange(literal[0], 'a', 'z')) {
     257    23752776 :     int key = literal[0] - 'a';
     258    23752776 :     if (one_character_strings_[key] == nullptr) {
     259             :       uint32_t hash = StringHasher::HashSequentialString<uint8_t>(
     260     4682170 :           literal.start(), literal.length(), hash_seed_);
     261     4682170 :       one_character_strings_[key] = GetString(hash, true, literal);
     262             :     }
     263    23752776 :     return one_character_strings_[key];
     264             :   }
     265             :   uint32_t hash = StringHasher::HashSequentialString<uint8_t>(
     266   121168245 :       literal.start(), literal.length(), hash_seed_);
     267   121168353 :   return GetString(hash, true, literal);
     268             : }
     269             : 
     270             : 
     271       66200 : AstRawString* AstValueFactory::GetTwoByteStringInternal(
     272             :     Vector<const uint16_t> literal) {
     273             :   uint32_t hash = StringHasher::HashSequentialString<uint16_t>(
     274       66200 :       literal.start(), literal.length(), hash_seed_);
     275       66200 :   return GetString(hash, false, Vector<const byte>::cast(literal));
     276             : }
     277             : 
     278             : 
     279     1321921 : const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
     280             :   AstRawString* result = NULL;
     281             :   DisallowHeapAllocation no_gc;
     282     1321921 :   String::FlatContent content = literal->GetFlatContent();
     283     1321921 :   if (content.IsOneByte()) {
     284     1321912 :     result = GetOneByteStringInternal(content.ToOneByteVector());
     285             :   } else {
     286             :     DCHECK(content.IsTwoByte());
     287           9 :     result = GetTwoByteStringInternal(content.ToUC16Vector());
     288             :   }
     289     1321920 :   return result;
     290             : }
     291             : 
     292    17714993 : AstConsString* AstValueFactory::NewConsString() {
     293    17714993 :   AstConsString* new_string = new (zone_) AstConsString;
     294             :   DCHECK_NOT_NULL(new_string);
     295             :   AddConsString(new_string);
     296    17714991 :   return new_string;
     297             : }
     298             : 
     299    10861298 : AstConsString* AstValueFactory::NewConsString(const AstRawString* str) {
     300    10861298 :   return NewConsString()->AddString(zone_, str);
     301             : }
     302             : 
     303       30615 : AstConsString* AstValueFactory::NewConsString(const AstRawString* str1,
     304             :                                               const AstRawString* str2) {
     305       30615 :   return NewConsString()->AddString(zone_, str1)->AddString(zone_, str2);
     306             : }
     307             : 
     308     5591148 : void AstValueFactory::Internalize(Isolate* isolate) {
     309             :   // Strings need to be internalized before values, because values refer to
     310             :   // strings.
     311    52550965 :   for (AstRawString* current = strings_; current != nullptr;) {
     312             :     AstRawString* next = current->next();
     313    41368670 :     current->Internalize(isolate);
     314             :     current = next;
     315             :   }
     316             : 
     317             :   // AstConsStrings refer to AstRawStrings.
     318    28415256 :   for (AstConsString* current = cons_strings_; current != nullptr;) {
     319             :     AstConsString* next = current->next();
     320    17232960 :     current->Internalize(isolate);
     321             :     current = next;
     322             :   }
     323             : 
     324    68531131 :   for (AstValue* current = values_; current != nullptr;) {
     325             :     AstValue* next = current->next();
     326    57348829 :     current->Internalize(isolate);
     327             :     current = next;
     328             :   }
     329             :   ResetStrings();
     330     5591153 :   values_ = nullptr;
     331     5591153 : }
     332             : 
     333             : 
     334    36639069 : const AstValue* AstValueFactory::NewString(const AstRawString* string) {
     335    36639069 :   AstValue* value = new (zone_) AstValue(string);
     336    36639061 :   CHECK_NOT_NULL(string);
     337    36639061 :   return AddValue(value);
     338             : }
     339             : 
     340        6119 : const AstValue* AstValueFactory::NewSymbol(AstSymbol symbol) {
     341        6119 :   AstValue* value = new (zone_) AstValue(symbol);
     342        6119 :   return AddValue(value);
     343             : }
     344             : 
     345             : 
     346     5080760 : const AstValue* AstValueFactory::NewNumber(double number, bool with_dot) {
     347    10161520 :   AstValue* value = new (zone_) AstValue(number, with_dot);
     348     5080760 :   return AddValue(value);
     349             : }
     350             : 
     351    30000283 : const AstValue* AstValueFactory::NewSmi(uint32_t number) {
     352    30000283 :   bool cacheable_smi = number <= kMaxCachedSmi;
     353    30000283 :   if (cacheable_smi && smis_[number] != nullptr) return smis_[number];
     354             : 
     355    28170273 :   AstValue* value = new (zone_) AstValue(AstValue::SMI, number);
     356    14085141 :   if (cacheable_smi) smis_[number] = value;
     357    14085141 :   return AddValue(value);
     358             : }
     359             : 
     360             : #define GENERATE_VALUE_GETTER(value, initializer)        \
     361             :   if (!value) {                                          \
     362             :     value = AddValue(new (zone_) AstValue(initializer)); \
     363             :   }                                                      \
     364             :   return value;
     365             : 
     366     1790872 : const AstValue* AstValueFactory::NewBoolean(bool b) {
     367     1790872 :   if (b) {
     368     1107567 :     GENERATE_VALUE_GETTER(true_value_, true);
     369             :   } else {
     370     1338776 :     GENERATE_VALUE_GETTER(false_value_, false);
     371             :   }
     372             : }
     373             : 
     374             : 
     375     1052943 : const AstValue* AstValueFactory::NewNull() {
     376     1422810 :   GENERATE_VALUE_GETTER(null_value_, AstValue::NULL_TYPE);
     377             : }
     378             : 
     379             : 
     380     1263283 : const AstValue* AstValueFactory::NewUndefined() {
     381     1764075 :   GENERATE_VALUE_GETTER(undefined_value_, AstValue::UNDEFINED);
     382             : }
     383             : 
     384             : 
     385     1437236 : const AstValue* AstValueFactory::NewTheHole() {
     386     1450913 :   GENERATE_VALUE_GETTER(the_hole_value_, AstValue::THE_HOLE);
     387             : }
     388             : 
     389             : 
     390             : #undef GENERATE_VALUE_GETTER
     391             : 
     392   125916650 : AstRawString* AstValueFactory::GetString(uint32_t hash, bool is_one_byte,
     393             :                                          Vector<const byte> literal_bytes) {
     394             :   // literal_bytes here points to whatever the user passed, and this is OK
     395             :   // because we use vector_compare (which checks the contents) to compare
     396             :   // against the AstRawStrings which are in the string_table_. We should not
     397             :   // return this AstRawString.
     398             :   AstRawString key(is_one_byte, literal_bytes, hash);
     399   251833498 :   base::HashMap::Entry* entry = string_table_.LookupOrInsert(&key, hash);
     400   125916848 :   if (entry->value == nullptr) {
     401             :     // Copy literal contents for later comparison.
     402    41441131 :     int length = literal_bytes.length();
     403    41441131 :     byte* new_literal_bytes = zone_->NewArray<byte>(length);
     404    41441133 :     memcpy(new_literal_bytes, literal_bytes.start(), length);
     405             :     AstRawString* new_string = new (zone_) AstRawString(
     406    41441133 :         is_one_byte, Vector<const byte>(new_literal_bytes, length), hash);
     407    41441090 :     CHECK_NOT_NULL(new_string);
     408             :     AddString(new_string);
     409    41441090 :     entry->key = new_string;
     410    41441090 :     entry->value = reinterpret_cast<void*>(1);
     411             :   }
     412   125916807 :   return reinterpret_cast<AstRawString*>(entry->key);
     413             : }
     414             : 
     415             : }  // namespace internal
     416             : }  // namespace v8

Generated by: LCOV version 1.10