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

Side by Side Diff: src/objects.cc

Issue 6525: Calculate string hash during flattening. (Closed)
Patch Set: Created 12 years, 2 months 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
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 503 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 } 514 }
515 case kConsStringTag: { 515 case kConsStringTag: {
516 ConsString* cs = ConsString::cast(this); 516 ConsString* cs = ConsString::cast(this);
517 if (String::cast(cs->second())->length() == 0) { 517 if (String::cast(cs->second())->length() == 0) {
518 return this; 518 return this;
519 } 519 }
520 // There's little point in putting the flat string in new space if the 520 // There's little point in putting the flat string in new space if the
521 // cons string is in old space. It can never get GCed until there is 521 // cons string is in old space. It can never get GCed until there is
522 // an old space GC. 522 // an old space GC.
523 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED; 523 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED;
524 int len = length();
524 Object* object = IsAscii() ? 525 Object* object = IsAscii() ?
525 Heap::AllocateRawAsciiString(length(), tenure) : 526 Heap::AllocateRawAsciiString(len, tenure) :
526 Heap::AllocateRawTwoByteString(length(), tenure); 527 Heap::AllocateRawTwoByteString(len, tenure);
527 if (object->IsFailure()) return object; 528 if (object->IsFailure()) return object;
528 String* result = String::cast(object); 529 String* result = String::cast(object);
529 Flatten(this, result, 0, length(), 0); 530 StringHasher hasher(len);
531 Flatten(this, result, 0, len, 0, &hasher);
532 if (hasher.is_valid()) {
533 #ifdef DEBUG
534 result->ComputeAndSetHash();
535 ASSERT(result->length_field() == hasher.GetHashField());
536 #else
537 result->set_length_field(hasher.GetHashField());
538 #endif
539 Heap::LookupSymbolIfExists(result, &result);
540 }
530 cs->set_first(result); 541 cs->set_first(result);
531 cs->set_second(Heap::empty_string()); 542 cs->set_second(Heap::empty_string());
532 return this; 543 return this;
533 } 544 }
534 default: 545 default:
535 return this; 546 return this;
536 } 547 }
537 } 548 }
538 549
539 550
(...skipping 3059 matching lines...) Expand 10 before | Expand all | Expand 10 after
3599 String* buf = String::cast(buffer()); 3610 String* buf = String::cast(buffer());
3600 ASSERT(!buf->StringIsSlicedString()); 3611 ASSERT(!buf->StringIsSlicedString());
3601 if (buf->StringIsConsString()) { 3612 if (buf->StringIsConsString()) {
3602 Object* ok = buf->Flatten(); 3613 Object* ok = buf->Flatten();
3603 if (ok->IsFailure()) return ok; 3614 if (ok->IsFailure()) return ok;
3604 } 3615 }
3605 return this; 3616 return this;
3606 } 3617 }
3607 3618
3608 3619
3609 void String::Flatten(String* src, String* sink, int f, int t, int so) { 3620 void String::Flatten(String* src,
3621 String* sink,
3622 int f,
3623 int t,
3624 int so,
3625 StringHasher* hasher) {
3610 String* source = src; 3626 String* source = src;
3611 int from = f; 3627 int from = f;
3612 int to = t; 3628 int to = t;
3613 int sink_offset = so; 3629 int sink_offset = so;
3614 while (true) { 3630 while (true) {
3615 ASSERT(0 <= from && from <= to && to <= source->length()); 3631 ASSERT(0 <= from && from <= to && to <= source->length());
3616 ASSERT(0 <= sink_offset && sink_offset < sink->length()); 3632 ASSERT(0 <= sink_offset && sink_offset < sink->length());
3617 switch (source->representation_tag()) { 3633 switch (source->representation_tag()) {
3618 case kSeqStringTag: 3634 case kSeqStringTag:
3619 case kExternalStringTag: { 3635 case kExternalStringTag: {
3620 Access<StringInputBuffer> buffer(&string_input_buffer); 3636 Access<StringInputBuffer> buffer(&string_input_buffer);
3621 buffer->Reset(from, source); 3637 buffer->Reset(from, source);
3622 int j = sink_offset; 3638 int j = sink_offset;
3623 for (int i = from; i < to; i++) { 3639 for (int i = from; i < to; i++) {
3624 sink->Set(j++, buffer->GetNext()); 3640 uc32 c = buffer->GetNext();
3641 if (hasher->is_valid())
3642 hasher->AddCharacter(c);
3643 sink->Set(j++, c);
3625 } 3644 }
3626 return; 3645 return;
3627 } 3646 }
3628 case kSlicedStringTag: { 3647 case kSlicedStringTag: {
3629 SlicedString* sliced_string = SlicedString::cast(source); 3648 SlicedString* sliced_string = SlicedString::cast(source);
3630 int start = sliced_string->start(); 3649 int start = sliced_string->start();
3631 from += start; 3650 from += start;
3632 to += start; 3651 to += start;
3633 source = String::cast(sliced_string->buffer()); 3652 source = String::cast(sliced_string->buffer());
3634 } 3653 }
3635 break; 3654 break;
3636 case kConsStringTag: { 3655 case kConsStringTag: {
3637 ConsString* cons_string = ConsString::cast(source); 3656 ConsString* cons_string = ConsString::cast(source);
3638 String* first = String::cast(cons_string->first()); 3657 String* first = String::cast(cons_string->first());
3639 int boundary = first->length(); 3658 int boundary = first->length();
3640 if (to - boundary > boundary - from) { 3659 if (to - boundary > boundary - from) {
Erik Corry 2008/10/07 10:04:34 >=
3641 // Right hand side is longer. Recurse over left. 3660 // Right hand side is longer. Recurse over left.
3642 if (from < boundary) { 3661 if (from < boundary) {
3643 Flatten(first, sink, from, boundary, sink_offset); 3662 Flatten(first, sink, from, boundary, sink_offset, hasher);
3644 sink_offset += boundary - from; 3663 sink_offset += boundary - from;
3645 from = 0; 3664 from = 0;
3646 } else { 3665 } else {
3647 from -= boundary; 3666 from -= boundary;
3648 } 3667 }
3649 to -= boundary; 3668 to -= boundary;
3650 source = String::cast(cons_string->second()); 3669 source = String::cast(cons_string->second());
3651 } else { 3670 } else {
3652 // Left hand side is longer. Recurse over right. 3671 // Left hand side is longer. Recurse over right. The hasher
3672 // needs us to visit the string from left to right so doing
3673 // this invalidates that hash.
3674 hasher->invalidate();
3653 if (to > boundary) { 3675 if (to > boundary) {
3654 String* second = String::cast(cons_string->second()); 3676 String* second = String::cast(cons_string->second());
3655 Flatten(second, 3677 Flatten(second,
3656 sink, 3678 sink,
3657 0, 3679 0,
3658 to - boundary, 3680 to - boundary,
3659 sink_offset + boundary - from); 3681 sink_offset + boundary - from,
3682 hasher);
3660 to = boundary; 3683 to = boundary;
3661 } 3684 }
3662 source = first; 3685 source = first;
3663 } 3686 }
3664 } 3687 }
3665 break; 3688 break;
3666 } 3689 }
3667 } 3690 }
3668 } 3691 }
3669 3692
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
3805 StringInputBuffer buffer(this); 3828 StringInputBuffer buffer(this);
3806 return ComputeArrayIndex(&buffer, index, length()); 3829 return ComputeArrayIndex(&buffer, index, length());
3807 } 3830 }
3808 3831
3809 3832
3810 static inline uint32_t HashField(uint32_t hash, bool is_array_index) { 3833 static inline uint32_t HashField(uint32_t hash, bool is_array_index) {
3811 return (hash << String::kLongLengthShift) | (is_array_index ? 3 : 1); 3834 return (hash << String::kLongLengthShift) | (is_array_index ? 3 : 1);
3812 } 3835 }
3813 3836
3814 3837
3838 uint32_t StringHasher::GetHashField() {
3839 ASSERT(is_valid());
3840 if (length_ <= String::kMaxShortStringSize) {
3841 uint32_t payload;
3842 if (is_array_index()) {
3843 payload = v8::internal::HashField(array_index(), true);
3844 } else {
3845 payload = v8::internal::HashField(GetHash(), false);
3846 }
3847 return (payload & 0x00FFFFFF) | (length_ << String::kShortLengthShift);
3848 } else if (length_ <= String::kMaxMediumStringSize) {
3849 uint32_t payload = v8::internal::HashField(GetHash(), false);
3850 return (payload & 0x0000FFFF) | (length_ << String::kMediumLengthShift);
3851 } else {
3852 return v8::internal::HashField(length_, false);
3853 }
3854 }
3855
3856
3815 uint32_t String::ComputeLengthAndHashField(unibrow::CharacterStream* buffer, 3857 uint32_t String::ComputeLengthAndHashField(unibrow::CharacterStream* buffer,
3816 int length) { 3858 int length) {
3817 // Large string (please note large strings cannot be an array index). 3859 StringHasher hasher(length);
3818 if (length > kMaxMediumStringSize) return HashField(length, false);
3819 3860
3820 // Note: the Jenkins one-at-a-time hash function 3861 // Very long strings have a trivial hash that doesn't inspect the
3821 uint32_t hash = 0; 3862 // string contents.
3822 while (buffer->has_more()) { 3863 if (hasher.has_trivial_hash())
3823 uc32 r = buffer->GetNext(); 3864 return hasher.GetHashField();
3824 hash += r;
3825 hash += (hash << 10);
3826 hash ^= (hash >> 6);
3827 }
3828 hash += (hash << 3);
3829 hash ^= (hash >> 11);
3830 hash += (hash << 15);
3831 3865
3832 // Short string. 3866 // Do the iterative array index computation as long as there is a
3833 if (length <= kMaxShortStringSize) { 3867 // chance this is an array index.
3834 // Make hash value consistent with value returned from String::Hash. 3868 while (buffer->has_more() && hasher.is_array_index())
3835 buffer->Rewind(); 3869 hasher.AddCharacter(buffer->GetNext());
3836 uint32_t index;
3837 hash = HashField(hash, ComputeArrayIndex(buffer, &index, length));
3838 hash = (hash & 0x00FFFFFF) | (length << kShortLengthShift);
3839 return hash;
3840 }
3841 3870
3842 // Medium string (please note medium strings cannot be an array index). 3871 // Process the remaining characters without updating the array
3843 ASSERT(length <= kMaxMediumStringSize); 3872 // index.
3844 // Make hash value consistent with value returned from String::Hash. 3873 while (buffer->has_more())
3845 hash = HashField(hash, false); 3874 hasher.AddCharacterNoIndex(buffer->GetNext());
3846 hash = (hash & 0x0000FFFF) | (length << kMediumLengthShift); 3875
3847 return hash; 3876 return hasher.GetHashField();
3848 } 3877 }
3849 3878
3850 3879
3851 Object* String::Slice(int start, int end) { 3880 Object* String::Slice(int start, int end) {
3852 if (start == 0 && end == length()) return this; 3881 if (start == 0 && end == length()) return this;
3853 int representation = representation_tag(); 3882 int representation = representation_tag();
3854 if (representation == kSlicedStringTag) { 3883 if (representation == kSlicedStringTag) {
3855 // Translate slices of a SlicedString into slices of the 3884 // Translate slices of a SlicedString into slices of the
3856 // underlying string buffer. 3885 // underlying string buffer.
3857 SlicedString* str = SlicedString::cast(this); 3886 SlicedString* str = SlicedString::cast(this);
(...skipping 1765 matching lines...) Expand 10 before | Expand all | Expand 10 after
5623 // Force instantiation of EvalCache's base class 5652 // Force instantiation of EvalCache's base class
5624 template class HashTable<0, 2>; 5653 template class HashTable<0, 2>;
5625 5654
5626 5655
5627 Object* SymbolTable::LookupString(String* string, Object** s) { 5656 Object* SymbolTable::LookupString(String* string, Object** s) {
5628 SymbolKey key(string); 5657 SymbolKey key(string);
5629 return LookupKey(&key, s); 5658 return LookupKey(&key, s);
5630 } 5659 }
5631 5660
5632 5661
5662 bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
5663 SymbolKey key(string);
5664 int entry = FindEntry(&key);
5665 if (entry == -1) {
5666 return false;
5667 } else {
5668 String* result = String::cast(KeyAt(entry));
5669 ASSERT(result->is_symbol());
5670 *symbol = result;
5671 return true;
5672 }
5673 }
5674
5675
5633 Object* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) { 5676 Object* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) {
5634 Utf8SymbolKey key(str); 5677 Utf8SymbolKey key(str);
5635 return LookupKey(&key, s); 5678 return LookupKey(&key, s);
5636 } 5679 }
5637 5680
5638 5681
5639 Object* SymbolTable::LookupKey(HashTableKey* key, Object** s) { 5682 Object* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
5640 int entry = FindEntry(key); 5683 int entry = FindEntry(key);
5641 5684
5642 // Symbol already in table. 5685 // Symbol already in table.
(...skipping 773 matching lines...) Expand 10 before | Expand all | Expand 10 after
6416 // No break point. 6459 // No break point.
6417 if (break_point_objects()->IsUndefined()) return 0; 6460 if (break_point_objects()->IsUndefined()) return 0;
6418 // Single beak point. 6461 // Single beak point.
6419 if (!break_point_objects()->IsFixedArray()) return 1; 6462 if (!break_point_objects()->IsFixedArray()) return 1;
6420 // Multiple break points. 6463 // Multiple break points.
6421 return FixedArray::cast(break_point_objects())->length(); 6464 return FixedArray::cast(break_point_objects())->length();
6422 } 6465 }
6423 6466
6424 6467
6425 } } // namespace v8::internal 6468 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | src/objects-inl.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698