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
-~----------~----~----~----~------~----~------~--~---

Reply via email to