LCOV - code coverage report
Current view: top level - src - string-hasher-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 49 49 100.0 %
Date: 2017-10-20 Functions: 8 8 100.0 %

          Line data    Source code
       1             : // Copyright 2017 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_STRING_HASHER_INL_H_
       6             : #define V8_STRING_HASHER_INL_H_
       7             : 
       8             : #include "src/char-predicates-inl.h"
       9             : #include "src/objects.h"
      10             : #include "src/string-hasher.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15             : StringHasher::StringHasher(int length, uint32_t seed)
      16             :     : length_(length),
      17             :       raw_running_hash_(seed),
      18             :       array_index_(0),
      19   194151244 :       is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
      20   405090403 :       is_first_char_(true) {
      21             :   DCHECK(FLAG_randomize_hashes || raw_running_hash_ == 0);
      22             : }
      23             : 
      24             : bool StringHasher::has_trivial_hash() {
      25             :   return length_ > String::kMaxHashCalcLength;
      26             : }
      27             : 
      28             : uint32_t StringHasher::AddCharacterCore(uint32_t running_hash, uint16_t c) {
      29  2442656346 :   running_hash += c;
      30  2442656346 :   running_hash += (running_hash << 10);
      31  2442656346 :   running_hash ^= (running_hash >> 6);
      32             :   return running_hash;
      33             : }
      34             : 
      35             : uint32_t StringHasher::GetHashCore(uint32_t running_hash) {
      36   217320001 :   running_hash += (running_hash << 3);
      37   217320001 :   running_hash ^= (running_hash >> 11);
      38   217320001 :   running_hash += (running_hash << 15);
      39   217320001 :   if ((running_hash & String::kHashBitMask) == 0) {
      40             :     return kZeroHash;
      41             :   }
      42             :   return running_hash;
      43             : }
      44             : 
      45             : uint32_t StringHasher::ComputeRunningHash(uint32_t running_hash,
      46             :                                           const uc16* chars, int length) {
      47             :   DCHECK_NOT_NULL(chars);
      48             :   DCHECK_GE(length, 0);
      49         125 :   for (int i = 0; i < length; ++i) {
      50         125 :     running_hash = AddCharacterCore(running_hash, *chars++);
      51             :   }
      52             :   return running_hash;
      53             : }
      54             : 
      55             : uint32_t StringHasher::ComputeRunningHashOneByte(uint32_t running_hash,
      56             :                                                  const char* chars,
      57             :                                                  int length) {
      58             :   DCHECK_NOT_NULL(chars);
      59             :   DCHECK_GE(length, 0);
      60       69552 :   for (int i = 0; i < length; ++i) {
      61       69552 :     uint16_t c = static_cast<uint16_t>(*chars++);
      62             :     running_hash = AddCharacterCore(running_hash, c);
      63             :   }
      64             :   return running_hash;
      65             : }
      66             : 
      67             : void StringHasher::AddCharacter(uint16_t c) {
      68             :   // Use the Jenkins one-at-a-time hash function to update the hash
      69             :   // for the given character.
      70  4760177420 :   raw_running_hash_ = AddCharacterCore(raw_running_hash_, c);
      71             : }
      72             : 
      73   157944461 : bool StringHasher::UpdateIndex(uint16_t c) {
      74             :   DCHECK(is_array_index_);
      75   315888922 :   if (!IsDecimalDigit(c)) {
      76   144420430 :     is_array_index_ = false;
      77   144420430 :     return false;
      78             :   }
      79             :   int d = c - '0';
      80    13524031 :   if (is_first_char_) {
      81     4082025 :     is_first_char_ = false;
      82     4082025 :     if (d == 0 && length_ > 1) {
      83       12863 :       is_array_index_ = false;
      84       12863 :       return false;
      85             :     }
      86             :   }
      87    13511168 :   if (array_index_ > 429496729U - ((d + 3) >> 3)) {
      88        3000 :     is_array_index_ = false;
      89        3000 :     return false;
      90             :   }
      91    13508168 :   array_index_ = array_index_ * 10 + d;
      92    13508168 :   return true;
      93             : }
      94             : 
      95             : template <typename Char>
      96   201162690 : inline void StringHasher::AddCharacters(const Char* chars, int length) {
      97             :   DCHECK(sizeof(Char) == 1 || sizeof(Char) == 2);
      98             :   int i = 0;
      99   201162690 :   if (is_array_index_) {
     100    13503218 :     for (; i < length; i++) {
     101   141153379 :       AddCharacter(chars[i]);
     102   141153379 :       if (!UpdateIndex(chars[i])) {
     103   127650165 :         i++;
     104   127650165 :         break;
     105             :       }
     106             :     }
     107             :   }
     108  1913998606 :   for (; i < length; i++) {
     109             :     DCHECK(!is_array_index_);
     110  1913998606 :     AddCharacter(chars[i]);
     111             :   }
     112   201162694 : }
     113             : 
     114             : template <typename schar>
     115   130302892 : uint32_t StringHasher::HashSequentialString(const schar* chars, int length,
     116             :                                             uint32_t seed) {
     117             :   StringHasher hasher(length, seed);
     118   130302892 :   if (!hasher.has_trivial_hash()) hasher.AddCharacters(chars, length);
     119   130302945 :   return hasher.GetHashField();
     120             : }
     121             : 
     122             : IteratingStringHasher::IteratingStringHasher(int len, uint32_t seed)
     123             :     : StringHasher(len, seed) {}
     124             : 
     125    63848352 : uint32_t IteratingStringHasher::Hash(String* string, uint32_t seed) {
     126             :   IteratingStringHasher hasher(string->length(), seed);
     127             :   // Nothing to do.
     128    63848352 :   if (hasher.has_trivial_hash()) return hasher.GetHashField();
     129    63803987 :   ConsString* cons_string = String::VisitFlat(&hasher, string);
     130    63804153 :   if (cons_string == nullptr) return hasher.GetHashField();
     131     1664856 :   hasher.VisitConsString(cons_string);
     132     1664856 :   return hasher.GetHashField();
     133             : }
     134             : 
     135             : void IteratingStringHasher::VisitOneByteString(const uint8_t* chars,
     136             :                                                int length) {
     137    68071599 :   AddCharacters(chars, length);
     138             : }
     139             : 
     140             : void IteratingStringHasher::VisitTwoByteString(const uint16_t* chars,
     141             :                                                int length) {
     142     2584113 :   AddCharacters(chars, length);
     143             : }
     144             : 
     145             : }  // namespace internal
     146             : }  // namespace v8
     147             : 
     148             : #endif  // V8_STRING_HASHER_INL_H_

Generated by: LCOV version 1.10