Author: [EMAIL PROTECTED]
Date: Wed Oct 22 23:20:57 2008
New Revision: 560
Modified:
branches/bleeding_edge/AUTHORS
branches/bleeding_edge/src/ic-ia32.cc
branches/bleeding_edge/src/objects-inl.h
branches/bleeding_edge/src/objects.cc
branches/bleeding_edge/src/objects.h
Log:
Apply Daniel's patch for array index strings.
Review URL: http://codereview.chromium.org/7869
Modified: branches/bleeding_edge/AUTHORS
==============================================================================
--- branches/bleeding_edge/AUTHORS (original)
+++ branches/bleeding_edge/AUTHORS Wed Oct 22 23:20:57 2008
@@ -10,3 +10,4 @@
Jay Freeman <[EMAIL PROTECTED]>
Daniel James <[EMAIL PROTECTED]>
Paolo Giarrusso <[EMAIL PROTECTED]>
+Daniel Andersson <[EMAIL PROTECTED]>
Modified: branches/bleeding_edge/src/ic-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/ic-ia32.cc (original)
+++ branches/bleeding_edge/src/ic-ia32.cc Wed Oct 22 23:20:57 2008
@@ -212,7 +212,7 @@
// -- 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 @@
__ 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 @@
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));
Modified: branches/bleeding_edge/src/objects-inl.h
==============================================================================
--- branches/bleeding_edge/src/objects-inl.h (original)
+++ branches/bleeding_edge/src/objects-inl.h Wed Oct 22 23:20:57 2008
@@ -2176,7 +2176,7 @@
// 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 @@
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;
Modified: branches/bleeding_edge/src/objects.cc
==============================================================================
--- branches/bleeding_edge/src/objects.cc (original)
+++ branches/bleeding_edge/src/objects.cc Wed Oct 22 23:20:57 2008
@@ -3903,7 +3903,7 @@
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::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 @@
// 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();
}
Modified: branches/bleeding_edge/src/objects.h
==============================================================================
--- branches/bleeding_edge/src/objects.h (original)
+++ branches/bleeding_edge/src/objects.h Wed Oct 22 23:20:57 2008
@@ -3099,7 +3099,7 @@
// 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,13 +3111,16 @@
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;
static const int kShortLengthShift = 3 * kBitsPerByte;
static const int kMediumLengthShift = 2 * kBitsPerByte;
static const int kLongLengthShift = kHashShift;
-
// Limit for truncation in short printing.
static const int kMaxShortPrintLength = 1024;
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---