Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: src/objects.cc

Issue 11593007: Replace the use CharacterStreams in Heap::AllocateSymbolInternal and String::ComputeHash (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: issues addressed Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 7003 matching lines...) Expand 10 before | Expand all | Expand 10 after
7014 start_ = content.ToUC16Vector().start(); 7014 start_ = content.ToUC16Vector().start();
7015 } 7015 }
7016 } 7016 }
7017 7017
7018 7018
7019 void StringInputBuffer::Seek(unsigned pos) { 7019 void StringInputBuffer::Seek(unsigned pos) {
7020 Reset(pos, input_); 7020 Reset(pos, input_);
7021 } 7021 }
7022 7022
7023 7023
7024 String* ConsStringIteratorOp::Operate(ConsString* cons_string, 7024 String* ConsStringIteratorOp::Operate(String* string,
7025 unsigned* offset_out, int32_t* type_out, unsigned* length_out) { 7025 unsigned* offset_out,
7026 ASSERT(*length_out == (unsigned)cons_string->length()); 7026 int32_t* type_out,
7027 ASSERT(depth_ == 0); 7027 unsigned* length_out) {
7028 // Push the root string. 7028 ASSERT(string->IsConsString());
7029 PushLeft(cons_string); 7029 ConsString* cons_string = ConsString::cast(string);
7030 // Set up search data.
7030 root_ = cons_string; 7031 root_ = cons_string;
7031 root_type_ = *type_out;
7032 root_length_ = *length_out;
7033 consumed_ = *offset_out; 7032 consumed_ = *offset_out;
7034 unsigned targetOffset = *offset_out; 7033 // Now search.
7034 return Search(offset_out, type_out, length_out);
7035 }
7036
7037
7038 String* ConsStringIteratorOp::Search(unsigned* offset_out,
7039 int32_t* type_out,
7040 unsigned* length_out) {
7041 ConsString* cons_string = root_;
7042 // Reset the stack, pushing the root string.
7043 depth_ = 1;
7044 maximum_depth_ = 1;
7045 frames_[0] = cons_string;
7046 const unsigned consumed = consumed_;
7035 unsigned offset = 0; 7047 unsigned offset = 0;
7036 while (true) { 7048 while (true) {
7037 // Loop until the string is found which contains the target offset. 7049 // Loop until the string is found which contains the target offset.
7038 String* string = cons_string->first(); 7050 String* string = cons_string->first();
7039 unsigned length = string->length(); 7051 unsigned length = string->length();
7040 int32_t type; 7052 int32_t type;
7041 if (targetOffset < offset + length) { 7053 if (consumed < offset + length) {
7042 // Target offset is in the left branch. 7054 // Target offset is in the left branch.
7043 // Keep going if we're still in a ConString. 7055 // Keep going if we're still in a ConString.
7044 type = string->map()->instance_type(); 7056 type = string->map()->instance_type();
7045 if ((type & kStringRepresentationMask) == kConsStringTag) { 7057 if ((type & kStringRepresentationMask) == kConsStringTag) {
7046 cons_string = ConsString::cast(string); 7058 cons_string = ConsString::cast(string);
7047 PushLeft(cons_string); 7059 PushLeft(cons_string);
7048 continue; 7060 continue;
7049 } 7061 }
7050 // Tell the stack we're done decending. 7062 // Tell the stack we're done decending.
7051 AdjustMaximumDepth(); 7063 AdjustMaximumDepth();
7052 } else { 7064 } else {
7053 // Descend right. 7065 // Descend right.
7054 // Update progress through the string. 7066 // Update progress through the string.
7055 offset += length; 7067 offset += length;
7056 // Keep going if we're still in a ConString. 7068 // Keep going if we're still in a ConString.
7057 string = cons_string->second(); 7069 string = cons_string->second();
7058 type = string->map()->instance_type(); 7070 type = string->map()->instance_type();
7059 if ((type & kStringRepresentationMask) == kConsStringTag) { 7071 if ((type & kStringRepresentationMask) == kConsStringTag) {
7060 cons_string = ConsString::cast(string); 7072 cons_string = ConsString::cast(string);
7061 PushRight(cons_string); 7073 PushRight(cons_string);
7062 // TODO(dcarney) Add back root optimization. 7074 // TODO(dcarney) Add back root optimization.
7063 continue; 7075 continue;
7064 } 7076 }
7065 // Need this to be updated for the current string. 7077 // Need this to be updated for the current string.
7066 length = string->length(); 7078 length = string->length();
7067 // Account for the possibility of an empty right leaf. 7079 // Account for the possibility of an empty right leaf.
7068 // This happens only if we have asked for an offset outside the string. 7080 // This happens only if we have asked for an offset outside the string.
7069 if (length == 0) { 7081 if (length == 0) {
7082 // Reset depth so future operations will return null immediately.
7070 Reset(); 7083 Reset();
7071 return NULL; 7084 return NULL;
7072 } 7085 }
7073 // Tell the stack we're done decending. 7086 // Tell the stack we're done decending.
7074 AdjustMaximumDepth(); 7087 AdjustMaximumDepth();
7075 // Pop stack so next iteration is in correct place. 7088 // Pop stack so next iteration is in correct place.
7076 Pop(); 7089 Pop();
7077 } 7090 }
7078 ASSERT(length != 0); 7091 ASSERT(length != 0);
7079 // Adjust return values and exit. 7092 // Adjust return values and exit.
7080 unsigned innerOffset = targetOffset - offset; 7093 consumed_ = offset + length;
7081 consumed_ += length - innerOffset; 7094 *offset_out = consumed - offset;
7082 *offset_out = innerOffset;
7083 *type_out = type; 7095 *type_out = type;
7084 *length_out = length; 7096 *length_out = length;
7085 return string; 7097 return string;
7086 } 7098 }
7087 UNREACHABLE(); 7099 UNREACHABLE();
7088 return NULL; 7100 return NULL;
7089 } 7101 }
7090 7102
7091 7103
7092 String* ConsStringIteratorOp::NextLeaf( 7104 String* ConsStringIteratorOp::NextLeaf(bool* blew_stack,
7093 bool* blew_stack, int32_t* type_out, unsigned* length_out) { 7105 int32_t* type_out,
7106 unsigned* length_out) {
7094 while (true) { 7107 while (true) {
7095 // Tree traversal complete. 7108 // Tree traversal complete.
7096 if (depth_ == 0) { 7109 if (depth_ == 0) {
7097 *blew_stack = false; 7110 *blew_stack = false;
7098 return NULL; 7111 return NULL;
7099 } 7112 }
7100 // We've lost track of higher nodes. 7113 // We've lost track of higher nodes.
7101 if (maximum_depth_ - depth_ == kStackSize) { 7114 if (maximum_depth_ - depth_ == kStackSize) {
7102 *blew_stack = true; 7115 *blew_stack = true;
7103 return NULL; 7116 return NULL;
7104 } 7117 }
7105 // Go right. 7118 // Go right.
7106 ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)]; 7119 ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
7107 String* string = cons_string->second(); 7120 String* string = cons_string->second();
7108 int32_t type = string->map()->instance_type(); 7121 int32_t type = string->map()->instance_type();
7109 if ((type & kStringRepresentationMask) != kConsStringTag) { 7122 if ((type & kStringRepresentationMask) != kConsStringTag) {
7110 // Pop stack so next iteration is in correct place. 7123 // Pop stack so next iteration is in correct place.
7111 Pop(); 7124 Pop();
7112 unsigned length = (unsigned) string->length(); 7125 unsigned length = (unsigned) string->length();
7113 // Could be a flattened ConsString. 7126 // Could be a flattened ConsString.
7114 if (length == 0) continue; 7127 if (length == 0) continue;
7115 *length_out = length; 7128 *length_out = length;
7116 *type_out = type; 7129 *type_out = type;
7130 consumed_ += length;
7117 return string; 7131 return string;
7118 } 7132 }
7119 cons_string = ConsString::cast(string); 7133 cons_string = ConsString::cast(string);
7120 // TODO(dcarney) Add back root optimization. 7134 // TODO(dcarney) Add back root optimization.
7121 PushRight(cons_string); 7135 PushRight(cons_string);
7122 // Need to traverse all the way left. 7136 // Need to traverse all the way left.
7123 while (true) { 7137 while (true) {
7124 // Continue left. 7138 // Continue left.
7125 string = cons_string->first(); 7139 string = cons_string->first();
7126 type = string->map()->instance_type(); 7140 type = string->map()->instance_type();
7127 if ((type & kStringRepresentationMask) != kConsStringTag) { 7141 if ((type & kStringRepresentationMask) != kConsStringTag) {
7128 AdjustMaximumDepth(); 7142 AdjustMaximumDepth();
7143 unsigned length = (unsigned) string->length();
7144 ASSERT(length != 0);
7145 *length_out = length;
7129 *type_out = type; 7146 *type_out = type;
7130 *length_out = string->length(); 7147 consumed_ += length;
7131 return string; 7148 return string;
7132 } 7149 }
7133 cons_string = ConsString::cast(string); 7150 cons_string = ConsString::cast(string);
7134 PushLeft(cons_string); 7151 PushLeft(cons_string);
7135 } 7152 }
7136 } 7153 }
7137 UNREACHABLE(); 7154 UNREACHABLE();
7138 return NULL; 7155 return NULL;
7139 } 7156 }
7140 7157
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after
7659 if (content.IsTwoByte()) { 7676 if (content.IsTwoByte()) {
7660 return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0; 7677 return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
7661 } 7678 }
7662 for (int i = 0; i < slen; i++) { 7679 for (int i = 0; i < slen; i++) {
7663 if (Get(i) != str[i]) return false; 7680 if (Get(i) != str[i]) return false;
7664 } 7681 }
7665 return true; 7682 return true;
7666 } 7683 }
7667 7684
7668 7685
7686 class IteratingStringHasher: public StringHasher {
7687 public:
7688 static inline uint32_t Hash(String* string, uint32_t seed) {
7689 const unsigned len = static_cast<unsigned>(string->length());
7690 IteratingStringHasher hasher(len, seed);
7691 if (hasher.has_trivial_hash()) {
7692 return hasher.GetHashField();
7693 }
7694 int32_t type = string->map()->instance_type();
7695 ConsStringNullOp null_op;
7696 String::Visit(string, 0, hasher, null_op, type, len);
7697 // Flat strings terminate immediately.
7698 if (hasher.consumed_ == len) {
7699 ASSERT(!string->IsConsString());
7700 return hasher.GetHashField();
7701 }
7702 ASSERT(string->IsConsString());
7703 // This is a ConsString, iterate across it.
7704 ConsStringIteratorOp op;
7705 unsigned offset = 0;
7706 unsigned leaf_length = len;
7707 string = op.Operate(string, &offset, &type, &leaf_length);
7708 while (true) {
7709 ASSERT(hasher.consumed_ < len);
7710 String::Visit(string, 0, hasher, null_op, type, leaf_length);
7711 if (hasher.consumed_ == len) break;
7712 string = op.ContinueOperation(&type, &leaf_length);
7713 // This should be taken care of by the length check.
7714 ASSERT(string != NULL);
7715 }
7716 return hasher.GetHashField();
7717 }
7718 inline void VisitOneByteString(const uint8_t* chars, unsigned length) {
7719 AddCharacters(chars, static_cast<int>(length));
7720 consumed_ += length;
7721 }
7722 inline void VisitTwoByteString(const uint16_t* chars, unsigned length) {
7723 AddCharacters(chars, static_cast<int>(length));
7724 consumed_ += length;
7725 }
7726
7727 private:
7728 inline IteratingStringHasher(int len, uint32_t seed)
7729 : StringHasher(len, seed),
7730 consumed_(0) {}
7731 unsigned consumed_;
7732 DISALLOW_COPY_AND_ASSIGN(IteratingStringHasher);
7733 };
7734
7735
7669 uint32_t String::ComputeAndSetHash() { 7736 uint32_t String::ComputeAndSetHash() {
7670 // Should only be called if hash code has not yet been computed. 7737 // Should only be called if hash code has not yet been computed.
7671 ASSERT(!HasHashCode()); 7738 ASSERT(!HasHashCode());
7672 7739
7673 const int len = length();
7674
7675 // Compute the hash code.
7676 uint32_t field = 0;
7677 if (StringShape(this).IsSequentialAscii()) {
7678 field = HashSequentialString(SeqOneByteString::cast(this)->GetChars(),
7679 len,
7680 GetHeap()->HashSeed());
7681 } else if (StringShape(this).IsSequentialTwoByte()) {
7682 field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(),
7683 len,
7684 GetHeap()->HashSeed());
7685 } else {
7686 StringInputBuffer buffer(this);
7687 field = ComputeHashField(&buffer, len, GetHeap()->HashSeed());
7688 }
7689
7690 // Store the hash code in the object. 7740 // Store the hash code in the object.
7741 uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed());
7691 set_hash_field(field); 7742 set_hash_field(field);
7692 7743
7693 // Check the hash code is there. 7744 // Check the hash code is there.
7694 ASSERT(HasHashCode()); 7745 ASSERT(HasHashCode());
7695 uint32_t result = field >> kHashShift; 7746 uint32_t result = field >> kHashShift;
7696 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. 7747 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
7697 return result; 7748 return result;
7698 } 7749 }
7699 7750
7700 7751
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
7784 value <<= String::kHashShift; 7835 value <<= String::kHashShift;
7785 value |= length << String::kArrayIndexHashLengthShift; 7836 value |= length << String::kArrayIndexHashLengthShift;
7786 7837
7787 ASSERT((value & String::kIsNotArrayIndexMask) == 0); 7838 ASSERT((value & String::kIsNotArrayIndexMask) == 0);
7788 ASSERT((length > String::kMaxCachedArrayIndexLength) || 7839 ASSERT((length > String::kMaxCachedArrayIndexLength) ||
7789 (value & String::kContainsCachedArrayIndexMask) == 0); 7840 (value & String::kContainsCachedArrayIndexMask) == 0);
7790 return value; 7841 return value;
7791 } 7842 }
7792 7843
7793 7844
7794 void StringHasher::AddSurrogatePair(uc32 c) {
7795 uint16_t lead = unibrow::Utf16::LeadSurrogate(c);
7796 AddCharacter(lead);
7797 uint16_t trail = unibrow::Utf16::TrailSurrogate(c);
7798 AddCharacter(trail);
7799 }
7800
7801
7802 void StringHasher::AddSurrogatePairNoIndex(uc32 c) {
7803 uint16_t lead = unibrow::Utf16::LeadSurrogate(c);
7804 AddCharacterNoIndex(lead);
7805 uint16_t trail = unibrow::Utf16::TrailSurrogate(c);
7806 AddCharacterNoIndex(trail);
7807 }
7808
7809
7810 uint32_t StringHasher::GetHashField() { 7845 uint32_t StringHasher::GetHashField() {
7811 if (length_ <= String::kMaxHashCalcLength) { 7846 if (length_ <= String::kMaxHashCalcLength) {
7812 if (is_array_index()) { 7847 if (is_array_index_) {
7813 return MakeArrayIndexHash(array_index(), length_); 7848 return MakeArrayIndexHash(array_index_, length_);
7814 } 7849 }
7815 return (GetHash() << String::kHashShift) | String::kIsNotArrayIndexMask; 7850 return (GetHashCore(raw_running_hash_) << String::kHashShift) |
7851 String::kIsNotArrayIndexMask;
7816 } else { 7852 } else {
7817 return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask; 7853 return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
7818 } 7854 }
7819 } 7855 }
7820 7856
7821 7857
7822 uint32_t String::ComputeHashField(unibrow::CharacterStream* buffer, 7858 uint32_t StringHasher::ComputeHashField(unibrow::CharacterStream* buffer,
7823 int length, 7859 int length,
7824 uint32_t seed) { 7860 uint32_t seed) {
7861 typedef unibrow::Utf16 u;
7825 StringHasher hasher(length, seed); 7862 StringHasher hasher(length, seed);
7826
7827 // Very long strings have a trivial hash that doesn't inspect the 7863 // Very long strings have a trivial hash that doesn't inspect the
7828 // string contents. 7864 // string contents.
7829 if (hasher.has_trivial_hash()) { 7865 if (hasher.has_trivial_hash()) {
7830 return hasher.GetHashField(); 7866 return hasher.GetHashField();
7831 } 7867 }
7832
7833 // Do the iterative array index computation as long as there is a 7868 // Do the iterative array index computation as long as there is a
7834 // chance this is an array index. 7869 // chance this is an array index.
7835 while (buffer->has_more() && hasher.is_array_index()) { 7870 if (hasher.is_array_index_) {
7836 hasher.AddCharacter(buffer->GetNext()); 7871 while (buffer->has_more()) {
7872 uint32_t c = buffer->GetNext();
7873 if (c > u::kMaxNonSurrogateCharCode) {
7874 uint16_t c1 = u::LeadSurrogate(c);
7875 uint16_t c2 = u::TrailSurrogate(c);
7876 hasher.AddCharacter(c1);
7877 hasher.AddCharacter(c2);
7878 if (!hasher.UpdateIndex(c1)) break;
7879 if (!hasher.UpdateIndex(c2)) break;
7880 } else {
7881 hasher.AddCharacter(c);
7882 if (!hasher.UpdateIndex(c)) break;
7883 }
7884 }
7837 } 7885 }
7838
7839 // Process the remaining characters without updating the array 7886 // Process the remaining characters without updating the array
7840 // index. 7887 // index.
7841 while (buffer->has_more()) { 7888 while (buffer->has_more()) {
7842 hasher.AddCharacterNoIndex(buffer->GetNext()); 7889 ASSERT(!hasher.is_array_index_);
7890 uint32_t c = buffer->GetNext();
7891 if (c > u::kMaxNonSurrogateCharCode) {
7892 hasher.AddCharacter(u::LeadSurrogate(c));
7893 hasher.AddCharacter(u::TrailSurrogate(c));
7894 } else {
7895 hasher.AddCharacter(c);
7896 }
7843 } 7897 }
7844
7845 return hasher.GetHashField(); 7898 return hasher.GetHashField();
7846 } 7899 }
7847 7900
7848 7901
7849 MaybeObject* String::SubString(int start, int end, PretenureFlag pretenure) { 7902 MaybeObject* String::SubString(int start, int end, PretenureFlag pretenure) {
7850 Heap* heap = GetHeap(); 7903 Heap* heap = GetHeap();
7851 if (start == 0 && end == length()) return this; 7904 if (start == 0 && end == length()) return this;
7852 MaybeObject* result = heap->AllocateSubString(this, start, end, pretenure); 7905 MaybeObject* result = heap->AllocateSubString(this, start, end, pretenure);
7853 return result; 7906 return result;
7854 } 7907 }
(...skipping 3790 matching lines...) Expand 10 before | Expand all | Expand 10 after
11645 11698
11646 bool IsMatch(Object* string) { 11699 bool IsMatch(Object* string) {
11647 return String::cast(string)->IsEqualTo(string_); 11700 return String::cast(string)->IsEqualTo(string_);
11648 } 11701 }
11649 11702
11650 uint32_t Hash() { 11703 uint32_t Hash() {
11651 if (hash_field_ != 0) return hash_field_ >> String::kHashShift; 11704 if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
11652 unibrow::Utf8InputBuffer<> buffer(string_.start(), 11705 unibrow::Utf8InputBuffer<> buffer(string_.start(),
11653 static_cast<unsigned>(string_.length())); 11706 static_cast<unsigned>(string_.length()));
11654 chars_ = buffer.Utf16Length(); 11707 chars_ = buffer.Utf16Length();
11655 hash_field_ = String::ComputeHashField(&buffer, chars_, seed_); 11708 hash_field_ = StringHasher::ComputeHashField(&buffer, chars_, seed_);
11656 uint32_t result = hash_field_ >> String::kHashShift; 11709 uint32_t result = hash_field_ >> String::kHashShift;
11657 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. 11710 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
11658 return result; 11711 return result;
11659 } 11712 }
11660 11713
11661 uint32_t HashForObject(Object* other) { 11714 uint32_t HashForObject(Object* other) {
11662 return String::cast(other)->Hash(); 11715 return String::cast(other)->Hash();
11663 } 11716 }
11664 11717
11665 MaybeObject* AsObject() { 11718 MaybeObject* AsObject() {
11666 if (hash_field_ == 0) Hash(); 11719 if (hash_field_ == 0) Hash();
11667 return Isolate::Current()->heap()->AllocateSymbol( 11720 return Isolate::Current()->heap()->AllocateSymbol(
11668 string_, chars_, hash_field_); 11721 string_, chars_, hash_field_);
11669 } 11722 }
11670 11723
11671 Vector<const char> string_; 11724 Vector<const char> string_;
11672 uint32_t hash_field_; 11725 uint32_t hash_field_;
11673 int chars_; // Caches the number of characters when computing the hash code. 11726 int chars_; // Caches the number of characters when computing the hash code.
11674 uint32_t seed_; 11727 uint32_t seed_;
11675 }; 11728 };
11676 11729
11677 11730
11678 template <typename Char> 11731 template <typename Char>
11679 class SequentialSymbolKey : public HashTableKey { 11732 class SequentialSymbolKey : public HashTableKey {
11680 public: 11733 public:
11681 explicit SequentialSymbolKey(Vector<const Char> string, uint32_t seed) 11734 explicit SequentialSymbolKey(Vector<const Char> string, uint32_t seed)
11682 : string_(string), hash_field_(0), seed_(seed) { } 11735 : string_(string), hash_field_(0), seed_(seed) { }
11683 11736
11684 uint32_t Hash() { 11737 uint32_t Hash() {
11685 StringHasher hasher(string_.length(), seed_); 11738 hash_field_ = StringHasher::HashSequentialString<Char>(string_.start(),
11686 11739 string_.length(),
11687 // Very long strings have a trivial hash that doesn't inspect the 11740 seed_);
11688 // string contents.
11689 if (hasher.has_trivial_hash()) {
11690 hash_field_ = hasher.GetHashField();
11691 } else {
11692 int i = 0;
11693 // Do the iterative array index computation as long as there is a
11694 // chance this is an array index.
11695 while (i < string_.length() && hasher.is_array_index()) {
11696 hasher.AddCharacter(static_cast<uc32>(string_[i]));
11697 i++;
11698 }
11699
11700 // Process the remaining characters without updating the array
11701 // index.
11702 while (i < string_.length()) {
11703 hasher.AddCharacterNoIndex(static_cast<uc32>(string_[i]));
11704 i++;
11705 }
11706 hash_field_ = hasher.GetHashField();
11707 }
11708 11741
11709 uint32_t result = hash_field_ >> String::kHashShift; 11742 uint32_t result = hash_field_ >> String::kHashShift;
11710 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. 11743 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
11711 return result; 11744 return result;
11712 } 11745 }
11713 11746
11714 11747
11715 uint32_t HashForObject(Object* other) { 11748 uint32_t HashForObject(Object* other) {
11716 return String::cast(other)->Hash(); 11749 return String::cast(other)->Hash();
11717 } 11750 }
(...skipping 24 matching lines...) Expand all
11742 class SubStringAsciiSymbolKey : public HashTableKey { 11775 class SubStringAsciiSymbolKey : public HashTableKey {
11743 public: 11776 public:
11744 explicit SubStringAsciiSymbolKey(Handle<SeqOneByteString> string, 11777 explicit SubStringAsciiSymbolKey(Handle<SeqOneByteString> string,
11745 int from, 11778 int from,
11746 int length) 11779 int length)
11747 : string_(string), from_(from), length_(length) { } 11780 : string_(string), from_(from), length_(length) { }
11748 11781
11749 uint32_t Hash() { 11782 uint32_t Hash() {
11750 ASSERT(length_ >= 0); 11783 ASSERT(length_ >= 0);
11751 ASSERT(from_ + length_ <= string_->length()); 11784 ASSERT(from_ + length_ <= string_->length());
11752 StringHasher hasher(length_, string_->GetHeap()->HashSeed()); 11785 char* chars = string_->GetChars() + from_;
11753 11786 hash_field_ = StringHasher::HashSequentialString(
11754 // Very long strings have a trivial hash that doesn't inspect the 11787 chars, length_, string_->GetHeap()->HashSeed());
11755 // string contents.
11756 if (hasher.has_trivial_hash()) {
11757 hash_field_ = hasher.GetHashField();
11758 } else {
11759 int i = 0;
11760 // Do the iterative array index computation as long as there is a
11761 // chance this is an array index.
11762 while (i < length_ && hasher.is_array_index()) {
11763 hasher.AddCharacter(static_cast<uc32>(
11764 string_->SeqOneByteStringGet(i + from_)));
11765 i++;
11766 }
11767
11768 // Process the remaining characters without updating the array
11769 // index.
11770 while (i < length_) {
11771 hasher.AddCharacterNoIndex(static_cast<uc32>(
11772 string_->SeqOneByteStringGet(i + from_)));
11773 i++;
11774 }
11775 hash_field_ = hasher.GetHashField();
11776 }
11777
11778 uint32_t result = hash_field_ >> String::kHashShift; 11788 uint32_t result = hash_field_ >> String::kHashShift;
11779 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. 11789 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
11780 return result; 11790 return result;
11781 } 11791 }
11782 11792
11783 11793
11784 uint32_t HashForObject(Object* other) { 11794 uint32_t HashForObject(Object* other) {
11785 return String::cast(other)->Hash(); 11795 return String::cast(other)->Hash();
11786 } 11796 }
11787 11797
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
11842 string_ = string_->TryFlattenGetString(); 11852 string_ = string_->TryFlattenGetString();
11843 Heap* heap = string_->GetHeap(); 11853 Heap* heap = string_->GetHeap();
11844 // Transform string to symbol if possible. 11854 // Transform string to symbol if possible.
11845 Map* map = heap->SymbolMapForString(string_); 11855 Map* map = heap->SymbolMapForString(string_);
11846 if (map != NULL) { 11856 if (map != NULL) {
11847 string_->set_map_no_write_barrier(map); 11857 string_->set_map_no_write_barrier(map);
11848 ASSERT(string_->IsSymbol()); 11858 ASSERT(string_->IsSymbol());
11849 return string_; 11859 return string_;
11850 } 11860 }
11851 // Otherwise allocate a new symbol. 11861 // Otherwise allocate a new symbol.
11852 StringInputBuffer buffer(string_); 11862 return heap->AllocateInternalSymbol(string_,
11853 return heap->AllocateInternalSymbol(&buffer,
11854 string_->length(), 11863 string_->length(),
11855 string_->hash_field()); 11864 string_->hash_field());
11856 } 11865 }
11857 11866
11858 static uint32_t StringHash(Object* obj) { 11867 static uint32_t StringHash(Object* obj) {
11859 return String::cast(obj)->Hash(); 11868 return String::cast(obj)->Hash();
11860 } 11869 }
11861 11870
11862 String* string_; 11871 String* string_;
11863 }; 11872 };
(...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after
12613 } 12622 }
12614 12623
12615 12624
12616 // This class is used for looking up two character strings in the symbol table. 12625 // This class is used for looking up two character strings in the symbol table.
12617 // If we don't have a hit we don't want to waste much time so we unroll the 12626 // If we don't have a hit we don't want to waste much time so we unroll the
12618 // string hash calculation loop here for speed. Doesn't work if the two 12627 // string hash calculation loop here for speed. Doesn't work if the two
12619 // characters form a decimal integer, since such strings have a different hash 12628 // characters form a decimal integer, since such strings have a different hash
12620 // algorithm. 12629 // algorithm.
12621 class TwoCharHashTableKey : public HashTableKey { 12630 class TwoCharHashTableKey : public HashTableKey {
12622 public: 12631 public:
12623 TwoCharHashTableKey(uint32_t c1, uint32_t c2, uint32_t seed) 12632 TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
12624 : c1_(c1), c2_(c2) { 12633 : c1_(c1), c2_(c2) {
12625 // Char 1. 12634 // Char 1.
12626 uint32_t hash = seed; 12635 uint32_t hash = seed;
12627 hash += c1; 12636 hash += c1;
12628 hash += hash << 10; 12637 hash += hash << 10;
12629 hash ^= hash >> 6; 12638 hash ^= hash >> 6;
12630 // Char 2. 12639 // Char 2.
12631 hash += c2; 12640 hash += c2;
12632 hash += hash << 10; 12641 hash += hash << 10;
12633 hash ^= hash >> 6; 12642 hash ^= hash >> 6;
12634 // GetHash. 12643 // GetHash.
12635 hash += hash << 3; 12644 hash += hash << 3;
12636 hash ^= hash >> 11; 12645 hash ^= hash >> 11;
12637 hash += hash << 15; 12646 hash += hash << 15;
12638 if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash; 12647 if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
12648 hash_ = hash;
12639 #ifdef DEBUG 12649 #ifdef DEBUG
12640 StringHasher hasher(2, seed);
12641 hasher.AddCharacter(c1);
12642 hasher.AddCharacter(c2);
12643 // If this assert fails then we failed to reproduce the two-character 12650 // If this assert fails then we failed to reproduce the two-character
12644 // version of the string hashing algorithm above. One reason could be 12651 // version of the string hashing algorithm above. One reason could be
12645 // that we were passed two digits as characters, since the hash 12652 // that we were passed two digits as characters, since the hash
12646 // algorithm is different in that case. 12653 // algorithm is different in that case.
12647 ASSERT_EQ(static_cast<int>(hasher.GetHash()), static_cast<int>(hash)); 12654 uint16_t chars[2] = {c1, c2};
12655 uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
12656 hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
12657 ASSERT_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash));
12648 #endif 12658 #endif
12649 hash_ = hash;
12650 } 12659 }
12651 12660
12652 bool IsMatch(Object* o) { 12661 bool IsMatch(Object* o) {
12653 if (!o->IsString()) return false; 12662 if (!o->IsString()) return false;
12654 String* other = String::cast(o); 12663 String* other = String::cast(o);
12655 if (other->length() != 2) return false; 12664 if (other->length() != 2) return false;
12656 if (other->Get(0) != c1_) return false; 12665 if (other->Get(0) != c1_) return false;
12657 return other->Get(1) == c2_; 12666 return other->Get(1) == c2_;
12658 } 12667 }
12659 12668
12660 uint32_t Hash() { return hash_; } 12669 uint32_t Hash() { return hash_; }
12661 uint32_t HashForObject(Object* key) { 12670 uint32_t HashForObject(Object* key) {
12662 if (!key->IsString()) return 0; 12671 if (!key->IsString()) return 0;
12663 return String::cast(key)->Hash(); 12672 return String::cast(key)->Hash();
12664 } 12673 }
12665 12674
12666 Object* AsObject() { 12675 Object* AsObject() {
12667 // The TwoCharHashTableKey is only used for looking in the symbol 12676 // The TwoCharHashTableKey is only used for looking in the symbol
12668 // table, not for adding to it. 12677 // table, not for adding to it.
12669 UNREACHABLE(); 12678 UNREACHABLE();
12670 return NULL; 12679 return NULL;
12671 } 12680 }
12672 12681
12673 private: 12682 private:
12674 uint32_t c1_; 12683 uint16_t c1_;
12675 uint32_t c2_; 12684 uint16_t c2_;
12676 uint32_t hash_; 12685 uint32_t hash_;
12677 }; 12686 };
12678 12687
12679 12688
12680 bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) { 12689 bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
12681 SymbolKey key(string); 12690 SymbolKey key(string);
12682 int entry = FindEntry(&key); 12691 int entry = FindEntry(&key);
12683 if (entry == kNotFound) { 12692 if (entry == kNotFound) {
12684 return false; 12693 return false;
12685 } else { 12694 } else {
12686 String* result = String::cast(KeyAt(entry)); 12695 String* result = String::cast(KeyAt(entry));
12687 ASSERT(StringShape(result).IsSymbol()); 12696 ASSERT(StringShape(result).IsSymbol());
12688 *symbol = result; 12697 *symbol = result;
12689 return true; 12698 return true;
12690 } 12699 }
12691 } 12700 }
12692 12701
12693 12702
12694 bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1, 12703 bool SymbolTable::LookupTwoCharsSymbolIfExists(uint16_t c1,
12695 uint32_t c2, 12704 uint16_t c2,
12696 String** symbol) { 12705 String** symbol) {
12697 TwoCharHashTableKey key(c1, c2, GetHeap()->HashSeed()); 12706 TwoCharHashTableKey key(c1, c2, GetHeap()->HashSeed());
12698 int entry = FindEntry(&key); 12707 int entry = FindEntry(&key);
12699 if (entry == kNotFound) { 12708 if (entry == kNotFound) {
12700 return false; 12709 return false;
12701 } else { 12710 } else {
12702 String* result = String::cast(KeyAt(entry)); 12711 String* result = String::cast(KeyAt(entry));
12703 ASSERT(StringShape(result).IsSymbol()); 12712 ASSERT(StringShape(result).IsSymbol());
12704 *symbol = result; 12713 *symbol = result;
12705 return true; 12714 return true;
(...skipping 1321 matching lines...) Expand 10 before | Expand all | Expand 10 after
14027 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 14036 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
14028 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 14037 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
14029 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 14038 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
14030 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 14039 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
14031 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 14040 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
14032 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 14041 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
14033 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 14042 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
14034 } 14043 }
14035 14044
14036 } } // namespace v8::internal 14045 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698