Replace special IC builtins and stubs in the map's cache by codestubs.
authorverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 21 Jan 2013 14:53:29 +0000 (14:53 +0000)
committerverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 21 Jan 2013 14:53:29 +0000 (14:53 +0000)
Review URL: https://chromiumcodereview.appspot.com/11973008

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

20 files changed:
src/arm/code-stubs-arm.cc
src/arm/ic-arm.cc
src/arm/stub-cache-arm.cc
src/ast.cc
src/builtins.cc
src/builtins.h
src/code-stubs.h
src/ia32/code-stubs-ia32.cc
src/ia32/ic-ia32.cc
src/ia32/stub-cache-ia32.cc
src/ic.cc
src/ic.h
src/objects-inl.h
src/stub-cache.cc
src/stub-cache.h
src/type-info.cc
src/type-info.h
src/x64/code-stubs-x64.cc
src/x64/ic-x64.cc
src/x64/stub-cache-x64.cc

index 521231c02ab7efb5db9720fde2630983492204e3..415f8bc4e711c7b3d9726114b0013d513d8d826d 100644 (file)
@@ -32,6 +32,7 @@
 #include "bootstrapper.h"
 #include "code-stubs.h"
 #include "regexp-macro-assembler.h"
+#include "stub-cache.h"
 
 namespace v8 {
 namespace internal {
@@ -4502,6 +4503,37 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
 }
 
 
+void StringLengthStub::Generate(MacroAssembler* masm) {
+  Label miss;
+  Register receiver;
+  if (kind() == Code::KEYED_LOAD_IC) {
+    // ----------- S t a t e -------------
+    //  -- lr    : return address
+    //  -- r0    : key
+    //  -- r1    : receiver
+    // -----------------------------------
+    __ cmp(r0, Operand(masm->isolate()->factory()->length_symbol()));
+    __ b(ne, &miss);
+    receiver = r1;
+  } else {
+    ASSERT(kind() == Code::LOAD_IC);
+    // ----------- S t a t e -------------
+    //  -- r2    : name
+    //  -- lr    : return address
+    //  -- r0    : receiver
+    //  -- sp[0] : receiver
+    // -----------------------------------
+    receiver = r0;
+  }
+
+  StubCompiler::GenerateLoadStringLength(masm, receiver, r3, r4, &miss,
+                                         support_wrapper_);
+
+  __ bind(&miss);
+  StubCompiler::GenerateLoadMiss(masm, kind());
+}
+
+
 Register InstanceofStub::left() { return r0; }
 
 
index 0db63e75b7c7b4c994a84b44418f1addfa587c3d..c9b7cb9b0070d4b12d2cc1eb941428514f059f2d 100644 (file)
@@ -228,23 +228,6 @@ void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
 }
 
 
-void LoadIC::GenerateStringLength(MacroAssembler* masm, bool support_wrappers) {
-  // ----------- S t a t e -------------
-  //  -- r2    : name
-  //  -- lr    : return address
-  //  -- r0    : receiver
-  //  -- sp[0] : receiver
-  // -----------------------------------
-  Label miss;
-
-  StubCompiler::GenerateLoadStringLength(masm, r0, r1, r3, &miss,
-                                         support_wrappers);
-  // Cache miss: Jump to runtime.
-  __ bind(&miss);
-  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
-}
-
-
 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
   // ----------- S t a t e -------------
   //  -- r2    : name
index d1b51e4122285d873c0bfba4392dda78b7e43f0a..236e9087d33838b7ef67c1e8a2e50c0cf9c92844 100644 (file)
@@ -3228,32 +3228,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
 }
 
 
-Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength(
-    Handle<String> name) {
-  // ----------- S t a t e -------------
-  //  -- lr    : return address
-  //  -- r0    : key
-  //  -- r1    : receiver
-  // -----------------------------------
-  Label miss;
-
-  Counters* counters = masm()->isolate()->counters();
-  __ IncrementCounter(counters->keyed_load_string_length(), 1, r2, r3);
-
-  // Check the key is the cached one.
-  __ cmp(r0, Operand(name));
-  __ b(ne, &miss);
-
-  GenerateLoadStringLength(masm(), r1, r2, r3, &miss, true);
-  __ bind(&miss);
-  __ DecrementCounter(counters->keyed_load_string_length(), 1, r2, r3);
-
-  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
-
-  return GetCode(Code::CALLBACKS, name);
-}
-
-
 Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
     Handle<String> name) {
   // ----------- S t a t e -------------
index e2acd20b3b8bcb68473f867a57dbdd7e96b673ce..f7c667fbc1ca3964195baf3aa5232034e9bb50d9 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <math.h>  // For isfinite.
 #include "builtins.h"
+#include "code-stubs.h"
 #include "conversions.h"
 #include "hashmap.h"
 #include "parser.h"
@@ -412,9 +413,10 @@ void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle,
   is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this);
   receiver_types_.Clear();
   if (key()->IsPropertyName()) {
+    StringLengthStub string_stub(Code::LOAD_IC, false);
     if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_ArrayLength)) {
       is_array_length_ = true;
-    } else if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_StringLength)) {
+    } else if (oracle->LoadIsStub(this, &string_stub)) {
       is_string_length_ = true;
     } else if (oracle->LoadIsBuiltin(this,
                                      Builtins::kLoadIC_FunctionPrototype)) {
index 786627da7ee9847af6a06986fde34b8305d23da5..4f373dd0f1934ae23c1483ffa7e845d50d23372c 100644 (file)
@@ -1458,16 +1458,6 @@ static void Generate_LoadIC_ArrayLength(MacroAssembler* masm) {
 }
 
 
-static void Generate_LoadIC_StringLength(MacroAssembler* masm) {
-  LoadIC::GenerateStringLength(masm, false);
-}
-
-
-static void Generate_LoadIC_StringWrapperLength(MacroAssembler* masm) {
-  LoadIC::GenerateStringLength(masm, true);
-}
-
-
 static void Generate_LoadIC_FunctionPrototype(MacroAssembler* masm) {
   LoadIC::GenerateFunctionPrototype(masm);
 }
index 9a02ad0f2cdaceba309d8eaf937bcdb9347712cc..619006a758b11f06e0ed36d4d03482e19c5b150a 100644 (file)
@@ -136,10 +136,6 @@ enum BuiltinExtraArguments {
                                     Code::kNoExtraICState)              \
   V(LoadIC_ArrayLength,             LOAD_IC, MONOMORPHIC,               \
                                     Code::kNoExtraICState)              \
-  V(LoadIC_StringLength,            LOAD_IC, MONOMORPHIC,               \
-                                    Code::kNoExtraICState)              \
-  V(LoadIC_StringWrapperLength,     LOAD_IC, MONOMORPHIC,               \
-                                    Code::kNoExtraICState)              \
   V(LoadIC_FunctionPrototype,       LOAD_IC, MONOMORPHIC,               \
                                     Code::kNoExtraICState)              \
   V(LoadIC_Megamorphic,             LOAD_IC, MEGAMORPHIC,               \
index 8cba9661917c64c9745ec44a9a494a5ec7ba3ae9..7e2ebe4d52730bb7527284523cc310d54f22bd8a 100644 (file)
@@ -47,6 +47,7 @@ namespace internal {
   V(Compare)                             \
   V(CompareIC)                           \
   V(MathPow)                             \
+  V(StringLength)                        \
   V(RecordWrite)                         \
   V(StoreBufferOverflow)                 \
   V(RegExpExec)                          \
@@ -539,6 +540,45 @@ class MathPowStub: public PlatformCodeStub {
 };
 
 
+class ICStub: public PlatformCodeStub {
+ public:
+  explicit ICStub(Code::Kind kind) : kind_(kind) { }
+  virtual int GetCodeKind() { return kind_; }
+  virtual InlineCacheState GetICState() { return MONOMORPHIC; }
+
+  bool Describes(Code* code) {
+    return GetMajorKey(code) == MajorKey() && code->stub_info() == MinorKey();
+  }
+
+ protected:
+  class KindBits: public BitField<Code::Kind, 0, 4> {};
+  virtual void FinishCode(Handle<Code> code) {
+    code->set_stub_info(MinorKey());
+  }
+  Code::Kind kind() { return kind_; }
+
+ private:
+  Code::Kind kind_;
+};
+
+
+class StringLengthStub: public ICStub {
+ public:
+  StringLengthStub(Code::Kind kind, bool support_wrapper)
+      : ICStub(kind), support_wrapper_(support_wrapper) { }
+  virtual void Generate(MacroAssembler* masm);
+
+ private:
+  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_;
+};
+
+
 class BinaryOpStub: public PlatformCodeStub {
  public:
   BinaryOpStub(Token::Value op, OverwriteMode mode)
index 4b71af66226ed584b1b719a7cffdba5003bb166e..cfeecf1981938eef431fb48328121da1f3d2eff7 100644 (file)
@@ -3259,6 +3259,26 @@ void MathPowStub::Generate(MacroAssembler* masm) {
 }
 
 
+void StringLengthStub::Generate(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- ecx    : name
+  //  -- edx    : receiver
+  //  -- esp[0] : return address
+  // -----------------------------------
+  Label miss;
+
+  if (kind() == Code::KEYED_LOAD_IC) {
+    __ cmp(ecx, Immediate(masm->isolate()->factory()->length_symbol()));
+    __ j(not_equal, &miss);
+  }
+
+  StubCompiler::GenerateLoadStringLength(masm, edx, eax, ebx, &miss,
+                                         support_wrapper_);
+  __ bind(&miss);
+  StubCompiler::GenerateLoadMiss(masm, kind());
+}
+
+
 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
   // The key is in edx and the parameter count is in eax.
 
index 3b5ef00684741147fef2a7a41f2a08920a3f8ce7..e5c14574e29bcd24ec24cb4c9f0528f7fad926dd 100644 (file)
@@ -230,22 +230,6 @@ void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
 }
 
 
-void LoadIC::GenerateStringLength(MacroAssembler* masm,
-                                  bool support_wrappers) {
-  // ----------- S t a t e -------------
-  //  -- ecx    : name
-  //  -- edx    : receiver
-  //  -- esp[0] : return address
-  // -----------------------------------
-  Label miss;
-
-  StubCompiler::GenerateLoadStringLength(masm, edx, eax, ebx, &miss,
-                                         support_wrappers);
-  __ bind(&miss);
-  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
-}
-
-
 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
   // ----------- S t a t e -------------
   //  -- ecx    : name
index 9e694d24db3bea706c186167eef8af41d6dd56fa..d500abd17cce512b613787bd6acc3cf222837e48 100644 (file)
@@ -3341,32 +3341,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
 }
 
 
-Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength(
-    Handle<String> name) {
-  // ----------- S t a t e -------------
-  //  -- ecx    : key
-  //  -- edx    : receiver
-  //  -- esp[0] : return address
-  // -----------------------------------
-  Label miss;
-
-  Counters* counters = isolate()->counters();
-  __ IncrementCounter(counters->keyed_load_string_length(), 1);
-
-  // Check that the name has not changed.
-  __ cmp(ecx, Immediate(name));
-  __ j(not_equal, &miss);
-
-  GenerateLoadStringLength(masm(), edx, eax, ebx, &miss, true);
-  __ bind(&miss);
-  __ DecrementCounter(counters->keyed_load_string_length(), 1);
-  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
-
-  // Return the generated code.
-  return GetCode(Code::CALLBACKS, name);
-}
-
-
 Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
     Handle<String> name) {
   // ----------- S t a t e -------------
index 0a99772585691b2da9dbc629e4dbd863bb620677..b6738658effc3c66ec16f66e6c08310b3f51dd7d 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -832,6 +832,46 @@ MaybeObject* KeyedCallIC::LoadFunction(State state,
 }
 
 
+bool IC::HandleLoad(State state,
+                    Handle<Object> object,
+                    Handle<String> name,
+                    MaybeObject** result) {
+  // 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(isolate()->heap()->length_symbol())) {
+    Handle<Code> stub;
+    if (state == UNINITIALIZED) {
+      stub = pre_monomorphic_stub();
+    } else if (state == PREMONOMORPHIC) {
+      StringLengthStub string_length_stub(kind(), !object->IsString());
+      stub = string_length_stub.GetCode();
+    } else if (state == MONOMORPHIC && object->IsStringWrapper()) {
+      StringLengthStub string_length_stub(kind(), true);
+      stub = string_length_stub.GetCode();
+    } else if (state != MEGAMORPHIC) {
+      ASSERT(state != GENERIC);
+      stub = megamorphic_stub();
+    }
+    if (!stub.is_null()) {
+      set_target(*stub);
+#ifdef DEBUG
+      if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
+#endif
+    }
+    // Get the string if we have a string wrapper object.
+    Handle<Object> string = object->IsJSValue()
+        ? Handle<Object>(Handle<JSValue>::cast(object)->value())
+        : object;
+    *result = Smi::FromInt(String::cast(*string)->length());
+    return true;
+  }
+  return false;
+}
+
+
 MaybeObject* LoadIC::Load(State state,
                           Handle<Object> object,
                           Handle<String> name) {
@@ -842,36 +882,9 @@ MaybeObject* LoadIC::Load(State state,
   }
 
   if (FLAG_use_ic) {
-    // 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(isolate()->heap()->length_symbol())) {
-      Handle<Code> stub;
-      if (state == UNINITIALIZED) {
-        stub = pre_monomorphic_stub();
-      } else if (state == PREMONOMORPHIC) {
-        stub = object->IsString()
-            ? isolate()->builtins()->LoadIC_StringLength()
-            : isolate()->builtins()->LoadIC_StringWrapperLength();
-      } else if (state == MONOMORPHIC && object->IsStringWrapper()) {
-        stub = isolate()->builtins()->LoadIC_StringWrapperLength();
-      } else if (state != MEGAMORPHIC) {
-        ASSERT(state != GENERIC);
-        stub = megamorphic_stub();
-      }
-      if (!stub.is_null()) {
-        set_target(*stub);
-#ifdef DEBUG
-        if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
-#endif
-      }
-      // Get the string if we have a string wrapper object.
-      Handle<Object> string = object->IsJSValue()
-          ? Handle<Object>(Handle<JSValue>::cast(object)->value())
-          : object;
-      return Smi::FromInt(String::cast(*string)->length());
+    MaybeObject* result;
+    if (HandleLoad(state, object, name, &result)) {
+      return result;
     }
 
     // Use specialized code for getting the length of arrays.
@@ -1156,20 +1169,12 @@ MaybeObject* KeyedLoadIC::Load(State state,
     }
 
     if (FLAG_use_ic) {
-      // TODO(1073): don't ignore the current stub state.
-
-      // Use specialized code for getting the length of strings.
-      if (object->IsString() &&
-          name->Equals(isolate()->heap()->length_symbol())) {
-        Handle<String> string = Handle<String>::cast(object);
-        Handle<Code> code =
-            isolate()->stub_cache()->ComputeKeyedLoadStringLength(name, string);
-        ASSERT(!code.is_null());
-        set_target(*code);
-        TRACE_IC("KeyedLoadIC", name, state, target());
-        return Smi::FromInt(string->length());
+      MaybeObject* result;
+      if (HandleLoad(state, object, name, &result)) {
+        return result;
       }
 
+      // TODO(1073): don't ignore the current stub state.
       // Use specialized code for getting the length of arrays.
       if (object->IsJSArray() &&
           name->Equals(isolate()->heap()->length_symbol())) {
@@ -1612,7 +1617,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
         isolate()->stub_cache()->Set(*name, receiver->map(), *code);
         set_target((strict_mode == kStrictMode)
                      ? megamorphic_stub_strict()
-                     : megamorphic_stub());
+                     : *megamorphic_stub());
       }
       break;
     case MEGAMORPHIC:
index 0cc6aa461354612ae774a6960537f5e9af465c04..a0c0f381e25f2d72a6fa677f75fde9af5a6f5cbd 100644 (file)
--- a/src/ic.h
+++ b/src/ic.h
@@ -133,6 +133,18 @@ class IC {
                                              InlineCacheHolderFlag holder);
 
  protected:
+  virtual Handle<Code> pre_monomorphic_stub() {
+    UNREACHABLE();
+    return Handle<Code>::null();
+  }
+  virtual Handle<Code> megamorphic_stub() {
+    UNREACHABLE();
+    return Handle<Code>::null();
+  }
+  virtual Code::Kind kind() const {
+    UNREACHABLE();
+    return Code::STUB;
+  }
   Address fp() const { return fp_; }
   Address pc() const { return *pc_address_; }
   Isolate* isolate() const { return isolate_; }
@@ -165,6 +177,11 @@ class IC {
   static inline void SetTargetAtAddress(Address address, Code* target);
   static void PostPatching(Address address, Code* target, Code* old_target);
 
+  bool HandleLoad(State state,
+                  Handle<Object> object,
+                  Handle<String> name,
+                  MaybeObject** result);
+
  private:
   // Frame pointer for the frame that uses (calls) the IC.
   Address fp_;
@@ -338,10 +355,15 @@ class LoadIC: public IC {
 
   // Specialized code generator routines.
   static void GenerateArrayLength(MacroAssembler* masm);
-  static void GenerateStringLength(MacroAssembler* masm,
-                                   bool support_wrappers);
   static void GenerateFunctionPrototype(MacroAssembler* masm);
 
+ protected:
+  virtual Code::Kind kind() const { return Code::LOAD_IC; }
+
+  virtual Handle<Code> megamorphic_stub() {
+    return isolate()->builtins()->LoadIC_Megamorphic();
+  }
+
  private:
   // Update the inline cache and the global stub cache based on the
   // lookup result.
@@ -351,14 +373,11 @@ class LoadIC: public IC {
                     Handle<String> name);
 
   // Stub accessors.
-  Handle<Code> megamorphic_stub() {
-    return isolate()->builtins()->LoadIC_Megamorphic();
-  }
   static Code* initialize_stub() {
     return Isolate::Current()->builtins()->builtin(
         Builtins::kLoadIC_Initialize);
   }
-  Handle<Code> pre_monomorphic_stub() {
+  virtual Handle<Code> pre_monomorphic_stub() {
     return isolate()->builtins()->LoadIC_PreMonomorphic();
   }
 
@@ -429,8 +448,6 @@ class KeyedIC: public IC {
     return Handle<Code>::null();
   }
 
-  virtual Code::Kind kind() const = 0;
-
   Handle<Code> ComputeStub(Handle<JSObject> receiver,
                            StubKind stub_kind,
                            StrictModeFlag strict_mode,
@@ -520,6 +537,10 @@ class KeyedLoadIC: public KeyedIC {
  protected:
   virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
 
+  virtual Handle<Code> megamorphic_stub() {
+    return isolate()->builtins()->KeyedLoadIC_Generic();
+  }
+
   virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
                                               StrictModeFlag strict_mode,
                                               KeyedAccessGrowMode grow_mode);
@@ -540,13 +561,10 @@ class KeyedLoadIC: public KeyedIC {
     return Isolate::Current()->builtins()->builtin(
         Builtins::kKeyedLoadIC_Initialize);
   }
-  Handle<Code> megamorphic_stub() {
-    return isolate()->builtins()->KeyedLoadIC_Generic();
-  }
   Handle<Code> generic_stub() const {
     return isolate()->builtins()->KeyedLoadIC_Generic();
   }
-  Handle<Code> pre_monomorphic_stub() {
+  virtual Handle<Code> pre_monomorphic_stub() {
     return isolate()->builtins()->KeyedLoadIC_PreMonomorphic();
   }
   Handle<Code> indexed_interceptor_stub() {
@@ -584,6 +602,12 @@ class StoreIC: public IC {
   static void GenerateGlobalProxy(MacroAssembler* masm,
                                   StrictModeFlag strict_mode);
 
+ protected:
+  virtual Code::Kind kind() const { return Code::STORE_IC; }
+  virtual Handle<Code> megamorphic_stub() {
+    return isolate()->builtins()->StoreIC_Megamorphic();
+  }
+
  private:
   // Update the inline cache and the global stub cache based on the
   // lookup result.
@@ -602,10 +626,6 @@ class StoreIC: public IC {
   }
 
   // Stub accessors.
-  Code* megamorphic_stub() {
-    return isolate()->builtins()->builtin(
-        Builtins::kStoreIC_Megamorphic);
-  }
   Code* megamorphic_stub_strict() {
     return isolate()->builtins()->builtin(
         Builtins::kStoreIC_Megamorphic_Strict);
index a865edc17309977659e737a9f739fbd8bb3da6d0..3251d9e9b3b3c8817472f9167224e0bcb0d0a5e8 100644 (file)
@@ -3456,6 +3456,8 @@ int Code::major_key() {
          kind() == UNARY_OP_IC ||
          kind() == BINARY_OP_IC ||
          kind() == COMPARE_IC ||
+         kind() == LOAD_IC ||
+         kind() == KEYED_LOAD_IC ||
          kind() == TO_BOOLEAN_IC);
   return StubMajorKeyField::decode(
       READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
@@ -3468,6 +3470,8 @@ void Code::set_major_key(int major) {
          kind() == UNARY_OP_IC ||
          kind() == BINARY_OP_IC ||
          kind() == COMPARE_IC ||
+         kind() == LOAD_IC ||
+         kind() == KEYED_LOAD_IC ||
          kind() == TO_BOOLEAN_IC);
   ASSERT(0 <= major && major < 256);
   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
@@ -4847,14 +4851,17 @@ void Code::set_type_feedback_info(Object* value, WriteBarrierMode mode) {
 
 
 int Code::stub_info() {
-  ASSERT(kind() == COMPARE_IC || kind() == BINARY_OP_IC);
+  ASSERT(kind() == COMPARE_IC || kind() == BINARY_OP_IC || kind() == LOAD_IC);
   Object* value = READ_FIELD(this, kTypeFeedbackInfoOffset);
   return Smi::cast(value)->value();
 }
 
 
 void Code::set_stub_info(int value) {
-  ASSERT(kind() == COMPARE_IC || kind() == BINARY_OP_IC);
+  ASSERT(kind() == COMPARE_IC ||
+         kind() == BINARY_OP_IC ||
+         kind() == LOAD_IC ||
+         kind() == KEYED_LOAD_IC);
   WRITE_FIELD(this, kTypeFeedbackInfoOffset, Smi::FromInt(value));
 }
 
index 1f954edfa782250d7060a618d00319aad1915619..ba681ca9f810007f05979beaf20068427de4107a 100644 (file)
@@ -365,23 +365,6 @@ Handle<Code> StubCache::ComputeKeyedLoadArrayLength(Handle<String> name,
 }
 
 
-Handle<Code> StubCache::ComputeKeyedLoadStringLength(Handle<String> name,
-                                                     Handle<String> receiver) {
-  Code::Flags flags =
-      Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, Code::CALLBACKS);
-  Handle<Map> map(receiver->map());
-  Handle<Object> probe(map->FindInCodeCache(*name, flags), isolate_);
-  if (probe->IsCode()) return Handle<Code>::cast(probe);
-
-  KeyedLoadStubCompiler compiler(isolate_);
-  Handle<Code> code = compiler.CompileLoadStringLength(name);
-  PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
-  GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
-  Map::UpdateCodeCache(map, name, code);
-  return code;
-}
-
-
 Handle<Code> StubCache::ComputeKeyedLoadFunctionPrototype(
     Handle<String> name,
     Handle<JSFunction> receiver) {
index c562bc714c8c124641c1265bbd08952ab58aaffa..555d66076052ef75d2b9741fc2699ecfc7fc894c 100644 (file)
@@ -136,9 +136,6 @@ class StubCache {
   Handle<Code> ComputeKeyedLoadArrayLength(Handle<String> name,
                                            Handle<JSArray> receiver);
 
-  Handle<Code> ComputeKeyedLoadStringLength(Handle<String> name,
-                                            Handle<String> receiver);
-
   Handle<Code> ComputeKeyedLoadFunctionPrototype(Handle<String> name,
                                                  Handle<JSFunction> receiver);
 
@@ -672,8 +669,6 @@ class KeyedLoadStubCompiler: public StubCompiler {
 
   Handle<Code> CompileLoadArrayLength(Handle<String> name);
 
-  Handle<Code> CompileLoadStringLength(Handle<String> name);
-
   Handle<Code> CompileLoadFunctionPrototype(Handle<String> name);
 
   Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
index 75e915bb846d9b0e8c57f8c29102c2c7526c939f..fb0f45a416791fa8c5e27b93eedaa9e197261f6e 100644 (file)
@@ -305,6 +305,15 @@ bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) {
 }
 
 
+bool TypeFeedbackOracle::LoadIsStub(Property* expr, ICStub* stub) {
+  Handle<Object> object = GetInfo(expr->PropertyFeedbackId());
+  if (!object->IsCode()) return false;
+  Handle<Code> code = Handle<Code>::cast(object);
+  if (!code->is_load_stub()) return false;
+  return stub->Describes(*code);
+}
+
+
 static TypeInfo TypeFromCompareType(CompareIC::State state) {
   switch (state) {
     case CompareIC::UNINITIALIZED:
index 330ecd34c32effa0efb6dd6c4836bb62147d80bb..1ad3233390e3b71a265bbffde501ccc519894131 100644 (file)
@@ -227,10 +227,11 @@ class CompareOperation;
 class CompilationInfo;
 class CountOperation;
 class Expression;
+class ForInStatement;
+class ICStub;
 class Property;
 class SmallMapList;
 class UnaryOperation;
-class ForInStatement;
 
 
 class TypeFeedbackOracle: public ZoneObject {
@@ -280,6 +281,7 @@ class TypeFeedbackOracle: public ZoneObject {
   Handle<Map> GetObjectLiteralStoreMap(ObjectLiteral::Property* prop);
 
   bool LoadIsBuiltin(Property* expr, Builtins::Name id);
+  bool LoadIsStub(Property* expr, ICStub* stub);
 
   // TODO(1571) We can't use ToBooleanStub::Types as the return value because
   // of various cylces in our headers. Death to tons of implementations in
index 82f910056466503164e54c9850a8038dd579f974..e557285a484e925c3d3561adaad37441b788ff2e 100644 (file)
@@ -32,6 +32,7 @@
 #include "bootstrapper.h"
 #include "code-stubs.h"
 #include "regexp-macro-assembler.h"
+#include "stub-cache.h"
 
 namespace v8 {
 namespace internal {
@@ -2359,6 +2360,34 @@ void MathPowStub::Generate(MacroAssembler* masm) {
 }
 
 
+void StringLengthStub::Generate(MacroAssembler* masm) {
+  Label miss;
+  Register receiver;
+  if (kind() == Code::KEYED_LOAD_IC) {
+    // ----------- S t a t e -------------
+    //  -- rax    : key
+    //  -- rdx    : receiver
+    //  -- rsp[0] : return address
+    // -----------------------------------
+    __ Cmp(rax, masm->isolate()->factory()->length_symbol());
+    receiver = rdx;
+  } else {
+    ASSERT(kind() == Code::LOAD_IC);
+    // ----------- S t a t e -------------
+    //  -- rax    : receiver
+    //  -- rcx    : name
+    //  -- rsp[0] : return address
+    // -----------------------------------
+    receiver = rax;
+  }
+
+  StubCompiler::GenerateLoadStringLength(masm, receiver, r8, r9, &miss,
+                                         support_wrapper_);
+  __ bind(&miss);
+  StubCompiler::GenerateLoadMiss(masm, kind());
+}
+
+
 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
   // The key is in rdx and the parameter count is in rax.
 
index 657c88aab7209625bcaee75d0e939341c6e21277..f903f8719684068e76eea16f941902f7feb7eb0b 100644 (file)
@@ -238,21 +238,6 @@ void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
 }
 
 
-void LoadIC::GenerateStringLength(MacroAssembler* masm, bool support_wrappers) {
-  // ----------- S t a t e -------------
-  //  -- rax    : receiver
-  //  -- rcx    : name
-  //  -- rsp[0] : return address
-  // -----------------------------------
-  Label miss;
-
-  StubCompiler::GenerateLoadStringLength(masm, rax, rdx, rbx, &miss,
-                                         support_wrappers);
-  __ bind(&miss);
-  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
-}
-
-
 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
   // ----------- S t a t e -------------
   //  -- rax    : receiver
index 46d74b6b2f4e52f463c96b36458a0250f607d3db..1b65dd05edd45c8c7581019baa6e79136336152b 100644 (file)
@@ -3154,32 +3154,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
 }
 
 
-Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength(
-    Handle<String> name) {
-  // ----------- S t a t e -------------
-  //  -- rax    : key
-  //  -- rdx    : receiver
-  //  -- rsp[0] : return address
-  // -----------------------------------
-  Label miss;
-
-  Counters* counters = isolate()->counters();
-  __ IncrementCounter(counters->keyed_load_string_length(), 1);
-
-  // Check that the name has not changed.
-  __ Cmp(rax, name);
-  __ j(not_equal, &miss);
-
-  GenerateLoadStringLength(masm(), rdx, rcx, rbx, &miss, true);
-  __ bind(&miss);
-  __ DecrementCounter(counters->keyed_load_string_length(), 1);
-  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
-
-  // Return the generated code.
-  return GetCode(Code::CALLBACKS, name);
-}
-
-
 Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
     Handle<String> name) {
   // ----------- S t a t e -------------