Apply Daniel's patch for array index strings.
authorkasperl@chromium.org <kasperl@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 23 Oct 2008 06:20:57 +0000 (06:20 +0000)
committerkasperl@chromium.org <kasperl@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 23 Oct 2008 06:20:57 +0000 (06:20 +0000)
Review URL: http://codereview.chromium.org/7869

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@560 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

AUTHORS
src/ic-ia32.cc
src/objects-inl.h
src/objects.cc
src/objects.h

diff --git a/AUTHORS b/AUTHORS
index cc96cd1..596cc58 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -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>
index dcc6590..d5fe47d 100644 (file)
@@ -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));
index 0974e9b..9efbe8a 100644 (file)
@@ -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;
index 1d7d125..50b89d5 100644 (file)
@@ -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();
 }
index 9addc94..7193a35 100644 (file)
@@ -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;