Commit b75da76a authored by kasperl@chromium.org's avatar kasperl@chromium.org

Apply Daniel's patch for array index strings.

Review URL: http://codereview.chromium.org/7869

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@560 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 8e675da3
...@@ -10,3 +10,4 @@ Rafal Krypa <rafal@krypa.net> ...@@ -10,3 +10,4 @@ Rafal Krypa <rafal@krypa.net>
Jay Freeman <saurik@saurik.com> Jay Freeman <saurik@saurik.com>
Daniel James <dnljms@gmail.com> Daniel James <dnljms@gmail.com>
Paolo Giarrusso <p.giarrusso@gmail.com> Paolo Giarrusso <p.giarrusso@gmail.com>
Daniel Andersson <kodandersson@gmail.com>
...@@ -212,7 +212,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { ...@@ -212,7 +212,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
// -- esp[4] : name // -- esp[4] : name
// -- esp[8] : receiver // -- esp[8] : receiver
// ----------------------------------- // -----------------------------------
Label slow, fast, check_string; Label slow, fast, check_string, index_int, index_string;
__ mov(eax, (Operand(esp, kPointerSize))); __ mov(eax, (Operand(esp, kPointerSize)));
__ mov(ecx, (Operand(esp, 2 * kPointerSize))); __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
...@@ -234,6 +234,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { ...@@ -234,6 +234,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ j(not_zero, &check_string, not_taken); __ j(not_zero, &check_string, not_taken);
__ sar(eax, kSmiTagSize); __ sar(eax, kSmiTagSize);
// Get the elements array of the object. // Get the elements array of the object.
__ bind(&index_int);
__ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset)); __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
// Check that the object is in fast mode (not dictionary). // Check that the object is in fast mode (not dictionary).
__ cmp(FieldOperand(ecx, HeapObject::kMapOffset), __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
...@@ -248,18 +249,28 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { ...@@ -248,18 +249,28 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kKeyedGetProperty));
// Check if the key is a symbol that is not an array index. // Check if the key is a symbol that is not an array index.
__ bind(&check_string); __ bind(&check_string);
__ mov(ebx, FieldOperand(eax, String::kLengthOffset));
__ test(ebx, Immediate(String::kIsArrayIndexMask));
__ j(not_zero, &index_string, not_taken);
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
__ test(ebx, Immediate(kIsSymbolMask)); __ test(ebx, Immediate(kIsSymbolMask));
__ j(zero, &slow, not_taken);
__ mov(ebx, FieldOperand(eax, String::kLengthOffset));
__ test(ebx, Immediate(String::kIsArrayIndexMask));
__ j(not_zero, &slow, not_taken); __ j(not_zero, &slow, not_taken);
// Probe the dictionary leaving result in ecx. // Probe the dictionary leaving result in ecx.
GenerateDictionaryLoad(masm, &slow, ebx, ecx, edx, eax); GenerateDictionaryLoad(masm, &slow, ebx, ecx, edx, eax);
__ mov(eax, Operand(ecx)); __ mov(eax, Operand(ecx));
__ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
__ ret(0); __ ret(0);
// Array index string: If short enough use cache in length/hash field (ebx).
__ bind(&index_string);
const int kLengthFieldLimit =
(String::kMaxCachedArrayIndexLength + 1) << String::kShortLengthShift;
__ cmp(ebx, kLengthFieldLimit);
__ j(above_equal, &slow);
__ mov(eax, Operand(ebx));
__ and_(eax, (1 << String::kShortLengthShift) - 1);
__ shr(eax, String::kLongLengthShift);
__ jmp(&index_int);
// Fast case: Do the load. // Fast case: Do the load.
__ bind(&fast); __ bind(&fast);
__ mov(eax, Operand(ecx, eax, times_4, Array::kHeaderSize - kHeapObjectTag)); __ mov(eax, Operand(ecx, eax, times_4, Array::kHeaderSize - kHeapObjectTag));
......
...@@ -2176,7 +2176,7 @@ uint32_t String::Hash() { ...@@ -2176,7 +2176,7 @@ uint32_t String::Hash() {
// Fast case: has hash code already been computed? // Fast case: has hash code already been computed?
uint32_t field = length_field(); uint32_t field = length_field();
if (field & kHashComputedMask) return field >> kHashShift; if (field & kHashComputedMask) return field >> kHashShift;
// Slow case: compute hash code and set it.. // Slow case: compute hash code and set it.
return ComputeAndSetHash(); return ComputeAndSetHash();
} }
...@@ -2196,11 +2196,12 @@ bool StringHasher::has_trivial_hash() { ...@@ -2196,11 +2196,12 @@ bool StringHasher::has_trivial_hash() {
void StringHasher::AddCharacter(uc32 c) { void StringHasher::AddCharacter(uc32 c) {
// Note: the Jenkins one-at-a-time hash function // Use the Jenkins one-at-a-time hash function to update the hash
// for the given character.
raw_running_hash_ += c; raw_running_hash_ += c;
raw_running_hash_ += (raw_running_hash_ << 10); raw_running_hash_ += (raw_running_hash_ << 10);
raw_running_hash_ ^= (raw_running_hash_ >> 6); raw_running_hash_ ^= (raw_running_hash_ >> 6);
// Incremental array index computation // Incremental array index computation.
if (is_array_index_) { if (is_array_index_) {
if (c < '0' || c > '9') { if (c < '0' || c > '9') {
is_array_index_ = false; is_array_index_ = false;
......
...@@ -3903,7 +3903,7 @@ uint32_t String::ComputeAndSetHash() { ...@@ -3903,7 +3903,7 @@ uint32_t String::ComputeAndSetHash() {
bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer, bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer,
uint32_t* index, uint32_t* index,
int length) { int length) {
if (length == 0) return false; if (length == 0 || length > kMaxArrayIndexSize) return false;
uc32 ch = buffer->GetNext(); uc32 ch = buffer->GetNext();
// If the string begins with a '0' character, it must only consist // If the string begins with a '0' character, it must only consist
...@@ -3931,8 +3931,16 @@ bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer, ...@@ -3931,8 +3931,16 @@ bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer,
bool String::SlowAsArrayIndex(uint32_t* index) { bool String::SlowAsArrayIndex(uint32_t* index) {
StringInputBuffer buffer(this); if (length() <= kMaxCachedArrayIndexLength) {
return ComputeArrayIndex(&buffer, index, length()); Hash(); // force computation of hash code
uint32_t field = length_field();
if ((field & kIsArrayIndexMask) == 0) return false;
*index = (field & ((1 << kShortLengthShift) - 1)) >> kLongLengthShift;
return true;
} else {
StringInputBuffer buffer(this);
return ComputeArrayIndex(&buffer, index, length());
}
} }
...@@ -3969,18 +3977,21 @@ uint32_t String::ComputeLengthAndHashField(unibrow::CharacterStream* buffer, ...@@ -3969,18 +3977,21 @@ uint32_t String::ComputeLengthAndHashField(unibrow::CharacterStream* buffer,
// Very long strings have a trivial hash that doesn't inspect the // Very long strings have a trivial hash that doesn't inspect the
// string contents. // string contents.
if (hasher.has_trivial_hash()) if (hasher.has_trivial_hash()) {
return hasher.GetHashField(); return hasher.GetHashField();
}
// Do the iterative array index computation as long as there is a // Do the iterative array index computation as long as there is a
// chance this is an array index. // chance this is an array index.
while (buffer->has_more() && hasher.is_array_index()) while (buffer->has_more() && hasher.is_array_index()) {
hasher.AddCharacter(buffer->GetNext()); hasher.AddCharacter(buffer->GetNext());
}
// Process the remaining characters without updating the array // Process the remaining characters without updating the array
// index. // index.
while (buffer->has_more()) while (buffer->has_more()) {
hasher.AddCharacterNoIndex(buffer->GetNext()); hasher.AddCharacterNoIndex(buffer->GetNext());
}
return hasher.GetHashField(); return hasher.GetHashField();
} }
......
...@@ -3099,7 +3099,7 @@ class String: public HeapObject { ...@@ -3099,7 +3099,7 @@ class String: public HeapObject {
// Max ascii char code. // Max ascii char code.
static const int kMaxAsciiCharCode = unibrow::Utf8::kMaxOneByteChar; static const int kMaxAsciiCharCode = unibrow::Utf8::kMaxOneByteChar;
// Minimum lenth for a cons or sliced string. // Minimum length for a cons or sliced string.
static const int kMinNonFlatLength = 13; static const int kMinNonFlatLength = 13;
// Mask constant for checking if a string has a computed hash code // Mask constant for checking if a string has a computed hash code
...@@ -3111,6 +3111,10 @@ class String: public HeapObject { ...@@ -3111,6 +3111,10 @@ class String: public HeapObject {
static const int kIsArrayIndexMask = 1 << 1; static const int kIsArrayIndexMask = 1 << 1;
static const int kNofLengthBitFields = 2; static const int kNofLengthBitFields = 2;
// Array index strings this short can keep their index in the hash
// field.
static const int kMaxCachedArrayIndexLength = 6;
// Shift constants for retriving length and hash code from // Shift constants for retriving length and hash code from
// length/hash field. // length/hash field.
static const int kHashShift = kNofLengthBitFields; static const int kHashShift = kNofLengthBitFields;
...@@ -3118,7 +3122,6 @@ class String: public HeapObject { ...@@ -3118,7 +3122,6 @@ class String: public HeapObject {
static const int kMediumLengthShift = 2 * kBitsPerByte; static const int kMediumLengthShift = 2 * kBitsPerByte;
static const int kLongLengthShift = kHashShift; static const int kLongLengthShift = kHashShift;
// Limit for truncation in short printing. // Limit for truncation in short printing.
static const int kMaxShortPrintLength = 1024; static const int kMaxShortPrintLength = 1024;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment