Author: [EMAIL PROTECTED]
Date: Mon Oct 27 07:36:08 2008
New Revision: 608

Modified:
    branches/bleeding_edge/src/ic-arm.cc
    branches/bleeding_edge/src/ic.cc
    branches/bleeding_edge/src/objects-inl.h
    branches/bleeding_edge/src/objects.h
    branches/bleeding_edge/src/stub-cache-ia32.cc

Log:
Allow inline caching for getting the length of string wrapper objects.
Review URL: http://codereview.chromium.org/8620

Modified: branches/bleeding_edge/src/ic-arm.cc
==============================================================================
--- branches/bleeding_edge/src/ic-arm.cc        (original)
+++ branches/bleeding_edge/src/ic-arm.cc        Mon Oct 27 07:36:08 2008
@@ -157,6 +157,28 @@
  }


+// Generate code to check if an object is a string.  If the object is
+// a string, the map's instance type is left in the scratch1 register.
+static void GenerateStringCheck(MacroAssembler* masm,
+                                Register receiver,
+                                Register scratch1,
+                                Register scratch2,
+                                Label* smi,
+                                Label* non_string_object) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, smi);
+
+  // Check that the object is a string.
+  __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
+  __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
+  // The cast is to resolve the overload for the argument of 0x0.
+  __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
+  __ b(ne, non_string_object);
+}
+
+
  void LoadIC::GenerateStringLength(MacroAssembler* masm) {
    // ----------- S t a t e -------------
    //  -- r2    : name
@@ -164,29 +186,32 @@
    //  -- [sp]  : receiver
    // -----------------------------------

-  Label miss;
+  Label miss, load_length, check_wrapper;

    __ ldr(r0, MemOperand(sp, 0));

-  // Check that the receiver isn't a smi.
-  __ tst(r0, Operand(kSmiTagMask));
-  __ b(eq, &miss);
-
-  // Check that the object is a string.
-  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
-  __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
-  __ and_(r3, r1, Operand(kIsNotStringMask));
-  // The cast is to resolve the overload for the argument of 0x0.
-  __ cmp(r3, Operand(static_cast<int32_t>(kStringTag)));
-  __ b(ne, &miss);
+  // Check if the object is a string.
+  GenerateStringCheck(masm, r0, r1, r3, &miss, &check_wrapper);

+  // Load length directly from the string.
+  __ bind(&load_length);
    __ and_(r1, r1, Operand(kStringSizeMask));
    __ add(r1, r1, Operand(String::kHashShift));
-  // Load length directly from the string.
    __ ldr(r0, FieldMemOperand(r0, String::kLengthOffset));
    __ mov(r0, Operand(r0, LSR, r1));
    __ mov(r0, Operand(r0, LSL, kSmiTagSize));
    __ Ret();
+
+  // Check if the object is a JSValue wrapper.
+  __ bind(&check_wrapper);
+  __ cmp(r0, Operand(JS_VALUE_TYPE));
+  __ b(ne, &miss);
+
+  // Check if the wrapped value is a string and load the length
+  // directly if it is.
+  __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
+  GenerateStringCheck(masm, r0, r1, r3, &miss, &miss);
+  __ b(&load_length);

    // Cache miss: Jump to runtime.
    __ bind(&miss);

Modified: branches/bleeding_edge/src/ic.cc
==============================================================================
--- branches/bleeding_edge/src/ic.cc    (original)
+++ branches/bleeding_edge/src/ic.cc    Mon Oct 27 07:36:08 2008
@@ -453,8 +453,17 @@
    }

    if (FLAG_use_ic) {
-    // Use specialized code for getting the length of strings.
-    if (object->IsString() && name->Equals(Heap::length_symbol())) {
+    // Use specialized code for getting the length of strings and
+    // string wrapper objects.  The length property of string wrapper
+    // objects is read-only and therefore always returns the length of
+    // the underlying string value.  See ECMA-262 15.5.5.1.
+    if ((object->IsString() || object->IsStringWrapper()) &&
+        name->Equals(Heap::length_symbol())) {
+      HandleScope scope;
+      // Get the string if we have a string wrapper object.
+      if (object->IsJSValue()) {
+        object = Handle<Object>(Handle<JSValue>::cast(object)->value());
+      }
  #ifdef DEBUG
        if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
  #endif

Modified: branches/bleeding_edge/src/objects-inl.h
==============================================================================
--- branches/bleeding_edge/src/objects-inl.h    (original)
+++ branches/bleeding_edge/src/objects-inl.h    Mon Oct 27 07:36:08 2008
@@ -301,6 +301,11 @@
  }


+bool Object::IsStringWrapper() {
+  return IsJSValue() && JSValue::cast(this)->value()->IsString();
+}
+
+
  bool Object::IsProxy() {
    return Object::IsHeapObject()
      && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;

Modified: branches/bleeding_edge/src/objects.h
==============================================================================
--- branches/bleeding_edge/src/objects.h        (original)
+++ branches/bleeding_edge/src/objects.h        Mon Oct 27 07:36:08 2008
@@ -626,6 +626,7 @@
    inline bool IsOddball();
    inline bool IsSharedFunctionInfo();
    inline bool IsJSValue();
+  inline bool IsStringWrapper();
    inline bool IsProxy();
    inline bool IsBoolean();
    inline bool IsJSArray();

Modified: branches/bleeding_edge/src/stub-cache-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/stub-cache-ia32.cc       (original)
+++ branches/bleeding_edge/src/stub-cache-ia32.cc       Mon Oct 27 07:36:08 2008
@@ -159,31 +159,55 @@
  }


-void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
-                                            Register receiver,
-                                            Register scratch,
-                                            Label* miss_label) {
-  // Check that the receiver isn't a smi.
+// Generate code to check if an object is a string.  If the object is
+// a string, the map's instance type is left in the scratch register.
+static void GenerateStringCheck(MacroAssembler* masm,
+                                Register receiver,
+                                Register scratch,
+                                Label* smi,
+                                Label* non_string_object) {
+  // Check that the object isn't a smi.
    __ test(receiver, Immediate(kSmiTagMask));
-  __ j(zero, miss_label, not_taken);
+  __ j(zero, smi, not_taken);

    // Check that the object is a string.
    __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
    __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
    ASSERT(kNotStringTag != 0);
    __ test(scratch, Immediate(kNotStringTag));
-  __ j(not_zero, miss_label, not_taken);
+  __ j(not_zero, non_string_object, not_taken);
+}

-  __ and_(scratch, kStringSizeMask);
+
+void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
+                                            Register receiver,
+                                            Register scratch,
+                                            Label* miss) {
+  Label load_length, check_wrapper;
+
+  // Check if the object is a string.
+  GenerateStringCheck(masm, receiver, scratch, miss, &check_wrapper);

    // Load length directly from the string.
+  __ bind(&load_length);
+  __ and_(scratch, kStringSizeMask);
    __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
-
    // ecx is also the receiver.
    __ lea(ecx, Operand(scratch, String::kLongLengthShift));
    __ shr(eax);  // ecx is implicit shift register.
    __ shl(eax, kSmiTagSize);
    __ ret(0);
+
+  // Check if the object is a JSValue wrapper.
+  __ bind(&check_wrapper);
+  __ cmp(receiver, JS_VALUE_TYPE);
+  __ j(not_equal, miss, not_taken);
+
+  // Check if the wrapped value is a string and load the length
+  // directly if it is.
+  __ mov(receiver, FieldOperand(receiver, JSValue::kValueOffset));
+  GenerateStringCheck(masm, receiver, scratch, miss, miss);
+  __ jmp(&load_length);
  }



--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to