LCOV - code coverage report
Current view: top level - src/ast - ast-value-factory.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 101 104 97.1 %
Date: 2019-01-20 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         156 :       literal_bytes_(lb), pos_(0) {}
      46             : 
      47        1550 :   bool HasMore() { return pos_ < literal_bytes_.length(); }
      48        3100 :   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    27927967 :   explicit AstRawStringInternalizationKey(const AstRawString* string)
      60    27927967 :       : StringTableKey(string->hash_field()), string_(string) {}
      61             : 
      62    76328084 :   bool IsMatch(Object other) override {
      63    76328084 :     if (string_->is_one_byte())
      64    76253615 :       return String::cast(other)->IsOneByteEqualTo(string_->literal_bytes_);
      65             :     return String::cast(other)->IsTwoByteEqualTo(
      66       74479 :         Vector<const uint16_t>::cast(string_->literal_bytes_));
      67             :   }
      68             : 
      69     8654582 :   Handle<String> AsHandle(Isolate* isolate) override {
      70     8707613 :     if (string_->is_one_byte())
      71             :       return isolate->factory()->NewOneByteInternalizedString(
      72     8601551 :           string_->literal_bytes_, string_->hash_field());
      73             :     return isolate->factory()->NewTwoByteInternalizedString(
      74             :         Vector<const uint16_t>::cast(string_->literal_bytes_),
      75       53031 :         string_->hash_field());
      76             :   }
      77             : 
      78             :  private:
      79             :   const AstRawString* string_;
      80             : };
      81             : 
      82    27927967 : void AstRawString::Internalize(Isolate* isolate) {
      83             :   DCHECK(!has_string_);
      84    55855934 :   if (literal_bytes_.length() == 0) {
      85             :     set_string(isolate->factory()->empty_string());
      86             :   } else {
      87             :     AstRawStringInternalizationKey key(this);
      88    27927967 :     set_string(StringTable::LookupKey(isolate, &key));
      89             :   }
      90    27927990 : }
      91             : 
      92    11398942 : 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    11398942 :   if ((hash_field_ & Name::kIsNotArrayIndexMask) != 0) return false;
      96        4416 :   if (length() <= Name::kMaxCachedArrayIndexLength) {
      97        4260 :     *index = Name::ArrayIndexValueBits::decode(hash_field_);
      98             :   } else {
      99             :     OneByteStringStream stream(literal_bytes_);
     100         156 :     CHECK(StringToArrayIndex(&stream, index));
     101             :   }
     102             :   return true;
     103             : }
     104             : 
     105      181053 : bool AstRawString::IsOneByteEqualTo(const char* data) const {
     106      181053 :   if (!is_one_byte()) return false;
     107             : 
     108      393138 :   size_t length = static_cast<size_t>(literal_bytes_.length());
     109      181066 :   if (length != strlen(data)) return false;
     110             : 
     111             :   return 0 == strncmp(reinterpret_cast<const char*>(literal_bytes_.start()),
     112       31006 :                       data, length);
     113             : }
     114             : 
     115     4168143 : uint16_t AstRawString::FirstCharacter() const {
     116     4168143 :   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    53438524 : 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    53438524 :   if (lhs->length() != rhs->length()) return false;
     127             :   const unsigned char* l = lhs->raw_data();
     128             :   const unsigned char* r = rhs->raw_data();
     129    53440515 :   size_t length = rhs->length();
     130    53440515 :   if (lhs->is_one_byte()) {
     131    53432763 :     if (rhs->is_one_byte()) {
     132             :       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
     133             :                                   reinterpret_cast<const uint8_t*>(r),
     134    53432757 :                                   length) == 0;
     135             :     } else {
     136             :       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
     137             :                                   reinterpret_cast<const uint16_t*>(r),
     138           6 :                                   length) == 0;
     139             :     }
     140             :   } else {
     141        7752 :     if (rhs->is_one_byte()) {
     142             :       return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
     143             :                                   reinterpret_cast<const uint8_t*>(r),
     144           0 :                                   length) == 0;
     145             :     } else {
     146             :       return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
     147             :                                   reinterpret_cast<const uint16_t*>(r),
     148        7752 :                                   length) == 0;
     149             :     }
     150             :   }
     151             : }
     152             : 
     153     8470449 : void AstConsString::Internalize(Isolate* isolate) {
     154     8470449 :   if (IsEmpty()) {
     155             :     set_string(isolate->factory()->empty_string());
     156     8470449 :     return;
     157             :   }
     158             :   // AstRawStrings are internalized before AstConsStrings, so
     159             :   // AstRawString::string() will just work.
     160     3401751 :   Handle<String> tmp(segment_.string->string());
     161     3725607 :   for (AstConsString::Segment* current = segment_.next; current != nullptr;
     162             :        current = current->next) {
     163             :     tmp = isolate->factory()
     164      323856 :               ->NewConsString(current->string->string(), tmp)
     165      647712 :               .ToHandleChecked();
     166             :   }
     167             :   set_string(tmp);
     168             : }
     169             : 
     170          42 : std::forward_list<const AstRawString*> AstConsString::ToRawStrings() const {
     171             :   std::forward_list<const AstRawString*> result;
     172          21 :   if (IsEmpty()) {
     173             :     return result;
     174             :   }
     175             : 
     176          21 :   result.emplace_front(segment_.string);
     177          21 :   for (AstConsString::Segment* current = segment_.next; current != nullptr;
     178             :        current = current->next) {
     179           0 :     result.emplace_front(current->string);
     180             :   }
     181             :   return result;
     182             : }
     183             : 
     184       62883 : AstStringConstants::AstStringConstants(Isolate* isolate, uint64_t hash_seed)
     185             :     : zone_(isolate->allocator(), ZONE_NAME),
     186             :       string_table_(AstRawString::Compare),
     187      125766 :       hash_seed_(hash_seed) {
     188             :   DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
     189             : #define F(name, str)                                                       \
     190             :   {                                                                        \
     191             :     const char* data = str;                                                \
     192             :     Vector<const uint8_t> literal(reinterpret_cast<const uint8_t*>(data),  \
     193             :                                   static_cast<int>(strlen(data)));         \
     194             :     uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>(     \
     195             :         literal.start(), literal.length(), hash_seed_);                    \
     196             :     name##_string_ = new (&zone_) AstRawString(true, literal, hash_field); \
     197             :     /* The Handle returned by the factory is located on the roots */       \
     198             :     /* array, not on the temporary HandleScope, so this is safe.  */       \
     199             :     name##_string_->set_string(isolate->factory()->name##_string());       \
     200             :     base::HashMap::Entry* entry =                                          \
     201             :         string_table_.InsertNew(name##_string_, name##_string_->Hash());   \
     202             :     DCHECK_NULL(entry->value);                                             \
     203             :     entry->value = reinterpret_cast<void*>(1);                             \
     204             :   }
     205     9495315 :   AST_STRING_CONSTANTS(F)
     206             : #undef F
     207       62883 : }
     208             : 
     209    99785141 : AstRawString* AstValueFactory::GetOneByteStringInternal(
     210             :     Vector<const uint8_t> literal) {
     211    99785141 :   if (literal.length() == 1 && literal[0] < kMaxOneCharStringValue) {
     212    20999332 :     int key = literal[0];
     213    20999332 :     if (V8_UNLIKELY(one_character_strings_[key] == nullptr)) {
     214             :       uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>(
     215     3775644 :           literal.start(), literal.length(), hash_seed_);
     216     3775645 :       one_character_strings_[key] = GetString(hash_field, true, literal);
     217             :     }
     218    20999317 :     return one_character_strings_[key];
     219             :   }
     220             :   uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>(
     221    78785809 :       literal.start(), literal.length(), hash_seed_);
     222    78808016 :   return GetString(hash_field, true, literal);
     223             : }
     224             : 
     225       77477 : AstRawString* AstValueFactory::GetTwoByteStringInternal(
     226             :     Vector<const uint16_t> literal) {
     227             :   uint32_t hash_field = StringHasher::HashSequentialString<uint16_t>(
     228      154954 :       literal.start(), literal.length(), hash_seed_);
     229       77477 :   return GetString(hash_field, false, Vector<const byte>::cast(literal));
     230             : }
     231             : 
     232      732279 : const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
     233             :   AstRawString* result = nullptr;
     234             :   DisallowHeapAllocation no_gc;
     235      732279 :   String::FlatContent content = literal->GetFlatContent(no_gc);
     236      732281 :   if (content.IsOneByte()) {
     237      732264 :     result = GetOneByteStringInternal(content.ToOneByteVector());
     238             :   } else {
     239             :     DCHECK(content.IsTwoByte());
     240          17 :     result = GetTwoByteStringInternal(content.ToUC16Vector());
     241             :   }
     242      732275 :   return result;
     243             : }
     244             : 
     245          80 : const AstRawString* AstValueFactory::CloneFromOtherFactory(
     246         160 :     const AstRawString* raw_string) {
     247             :   const AstRawString* result = GetString(
     248             :       raw_string->hash_field(), raw_string->is_one_byte(),
     249         240 :       Vector<const byte>(raw_string->raw_data(), raw_string->byte_length()));
     250          80 :   return result;
     251             : }
     252             : 
     253    10273532 : AstConsString* AstValueFactory::NewConsString() {
     254    10273532 :   AstConsString* new_string = new (zone_) AstConsString;
     255             :   DCHECK_NOT_NULL(new_string);
     256             :   AddConsString(new_string);
     257    10273612 :   return new_string;
     258             : }
     259             : 
     260     6829878 : AstConsString* AstValueFactory::NewConsString(const AstRawString* str) {
     261     6829878 :   return NewConsString()->AddString(zone_, str);
     262             : }
     263             : 
     264       27168 : AstConsString* AstValueFactory::NewConsString(const AstRawString* str1,
     265             :                                               const AstRawString* str2) {
     266       27168 :   return NewConsString()->AddString(zone_, str1)->AddString(zone_, str2);
     267             : }
     268             : 
     269     3784904 : void AstValueFactory::Internalize(Isolate* isolate) {
     270             :   // Strings need to be internalized before values, because values refer to
     271             :   // strings.
     272    35497804 :   for (AstRawString* current = strings_; current != nullptr;) {
     273             :     AstRawString* next = current->next();
     274    27927965 :     current->Internalize(isolate);
     275             :     current = next;
     276             :   }
     277             : 
     278             :   // AstConsStrings refer to AstRawStrings.
     279    16040321 :   for (AstConsString* current = cons_strings_; current != nullptr;) {
     280             :     AstConsString* next = current->next();
     281     8470451 :     current->Internalize(isolate);
     282             :     current = next;
     283             :   }
     284             : 
     285             :   ResetStrings();
     286     3784935 : }
     287             : 
     288    82680882 : AstRawString* AstValueFactory::GetString(uint32_t hash_field, bool is_one_byte,
     289             :                                          Vector<const byte> literal_bytes) {
     290             :   // literal_bytes here points to whatever the user passed, and this is OK
     291             :   // because we use vector_compare (which checks the contents) to compare
     292             :   // against the AstRawStrings which are in the string_table_. We should not
     293             :   // return this AstRawString.
     294             :   AstRawString key(is_one_byte, literal_bytes, hash_field);
     295   165363833 :   base::HashMap::Entry* entry = string_table_.LookupOrInsert(&key, key.Hash());
     296    82682951 :   if (entry->value == nullptr) {
     297             :     // Copy literal contents for later comparison.
     298    31716644 :     int length = literal_bytes.length();
     299    31716644 :     byte* new_literal_bytes = zone_->NewArray<byte>(length);
     300    31716216 :     memcpy(new_literal_bytes, literal_bytes.start(), length);
     301             :     AstRawString* new_string = new (zone_) AstRawString(
     302    31716216 :         is_one_byte, Vector<const byte>(new_literal_bytes, length), hash_field);
     303    31713756 :     CHECK_NOT_NULL(new_string);
     304             :     AddString(new_string);
     305    31713756 :     entry->key = new_string;
     306    31713756 :     entry->value = reinterpret_cast<void*>(1);
     307             :   }
     308    82680063 :   return reinterpret_cast<AstRawString*>(entry->key);
     309             : }
     310             : 
     311             : }  // namespace internal
     312      183867 : }  // namespace v8

Generated by: LCOV version 1.10