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>
Jay Freeman <saurik@saurik.com>
Daniel James <dnljms@gmail.com>
Paolo Giarrusso <p.giarrusso@gmail.com>
Daniel Andersson <kodandersson@gmail.com>
......@@ -212,7 +212,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
// -- esp[4] : name
// -- esp[8] : receiver
// -----------------------------------
Label slow, fast, check_string;
Label slow, fast, check_string, index_int, index_string;
__ mov(eax, (Operand(esp, kPointerSize)));
__ mov(ecx, (Operand(esp, 2 * kPointerSize)));
......@@ -234,6 +234,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ j(not_zero, &check_string, not_taken);
__ sar(eax, kSmiTagSize);
// Get the elements array of the object.
__ bind(&index_int);
__ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
// Check that the object is in fast mode (not dictionary).
__ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
......@@ -248,18 +249,28 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kKeyedGetProperty));
// Check if the key is a symbol that is not an array index.
__ 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));
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
__ 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);
// Probe the dictionary leaving result in ecx.
GenerateDictionaryLoad(masm, &slow, ebx, ecx, edx, eax);
__ mov(eax, Operand(ecx));
__ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
__ 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.
__ bind(&fast);
__ mov(eax, Operand(ecx, eax, times_4, Array::kHeaderSize - kHeapObjectTag));
......
......@@ -2176,7 +2176,7 @@ uint32_t String::Hash() {
// Fast case: has hash code already been computed?
uint32_t field = length_field();
if (field & kHashComputedMask) return field >> kHashShift;
// Slow case: compute hash code and set it..
// Slow case: compute hash code and set it.
return ComputeAndSetHash();
}
......@@ -2196,11 +2196,12 @@ bool StringHasher::has_trivial_hash() {
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_ += (raw_running_hash_ << 10);
raw_running_hash_ ^= (raw_running_hash_ >> 6);
// Incremental array index computation
// Incremental array index computation.
if (is_array_index_) {
if (c < '0' || c > '9') {
is_array_index_ = false;
......
......@@ -3903,7 +3903,7 @@ uint32_t String::ComputeAndSetHash() {
bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer,
uint32_t* index,
int length) {
if (length == 0) return false;
if (length == 0 || length > kMaxArrayIndexSize) return false;
uc32 ch = buffer->GetNext();
// If the string begins with a '0' character, it must only consist
......@@ -3931,8 +3931,16 @@ bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer,
bool String::SlowAsArrayIndex(uint32_t* index) {
StringInputBuffer buffer(this);
return ComputeArrayIndex(&buffer, index, length());
if (length() <= kMaxCachedArrayIndexLength) {
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,
// Very long strings have a trivial hash that doesn't inspect the
// string contents.
if (hasher.has_trivial_hash())
if (hasher.has_trivial_hash()) {
return hasher.GetHashField();
}
// Do the iterative array index computation as long as there is a
// 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());
}
// Process the remaining characters without updating the array
// index.
while (buffer->has_more())
while (buffer->has_more()) {
hasher.AddCharacterNoIndex(buffer->GetNext());
}
return hasher.GetHashField();
}
......
......@@ -3099,7 +3099,7 @@ class String: public HeapObject {
// Max ascii char code.
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;
// Mask constant for checking if a string has a computed hash code
......@@ -3111,6 +3111,10 @@ class String: public HeapObject {
static const int kIsArrayIndexMask = 1 << 1;
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
// length/hash field.
static const int kHashShift = kNofLengthBitFields;
......@@ -3118,7 +3122,6 @@ class String: public HeapObject {
static const int kMediumLengthShift = 2 * kBitsPerByte;
static const int kLongLengthShift = kHashShift;
// Limit for truncation in short printing.
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