Vector ICs: Ensure KeyedAccessStore mode is encoded in all handlers.
authormvstanton <mvstanton@chromium.org>
Wed, 26 Aug 2015 10:47:49 +0000 (03:47 -0700)
committerCommit bot <commit-bot@chromium.org>
Wed, 26 Aug 2015 10:48:06 +0000 (10:48 +0000)
For vector-based keyed store ics, we need to know the current
KeyedAccessStore mode on ic MISS, and to produce optimized code.

We can't store this mode, which can change on any MISS in the IC
without patching. Therefore, this CL makes sure that the information is
redundantly available in the handlers embedded in the IC. This way,
when --vector-stores is turned on, we'll be able to extract that
information from the vector which maintains a list of these handlers.

BUG=

Review URL: https://codereview.chromium.org/1312693004

Cr-Commit-Position: refs/heads/master@{#30378}

src/ast.h
src/code-stubs.h
src/ic/ic-compiler.cc
src/ic/ic.cc
src/ic/ic.h

index 6e9390f..aa9cbb9 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -2234,8 +2234,8 @@ class CountOperation final : public Expression {
 
   class IsPrefixField : public BitField16<bool, 0, 1> {};
   class KeyTypeField : public BitField16<IcCheckType, 1, 1> {};
-  class StoreModeField : public BitField16<KeyedAccessStoreMode, 2, 4> {};
-  class TokenField : public BitField16<Token::Value, 6, 8> {};
+  class StoreModeField : public BitField16<KeyedAccessStoreMode, 2, 3> {};
+  class TokenField : public BitField16<Token::Value, 5, 8> {};
 
   // Starts with 16-bit field, which should get packed together with
   // Expression's trailing 16-bit field.
@@ -2405,8 +2405,8 @@ class Assignment final : public Expression {
 
   class IsUninitializedField : public BitField16<bool, 0, 1> {};
   class KeyTypeField : public BitField16<IcCheckType, 1, 1> {};
-  class StoreModeField : public BitField16<KeyedAccessStoreMode, 2, 4> {};
-  class TokenField : public BitField16<Token::Value, 6, 8> {};
+  class StoreModeField : public BitField16<KeyedAccessStoreMode, 2, 3> {};
+  class TokenField : public BitField16<Token::Value, 5, 8> {};
 
   // Starts with 16-bit field, which should get packed together with
   // Expression's trailing 16-bit field.
index ed4dec9..a1e0158 100644 (file)
@@ -1140,10 +1140,15 @@ class KeyedLoadSloppyArgumentsStub : public HandlerStub {
 };
 
 
+class CommonStoreModeBits : public BitField<KeyedAccessStoreMode, 0, 3> {};
+
 class KeyedStoreSloppyArgumentsStub : public HandlerStub {
  public:
-  explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate)
-      : HandlerStub(isolate) {}
+  explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate,
+                                         KeyedAccessStoreMode mode)
+      : HandlerStub(isolate) {
+    set_sub_minor_key(CommonStoreModeBits::encode(mode));
+  }
 
  protected:
   Code::Kind kind() const override { return Code::KEYED_STORE_IC; }
@@ -2595,9 +2600,9 @@ class StoreFastElementStub : public HydrogenCodeStub {
   StoreFastElementStub(Isolate* isolate, bool is_js_array,
                        ElementsKind elements_kind, KeyedAccessStoreMode mode)
       : HydrogenCodeStub(isolate) {
-    set_sub_minor_key(ElementsKindBits::encode(elements_kind) |
-                      IsJSArrayBits::encode(is_js_array) |
-                      StoreModeBits::encode(mode));
+    set_sub_minor_key(CommonStoreModeBits::encode(mode) |
+                      ElementsKindBits::encode(elements_kind) |
+                      IsJSArrayBits::encode(is_js_array));
   }
 
   static void GenerateAheadOfTime(Isolate* isolate);
@@ -2609,7 +2614,7 @@ class StoreFastElementStub : public HydrogenCodeStub {
   }
 
   KeyedAccessStoreMode store_mode() const {
-    return StoreModeBits::decode(sub_minor_key());
+    return CommonStoreModeBits::decode(sub_minor_key());
   }
 
   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
@@ -2619,10 +2624,11 @@ class StoreFastElementStub : public HydrogenCodeStub {
     return StoreDescriptor(isolate());
   }
 
+  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
+
  private:
-  class ElementsKindBits: public BitField<ElementsKind,      0, 8> {};
-  class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
-  class IsJSArrayBits: public BitField<bool,                12, 1> {};
+  class ElementsKindBits : public BitField<ElementsKind, 3, 8> {};
+  class IsJSArrayBits : public BitField<bool, 11, 1> {};
 
   DEFINE_HYDROGEN_CODE_STUB(StoreFastElement, HydrogenCodeStub);
 };
@@ -2836,9 +2842,11 @@ class InternalArrayNArgumentsConstructorStub : public
 
 class StoreElementStub : public PlatformCodeStub {
  public:
-  StoreElementStub(Isolate* isolate, ElementsKind elements_kind)
+  StoreElementStub(Isolate* isolate, ElementsKind elements_kind,
+                   KeyedAccessStoreMode mode)
       : PlatformCodeStub(isolate) {
-    minor_key_ = ElementsKindBits::encode(elements_kind);
+    minor_key_ = ElementsKindBits::encode(elements_kind) |
+                 CommonStoreModeBits::encode(mode);
   }
 
   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
@@ -2848,12 +2856,14 @@ class StoreElementStub : public PlatformCodeStub {
     return StoreDescriptor(isolate());
   }
 
+  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
+
  private:
   ElementsKind elements_kind() const {
     return ElementsKindBits::decode(minor_key_);
   }
 
-  class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
+  class ElementsKindBits : public BitField<ElementsKind, 3, 8> {};
 
   DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub);
 };
@@ -2957,25 +2967,25 @@ class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
                                  ElementsKind to_kind, bool is_jsarray,
                                  KeyedAccessStoreMode store_mode)
       : HydrogenCodeStub(isolate) {
-    set_sub_minor_key(FromBits::encode(from_kind) | ToBits::encode(to_kind) |
-                      IsJSArrayBits::encode(is_jsarray) |
-                      StoreModeBits::encode(store_mode));
+    set_sub_minor_key(CommonStoreModeBits::encode(store_mode) |
+                      FromBits::encode(from_kind) | ToBits::encode(to_kind) |
+                      IsJSArrayBits::encode(is_jsarray));
   }
 
   ElementsKind from_kind() const { return FromBits::decode(sub_minor_key()); }
   ElementsKind to_kind() const { return ToBits::decode(sub_minor_key()); }
   bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); }
   KeyedAccessStoreMode store_mode() const {
-    return StoreModeBits::decode(sub_minor_key());
+    return CommonStoreModeBits::decode(sub_minor_key());
   }
 
   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
+  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
 
  private:
-  class FromBits : public BitField<ElementsKind, 0, 8> {};
-  class ToBits : public BitField<ElementsKind, 8, 8> {};
-  class IsJSArrayBits : public BitField<bool, 16, 1> {};
-  class StoreModeBits : public BitField<KeyedAccessStoreMode, 17, 4> {};
+  class FromBits : public BitField<ElementsKind, 3, 8> {};
+  class ToBits : public BitField<ElementsKind, 11, 8> {};
+  class IsJSArrayBits : public BitField<bool, 19, 1> {};
 
   DEFINE_HYDROGEN_CODE_STUB(ElementsTransitionAndStore, HydrogenCodeStub);
 };
index d7b95da..2f9830a 100644 (file)
@@ -362,16 +362,20 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
                                          transitioned_map->elements_kind(),
                                          is_js_array, store_mode).GetCode();
     } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) {
+      // TODO(mvstanton): Consider embedding store_mode in the state of the slow
+      // keyed store ic for uniformity.
       cached_stub = isolate()->builtins()->KeyedStoreIC_Slow();
     } else {
       if (IsSloppyArgumentsElements(elements_kind)) {
-        cached_stub = KeyedStoreSloppyArgumentsStub(isolate()).GetCode();
+        cached_stub =
+            KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
       } else if (receiver_map->has_fast_elements() ||
                  receiver_map->has_fixed_typed_array_elements()) {
         cached_stub = StoreFastElementStub(isolate(), is_js_array,
                                            elements_kind, store_mode).GetCode();
       } else {
-        cached_stub = StoreElementStub(isolate(), elements_kind).GetCode();
+        cached_stub =
+            StoreElementStub(isolate(), elements_kind, store_mode).GetCode();
       }
     }
     DCHECK(!cached_stub.is_null());
@@ -396,13 +400,13 @@ Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic(
   bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
   Handle<Code> stub;
   if (receiver_map->has_sloppy_arguments_elements()) {
-    stub = KeyedStoreSloppyArgumentsStub(isolate()).GetCode();
+    stub = KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
   } else if (receiver_map->has_fast_elements() ||
              receiver_map->has_fixed_typed_array_elements()) {
     stub = StoreFastElementStub(isolate(), is_jsarray, elements_kind,
                                 store_mode).GetCode();
   } else {
-    stub = StoreElementStub(isolate(), elements_kind).GetCode();
+    stub = StoreElementStub(isolate(), elements_kind, store_mode).GetCode();
   }
 
   Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
index 373aec7..b35c2a8 100644 (file)
@@ -2059,6 +2059,44 @@ static KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
 }
 
 
+void KeyedStoreIC::ValidateStoreMode(Handle<Code> stub) {
+#ifdef DEBUG
+  DCHECK(!FLAG_vector_stores);
+  if (stub.is_null() || *stub == *megamorphic_stub() || *stub == *slow_stub()) {
+    return;
+  }
+
+  // Query the keyed store mode.
+  ExtraICState state = stub->extra_ic_state();
+  KeyedAccessStoreMode stub_mode = GetKeyedAccessStoreMode(state);
+
+  MapHandleList map_list;
+  stub->FindAllMaps(&map_list);
+  CodeHandleList list;
+  stub->FindHandlers(&list, map_list.length());
+  for (int i = 0; i < list.length(); i++) {
+    Handle<Code> handler = list.at(i);
+    CHECK(handler->is_handler());
+    CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key());
+    uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key());
+    // Ensure that we only see handlers we know have the store mode embedded.
+    CHECK(major_key == CodeStub::KeyedStoreSloppyArguments ||
+          major_key == CodeStub::StoreFastElement ||
+          major_key == CodeStub::StoreElement ||
+          major_key == CodeStub::ElementsTransitionAndStore ||
+          *handler == *isolate()->builtins()->KeyedStoreIC_Slow());
+    // Ensure that the store mode matches that of the IC.
+    CHECK(major_key == CodeStub::NoCache ||
+          stub_mode == CommonStoreModeBits::decode(minor_key));
+    // The one exception is the keyed store slow builtin, which doesn't include
+    // store mode.
+    CHECK(major_key != CodeStub::NoCache ||
+          *handler == *isolate()->builtins()->KeyedStoreIC_Slow());
+  }
+#endif  // DEBUG
+}
+
+
 MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
                                         Handle<Object> key,
                                         Handle<Object> value) {
@@ -2139,6 +2177,10 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
           KeyedAccessStoreMode store_mode =
               GetStoreMode(receiver, index, value);
           stub = StoreElementStub(receiver, store_mode);
+
+          // Validate that the store_mode in the stub can also be derived
+          // from peeking in the code bits of the handlers.
+          ValidateStoreMode(stub);
         } else {
           TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "dictionary prototype");
         }
index ee5fd26..f8076cc 100644 (file)
@@ -525,9 +525,9 @@ class KeyedStoreIC : public StoreIC {
   // When more language modes are added, these BitFields need to move too.
   STATIC_ASSERT(i::LANGUAGE_END == 3);
   class ExtraICStateKeyedAccessStoreMode
-      : public BitField<KeyedAccessStoreMode, 3, 4> {};  // NOLINT
+      : public BitField<KeyedAccessStoreMode, 3, 3> {};  // NOLINT
 
-  class IcCheckTypeField : public BitField<IcCheckType, 7, 1> {};
+  class IcCheckTypeField : public BitField<IcCheckType, 6, 1> {};
 
   static ExtraICState ComputeExtraICState(LanguageMode flag,
                                           KeyedAccessStoreMode mode) {
@@ -599,6 +599,8 @@ class KeyedStoreIC : public StoreIC {
   Handle<Map> ComputeTransitionedMap(Handle<Map> map,
                                      KeyedAccessStoreMode store_mode);
 
+  void ValidateStoreMode(Handle<Code> stub);
+
   friend class IC;
 };