| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #include "accessors.h" | 7 #include "accessors.h" |
| 8 #include "allocation-site-scopes.h" | 8 #include "allocation-site-scopes.h" |
| 9 #include "api.h" | 9 #include "api.h" |
| 10 #include "arguments.h" | 10 #include "arguments.h" |
| (...skipping 8835 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8846 ASSERT(content.IsFlat()); | 8846 ASSERT(content.IsFlat()); |
| 8847 is_ascii_ = content.IsAscii(); | 8847 is_ascii_ = content.IsAscii(); |
| 8848 if (is_ascii_) { | 8848 if (is_ascii_) { |
| 8849 start_ = content.ToOneByteVector().start(); | 8849 start_ = content.ToOneByteVector().start(); |
| 8850 } else { | 8850 } else { |
| 8851 start_ = content.ToUC16Vector().start(); | 8851 start_ = content.ToUC16Vector().start(); |
| 8852 } | 8852 } |
| 8853 } | 8853 } |
| 8854 | 8854 |
| 8855 | 8855 |
| 8856 String* ConsStringIteratorOp::Operate(String* string, | 8856 void ConsStringIteratorOp::Initialize(ConsString* cons_string, int offset) { |
| 8857 unsigned* offset_out, | 8857 ASSERT(cons_string != NULL); |
| 8858 int32_t* type_out, | |
| 8859 unsigned* length_out) { | |
| 8860 ASSERT(string->IsConsString()); | |
| 8861 ConsString* cons_string = ConsString::cast(string); | |
| 8862 // Set up search data. | |
| 8863 root_ = cons_string; | 8858 root_ = cons_string; |
| 8864 consumed_ = *offset_out; | 8859 consumed_ = offset; |
| 8865 // Now search. | 8860 // Force stack blown condition to trigger restart. |
| 8866 return Search(offset_out, type_out, length_out); | 8861 depth_ = 1; |
| 8862 maximum_depth_ = kStackSize + depth_; |
| 8863 ASSERT(StackBlown()); |
| 8867 } | 8864 } |
| 8868 | 8865 |
| 8869 | 8866 |
| 8870 String* ConsStringIteratorOp::Search(unsigned* offset_out, | 8867 String* ConsStringIteratorOp::Continue(int* offset_out) { |
| 8871 int32_t* type_out, | 8868 ASSERT(depth_ != 0); |
| 8872 unsigned* length_out) { | 8869 ASSERT_EQ(0, *offset_out); |
| 8870 bool blew_stack = StackBlown(); |
| 8871 String* string = NULL; |
| 8872 // Get the next leaf if there is one. |
| 8873 if (!blew_stack) string = NextLeaf(&blew_stack); |
| 8874 // Restart search from root. |
| 8875 if (blew_stack) { |
| 8876 ASSERT(string == NULL); |
| 8877 string = Search(offset_out); |
| 8878 } |
| 8879 // Ensure future calls return null immediately. |
| 8880 if (string == NULL) Reset(NULL); |
| 8881 return string; |
| 8882 } |
| 8883 |
| 8884 |
| 8885 String* ConsStringIteratorOp::Search(int* offset_out) { |
| 8873 ConsString* cons_string = root_; | 8886 ConsString* cons_string = root_; |
| 8874 // Reset the stack, pushing the root string. | 8887 // Reset the stack, pushing the root string. |
| 8875 depth_ = 1; | 8888 depth_ = 1; |
| 8876 maximum_depth_ = 1; | 8889 maximum_depth_ = 1; |
| 8877 frames_[0] = cons_string; | 8890 frames_[0] = cons_string; |
| 8878 const unsigned consumed = consumed_; | 8891 const int consumed = consumed_; |
| 8879 unsigned offset = 0; | 8892 int offset = 0; |
| 8880 while (true) { | 8893 while (true) { |
| 8881 // Loop until the string is found which contains the target offset. | 8894 // Loop until the string is found which contains the target offset. |
| 8882 String* string = cons_string->first(); | 8895 String* string = cons_string->first(); |
| 8883 unsigned length = string->length(); | 8896 int length = string->length(); |
| 8884 int32_t type; | 8897 int32_t type; |
| 8885 if (consumed < offset + length) { | 8898 if (consumed < offset + length) { |
| 8886 // Target offset is in the left branch. | 8899 // Target offset is in the left branch. |
| 8887 // Keep going if we're still in a ConString. | 8900 // Keep going if we're still in a ConString. |
| 8888 type = string->map()->instance_type(); | 8901 type = string->map()->instance_type(); |
| 8889 if ((type & kStringRepresentationMask) == kConsStringTag) { | 8902 if ((type & kStringRepresentationMask) == kConsStringTag) { |
| 8890 cons_string = ConsString::cast(string); | 8903 cons_string = ConsString::cast(string); |
| 8891 PushLeft(cons_string); | 8904 PushLeft(cons_string); |
| 8892 continue; | 8905 continue; |
| 8893 } | 8906 } |
| 8894 // Tell the stack we're done decending. | 8907 // Tell the stack we're done descending. |
| 8895 AdjustMaximumDepth(); | 8908 AdjustMaximumDepth(); |
| 8896 } else { | 8909 } else { |
| 8897 // Descend right. | 8910 // Descend right. |
| 8898 // Update progress through the string. | 8911 // Update progress through the string. |
| 8899 offset += length; | 8912 offset += length; |
| 8900 // Keep going if we're still in a ConString. | 8913 // Keep going if we're still in a ConString. |
| 8901 string = cons_string->second(); | 8914 string = cons_string->second(); |
| 8902 type = string->map()->instance_type(); | 8915 type = string->map()->instance_type(); |
| 8903 if ((type & kStringRepresentationMask) == kConsStringTag) { | 8916 if ((type & kStringRepresentationMask) == kConsStringTag) { |
| 8904 cons_string = ConsString::cast(string); | 8917 cons_string = ConsString::cast(string); |
| 8905 PushRight(cons_string); | 8918 PushRight(cons_string); |
| 8906 // TODO(dcarney) Add back root optimization. | |
| 8907 continue; | 8919 continue; |
| 8908 } | 8920 } |
| 8909 // Need this to be updated for the current string. | 8921 // Need this to be updated for the current string. |
| 8910 length = string->length(); | 8922 length = string->length(); |
| 8911 // Account for the possibility of an empty right leaf. | 8923 // Account for the possibility of an empty right leaf. |
| 8912 // This happens only if we have asked for an offset outside the string. | 8924 // This happens only if we have asked for an offset outside the string. |
| 8913 if (length == 0) { | 8925 if (length == 0) { |
| 8914 // Reset depth so future operations will return null immediately. | 8926 // Reset so future operations will return null immediately. |
| 8915 Reset(); | 8927 Reset(NULL); |
| 8916 return NULL; | 8928 return NULL; |
| 8917 } | 8929 } |
| 8918 // Tell the stack we're done decending. | 8930 // Tell the stack we're done descending. |
| 8919 AdjustMaximumDepth(); | 8931 AdjustMaximumDepth(); |
| 8920 // Pop stack so next iteration is in correct place. | 8932 // Pop stack so next iteration is in correct place. |
| 8921 Pop(); | 8933 Pop(); |
| 8922 } | 8934 } |
| 8923 ASSERT(length != 0); | 8935 ASSERT(length != 0); |
| 8924 // Adjust return values and exit. | 8936 // Adjust return values and exit. |
| 8925 consumed_ = offset + length; | 8937 consumed_ = offset + length; |
| 8926 *offset_out = consumed - offset; | 8938 *offset_out = consumed - offset; |
| 8927 *type_out = type; | |
| 8928 *length_out = length; | |
| 8929 return string; | 8939 return string; |
| 8930 } | 8940 } |
| 8931 UNREACHABLE(); | 8941 UNREACHABLE(); |
| 8932 return NULL; | 8942 return NULL; |
| 8933 } | 8943 } |
| 8934 | 8944 |
| 8935 | 8945 |
| 8936 String* ConsStringIteratorOp::NextLeaf(bool* blew_stack, | 8946 String* ConsStringIteratorOp::NextLeaf(bool* blew_stack) { |
| 8937 int32_t* type_out, | |
| 8938 unsigned* length_out) { | |
| 8939 while (true) { | 8947 while (true) { |
| 8940 // Tree traversal complete. | 8948 // Tree traversal complete. |
| 8941 if (depth_ == 0) { | 8949 if (depth_ == 0) { |
| 8942 *blew_stack = false; | 8950 *blew_stack = false; |
| 8943 return NULL; | 8951 return NULL; |
| 8944 } | 8952 } |
| 8945 // We've lost track of higher nodes. | 8953 // We've lost track of higher nodes. |
| 8946 if (maximum_depth_ - depth_ == kStackSize) { | 8954 if (StackBlown()) { |
| 8947 *blew_stack = true; | 8955 *blew_stack = true; |
| 8948 return NULL; | 8956 return NULL; |
| 8949 } | 8957 } |
| 8950 // Go right. | 8958 // Go right. |
| 8951 ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)]; | 8959 ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)]; |
| 8952 String* string = cons_string->second(); | 8960 String* string = cons_string->second(); |
| 8953 int32_t type = string->map()->instance_type(); | 8961 int32_t type = string->map()->instance_type(); |
| 8954 if ((type & kStringRepresentationMask) != kConsStringTag) { | 8962 if ((type & kStringRepresentationMask) != kConsStringTag) { |
| 8955 // Pop stack so next iteration is in correct place. | 8963 // Pop stack so next iteration is in correct place. |
| 8956 Pop(); | 8964 Pop(); |
| 8957 unsigned length = static_cast<unsigned>(string->length()); | 8965 int length = string->length(); |
| 8958 // Could be a flattened ConsString. | 8966 // Could be a flattened ConsString. |
| 8959 if (length == 0) continue; | 8967 if (length == 0) continue; |
| 8960 *length_out = length; | |
| 8961 *type_out = type; | |
| 8962 consumed_ += length; | 8968 consumed_ += length; |
| 8963 return string; | 8969 return string; |
| 8964 } | 8970 } |
| 8965 cons_string = ConsString::cast(string); | 8971 cons_string = ConsString::cast(string); |
| 8966 // TODO(dcarney) Add back root optimization. | |
| 8967 PushRight(cons_string); | 8972 PushRight(cons_string); |
| 8968 // Need to traverse all the way left. | 8973 // Need to traverse all the way left. |
| 8969 while (true) { | 8974 while (true) { |
| 8970 // Continue left. | 8975 // Continue left. |
| 8971 string = cons_string->first(); | 8976 string = cons_string->first(); |
| 8972 type = string->map()->instance_type(); | 8977 type = string->map()->instance_type(); |
| 8973 if ((type & kStringRepresentationMask) != kConsStringTag) { | 8978 if ((type & kStringRepresentationMask) != kConsStringTag) { |
| 8974 AdjustMaximumDepth(); | 8979 AdjustMaximumDepth(); |
| 8975 unsigned length = static_cast<unsigned>(string->length()); | 8980 int length = string->length(); |
| 8976 ASSERT(length != 0); | 8981 ASSERT(length != 0); |
| 8977 *length_out = length; | |
| 8978 *type_out = type; | |
| 8979 consumed_ += length; | 8982 consumed_ += length; |
| 8980 return string; | 8983 return string; |
| 8981 } | 8984 } |
| 8982 cons_string = ConsString::cast(string); | 8985 cons_string = ConsString::cast(string); |
| 8983 PushLeft(cons_string); | 8986 PushLeft(cons_string); |
| 8984 } | 8987 } |
| 8985 } | 8988 } |
| 8986 UNREACHABLE(); | 8989 UNREACHABLE(); |
| 8987 return NULL; | 8990 return NULL; |
| 8988 } | 8991 } |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9243 } | 9246 } |
| 9244 }; | 9247 }; |
| 9245 | 9248 |
| 9246 | 9249 |
| 9247 class StringComparator { | 9250 class StringComparator { |
| 9248 class State { | 9251 class State { |
| 9249 public: | 9252 public: |
| 9250 explicit inline State(ConsStringIteratorOp* op) | 9253 explicit inline State(ConsStringIteratorOp* op) |
| 9251 : op_(op), is_one_byte_(true), length_(0), buffer8_(NULL) {} | 9254 : op_(op), is_one_byte_(true), length_(0), buffer8_(NULL) {} |
| 9252 | 9255 |
| 9253 inline void Init(String* string, unsigned len) { | 9256 inline void Init(String* string) { |
| 9254 op_->Reset(); | 9257 ConsString* cons_string = String::VisitFlat(this, string); |
| 9255 int32_t type = string->map()->instance_type(); | 9258 op_->Reset(cons_string); |
| 9256 String::Visit(string, 0, *this, *op_, type, len); | 9259 if (cons_string != NULL) { |
| 9260 int offset; |
| 9261 string = op_->Next(&offset); |
| 9262 String::VisitFlat(this, string, offset); |
| 9263 } |
| 9257 } | 9264 } |
| 9258 | 9265 |
| 9259 inline void VisitOneByteString(const uint8_t* chars, unsigned length) { | 9266 inline void VisitOneByteString(const uint8_t* chars, int length) { |
| 9260 is_one_byte_ = true; | 9267 is_one_byte_ = true; |
| 9261 buffer8_ = chars; | 9268 buffer8_ = chars; |
| 9262 length_ = length; | 9269 length_ = length; |
| 9263 } | 9270 } |
| 9264 | 9271 |
| 9265 inline void VisitTwoByteString(const uint16_t* chars, unsigned length) { | 9272 inline void VisitTwoByteString(const uint16_t* chars, int length) { |
| 9266 is_one_byte_ = false; | 9273 is_one_byte_ = false; |
| 9267 buffer16_ = chars; | 9274 buffer16_ = chars; |
| 9268 length_ = length; | 9275 length_ = length; |
| 9269 } | 9276 } |
| 9270 | 9277 |
| 9271 void Advance(unsigned consumed) { | 9278 void Advance(int consumed) { |
| 9272 ASSERT(consumed <= length_); | 9279 ASSERT(consumed <= length_); |
| 9273 // Still in buffer. | 9280 // Still in buffer. |
| 9274 if (length_ != consumed) { | 9281 if (length_ != consumed) { |
| 9275 if (is_one_byte_) { | 9282 if (is_one_byte_) { |
| 9276 buffer8_ += consumed; | 9283 buffer8_ += consumed; |
| 9277 } else { | 9284 } else { |
| 9278 buffer16_ += consumed; | 9285 buffer16_ += consumed; |
| 9279 } | 9286 } |
| 9280 length_ -= consumed; | 9287 length_ -= consumed; |
| 9281 return; | 9288 return; |
| 9282 } | 9289 } |
| 9283 // Advance state. | 9290 // Advance state. |
| 9284 ASSERT(op_->HasMore()); | 9291 int offset; |
| 9285 int32_t type = 0; | 9292 String* next = op_->Next(&offset); |
| 9286 unsigned length = 0; | 9293 ASSERT_EQ(0, offset); |
| 9287 String* next = op_->ContinueOperation(&type, &length); | |
| 9288 ASSERT(next != NULL); | 9294 ASSERT(next != NULL); |
| 9289 ConsStringNullOp null_op; | 9295 String::VisitFlat(this, next); |
| 9290 String::Visit(next, 0, *this, null_op, type, length); | |
| 9291 } | 9296 } |
| 9292 | 9297 |
| 9293 ConsStringIteratorOp* const op_; | 9298 ConsStringIteratorOp* const op_; |
| 9294 bool is_one_byte_; | 9299 bool is_one_byte_; |
| 9295 unsigned length_; | 9300 int length_; |
| 9296 union { | 9301 union { |
| 9297 const uint8_t* buffer8_; | 9302 const uint8_t* buffer8_; |
| 9298 const uint16_t* buffer16_; | 9303 const uint16_t* buffer16_; |
| 9299 }; | 9304 }; |
| 9300 | 9305 |
| 9301 private: | 9306 private: |
| 9302 DISALLOW_IMPLICIT_CONSTRUCTORS(State); | 9307 DISALLOW_IMPLICIT_CONSTRUCTORS(State); |
| 9303 }; | 9308 }; |
| 9304 | 9309 |
| 9305 public: | 9310 public: |
| 9306 inline StringComparator(ConsStringIteratorOp* op_1, | 9311 inline StringComparator(ConsStringIteratorOp* op_1, |
| 9307 ConsStringIteratorOp* op_2) | 9312 ConsStringIteratorOp* op_2) |
| 9308 : state_1_(op_1), | 9313 : state_1_(op_1), |
| 9309 state_2_(op_2) { | 9314 state_2_(op_2) { |
| 9310 } | 9315 } |
| 9311 | 9316 |
| 9312 template<typename Chars1, typename Chars2> | 9317 template<typename Chars1, typename Chars2> |
| 9313 static inline bool Equals(State* state_1, State* state_2, unsigned to_check) { | 9318 static inline bool Equals(State* state_1, State* state_2, int to_check) { |
| 9314 const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_); | 9319 const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_); |
| 9315 const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_); | 9320 const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_); |
| 9316 return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check); | 9321 return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check); |
| 9317 } | 9322 } |
| 9318 | 9323 |
| 9319 bool Equals(unsigned length, String* string_1, String* string_2) { | 9324 bool Equals(String* string_1, String* string_2) { |
| 9320 ASSERT(length != 0); | 9325 int length = string_1->length(); |
| 9321 state_1_.Init(string_1, length); | 9326 state_1_.Init(string_1); |
| 9322 state_2_.Init(string_2, length); | 9327 state_2_.Init(string_2); |
| 9323 while (true) { | 9328 while (true) { |
| 9324 unsigned to_check = Min(state_1_.length_, state_2_.length_); | 9329 int to_check = Min(state_1_.length_, state_2_.length_); |
| 9325 ASSERT(to_check > 0 && to_check <= length); | 9330 ASSERT(to_check > 0 && to_check <= length); |
| 9326 bool is_equal; | 9331 bool is_equal; |
| 9327 if (state_1_.is_one_byte_) { | 9332 if (state_1_.is_one_byte_) { |
| 9328 if (state_2_.is_one_byte_) { | 9333 if (state_2_.is_one_byte_) { |
| 9329 is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check); | 9334 is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check); |
| 9330 } else { | 9335 } else { |
| 9331 is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check); | 9336 is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check); |
| 9332 } | 9337 } |
| 9333 } else { | 9338 } else { |
| 9334 if (state_2_.is_one_byte_) { | 9339 if (state_2_.is_one_byte_) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9378 } | 9383 } |
| 9379 } | 9384 } |
| 9380 #endif | 9385 #endif |
| 9381 if (Hash() != other->Hash()) return false; | 9386 if (Hash() != other->Hash()) return false; |
| 9382 } | 9387 } |
| 9383 | 9388 |
| 9384 // We know the strings are both non-empty. Compare the first chars | 9389 // We know the strings are both non-empty. Compare the first chars |
| 9385 // before we try to flatten the strings. | 9390 // before we try to flatten the strings. |
| 9386 if (this->Get(0) != other->Get(0)) return false; | 9391 if (this->Get(0) != other->Get(0)) return false; |
| 9387 | 9392 |
| 9388 // TODO(dcarney): Compare all types of flat strings with a Visitor. | |
| 9389 if (IsSeqOneByteString() && other->IsSeqOneByteString()) { | 9393 if (IsSeqOneByteString() && other->IsSeqOneByteString()) { |
| 9390 const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars(); | 9394 const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars(); |
| 9391 const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars(); | 9395 const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars(); |
| 9392 return CompareRawStringContents(str1, str2, len); | 9396 return CompareRawStringContents(str1, str2, len); |
| 9393 } | 9397 } |
| 9394 | 9398 |
| 9395 Isolate* isolate = GetIsolate(); | 9399 Isolate* isolate = GetIsolate(); |
| 9396 StringComparator comparator(isolate->objects_string_compare_iterator_a(), | 9400 StringComparator comparator(isolate->objects_string_compare_iterator_a(), |
| 9397 isolate->objects_string_compare_iterator_b()); | 9401 isolate->objects_string_compare_iterator_b()); |
| 9398 | 9402 |
| 9399 return comparator.Equals(static_cast<unsigned>(len), this, other); | 9403 return comparator.Equals(this, other); |
| 9400 } | 9404 } |
| 9401 | 9405 |
| 9402 | 9406 |
| 9403 bool String::SlowEquals(Handle<String> one, Handle<String> two) { | 9407 bool String::SlowEquals(Handle<String> one, Handle<String> two) { |
| 9404 // Fast check: negative check with lengths. | 9408 // Fast check: negative check with lengths. |
| 9405 int one_length = one->length(); | 9409 int one_length = one->length(); |
| 9406 if (one_length != two->length()) return false; | 9410 if (one_length != two->length()) return false; |
| 9407 if (one_length == 0) return true; | 9411 if (one_length == 0) return true; |
| 9408 | 9412 |
| 9409 // Fast check: if hash code is computed for both strings | 9413 // Fast check: if hash code is computed for both strings |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9524 for (int i = 0; i < slen; i++) { | 9528 for (int i = 0; i < slen; i++) { |
| 9525 if (Get(i) != str[i]) return false; | 9529 if (Get(i) != str[i]) return false; |
| 9526 } | 9530 } |
| 9527 return true; | 9531 return true; |
| 9528 } | 9532 } |
| 9529 | 9533 |
| 9530 | 9534 |
| 9531 class IteratingStringHasher: public StringHasher { | 9535 class IteratingStringHasher: public StringHasher { |
| 9532 public: | 9536 public: |
| 9533 static inline uint32_t Hash(String* string, uint32_t seed) { | 9537 static inline uint32_t Hash(String* string, uint32_t seed) { |
| 9534 const unsigned len = static_cast<unsigned>(string->length()); | 9538 IteratingStringHasher hasher(string->length(), seed); |
| 9535 IteratingStringHasher hasher(len, seed); | 9539 // Nothing to do. |
| 9536 if (hasher.has_trivial_hash()) { | 9540 if (hasher.has_trivial_hash()) return hasher.GetHashField(); |
| 9537 return hasher.GetHashField(); | 9541 ConsString* cons_string = String::VisitFlat(&hasher, string); |
| 9538 } | 9542 // The string was flat. |
| 9539 int32_t type = string->map()->instance_type(); | 9543 if (cons_string == NULL) return hasher.GetHashField(); |
| 9540 ConsStringNullOp null_op; | |
| 9541 String::Visit(string, 0, hasher, null_op, type, len); | |
| 9542 // Flat strings terminate immediately. | |
| 9543 if (hasher.consumed_ == len) { | |
| 9544 ASSERT(!string->IsConsString()); | |
| 9545 return hasher.GetHashField(); | |
| 9546 } | |
| 9547 ASSERT(string->IsConsString()); | |
| 9548 // This is a ConsString, iterate across it. | 9544 // This is a ConsString, iterate across it. |
| 9549 ConsStringIteratorOp op; | 9545 ConsStringIteratorOp op(cons_string); |
| 9550 unsigned offset = 0; | 9546 int offset; |
| 9551 unsigned leaf_length = len; | 9547 while (NULL != (string = op.Next(&offset))) { |
| 9552 string = op.Operate(string, &offset, &type, &leaf_length); | 9548 String::VisitFlat(&hasher, string, offset); |
| 9553 while (true) { | |
| 9554 ASSERT(hasher.consumed_ < len); | |
| 9555 String::Visit(string, 0, hasher, null_op, type, leaf_length); | |
| 9556 if (hasher.consumed_ == len) break; | |
| 9557 string = op.ContinueOperation(&type, &leaf_length); | |
| 9558 // This should be taken care of by the length check. | |
| 9559 ASSERT(string != NULL); | |
| 9560 } | 9549 } |
| 9561 return hasher.GetHashField(); | 9550 return hasher.GetHashField(); |
| 9562 } | 9551 } |
| 9563 inline void VisitOneByteString(const uint8_t* chars, unsigned length) { | 9552 inline void VisitOneByteString(const uint8_t* chars, int length) { |
| 9564 AddCharacters(chars, static_cast<int>(length)); | 9553 AddCharacters(chars, length); |
| 9565 consumed_ += length; | |
| 9566 } | 9554 } |
| 9567 inline void VisitTwoByteString(const uint16_t* chars, unsigned length) { | 9555 inline void VisitTwoByteString(const uint16_t* chars, int length) { |
| 9568 AddCharacters(chars, static_cast<int>(length)); | 9556 AddCharacters(chars, length); |
| 9569 consumed_ += length; | |
| 9570 } | 9557 } |
| 9571 | 9558 |
| 9572 private: | 9559 private: |
| 9573 inline IteratingStringHasher(int len, uint32_t seed) | 9560 inline IteratingStringHasher(int len, uint32_t seed) |
| 9574 : StringHasher(len, seed), | 9561 : StringHasher(len, seed) { |
| 9575 consumed_(0) {} | 9562 } |
| 9576 unsigned consumed_; | |
| 9577 DISALLOW_COPY_AND_ASSIGN(IteratingStringHasher); | 9563 DISALLOW_COPY_AND_ASSIGN(IteratingStringHasher); |
| 9578 }; | 9564 }; |
| 9579 | 9565 |
| 9580 | 9566 |
| 9581 uint32_t String::ComputeAndSetHash() { | 9567 uint32_t String::ComputeAndSetHash() { |
| 9582 // Should only be called if hash code has not yet been computed. | 9568 // Should only be called if hash code has not yet been computed. |
| 9583 ASSERT(!HasHashCode()); | 9569 ASSERT(!HasHashCode()); |
| 9584 | 9570 |
| 9585 // Store the hash code in the object. | 9571 // Store the hash code in the object. |
| 9586 uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed()); | 9572 uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed()); |
| (...skipping 7699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17286 #define ERROR_MESSAGES_TEXTS(C, T) T, | 17272 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 17287 static const char* error_messages_[] = { | 17273 static const char* error_messages_[] = { |
| 17288 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 17274 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 17289 }; | 17275 }; |
| 17290 #undef ERROR_MESSAGES_TEXTS | 17276 #undef ERROR_MESSAGES_TEXTS |
| 17291 return error_messages_[reason]; | 17277 return error_messages_[reason]; |
| 17292 } | 17278 } |
| 17293 | 17279 |
| 17294 | 17280 |
| 17295 } } // namespace v8::internal | 17281 } } // namespace v8::internal |
| OLD | NEW |