Revision: 16709
Author:   [email protected]
Date:     Fri Sep 13 09:57:48 2013 UTC
Log:      Use regular map-checks to guard string-length loading.

[email protected]

Review URL: https://chromiumcodereview.appspot.com/23702039
http://code.google.com/p/v8/source/detail?r=16709

Modified:
 /branches/bleeding_edge/src/arm/code-stubs-arm.cc
 /branches/bleeding_edge/src/arm/stub-cache-arm.cc
 /branches/bleeding_edge/src/ast.cc
 /branches/bleeding_edge/src/ast.h
 /branches/bleeding_edge/src/code-stubs.h
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
 /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
 /branches/bleeding_edge/src/ic.cc
 /branches/bleeding_edge/src/mips/code-stubs-mips.cc
 /branches/bleeding_edge/src/mips/stub-cache-mips.cc
 /branches/bleeding_edge/src/stub-cache.h
 /branches/bleeding_edge/src/x64/code-stubs-x64.cc
 /branches/bleeding_edge/src/x64/stub-cache-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Thu Sep 12 17:59:41 2013 UTC +++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Fri Sep 13 09:57:48 2013 UTC
@@ -3375,8 +3375,7 @@
     receiver = r0;
   }

-  StubCompiler::GenerateLoadStringLength(masm, receiver, r3, r4, &miss,
-                                         support_wrapper_);
+  StubCompiler::GenerateLoadStringLength(masm, receiver, r3, r4, &miss);

   __ bind(&miss);
   StubCompiler::TailCallBuiltin(
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Thu Sep 12 14:32:14 2013 UTC +++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Fri Sep 13 09:57:48 2013 UTC
@@ -380,31 +380,27 @@
                                             Register receiver,
                                             Register scratch1,
                                             Register scratch2,
-                                            Label* miss,
-                                            bool support_wrappers) {
+                                            Label* miss) {
   Label check_wrapper;

   // Check if the object is a string leaving the instance type in the
   // scratch1 register.
-  GenerateStringCheck(masm, receiver, scratch1, scratch2, miss,
-                      support_wrappers ? &check_wrapper : miss);
+ GenerateStringCheck(masm, receiver, scratch1, scratch2, miss, &check_wrapper);

   // Load length directly from the string.
   __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset));
   __ Ret();

-  if (support_wrappers) {
-    // Check if the object is a JSValue wrapper.
-    __ bind(&check_wrapper);
-    __ cmp(scratch1, Operand(JS_VALUE_TYPE));
-    __ b(ne, miss);
+  // Check if the object is a JSValue wrapper.
+  __ bind(&check_wrapper);
+  __ cmp(scratch1, Operand(JS_VALUE_TYPE));
+  __ b(ne, miss);

-    // Unwrap the value and check if the wrapped value is a string.
-    __ ldr(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset));
-    GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss);
-    __ ldr(r0, FieldMemOperand(scratch1, String::kLengthOffset));
-    __ Ret();
-  }
+  // Unwrap the value and check if the wrapped value is a string.
+  __ ldr(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset));
+  GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss);
+  __ ldr(r0, FieldMemOperand(scratch1, String::kLengthOffset));
+  __ Ret();
 }


=======================================
--- /branches/bleeding_edge/src/ast.cc  Tue Sep 10 14:30:36 2013 UTC
+++ /branches/bleeding_edge/src/ast.cc  Fri Sep 13 09:57:48 2013 UTC
@@ -460,10 +460,7 @@
   receiver_types_.Clear();
   if (key()->IsPropertyName()) {
     FunctionPrototypeStub proto_stub(Code::LOAD_IC);
-    StringLengthStub string_stub(Code::LOAD_IC, false);
-    if (oracle->LoadIsStub(this, &string_stub)) {
-      is_string_length_ = true;
-    } else if (oracle->LoadIsStub(this, &proto_stub)) {
+    if (oracle->LoadIsStub(this, &proto_stub)) {
       is_function_prototype_ = true;
     } else {
       Literal* lit_key = key()->AsLiteral();
=======================================
--- /branches/bleeding_edge/src/ast.h   Fri Sep  6 11:32:46 2013 UTC
+++ /branches/bleeding_edge/src/ast.h   Fri Sep 13 09:57:48 2013 UTC
@@ -1646,7 +1646,6 @@

   BailoutId LoadId() const { return load_id_; }

-  bool IsStringLength() const { return is_string_length_; }
   bool IsStringAccess() const { return is_string_access_; }
   bool IsFunctionPrototype() const { return is_function_prototype_; }

@@ -1674,7 +1673,6 @@
         load_id_(GetNextId(isolate)),
         is_monomorphic_(false),
         is_uninitialized_(false),
-        is_string_length_(false),
         is_string_access_(false),
         is_function_prototype_(false) { }

@@ -1687,7 +1685,6 @@
   SmallMapList receiver_types_;
   bool is_monomorphic_ : 1;
   bool is_uninitialized_ : 1;
-  bool is_string_length_ : 1;
   bool is_string_access_ : 1;
   bool is_function_prototype_ : 1;
 };
=======================================
--- /branches/bleeding_edge/src/code-stubs.h    Thu Sep 12 17:59:41 2013 UTC
+++ /branches/bleeding_edge/src/code-stubs.h    Fri Sep 13 09:57:48 2013 UTC
@@ -830,19 +830,12 @@

 class StringLengthStub: public ICStub {
  public:
-  StringLengthStub(Code::Kind kind, bool support_wrapper)
-      : ICStub(kind), support_wrapper_(support_wrapper) { }
+  explicit StringLengthStub(Code::Kind kind) : ICStub(kind) { }
   virtual void Generate(MacroAssembler* masm);

  private:
   STATIC_ASSERT(KindBits::kSize == 4);
-  class WrapperModeBits: public BitField<bool, 4, 1> {};
-  virtual CodeStub::Major MajorKey() { return StringLength; }
-  virtual int MinorKey() {
- return KindBits::encode(kind()) | WrapperModeBits::encode(support_wrapper_);
-  }
-
-  bool support_wrapper_;
+    virtual CodeStub::Major MajorKey() { return StringLength; }
 };


=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Fri Sep 13 09:51:11 2013 UTC
+++ /branches/bleeding_edge/src/hydrogen.cc     Fri Sep 13 09:57:48 2013 UTC
@@ -5135,9 +5135,7 @@
     CHECK_ALIVE(VisitForValue(prop->obj()));
     HValue* object = Top();
     HValue* key = NULL;
-    if ((!prop->IsStringLength() &&
-         !prop->IsFunctionPrototype() &&
-         !prop->key()->IsPropertyName()) ||
+    if ((!prop->IsFunctionPrototype() && !prop->key()->IsPropertyName()) ||
         prop->IsStringAccess()) {
       CHECK_ALIVE(VisitForValue(prop->key()));
       key = Top();
@@ -5825,19 +5823,22 @@
   if (key != NULL) Push(key);
   BuildLoad(expr, position, expr->LoadId());
 }
+
+
+static bool AreStringTypes(SmallMapList* types) {
+  if (types == NULL || types->length() == 0) return false;
+  for (int i = 0; i < types->length(); i++) {
+ if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
+  }
+  return true;
+}


 void HOptimizedGraphBuilder::BuildLoad(Property* expr,
                                        int position,
                                        BailoutId ast_id) {
   HInstruction* instr = NULL;
-  if (expr->IsStringLength()) {
-    HValue* string = Pop();
-    BuildCheckHeapObject(string);
-    HInstruction* checkstring =
-        AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
-    instr = BuildLoadStringLength(string, checkstring);
-  } else if (expr->IsStringAccess()) {
+  if (expr->IsStringAccess()) {
     HValue* index = Pop();
     HValue* string = Pop();
     HValue* context = environment()->context();
@@ -5873,6 +5874,12 @@
       } else {
         instr = BuildLoadNamedMonomorphic(Pop(), name, map);
       }
+    } else if (AreStringTypes(types) &&
+               name->Equals(isolate()->heap()->length_string())) {
+      BuildCheckHeapObject(Pop());
+      HValue* checked_object =
+          AddInstruction(HCheckInstanceType::NewIsString(object, zone()));
+      instr = BuildLoadStringLength(object, checked_object);
     } else if (types != NULL && types->length() > 1) {
       return HandlePolymorphicLoadNamedField(
           position, ast_id, Pop(), types, name);
@@ -5913,9 +5920,7 @@
   if (TryArgumentsAccess(expr)) return;

   CHECK_ALIVE(VisitForValue(expr->obj()));
-  if ((!expr->IsStringLength() &&
-       !expr->IsFunctionPrototype() &&
-       !expr->key()->IsPropertyName()) ||
+  if ((!expr->IsFunctionPrototype() && !expr->key()->IsPropertyName()) ||
       expr->IsStringAccess()) {
     CHECK_ALIVE(VisitForValue(expr->key()));
   }
@@ -7566,9 +7571,7 @@
   HValue* object = Top();

   HValue* key = NULL;
-  if ((!prop->IsStringLength() &&
-       !prop->IsFunctionPrototype() &&
-       !prop->key()->IsPropertyName()) ||
+  if ((!prop->IsFunctionPrototype() && !prop->key()->IsPropertyName()) ||
       prop->IsStringAccess()) {
     CHECK_ALIVE(VisitForValue(prop->key()));
     key = Top();
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Fri Sep 13 07:59:48 2013 UTC +++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Fri Sep 13 09:57:48 2013 UTC
@@ -2756,8 +2756,7 @@
     __ j(not_equal, &miss);
   }

-  StubCompiler::GenerateLoadStringLength(masm, edx, eax, ebx, &miss,
-                                         support_wrapper_);
+  StubCompiler::GenerateLoadStringLength(masm, edx, eax, ebx, &miss);
   __ bind(&miss);
   StubCompiler::TailCallBuiltin(
       masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Fri Sep 13 07:59:48 2013 UTC +++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Fri Sep 13 09:57:48 2013 UTC
@@ -329,32 +329,28 @@
                                             Register receiver,
                                             Register scratch1,
                                             Register scratch2,
-                                            Label* miss,
-                                            bool support_wrappers) {
+                                            Label* miss) {
   Label check_wrapper;

   // Check if the object is a string leaving the instance type in the
   // scratch register.
-  GenerateStringCheck(masm, receiver, scratch1, miss,
-                      support_wrappers ? &check_wrapper : miss);
+  GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper);

   // Load length from the string and convert to a smi.
   __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
   __ ret(0);

-  if (support_wrappers) {
-    // Check if the object is a JSValue wrapper.
-    __ bind(&check_wrapper);
-    __ cmp(scratch1, JS_VALUE_TYPE);
-    __ j(not_equal, miss);
+  // Check if the object is a JSValue wrapper.
+  __ bind(&check_wrapper);
+  __ cmp(scratch1, JS_VALUE_TYPE);
+  __ j(not_equal, miss);

-    // Check if the wrapped value is a string and load the length
-    // directly if it is.
-    __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
-    GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
-    __ mov(eax, FieldOperand(scratch2, String::kLengthOffset));
-    __ ret(0);
-  }
+  // Check if the wrapped value is a string and load the length
+  // directly if it is.
+  __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
+  GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
+  __ mov(eax, FieldOperand(scratch2, String::kLengthOffset));
+  __ ret(0);
 }


=======================================
--- /branches/bleeding_edge/src/ic.cc   Thu Sep 12 22:04:04 2013 UTC
+++ /branches/bleeding_edge/src/ic.cc   Fri Sep 13 09:57:48 2013 UTC
@@ -879,17 +879,14 @@
     // 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()) &&
+    if (object->IsStringWrapper() &&
         name->Equals(isolate()->heap()->length_string())) {
       Handle<Code> stub;
       if (state == UNINITIALIZED) {
         stub = pre_monomorphic_stub();
-      } else if (state == PREMONOMORPHIC) {
-        StringLengthStub string_length_stub(kind(), !object->IsString());
+      } else if (state == PREMONOMORPHIC || state == MONOMORPHIC) {
+        StringLengthStub string_length_stub(kind());
         stub = string_length_stub.GetCode(isolate());
-      } else if (state == MONOMORPHIC && object->IsStringWrapper()) {
-        StringLengthStub string_length_stub(kind(), true);
-        stub = string_length_stub.GetCode(isolate());
       } else if (state != MEGAMORPHIC) {
         ASSERT(state != GENERIC);
         stub = megamorphic_stub();
@@ -897,14 +894,12 @@
       if (!stub.is_null()) {
         set_target(*stub);
 #ifdef DEBUG
-        if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
+        if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n");
 #endif
       }
       // Get the string if we have a string wrapper object.
-      Handle<Object> string = object->IsJSValue()
- ? Handle<Object>(Handle<JSValue>::cast(object)->value(), isolate())
-          : object;
-      return Smi::FromInt(String::cast(*string)->length());
+      String* string = String::cast(JSValue::cast(*object)->value());
+      return Smi::FromInt(string->length());
     }

     // Use specialized code for getting prototype of functions.
@@ -1265,6 +1260,8 @@
                           State state,
                           Handle<Object> object,
                           Handle<String> name) {
+ // TODO(verwaest): It would be nice to support loading fields from smis as
+  // well. For now just fail to update the cache.
   if (!object->IsHeapObject()) return;

   Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
@@ -1278,6 +1275,16 @@
   } else if (!lookup->IsCacheable()) {
     // Bail out if the result is not cacheable.
     code = slow_stub();
+  } else if (object->IsString() &&
+             name->Equals(isolate()->heap()->length_string())) {
+    int length_index = String::kLengthOffset / kPointerSize;
+    if (target()->is_load_stub()) {
+      LoadFieldStub stub(true, length_index, Representation::Tagged());
+      code = stub.GetCode(isolate());
+    } else {
+ KeyedLoadFieldStub stub(true, length_index, Representation::Tagged());
+      code = stub.GetCode(isolate());
+    }
   } else if (!object->IsJSObject()) {
     // TODO(jkummerow): It would be nice to support non-JSObjects in
     // ComputeLoadHandler, then we wouldn't need to go generic here.
@@ -1362,9 +1369,9 @@
         return isolate()->stub_cache()->ComputeLoadViaGetter(
             name, receiver, holder, function);
       } else if (receiver->IsJSArray() &&
-          name->Equals(isolate()->heap()->length_string())) {
-        PropertyIndex lengthIndex =
- PropertyIndex::NewHeaderIndex(JSArray::kLengthOffset / kPointerSize);
+                 name->Equals(isolate()->heap()->length_string())) {
+        PropertyIndex lengthIndex = PropertyIndex::NewHeaderIndex(
+            JSArray::kLengthOffset / kPointerSize);
         return isolate()->stub_cache()->ComputeLoadField(
             name, receiver, holder, lengthIndex, Representation::Tagged());
       }
=======================================
--- /branches/bleeding_edge/src/mips/code-stubs-mips.cc Fri Sep 13 00:10:24 2013 UTC +++ /branches/bleeding_edge/src/mips/code-stubs-mips.cc Fri Sep 13 09:57:48 2013 UTC
@@ -3408,8 +3408,7 @@
     receiver = a0;
   }

-  StubCompiler::GenerateLoadStringLength(masm, receiver, a3, t0, &miss,
-                                         support_wrapper_);
+  StubCompiler::GenerateLoadStringLength(masm, receiver, a3, t0, &miss);

   __ bind(&miss);
   StubCompiler::TailCallBuiltin(
=======================================
--- /branches/bleeding_edge/src/mips/stub-cache-mips.cc Fri Sep 13 00:04:29 2013 UTC +++ /branches/bleeding_edge/src/mips/stub-cache-mips.cc Fri Sep 13 09:57:48 2013 UTC
@@ -374,30 +374,26 @@
                                             Register receiver,
                                             Register scratch1,
                                             Register scratch2,
-                                            Label* miss,
-                                            bool support_wrappers) {
+                                            Label* miss) {
   Label check_wrapper;

   // Check if the object is a string leaving the instance type in the
   // scratch1 register.
-  GenerateStringCheck(masm, receiver, scratch1, scratch2, miss,
-                      support_wrappers ? &check_wrapper : miss);
+ GenerateStringCheck(masm, receiver, scratch1, scratch2, miss, &check_wrapper);

   // Load length directly from the string.
   __ Ret(USE_DELAY_SLOT);
   __ lw(v0, FieldMemOperand(receiver, String::kLengthOffset));

-  if (support_wrappers) {
-    // Check if the object is a JSValue wrapper.
-    __ bind(&check_wrapper);
-    __ Branch(miss, ne, scratch1, Operand(JS_VALUE_TYPE));
+  // Check if the object is a JSValue wrapper.
+  __ bind(&check_wrapper);
+  __ Branch(miss, ne, scratch1, Operand(JS_VALUE_TYPE));

-    // Unwrap the value and check if the wrapped value is a string.
-    __ lw(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset));
-    GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss);
-    __ Ret(USE_DELAY_SLOT);
-    __ lw(v0, FieldMemOperand(scratch1, String::kLengthOffset));
-  }
+  // Unwrap the value and check if the wrapped value is a string.
+  __ lw(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset));
+  GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss);
+  __ Ret(USE_DELAY_SLOT);
+  __ lw(v0, FieldMemOperand(scratch1, String::kLengthOffset));
 }


=======================================
--- /branches/bleeding_edge/src/stub-cache.h    Thu Sep 12 22:04:04 2013 UTC
+++ /branches/bleeding_edge/src/stub-cache.h    Fri Sep 13 09:57:48 2013 UTC
@@ -572,8 +572,7 @@
                                        Register receiver,
                                        Register scratch1,
                                        Register scratch2,
-                                       Label* miss_label,
-                                       bool support_wrappers);
+                                       Label* miss_label);

   static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
                                             Register receiver,
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Fri Sep 13 07:59:48 2013 UTC +++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Fri Sep 13 09:57:48 2013 UTC
@@ -1902,8 +1902,7 @@
     receiver = rax;
   }

-  StubCompiler::GenerateLoadStringLength(masm, receiver, r8, r9, &miss,
-                                         support_wrapper_);
+  StubCompiler::GenerateLoadStringLength(masm, receiver, r8, r9, &miss);
   __ bind(&miss);
   StubCompiler::TailCallBuiltin(
       masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Fri Sep 13 07:59:48 2013 UTC +++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Fri Sep 13 09:57:48 2013 UTC
@@ -304,32 +304,28 @@
                                             Register receiver,
                                             Register scratch1,
                                             Register scratch2,
-                                            Label* miss,
-                                            bool support_wrappers) {
+                                            Label* miss) {
   Label check_wrapper;

   // Check if the object is a string leaving the instance type in the
   // scratch register.
-  GenerateStringCheck(masm, receiver, scratch1, miss,
-                      support_wrappers ? &check_wrapper : miss);
+  GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper);

   // Load length directly from the string.
   __ movq(rax, FieldOperand(receiver, String::kLengthOffset));
   __ ret(0);

-  if (support_wrappers) {
-    // Check if the object is a JSValue wrapper.
-    __ bind(&check_wrapper);
-    __ cmpl(scratch1, Immediate(JS_VALUE_TYPE));
-    __ j(not_equal, miss);
+  // Check if the object is a JSValue wrapper.
+  __ bind(&check_wrapper);
+  __ cmpl(scratch1, Immediate(JS_VALUE_TYPE));
+  __ j(not_equal, miss);

-    // Check if the wrapped value is a string and load the length
-    // directly if it is.
-    __ movq(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
-    GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
-    __ movq(rax, FieldOperand(scratch2, String::kLengthOffset));
-    __ ret(0);
-  }
+  // Check if the wrapped value is a string and load the length
+  // directly if it is.
+  __ movq(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
+  GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
+  __ movq(rax, FieldOperand(scratch2, String::kLengthOffset));
+  __ ret(0);
 }


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to