LCOV - code coverage report
Current view: top level - src/ast - ast-value-factory.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 166 171 97.1 %
Date: 2017-10-20 Functions: 31 33 93.9 %

          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/string-hasher.h"
      35             : #include "src/utils-inl.h"
      36             : 
      37             : namespace v8 {
      38             : namespace internal {
      39             : 
      40             : namespace {
      41             : 
      42             : // For using StringToArrayIndex.
      43             : class OneByteStringStream {
      44             :  public:
      45             :   explicit OneByteStringStream(Vector<const byte> lb) :
      46          29 :       literal_bytes_(lb), pos_(0) {}
      47             : 
      48         266 :   bool HasMore() { return pos_ < literal_bytes_.length(); }
      49         532 :   uint16_t GetNext() { return literal_bytes_[pos_++]; }
      50             : 
      51             :  private:
      52             :   Vector<const byte> literal_bytes_;
      53             :   int pos_;
      54             : };
      55             : 
      56             : }  // namespace
      57             : 
      58           0 : class AstRawStringInternalizationKey : public StringTableKey {
      59             :  public:
      60    31140861 :   explicit AstRawStringInternalizationKey(const AstRawString* string)
      61    31140861 :       : StringTableKey(string->hash_field()), string_(string) {}
      62             : 
      63    77668284 :   bool IsMatch(Object* other) override {
      64    77668284 :     if (string_->is_one_byte())
      65    77642790 :       return String::cast(other)->IsOneByteEqualTo(string_->literal_bytes_);
      66             :     return String::cast(other)->IsTwoByteEqualTo(
      67       25494 :         Vector<const uint16_t>::cast(string_->literal_bytes_));
      68             :   }
      69             : 
      70    10625258 :   Handle<String> AsHandle(Isolate* isolate) override {
      71    10646262 :     if (string_->is_one_byte())
      72             :       return isolate->factory()->NewOneByteInternalizedString(
      73    10604254 :           string_->literal_bytes_, string_->hash_field());
      74             :     return isolate->factory()->NewTwoByteInternalizedString(
      75             :         Vector<const uint16_t>::cast(string_->literal_bytes_),
      76       21004 :         string_->hash_field());
      77             :   }
      78             : 
      79             :  private:
      80             :   const AstRawString* string_;
      81             : };
      82             : 
      83    31140861 : void AstRawString::Internalize(Isolate* isolate) {
      84             :   DCHECK(!has_string_);
      85    62281722 :   if (literal_bytes_.length() == 0) {
      86             :     set_string(isolate->factory()->empty_string());
      87             :   } else {
      88             :     AstRawStringInternalizationKey key(this);
      89    31140861 :     set_string(StringTable::LookupKey(isolate, &key));
      90             :   }
      91    31140860 : }
      92             : 
      93    12036075 : bool AstRawString::AsArrayIndex(uint32_t* index) const {
      94             :   // The StringHasher will set up the hash in such a way that we can use it to
      95             :   // figure out whether the string is convertible to an array index.
      96    12036075 :   if ((hash_field_ & Name::kIsNotArrayIndexMask) != 0) return false;
      97     1580847 :   if (length() <= Name::kMaxCachedArrayIndexLength) {
      98     1580818 :     *index = Name::ArrayIndexValueBits::decode(hash_field_);
      99             :   } else {
     100             :     OneByteStringStream stream(literal_bytes_);
     101          29 :     CHECK(StringToArrayIndex(&stream, index));
     102             :   }
     103             :   return true;
     104             : }
     105             : 
     106      127208 : bool AstRawString::IsOneByteEqualTo(const char* data) const {
     107      127208 :   if (!is_one_byte()) return false;
     108             : 
     109      280765 :   size_t length = static_cast<size_t>(literal_bytes_.length());
     110      127208 :   if (length != strlen(data)) return false;
     111             : 
     112             :   return 0 == strncmp(reinterpret_cast<const char*>(literal_bytes_.start()),
     113       26349 :                       data, length);
     114             : }
     115             : 
     116     1782837 : uint16_t AstRawString::FirstCharacter() const {
     117     1782837 :   if (is_one_byte()) return literal_bytes_[0];
     118             :   const uint16_t* c = reinterpret_cast<const uint16_t*>(literal_bytes_.start());
     119           7 :   return *c;
     120             : }
     121             : 
     122    70733134 : bool AstRawString::Compare(void* a, void* b) {
     123             :   const AstRawString* lhs = static_cast<AstRawString*>(a);
     124             :   const AstRawString* rhs = static_cast<AstRawString*>(b);
     125             :   DCHECK_EQ(lhs->Hash(), rhs->Hash());
     126             : 
     127    70733134 :   if (lhs->length() != rhs->length()) return false;
     128             :   const unsigned char* l = lhs->raw_data();
     129             :   const unsigned char* r = rhs->raw_data();
     130    70733116 :   size_t length = rhs->length();
     131    70733116 :   if (lhs->is_one_byte()) {
     132    70718478 :     if (rhs->is_one_byte()) {
     133             :       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
     134             :                                   reinterpret_cast<const uint8_t*>(r),
     135    70718471 :                                   length) == 0;
     136             :     } else {
     137             :       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
     138             :                                   reinterpret_cast<const uint16_t*>(r),
     139           7 :                                   length) == 0;
     140             :     }
     141             :   } else {
     142       14638 :     if (rhs->is_one_byte()) {
     143             :       return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
     144             :                                   reinterpret_cast<const uint8_t*>(r),
     145           0 :                                   length) == 0;
     146             :     } else {
     147             :       return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
     148             :                                   reinterpret_cast<const uint16_t*>(r),
     149       14638 :                                   length) == 0;
     150             :     }
     151             :   }
     152             : }
     153             : 
     154    11348808 : void AstConsString::Internalize(Isolate* isolate) {
     155    11348808 :   if (IsEmpty()) {
     156             :     set_string(isolate->factory()->empty_string());
     157    11348808 :     return;
     158             :   }
     159             :   // AstRawStrings are internalized before AstConsStrings, so
     160             :   // AstRawString::string() will just work.
     161     5457219 :   Handle<String> tmp(segment_.string->string());
     162     9156773 :   for (AstConsString::Segment* current = segment_.next; current != nullptr;
     163             :        current = current->next) {
     164             :     tmp = isolate->factory()
     165     3699554 :               ->NewConsString(current->string->string(), tmp)
     166     7399108 :               .ToHandleChecked();
     167             :   }
     168             :   set_string(tmp);
     169             : }
     170             : 
     171     4164121 : AstValue::AstValue(double n) : next_(nullptr) {
     172             :   int int_value;
     173     4164121 :   if (DoubleToSmiInteger(n, &int_value)) {
     174     2740808 :     type_ = SMI;
     175     2740808 :     smi_ = int_value;
     176             :   } else {
     177     1423313 :     type_ = NUMBER;
     178     1423313 :     number_ = n;
     179             :   }
     180     4164121 : }
     181             : 
     182     2546009 : bool AstValue::ToUint32(uint32_t* value) const {
     183     2546009 :   if (IsSmi()) {
     184      913629 :     int num = smi_;
     185      913629 :     if (num < 0) return false;
     186      913629 :     *value = static_cast<uint32_t>(num);
     187      913629 :     return true;
     188             :   }
     189     1632380 :   if (IsHeapNumber()) {
     190          34 :     return DoubleToUint32IfEqualToSelf(number_, value);
     191             :   }
     192             :   return false;
     193             : }
     194             : 
     195     8972171 : bool AstValue::IsPropertyName() const {
     196     8972171 :   if (type_ == STRING) {
     197             :     uint32_t index;
     198     8660792 :     return !string_->AsArrayIndex(&index);
     199             :   }
     200             :   return false;
     201             : }
     202             : 
     203             : 
     204       60216 : bool AstValue::BooleanValue() const {
     205       60216 :   switch (type_) {
     206             :     case STRING:
     207             :       DCHECK_NOT_NULL(string_);
     208         862 :       return !string_->IsEmpty();
     209             :     case SYMBOL:
     210           0 :       UNREACHABLE();
     211             :       break;
     212             :     case NUMBER:
     213         165 :       return DoubleToBoolean(number_);
     214             :     case SMI:
     215       48614 :       return smi_ != 0;
     216             :     case BIGINT: {
     217          14 :       size_t length = strlen(bigint_buffer_);
     218             :       DCHECK_GT(length, 0);
     219          14 :       if (length == 1 && bigint_buffer_[0] == '0') return false;
     220             :       // Skip over any radix prefix; BigInts with length > 1 only
     221             :       // begin with zero if they include a radix.
     222          47 :       for (size_t i = (bigint_buffer_[0] == '0') ? 2 : 0; i < length; ++i) {
     223          41 :         if (bigint_buffer_[i] != '0') return true;
     224             :       }
     225             :       return false;
     226             :     }
     227             :     case BOOLEAN:
     228       10956 :       return bool_;
     229             :     case NULL_TYPE:
     230             :       return false;
     231             :     case THE_HOLE:
     232           0 :       UNREACHABLE();
     233             :       break;
     234             :     case UNDEFINED:
     235             :       return false;
     236             :   }
     237           0 :   UNREACHABLE();
     238             : }
     239             : 
     240             : 
     241    32991347 : void AstValue::Internalize(Isolate* isolate) {
     242    32991347 :   switch (type_) {
     243             :     case STRING:
     244             :       DCHECK_NOT_NULL(string_);
     245             :       // Strings are already internalized.
     246             :       DCHECK(!string_->string().is_null());
     247             :       break;
     248             :     case SYMBOL:
     249        2038 :       switch (symbol_) {
     250             :         case AstSymbol::kHomeObjectSymbol:
     251             :           set_value(isolate->factory()->home_object_symbol());
     252        2038 :           break;
     253             :       }
     254             :       break;
     255             :     case NUMBER:
     256     1422338 :       set_value(isolate->factory()->NewNumber(number_, TENURED));
     257             :       break;
     258             :     case SMI:
     259    12228488 :       set_value(handle(Smi::FromInt(smi_), isolate));
     260    12228488 :       break;
     261             :     case BIGINT:
     262             :       // TODO(adamk): Don't check-fail on conversion failure; instead
     263             :       // check for errors during parsing and throw at that point.
     264          50 :       set_value(BigIntLiteral(isolate, bigint_buffer_).ToHandleChecked());
     265          25 :       break;
     266             :     case BOOLEAN:
     267      251795 :       if (bool_) {
     268             :         set_value(isolate->factory()->true_value());
     269             :       } else {
     270             :         set_value(isolate->factory()->false_value());
     271             :       }
     272             :       break;
     273             :     case NULL_TYPE:
     274             :       set_value(isolate->factory()->null_value());
     275      101245 :       break;
     276             :     case THE_HOLE:
     277             :       set_value(isolate->factory()->the_hole_value());
     278        5887 :       break;
     279             :     case UNDEFINED:
     280             :       set_value(isolate->factory()->undefined_value());
     281      180751 :       break;
     282             :   }
     283    32991347 : }
     284             : 
     285       54999 : AstStringConstants::AstStringConstants(Isolate* isolate, uint32_t hash_seed)
     286             :     : zone_(isolate->allocator(), ZONE_NAME),
     287             :       string_table_(AstRawString::Compare),
     288      109998 :       hash_seed_(hash_seed) {
     289             :   DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
     290             : #define F(name, str)                                                       \
     291             :   {                                                                        \
     292             :     const char* data = str;                                                \
     293             :     Vector<const uint8_t> literal(reinterpret_cast<const uint8_t*>(data),  \
     294             :                                   static_cast<int>(strlen(data)));         \
     295             :     uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>(     \
     296             :         literal.start(), literal.length(), hash_seed_);                    \
     297             :     name##_string_ = new (&zone_) AstRawString(true, literal, hash_field); \
     298             :     /* The Handle returned by the factory is located on the roots */       \
     299             :     /* array, not on the temporary HandleScope, so this is safe.  */       \
     300             :     name##_string_->set_string(isolate->factory()->name##_string());       \
     301             :     base::HashMap::Entry* entry =                                          \
     302             :         string_table_.InsertNew(name##_string_, name##_string_->Hash());   \
     303             :     DCHECK_NULL(entry->value);                                             \
     304             :     entry->value = reinterpret_cast<void*>(1);                             \
     305             :   }
     306     6819876 :   AST_STRING_CONSTANTS(F)
     307             : #undef F
     308       54999 : }
     309             : 
     310   115714208 : AstRawString* AstValueFactory::GetOneByteStringInternal(
     311             :     Vector<const uint8_t> literal) {
     312   136611502 :   if (literal.length() == 1 && IsInRange(literal[0], 'a', 'z')) {
     313    16677124 :     int key = literal[0] - 'a';
     314    16677124 :     if (one_character_strings_[key] == nullptr) {
     315             :       uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>(
     316     3256646 :           literal.start(), literal.length(), hash_seed_);
     317     3256646 :       one_character_strings_[key] = GetString(hash_field, true, literal);
     318             :     }
     319    16677124 :     return one_character_strings_[key];
     320             :   }
     321             :   uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>(
     322    99037084 :       literal.start(), literal.length(), hash_seed_);
     323    99037128 :   return GetString(hash_field, true, literal);
     324             : }
     325             : 
     326             : 
     327       42432 : AstRawString* AstValueFactory::GetTwoByteStringInternal(
     328             :     Vector<const uint16_t> literal) {
     329             :   uint32_t hash_field = StringHasher::HashSequentialString<uint16_t>(
     330       84864 :       literal.start(), literal.length(), hash_seed_);
     331       42432 :   return GetString(hash_field, false, Vector<const byte>::cast(literal));
     332             : }
     333             : 
     334             : 
     335      697184 : const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
     336             :   AstRawString* result = nullptr;
     337             :   DisallowHeapAllocation no_gc;
     338      697184 :   String::FlatContent content = literal->GetFlatContent();
     339      697184 :   if (content.IsOneByte()) {
     340      697177 :     result = GetOneByteStringInternal(content.ToOneByteVector());
     341             :   } else {
     342             :     DCHECK(content.IsTwoByte());
     343           7 :     result = GetTwoByteStringInternal(content.ToUC16Vector());
     344             :   }
     345      697184 :   return result;
     346             : }
     347             : 
     348    12874356 : AstConsString* AstValueFactory::NewConsString() {
     349    12874356 :   AstConsString* new_string = new (zone_) AstConsString;
     350             :   DCHECK_NOT_NULL(new_string);
     351             :   AddConsString(new_string);
     352    12874357 :   return new_string;
     353             : }
     354             : 
     355     8034177 : AstConsString* AstValueFactory::NewConsString(const AstRawString* str) {
     356     8034177 :   return NewConsString()->AddString(zone_, str);
     357             : }
     358             : 
     359       25038 : AstConsString* AstValueFactory::NewConsString(const AstRawString* str1,
     360             :                                               const AstRawString* str2) {
     361       25038 :   return NewConsString()->AddString(zone_, str1)->AddString(zone_, str2);
     362             : }
     363             : 
     364     2997358 : void AstValueFactory::Internalize(Isolate* isolate) {
     365             :   // Strings need to be internalized before values, because values refer to
     366             :   // strings.
     367    37135577 :   for (AstRawString* current = strings_; current != nullptr;) {
     368             :     AstRawString* next = current->next();
     369    31140859 :     current->Internalize(isolate);
     370             :     current = next;
     371             :   }
     372             : 
     373             :   // AstConsStrings refer to AstRawStrings.
     374    17343527 :   for (AstConsString* current = cons_strings_; current != nullptr;) {
     375             :     AstConsString* next = current->next();
     376    11348808 :     current->Internalize(isolate);
     377             :     current = next;
     378             :   }
     379             : 
     380    38986065 :   for (AstValue* current = values_; current != nullptr;) {
     381             :     AstValue* next = current->next();
     382    32991347 :     current->Internalize(isolate);
     383             :     current = next;
     384             :   }
     385             :   ResetStrings();
     386     2997359 :   values_ = nullptr;
     387     2997359 : }
     388             : 
     389             : 
     390    20058082 : const AstValue* AstValueFactory::NewString(const AstRawString* string) {
     391    20058082 :   AstValue* value = new (zone_) AstValue(string);
     392    20058072 :   CHECK_NOT_NULL(string);
     393    20058072 :   return AddValue(value);
     394             : }
     395             : 
     396        2814 : const AstValue* AstValueFactory::NewSymbol(AstSymbol symbol) {
     397        2814 :   AstValue* value = new (zone_) AstValue(symbol);
     398        2814 :   return AddValue(value);
     399             : }
     400             : 
     401     4164121 : const AstValue* AstValueFactory::NewNumber(double number) {
     402     8328242 :   AstValue* value = new (zone_) AstValue(number);
     403     4164121 :   return AddValue(value);
     404             : }
     405             : 
     406    20530753 : const AstValue* AstValueFactory::NewSmi(uint32_t number) {
     407    20530753 :   bool cacheable_smi = number <= kMaxCachedSmi;
     408    20530753 :   if (cacheable_smi && smis_[number] != nullptr) return smis_[number];
     409             : 
     410    20089986 :   AstValue* value = new (zone_) AstValue(AstValue::SMI, number);
     411    10044993 :   if (cacheable_smi) smis_[number] = value;
     412    10044993 :   return AddValue(value);
     413             : }
     414             : 
     415          39 : const AstValue* AstValueFactory::NewBigInt(const char* number) {
     416          39 :   AstValue* value = new (zone_) AstValue(number);
     417          39 :   return AddValue(value);
     418             : }
     419             : 
     420             : #define GENERATE_VALUE_GETTER(value, initializer)        \
     421             :   if (!value) {                                          \
     422             :     value = AddValue(new (zone_) AstValue(initializer)); \
     423             :   }                                                      \
     424             :   return value;
     425             : 
     426      969530 : const AstValue* AstValueFactory::NewBoolean(bool b) {
     427      969530 :   if (b) {
     428      592151 :     GENERATE_VALUE_GETTER(true_value_, true);
     429             :   } else {
     430      753199 :     GENERATE_VALUE_GETTER(false_value_, false);
     431             :   }
     432             : }
     433             : 
     434             : 
     435      455723 : const AstValue* AstValueFactory::NewNull() {
     436      681171 :   GENERATE_VALUE_GETTER(null_value_, AstValue::NULL_TYPE);
     437             : }
     438             : 
     439             : 
     440      667296 : const AstValue* AstValueFactory::NewUndefined() {
     441      987792 :   GENERATE_VALUE_GETTER(undefined_value_, AstValue::UNDEFINED);
     442             : }
     443             : 
     444             : 
     445     1173912 : const AstValue* AstValueFactory::NewTheHole() {
     446     1187269 :   GENERATE_VALUE_GETTER(the_hole_value_, AstValue::THE_HOLE);
     447             : }
     448             : 
     449             : 
     450             : #undef GENERATE_VALUE_GETTER
     451             : 
     452   102336193 : AstRawString* AstValueFactory::GetString(uint32_t hash_field, bool is_one_byte,
     453             :                                          Vector<const byte> literal_bytes) {
     454             :   // literal_bytes here points to whatever the user passed, and this is OK
     455             :   // because we use vector_compare (which checks the contents) to compare
     456             :   // against the AstRawStrings which are in the string_table_. We should not
     457             :   // return this AstRawString.
     458             :   AstRawString key(is_one_byte, literal_bytes, hash_field);
     459   204672482 :   base::HashMap::Entry* entry = string_table_.LookupOrInsert(&key, key.Hash());
     460   102336289 :   if (entry->value == nullptr) {
     461             :     // Copy literal contents for later comparison.
     462    32175351 :     int length = literal_bytes.length();
     463    32175351 :     byte* new_literal_bytes = zone_->NewArray<byte>(length);
     464    32175350 :     memcpy(new_literal_bytes, literal_bytes.start(), length);
     465             :     AstRawString* new_string = new (zone_) AstRawString(
     466    32175350 :         is_one_byte, Vector<const byte>(new_literal_bytes, length), hash_field);
     467    32175330 :     CHECK_NOT_NULL(new_string);
     468             :     AddString(new_string);
     469    32175330 :     entry->key = new_string;
     470    32175330 :     entry->value = reinterpret_cast<void*>(1);
     471             :   }
     472   102336268 :   return reinterpret_cast<AstRawString*>(entry->key);
     473             : }
     474             : 
     475             : }  // namespace internal
     476             : }  // namespace v8

Generated by: LCOV version 1.10