Revision: 24500
Author:   [email protected]
Date:     Thu Oct  9 14:30:44 2014 UTC
Log:      Add MEGAMORPHIC state support for KeyedStoreIC

[email protected]

Review URL: https://codereview.chromium.org/584043002
https://code.google.com/p/v8/source/detail?r=24500

Modified:
 /branches/bleeding_edge/src/builtins.cc
 /branches/bleeding_edge/src/builtins.h
 /branches/bleeding_edge/src/ic/arm/ic-arm.cc
 /branches/bleeding_edge/src/ic/arm64/ic-arm64.cc
 /branches/bleeding_edge/src/ic/ia32/ic-ia32.cc
 /branches/bleeding_edge/src/ic/ic.cc
 /branches/bleeding_edge/src/ic/ic.h
 /branches/bleeding_edge/src/ic/x64/ic-x64.cc
 /branches/bleeding_edge/src/ic/x64/stub-cache-x64.cc

=======================================
--- /branches/bleeding_edge/src/builtins.cc     Mon Sep 29 08:22:24 2014 UTC
+++ /branches/bleeding_edge/src/builtins.cc     Thu Oct  9 14:30:44 2014 UTC
@@ -1312,15 +1312,25 @@
 static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
   NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
 }
+
+
+static void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
+  KeyedStoreIC::GenerateGeneric(masm, SLOPPY, kMissOnMissingHandler);
+}
+
+
+static void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
+  KeyedStoreIC::GenerateGeneric(masm, STRICT, kMissOnMissingHandler);
+}


 static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
-  KeyedStoreIC::GenerateGeneric(masm, SLOPPY);
+ KeyedStoreIC::GenerateGeneric(masm, SLOPPY, kCallRuntimeOnMissingHandler);
 }


 static void Generate_KeyedStoreIC_Generic_Strict(MacroAssembler* masm) {
-  KeyedStoreIC::GenerateGeneric(masm, STRICT);
+ KeyedStoreIC::GenerateGeneric(masm, STRICT, kCallRuntimeOnMissingHandler);
 }


=======================================
--- /branches/bleeding_edge/src/builtins.h      Mon Sep 22 13:23:27 2014 UTC
+++ /branches/bleeding_edge/src/builtins.h      Thu Oct  9 14:30:44 2014 UTC
@@ -95,12 +95,15 @@
V(KeyedStoreIC_Initialize, KEYED_STORE_IC, UNINITIALIZED, kNoExtraICState) \ V(KeyedStoreIC_PreMonomorphic, KEYED_STORE_IC, PREMONOMORPHIC, \ kNoExtraICState) \ + V(KeyedStoreIC_Megamorphic, KEYED_STORE_IC, MEGAMORPHIC, kNoExtraICState) \ V(KeyedStoreIC_Generic, KEYED_STORE_IC, GENERIC, kNoExtraICState) \ \ V(KeyedStoreIC_Initialize_Strict, KEYED_STORE_IC, UNINITIALIZED, \ StoreIC::kStrictModeState) \ V(KeyedStoreIC_PreMonomorphic_Strict, KEYED_STORE_IC, PREMONOMORPHIC, \ StoreIC::kStrictModeState) \ + V(KeyedStoreIC_Megamorphic_Strict, KEYED_STORE_IC, MEGAMORPHIC, \ + StoreIC::kStrictModeState) \ V(KeyedStoreIC_Generic_Strict, KEYED_STORE_IC, GENERIC, \ StoreIC::kStrictModeState) \ V(KeyedStoreIC_SloppyArguments, KEYED_STORE_IC, MONOMORPHIC, \
=======================================
--- /branches/bleeding_edge/src/ic/arm/ic-arm.cc Mon Sep 22 13:23:27 2014 UTC +++ /branches/bleeding_edge/src/ic/arm/ic-arm.cc Thu Oct 9 14:30:44 2014 UTC
@@ -765,8 +765,9 @@
 }


-void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
-                                   StrictMode strict_mode) {
+void KeyedStoreIC::GenerateGeneric(
+    MacroAssembler* masm, StrictMode strict_mode,
+    KeyedStoreStubCacheRequirement handler_requirement) {
   // ---------- S t a t e --------------
   //  -- r0     : value
   //  -- r1     : key
@@ -775,7 +776,7 @@
   // -----------------------------------
   Label slow, fast_object, fast_object_grow;
   Label fast_double, fast_double_grow;
-  Label array, extra, check_if_double_array;
+  Label array, extra, check_if_double_array, maybe_name_key, miss;

   // Register usage.
   Register value = StoreDescriptor::ValueRegister();
@@ -790,7 +791,7 @@
   // r4 and r5 are used as general scratch registers.

   // Check that the key is a smi.
-  __ JumpIfNotSmi(key, &slow);
+  __ JumpIfNotSmi(key, &maybe_name_key);
   // Check that the object isn't a smi.
   __ JumpIfSmi(receiver, &slow);
   // Get the map of the object.
@@ -822,6 +823,23 @@
   // r1: key.
   // r2: receiver.
   PropertyICCompiler::GenerateRuntimeSetProperty(masm, strict_mode);
+  // Never returns to here.
+
+  __ bind(&maybe_name_key);
+  __ ldr(r4, FieldMemOperand(key, HeapObject::kMapOffset));
+  __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
+  __ JumpIfNotUniqueNameInstanceType(r4, &slow);
+  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
+      Code::ComputeHandlerFlags(Code::STORE_IC));
+ masm->isolate()->stub_cache()->GenerateProbe(masm, flags, false, receiver,
+                                               key, r3, r4, r5, r6);
+  // Cache miss.
+  if (handler_requirement == kCallRuntimeOnMissingHandler) {
+    __ b(&slow);
+  } else {
+    DCHECK(handler_requirement == kMissOnMissingHandler);
+    __ b(&miss);
+  }

   // Extra capacity case: Check if there is extra capacity to
   // perform the store and update the length. Used for adding one
@@ -863,6 +881,9 @@
&slow, kDontCheckMap, kIncrementLength, value, key, receiver, receiver_map, elements_map,
                                   elements);
+
+  __ bind(&miss);
+  GenerateMiss(masm);
 }


=======================================
--- /branches/bleeding_edge/src/ic/arm64/ic-arm64.cc Mon Sep 22 13:23:27 2014 UTC +++ /branches/bleeding_edge/src/ic/arm64/ic-arm64.cc Thu Oct 9 14:30:44 2014 UTC
@@ -798,8 +798,9 @@
 }


-void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
-                                   StrictMode strict_mode) {
+void KeyedStoreIC::GenerateGeneric(
+    MacroAssembler* masm, StrictMode strict_mode,
+    KeyedStoreStubCacheRequirement handler_requirement) {
   ASM_LOCATION("KeyedStoreIC::GenerateGeneric");
   Label slow;
   Label array;
@@ -808,6 +809,8 @@
   Label fast_object_grow;
   Label fast_double_grow;
   Label fast_double;
+  Label maybe_name_key;
+  Label miss;

   Register value = StoreDescriptor::ValueRegister();
   Register key = StoreDescriptor::NameRegister();
@@ -820,7 +823,7 @@
   Register elements = x4;
   Register elements_map = x5;

-  __ JumpIfNotSmi(key, &slow);
+  __ JumpIfNotSmi(key, &maybe_name_key);
   __ JumpIfSmi(receiver, &slow);
   __ Ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset));

@@ -853,7 +856,23 @@
   //  x1: key
   //  x2: receiver
   PropertyICCompiler::GenerateRuntimeSetProperty(masm, strict_mode);
+  // Never returns to here.

+  __ bind(&maybe_name_key);
+  __ Ldr(x10, FieldMemOperand(key, HeapObject::kMapOffset));
+  __ Ldrb(x10, FieldMemOperand(x10, Map::kInstanceTypeOffset));
+  __ JumpIfNotUniqueNameInstanceType(x10, &slow);
+  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
+      Code::ComputeHandlerFlags(Code::STORE_IC));
+ masm->isolate()->stub_cache()->GenerateProbe(masm, flags, false, receiver,
+                                               key, x3, x4, x5, x6);
+  // Cache miss.
+  if (handler_requirement == kCallRuntimeOnMissingHandler) {
+    __ B(&slow);
+  } else {
+    DCHECK(handler_requirement == kMissOnMissingHandler);
+    __ B(&miss);
+  }

   __ Bind(&extra);
   // Extra capacity case: Check if there is extra capacity to
@@ -895,6 +914,11 @@
&slow, kDontCheckMap, kIncrementLength, value, key, receiver, receiver_map, elements_map,
                                   elements);
+
+  if (handler_requirement == kMissOnMissingHandler) {
+    __ bind(&miss);
+    GenerateMiss(masm);
+  }
 }


=======================================
--- /branches/bleeding_edge/src/ic/ia32/ic-ia32.cc Mon Sep 22 13:23:27 2014 UTC +++ /branches/bleeding_edge/src/ic/ia32/ic-ia32.cc Thu Oct 9 14:30:44 2014 UTC
@@ -672,12 +672,13 @@
 }


-void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
-                                   StrictMode strict_mode) {
+void KeyedStoreIC::GenerateGeneric(
+    MacroAssembler* masm, StrictMode strict_mode,
+    KeyedStoreStubCacheRequirement handler_requirement) {
   // Return address is on the stack.
   Label slow, fast_object, fast_object_grow;
   Label fast_double, fast_double_grow;
-  Label array, extra, check_if_double_array;
+  Label array, extra, check_if_double_array, maybe_name_key, miss;
   Register receiver = StoreDescriptor::ReceiverRegister();
   Register key = StoreDescriptor::NameRegister();
   DCHECK(receiver.is(edx));
@@ -693,7 +694,7 @@
             1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved);
   __ j(not_zero, &slow);
   // Check that the key is a smi.
-  __ JumpIfNotSmi(key, &slow);
+  __ JumpIfNotSmi(key, &maybe_name_key);
   __ CmpInstanceType(edi, JS_ARRAY_TYPE);
   __ j(equal, &array);
   // Check that the object is some kind of JSObject.
@@ -711,6 +712,23 @@
   // Slow case: call runtime.
   __ bind(&slow);
   PropertyICCompiler::GenerateRuntimeSetProperty(masm, strict_mode);
+  // Never returns to here.
+
+  __ bind(&maybe_name_key);
+  __ mov(ebx, FieldOperand(key, HeapObject::kMapOffset));
+  __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
+  __ JumpIfNotUniqueNameInstanceType(ebx, &slow);
+  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
+      Code::ComputeHandlerFlags(Code::STORE_IC));
+ masm->isolate()->stub_cache()->GenerateProbe(masm, flags, false, receiver,
+                                               key, ebx, no_reg);
+  // Cache miss.
+  if (handler_requirement == kCallRuntimeOnMissingHandler) {
+    __ jmp(&slow);
+  } else {
+    DCHECK(handler_requirement == kMissOnMissingHandler);
+    __ jmp(&miss);
+  }

   // Extra capacity case: Check if there is extra capacity to
   // perform the store and update the length. Used for adding one
@@ -753,6 +771,11 @@
                                   kCheckMap, kDontIncrementLength);
KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow,
                                   &slow, kDontCheckMap, kIncrementLength);
+
+  if (handler_requirement == kMissOnMissingHandler) {
+    __ bind(&miss);
+    GenerateMiss(masm);
+  }
 }


=======================================
--- /branches/bleeding_edge/src/ic/ic.cc        Wed Oct  8 09:15:09 2014 UTC
+++ /branches/bleeding_edge/src/ic/ic.cc        Thu Oct  9 14:30:44 2014 UTC
@@ -801,18 +801,26 @@
     case POLYMORPHIC:
       if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) {
         if (UpdatePolymorphicIC(name, code)) break;
+        // For keyed stubs, we can't know whether old handlers were for the
+        // same key.
         CopyICToMegamorphicCache(name);
       }
       set_target(*megamorphic_stub());
     // Fall through.
     case MEGAMORPHIC:
       UpdateMegamorphicCache(*receiver_type(), *name, *code);
+      // Indicate that we've handled this case.
+      target_set_ = true;
       break;
     case DEBUG_STUB:
       break;
     case DEFAULT:
+      UNREACHABLE();
+      break;
     case GENERIC:
-      UNREACHABLE();
+ // The generic keyed store stub re-uses store handlers, which can miss.
+      // That's ok, no reason to do anything.
+      DCHECK(target()->kind() == Code::KEYED_STORE_IC);
       break;
   }
 }
@@ -894,7 +902,8 @@


 void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) {
- if (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC) return;
+  // Megamorphic state isn't implemented for keyed loads currently.
+  if (kind() == Code::KEYED_LOAD_IC) return;
   Map* map = *TypeToMap(type, isolate());
   isolate()->stub_cache()->Set(name, map, code);
 }
@@ -1365,9 +1374,9 @@
   } else {
     DCHECK(kind() == Code::KEYED_STORE_IC);
     if (strict_mode() == STRICT) {
-      return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
+      return isolate()->builtins()->KeyedStoreIC_Megamorphic_Strict();
     } else {
-      return isolate()->builtins()->KeyedStoreIC_Generic();
+      return isolate()->builtins()->KeyedStoreIC_Megamorphic();
     }
   }
 }
@@ -1813,12 +1822,12 @@
         StoreIC::Store(object, Handle<String>::cast(key), value,
                        JSReceiver::MAY_BE_STORE_FROM_KEYED),
         Object);
-    // TODO(jkummerow): Ideally we'd wrap this in "if (!is_target_set())",
-    // but doing so causes Hydrogen crashes. Needs investigation.
-    TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
-                     "unhandled internalized string key");
-    TRACE_IC("StoreIC", key);
-    set_target(*stub);
+    if (!is_target_set()) {
+      TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
+                       "unhandled internalized string key");
+      TRACE_IC("StoreIC", key);
+      set_target(*stub);
+    }
     return store_handle;
   }

@@ -2088,7 +2097,7 @@
   DCHECK(args.length() == 3);
   StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
   Handle<Object> receiver = args.at<Object>(0);
-  Handle<String> key = args.at<String>(1);
+  Handle<Name> key = args.at<Name>(1);
   ic.UpdateState(receiver, key);
   Handle<Object> result;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
@@ -2103,7 +2112,7 @@
   DCHECK(args.length() == 3 || args.length() == 4);
   StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
   Handle<Object> receiver = args.at<Object>(0);
-  Handle<String> key = args.at<String>(1);
+  Handle<Name> key = args.at<Name>(1);
   ic.UpdateState(receiver, key);
   Handle<Object> result;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
=======================================
--- /branches/bleeding_edge/src/ic/ic.h Wed Oct  8 09:15:09 2014 UTC
+++ /branches/bleeding_edge/src/ic/ic.h Thu Oct  9 14:30:44 2014 UTC
@@ -223,7 +223,6 @@
     return target_maps_.length() > 0 ? *target_maps_.at(0) : NULL;
   }

- protected:
   inline void UpdateTarget();

  private:
@@ -526,6 +525,12 @@
 enum KeyedStoreIncrementLength { kDontIncrementLength, kIncrementLength };


+enum KeyedStoreStubCacheRequirement {
+  kCallRuntimeOnMissingHandler,
+  kMissOnMissingHandler
+};
+
+
 class KeyedStoreIC : public StoreIC {
  public:
   // ExtraICState bits (building on IC)
@@ -559,7 +564,9 @@
   }
   static void GenerateMiss(MacroAssembler* masm);
   static void GenerateSlow(MacroAssembler* masm);
- static void GenerateGeneric(MacroAssembler* masm, StrictMode strict_mode);
+  static void GenerateGeneric(
+      MacroAssembler* masm, StrictMode strict_mode,
+      KeyedStoreStubCacheRequirement handler_requirement);
   static void GenerateSloppyArguments(MacroAssembler* masm);

  protected:
=======================================
--- /branches/bleeding_edge/src/ic/x64/ic-x64.cc Mon Sep 22 13:23:27 2014 UTC +++ /branches/bleeding_edge/src/ic/x64/ic-x64.cc Thu Oct 9 14:30:44 2014 UTC
@@ -566,12 +566,13 @@
 }


-void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
-                                   StrictMode strict_mode) {
+void KeyedStoreIC::GenerateGeneric(
+    MacroAssembler* masm, StrictMode strict_mode,
+    KeyedStoreStubCacheRequirement handler_requirement) {
   // Return address is on the stack.
   Label slow, slow_with_tagged_index, fast_object, fast_object_grow;
   Label fast_double, fast_double_grow;
-  Label array, extra, check_if_double_array;
+  Label array, extra, check_if_double_array, maybe_name_key, miss;
   Register receiver = StoreDescriptor::ReceiverRegister();
   Register key = StoreDescriptor::NameRegister();
   DCHECK(receiver.is(rdx));
@@ -587,7 +588,7 @@
Immediate(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved));
   __ j(not_zero, &slow_with_tagged_index);
   // Check that the key is a smi.
-  __ JumpIfNotSmi(key, &slow_with_tagged_index);
+  __ JumpIfNotSmi(key, &maybe_name_key);
   __ SmiToInteger32(key, key);

   __ CmpInstanceType(r9, JS_ARRAY_TYPE);
@@ -609,6 +610,22 @@
   __ bind(&slow_with_tagged_index);
   PropertyICCompiler::GenerateRuntimeSetProperty(masm, strict_mode);
   // Never returns to here.
+
+  __ bind(&maybe_name_key);
+  __ movp(r9, FieldOperand(key, HeapObject::kMapOffset));
+  __ movzxbp(r9, FieldOperand(r9, Map::kInstanceTypeOffset));
+  __ JumpIfNotUniqueNameInstanceType(r9, &slow_with_tagged_index);
+  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
+      Code::ComputeHandlerFlags(Code::STORE_IC));
+ masm->isolate()->stub_cache()->GenerateProbe(masm, flags, false, receiver,
+                                               key, rbx, no_reg);
+  // Cache miss.
+  if (handler_requirement == kCallRuntimeOnMissingHandler) {
+    __ jmp(&slow_with_tagged_index);
+  } else {
+    DCHECK(handler_requirement == kMissOnMissingHandler);
+    __ jmp(&miss);
+  }

   // Extra capacity case: Check if there is extra capacity to
   // perform the store and update the length. Used for adding one
@@ -648,6 +665,11 @@
                                   kCheckMap, kDontIncrementLength);
KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow,
                                   &slow, kDontCheckMap, kIncrementLength);
+
+  if (handler_requirement == kMissOnMissingHandler) {
+    __ bind(&miss);
+    GenerateMiss(masm);
+  }
 }


=======================================
--- /branches/bleeding_edge/src/ic/x64/stub-cache-x64.cc Mon Sep 8 12:51:29 2014 UTC +++ /branches/bleeding_edge/src/ic/x64/stub-cache-x64.cc Thu Oct 9 14:30:44 2014 UTC
@@ -41,14 +41,14 @@
   __ LoadAddress(kScratchRegister, key_offset);

   // Check that the key in the entry matches the name.
-  // Multiply entry offset by 16 to get the entry address. Since the
-  // offset register already holds the entry offset times four, multiply
-  // by a further four.
-  __ cmpl(name, Operand(kScratchRegister, offset, scale_factor, 0));
+  __ cmpp(name, Operand(kScratchRegister, offset, scale_factor, 0));
   __ j(not_equal, &miss);

   // Get the map entry from the cache.
   // Use key_offset + kPointerSize * 2, rather than loading map_offset.
+  DCHECK(isolate->stub_cache()->map_reference(table).address() -
+             isolate->stub_cache()->key_reference(table).address() ==
+         kPointerSize * 2);
   __ movp(kScratchRegister,
Operand(kScratchRegister, offset, scale_factor, kPointerSize * 2)); __ cmpp(kScratchRegister, FieldOperand(receiver, HeapObject::kMapOffset));

--
--
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/d/optout.

Reply via email to