LCOV - code coverage report
Current view: top level - src/ast - ast-value-factory.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 102 105 97.1 %
Date: 2019-02-19 Functions: 21 23 91.3 %

          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/char-predicates-inl.h"
      31             : #include "src/objects-inl.h"
      32             : #include "src/objects.h"
      33             : #include "src/string-hasher.h"
      34             : #include "src/utils-inl.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         155 :       literal_bytes_(lb), pos_(0) {}
      46             : 
      47        1541 :   bool HasMore() { return pos_ < literal_bytes_.length(); }
      48        3080 :   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 StringTableKey {
      58             :  public:
      59    27526063 :   explicit AstRawStringInternalizationKey(const AstRawString* string)
      60    27526063 :       : StringTableKey(string->hash_field()), string_(string) {}
      61             : 
      62    78063169 :   bool IsMatch(Object other) override {
      63    78063169 :     if (string_->is_one_byte())
      64    77987056 :       return String::cast(other)->IsOneByteEqualTo(string_->literal_bytes_);
      65             :     return String::cast(other)->IsTwoByteEqualTo(
      66       76116 :         Vector<const uint16_t>::cast(string_->literal_bytes_));
      67             :   }
      68             : 
      69     8766831 :   Handle<String> AsHandle(Isolate* isolate) override {
      70     8819164 :     if (string_->is_one_byte())
      71             :       return isolate->factory()->NewOneByteInternalizedString(
      72     8714498 :           string_->literal_bytes_, string_->hash_field());
      73             :     return isolate->factory()->NewTwoByteInternalizedString(
      74             :         Vector<const uint16_t>::cast(string_->literal_bytes_),
      75       52333 :         string_->hash_field());
      76             :   }
      77             : 
      78             :  private:
      79             :   const AstRawString* string_;
      80             : };
      81             : 
      82    27526063 : void AstRawString::Internalize(Isolate* isolate) {
      83             :   DCHECK(!has_string_);
      84    55052126 :   if (literal_bytes_.length() == 0) {
      85             :     set_string(isolate->factory()->empty_string());
      86             :   } else {
      87             :     AstRawStringInternalizationKey key(this);
      88    27526063 :     set_string(StringTable::LookupKey(isolate, &key));
      89             :   }
      90    27526074 : }
      91             : 
      92    11282014 : bool AstRawString::AsArrayIndex(uint32_t* index) const {
      93             :   // The StringHasher will set up the hash in such a way that we can use it to
      94             :   // figure out whether the string is convertible to an array index.
      95    11282014 :   if ((hash_field_ & Name::kIsNotArrayIndexMask) != 0) return false;
      96        4413 :   if (length() <= Name::kMaxCachedArrayIndexLength) {
      97        4258 :     *index = Name::ArrayIndexValueBits::decode(hash_field_);
      98             :   } else {
      99             :     OneByteStringStream stream(literal_bytes_);
     100         155 :     CHECK(StringToArrayIndex(&stream, index));
     101             :   }
     102             :   return true;
     103             : }
     104             : 
     105      212745 : bool AstRawString::IsOneByteEqualTo(const char* data) const {
     106      212745 :   if (!is_one_byte()) return false;
     107             : 
     108      482567 :   size_t length = static_cast<size_t>(literal_bytes_.length());
     109      212755 :   if (length != strlen(data)) return false;
     110             : 
     111             :   return 0 == strncmp(reinterpret_cast<const char*>(literal_bytes_.start()),
     112       57057 :                       data, length);
     113             : }
     114             : 
     115     7888412 : uint16_t AstRawString::FirstCharacter() const {
     116     7888412 :   if (is_one_byte()) return literal_bytes_[0];
     117             :   const uint16_t* c = reinterpret_cast<const uint16_t*>(literal_bytes_.start());
     118          18 :   return *c;
     119             : }
     120             : 
     121    54838234 : bool AstRawString::Compare(void* a, void* b) {
     122             :   const AstRawString* lhs = static_cast<AstRawString*>(a);
     123             :   const AstRawString* rhs = static_cast<AstRawString*>(b);
     124             :   DCHECK_EQ(lhs->Hash(), rhs->Hash());
     125             : 
     126    54838234 :   if (lhs->length() != rhs->length()) return false;
     127    54839045 :   if (lhs->length() == 0) return true;
     128             :   const unsigned char* l = lhs->raw_data();
     129             :   const unsigned char* r = rhs->raw_data();
     130    54224597 :   size_t length = rhs->length();
     131    54224597 :   if (lhs->is_one_byte()) {
     132    54216825 :     if (rhs->is_one_byte()) {
     133             :       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
     134             :                                   reinterpret_cast<const uint8_t*>(r),
     135    54216819 :                                   length) == 0;
     136             :     } else {
     137             :       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
     138             :                                   reinterpret_cast<const uint16_t*>(r),
     139           6 :                                   length) == 0;
     140             :     }
     141             :   } else {
     142        7772 :     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        7772 :                                   length) == 0;
     150             :     }
     151             :   }
     152             : }
     153             : 
     154     8452177 : void AstConsString::Internalize(Isolate* isolate) {
     155     8452177 :   if (IsEmpty()) {
     156             :     set_string(isolate->factory()->empty_string());
     157     8452177 :     return;
     158             :   }
     159             :   // AstRawStrings are internalized before AstConsStrings, so
     160             :   // AstRawString::string() will just work.
     161     3434492 :   Handle<String> tmp(segment_.string->string());
     162     3750813 :   for (AstConsString::Segment* current = segment_.next; current != nullptr;
     163             :        current = current->next) {
     164             :     tmp = isolate->factory()
     165      316321 :               ->NewConsString(current->string->string(), tmp)
     166      632642 :               .ToHandleChecked();
     167             :   }
     168             :   set_string(tmp);
     169             : }
     170             : 
     171          34 : std::forward_list<const AstRawString*> AstConsString::ToRawStrings() const {
     172             :   std::forward_list<const AstRawString*> result;
     173          17 :   if (IsEmpty()) {
     174             :     return result;
     175             :   }
     176             : 
     177          17 :   result.emplace_front(segment_.string);
     178          17 :   for (AstConsString::Segment* current = segment_.next; current != nullptr;
     179             :        current = current->next) {
     180           0 :     result.emplace_front(current->string);
     181             :   }
     182             :   return result;
     183             : }
     184             : 
     185       61049 : AstStringConstants::AstStringConstants(Isolate* isolate, uint64_t hash_seed)
     186             :     : zone_(isolate->allocator(), ZONE_NAME),
     187             :       string_table_(AstRawString::Compare),
     188      122098 :       hash_seed_(hash_seed) {
     189             :   DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
     190             : #define F(name, str)                                                       \
     191             :   {                                                                        \
     192             :     const char* data = str;                                                \
     193             :     Vector<const uint8_t> literal(reinterpret_cast<const uint8_t*>(data),  \
     194             :                                   static_cast<int>(strlen(data)));         \
     195             :     uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>(     \
     196             :         literal.start(), literal.length(), hash_seed_);                    \
     197             :     name##_string_ = new (&zone_) AstRawString(true, literal, hash_field); \
     198             :     /* The Handle returned by the factory is located on the roots */       \
     199             :     /* array, not on the temporary HandleScope, so this is safe.  */       \
     200             :     name##_string_->set_string(isolate->factory()->name##_string());       \
     201             :     base::HashMap::Entry* entry =                                          \
     202             :         string_table_.InsertNew(name##_string_, name##_string_->Hash());   \
     203             :     DCHECK_NULL(entry->value);                                             \
     204             :     entry->value = reinterpret_cast<void*>(1);                             \
     205             :   }
     206     9218399 :   AST_STRING_CONSTANTS(F)
     207             : #undef F
     208       61049 : }
     209             : 
     210   101079922 : AstRawString* AstValueFactory::GetOneByteStringInternal(
     211             :     Vector<const uint8_t> literal) {
     212   101079922 :   if (literal.length() == 1 && literal[0] < kMaxOneCharStringValue) {
     213    21179830 :     int key = literal[0];
     214    21179830 :     if (V8_UNLIKELY(one_character_strings_[key] == nullptr)) {
     215             :       uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>(
     216     3772933 :           literal.start(), literal.length(), hash_seed_);
     217     3772883 :       one_character_strings_[key] = GetString(hash_field, true, literal);
     218             :     }
     219    21179861 :     return one_character_strings_[key];
     220             :   }
     221             :   uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>(
     222    79900092 :       literal.start(), literal.length(), hash_seed_);
     223    79926241 :   return GetString(hash_field, true, literal);
     224             : }
     225             : 
     226       76324 : AstRawString* AstValueFactory::GetTwoByteStringInternal(
     227             :     Vector<const uint16_t> literal) {
     228             :   uint32_t hash_field = StringHasher::HashSequentialString<uint16_t>(
     229      152648 :       literal.start(), literal.length(), hash_seed_);
     230       76327 :   return GetString(hash_field, false, Vector<const byte>::cast(literal));
     231             : }
     232             : 
     233      724740 : const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
     234             :   AstRawString* result = nullptr;
     235             :   DisallowHeapAllocation no_gc;
     236      724740 :   String::FlatContent content = literal->GetFlatContent(no_gc);
     237      724741 :   if (content.IsOneByte()) {
     238      724724 :     result = GetOneByteStringInternal(content.ToOneByteVector());
     239             :   } else {
     240             :     DCHECK(content.IsTwoByte());
     241          17 :     result = GetTwoByteStringInternal(content.ToUC16Vector());
     242             :   }
     243      724742 :   return result;
     244             : }
     245             : 
     246          80 : const AstRawString* AstValueFactory::CloneFromOtherFactory(
     247         160 :     const AstRawString* raw_string) {
     248             :   const AstRawString* result = GetString(
     249             :       raw_string->hash_field(), raw_string->is_one_byte(),
     250         240 :       Vector<const byte>(raw_string->raw_data(), raw_string->byte_length()));
     251          80 :   return result;
     252             : }
     253             : 
     254    10289389 : AstConsString* AstValueFactory::NewConsString() {
     255    10289389 :   AstConsString* new_string = new (zone_) AstConsString;
     256             :   DCHECK_NOT_NULL(new_string);
     257             :   AddConsString(new_string);
     258    10289487 :   return new_string;
     259             : }
     260             : 
     261     6850987 : AstConsString* AstValueFactory::NewConsString(const AstRawString* str) {
     262     6850987 :   return NewConsString()->AddString(zone_, str);
     263             : }
     264             : 
     265       27558 : AstConsString* AstValueFactory::NewConsString(const AstRawString* str1,
     266             :                                               const AstRawString* str2) {
     267       27558 :   return NewConsString()->AddString(zone_, str1)->AddString(zone_, str2);
     268             : }
     269             : 
     270     3769297 : void AstValueFactory::Internalize(Isolate* isolate) {
     271             :   // Strings need to be internalized before values, because values refer to
     272             :   // strings.
     273    35064667 :   for (AstRawString* current = strings_; current != nullptr;) {
     274             :     AstRawString* next = current->next();
     275    27526065 :     current->Internalize(isolate);
     276             :     current = next;
     277             :   }
     278             : 
     279             :   // AstConsStrings refer to AstRawStrings.
     280    15990790 :   for (AstConsString* current = cons_strings_; current != nullptr;) {
     281             :     AstConsString* next = current->next();
     282     8452183 :     current->Internalize(isolate);
     283             :     current = next;
     284             :   }
     285             : 
     286             :   ResetStrings();
     287     3769302 : }
     288             : 
     289    83790447 : AstRawString* AstValueFactory::GetString(uint32_t hash_field, bool is_one_byte,
     290             :                                          Vector<const byte> literal_bytes) {
     291             :   // literal_bytes here points to whatever the user passed, and this is OK
     292             :   // because we use vector_compare (which checks the contents) to compare
     293             :   // against the AstRawStrings which are in the string_table_. We should not
     294             :   // return this AstRawString.
     295             :   AstRawString key(is_one_byte, literal_bytes, hash_field);
     296   167580278 :   base::HashMap::Entry* entry = string_table_.LookupOrInsert(&key, key.Hash());
     297    83789831 :   if (entry->value == nullptr) {
     298             :     // Copy literal contents for later comparison.
     299    31398211 :     int length = literal_bytes.length();
     300    31398211 :     byte* new_literal_bytes = zone_->NewArray<byte>(length);
     301    31397985 :     memcpy(new_literal_bytes, literal_bytes.start(), length);
     302             :     AstRawString* new_string = new (zone_) AstRawString(
     303    31397985 :         is_one_byte, Vector<const byte>(new_literal_bytes, length), hash_field);
     304    31395782 :     CHECK_NOT_NULL(new_string);
     305             :     AddString(new_string);
     306    31395782 :     entry->key = new_string;
     307    31395782 :     entry->value = reinterpret_cast<void*>(1);
     308             :   }
     309    83787402 :   return reinterpret_cast<AstRawString*>(entry->key);
     310             : }
     311             : 
     312             : }  // namespace internal
     313      178779 : }  // namespace v8

Generated by: LCOV version 1.10