Reviewers: mvstanton,

Message:
So much plumbing for such a small change...

The interesting bits are ic-compiler.cc and hydrogen.cc. Please take a look.

Description:
Fix type feedback for name-keyed stores

BUG=chromium:422212
LOG=n

Please review this at https://codereview.chromium.org/648703002/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+59, -23 lines):
  M src/ast.h
  M src/hydrogen.cc
  M src/ic/ic.h
  M src/ic/ic-compiler.h
  M src/ic/ic-compiler.cc
  M src/objects.h
  M src/type-info.h
  M src/type-info.cc
  M src/typing.cc


Index: src/ast.h
diff --git a/src/ast.h b/src/ast.h
index 6cb866925968ee34f2b08ccc88a23e34eebe31d6..f4ed5acad284a48ed348e980bda224ba156a7723 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -377,6 +377,10 @@ class Expression : public AstNode {
     UNREACHABLE();
     return STANDARD_STORE;
   }
+  virtual IcCheckType GetKeyType() {
+    UNREACHABLE();
+    return ELEMENT;
+  }

   // TODO(rossberg): this should move to its own AST node eventually.
   virtual void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle);
@@ -2101,10 +2105,12 @@ class CountOperation FINAL : public Expression {
   virtual SmallMapList* GetReceiverTypes() OVERRIDE {
     return &receiver_types_;
   }
+  virtual IcCheckType GetKeyType() OVERRIDE { return key_type_; }
   virtual KeyedAccessStoreMode GetStoreMode() OVERRIDE {
     return store_mode_;
   }
   Type* type() const { return type_; }
+  void set_key_type(IcCheckType type) { key_type_ = type; }
   void set_store_mode(KeyedAccessStoreMode mode) { store_mode_ = mode; }
   void set_type(Type* type) { type_ = type; }

@@ -2131,6 +2137,7 @@ class CountOperation FINAL : public Expression {
  private:
   Token::Value op_;
   bool is_prefix_ : 1;
+  IcCheckType key_type_ : 1;
   KeyedAccessStoreMode store_mode_ : 5;  // Windows treats as signed,
                                          // must have extra bit.
   Type* type_;
@@ -2243,10 +2250,12 @@ class Assignment FINAL : public Expression {
   virtual SmallMapList* GetReceiverTypes() OVERRIDE {
     return &receiver_types_;
   }
+  virtual IcCheckType GetKeyType() OVERRIDE { return key_type_; }
   virtual KeyedAccessStoreMode GetStoreMode() OVERRIDE {
     return store_mode_;
   }
   void set_is_uninitialized(bool b) { is_uninitialized_ = b; }
+  void set_key_type(IcCheckType key_type) { key_type_ = key_type; }
   void set_store_mode(KeyedAccessStoreMode mode) { store_mode_ = mode; }

  protected:
@@ -2271,6 +2280,7 @@ class Assignment FINAL : public Expression {
   Expression* value_;
   BinaryOperation* binary_operation_;
   bool is_uninitialized_ : 1;
+  IcCheckType key_type_ : 1;
   KeyedAccessStoreMode store_mode_ : 5;  // Windows treats as signed,
                                          // must have extra bit.
   SmallMapList receiver_types_;
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 2c4435cc4cb2d1c89917ee5f11e701b7f737cfac..e956947495ebdebb7da03741ce57dc1d97f31173 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -7174,8 +7174,14 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
   bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone());

   bool force_generic = false;
-  if (access_type == STORE &&
-      (monomorphic || (types != NULL && !types->is_empty()))) {
+  if (access_type == STORE && expr->GetKeyType() == PROPERTY) {
+ // Non-Generic accesses assume that elements are being accessed, and will
+    // deopt for non-index keys, which the IC knows will occur.
+ // TODO(jkummerow): Consider adding proper support for property accesses.
+    force_generic = true;
+    monomorphic = false;
+  } else if (access_type == STORE &&
+             (monomorphic || (types != NULL && !types->is_empty()))) {
// Stores can't be mono/polymorphic if their prototype chain has dictionary
     // elements. However a receiver map that has dictionary elements itself
// should be left to normal mono/poly behavior (the other maps may benefit
Index: src/ic/ic-compiler.cc
diff --git a/src/ic/ic-compiler.cc b/src/ic/ic-compiler.cc
index aeae4ba90e5d0ef6e216e5e34095e8d3e16fca53..24715645da13d0c3a7db82b93238861ad36ecb5b 100644
--- a/src/ic/ic-compiler.cc
+++ b/src/ic/ic-compiler.cc
@@ -57,6 +57,13 @@ Handle<Code> PropertyICCompiler::ComputeMonomorphic(

   CacheHolderFlag flag;
   Handle<Map> stub_holder = IC::GetICCacheHolder(*type, isolate, &flag);
+  if (kind == Code::KEYED_STORE_IC) {
+    // Always set the "property" bit.
+    extra_ic_state =
+        KeyedStoreIC::IcCheckTypeField::update(extra_ic_state, PROPERTY);
+    DCHECK(STANDARD_STORE ==
+           KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state));
+  }

   Handle<Code> ic;
   // There are multiple string maps that all use the same prototype. That
@@ -68,13 +75,6 @@ Handle<Code> PropertyICCompiler::ComputeMonomorphic(
     if (!ic.is_null()) return ic;
   }

-#ifdef DEBUG
-  if (kind == Code::KEYED_STORE_IC) {
-    DCHECK(STANDARD_STORE ==
-           KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state));
-  }
-#endif
-
   PropertyICCompiler ic_compiler(isolate, kind, extra_ic_state, flag);
   ic = ic_compiler.CompileMonomorphic(type, handler, name, PROPERTY);

Index: src/ic/ic-compiler.h
diff --git a/src/ic/ic-compiler.h b/src/ic/ic-compiler.h
index 3b12157a0786f26148e379acf9dd5ef27b6c1449..97c07d0ecaf65a55c110470cf07caf00a711b764 100644
--- a/src/ic/ic-compiler.h
+++ b/src/ic/ic-compiler.h
@@ -11,9 +11,6 @@ namespace v8 {
 namespace internal {


-enum IcCheckType { ELEMENT, PROPERTY };
-
-
 class PropertyICCompiler : public PropertyAccessCompiler {
  public:
   // Finds the Code object stored in the Heap::non_monomorphic_cache().
Index: src/ic/ic.h
diff --git a/src/ic/ic.h b/src/ic/ic.h
index 15479371cb6f80e217309bd801f222add71b0637..7a6ee616b8061be2fa0e36eb1f1131342fdeb37f 100644
--- a/src/ic/ic.h
+++ b/src/ic/ic.h
@@ -542,6 +542,8 @@ class KeyedStoreIC : public StoreIC {
   class ExtraICStateKeyedAccessStoreMode
       : public BitField<KeyedAccessStoreMode, 2, 4> {};  // NOLINT

+  class IcCheckTypeField : public BitField<IcCheckType, 6, 1> {};
+
   static ExtraICState ComputeExtraICState(StrictMode flag,
                                           KeyedAccessStoreMode mode) {
     return StrictModeState::encode(flag) |
@@ -553,6 +555,10 @@ class KeyedStoreIC : public StoreIC {
     return ExtraICStateKeyedAccessStoreMode::decode(extra_state);
   }

+  static IcCheckType GetKeyType(ExtraICState extra_state) {
+    return IcCheckTypeField::decode(extra_state);
+  }
+
KeyedStoreIC(FrameDepth depth, Isolate* isolate) : StoreIC(depth, isolate) {
     DCHECK(target()->is_keyed_store_stub());
   }
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index 1faae8613b4d2e61e57a47bcef8c9f0f7df1b8f0..277df06ccac555344997191744076506f6e2ee20 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -232,6 +232,9 @@ static inline bool IsGrowStoreMode(KeyedAccessStoreMode store_mode) {
 }


+enum IcCheckType { ELEMENT, PROPERTY };
+
+
 // Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER.
 enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER };

Index: src/type-info.cc
diff --git a/src/type-info.cc b/src/type-info.cc
index 5b9a71dcb9bae6dc5aed3cc78f301ba27cb08175..9f50a38509590511a94c2c9d7993329ecf2e5539 100644
--- a/src/type-info.cc
+++ b/src/type-info.cc
@@ -101,16 +101,21 @@ byte TypeFeedbackOracle::ForInType(int feedback_vector_slot) {
 }


-KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode(
-    TypeFeedbackId ast_id) {
+void TypeFeedbackOracle::GetStoreModeAndKeyType(
+    TypeFeedbackId ast_id, KeyedAccessStoreMode* store_mode,
+    IcCheckType* key_type) {
   Handle<Object> maybe_code = GetInfo(ast_id);
   if (maybe_code->IsCode()) {
     Handle<Code> code = Handle<Code>::cast(maybe_code);
     if (code->kind() == Code::KEYED_STORE_IC) {
-      return KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state());
+      ExtraICState extra_ic_state = code->extra_ic_state();
+      *store_mode = KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state);
+      *key_type = KeyedStoreIC::GetKeyType(extra_ic_state);
+      return;
     }
   }
-  return STANDARD_STORE;
+  *store_mode = STANDARD_STORE;
+  *key_type = ELEMENT;
 }


@@ -271,10 +276,10 @@ void TypeFeedbackOracle::AssignmentReceiverTypes(

 void TypeFeedbackOracle::KeyedAssignmentReceiverTypes(
     TypeFeedbackId id, SmallMapList* receiver_types,
-    KeyedAccessStoreMode* store_mode) {
+    KeyedAccessStoreMode* store_mode, IcCheckType* key_type) {
   receiver_types->Clear();
   CollectReceiverTypes(id, receiver_types);
-  *store_mode = GetStoreMode(id);
+  GetStoreModeAndKeyType(id, store_mode, key_type);
 }


Index: src/type-info.h
diff --git a/src/type-info.h b/src/type-info.h
index 1343e0a76bf865015b93a3343946cb22e4d4a51a..bae11d7f1e7218c79903e1cdc807ed5d5b049571 100644
--- a/src/type-info.h
+++ b/src/type-info.h
@@ -36,7 +36,9 @@ class TypeFeedbackOracle: public ZoneObject {
   // be possible.
   byte ForInType(int feedback_vector_slot);

-  KeyedAccessStoreMode GetStoreMode(TypeFeedbackId id);
+  void GetStoreModeAndKeyType(TypeFeedbackId id,
+                              KeyedAccessStoreMode* store_mode,
+                              IcCheckType* key_type);

   void PropertyReceiverTypes(TypeFeedbackId id, Handle<String> name,
                              SmallMapList* receiver_types);
@@ -48,7 +50,8 @@ class TypeFeedbackOracle: public ZoneObject {
                                SmallMapList* receiver_types);
   void KeyedAssignmentReceiverTypes(TypeFeedbackId id,
                                     SmallMapList* receiver_types,
-                                    KeyedAccessStoreMode* store_mode);
+                                    KeyedAccessStoreMode* store_mode,
+                                    IcCheckType* key_type);
   void CountReceiverTypes(TypeFeedbackId id,
                           SmallMapList* receiver_types);

Index: src/typing.cc
diff --git a/src/typing.cc b/src/typing.cc
index a94cf623ed69201f78ca0e2caa4ca7088dc2ccef..1cfaf64f64a403e4a44b035c889c091625ac0592 100644
--- a/src/typing.cc
+++ b/src/typing.cc
@@ -444,9 +444,11 @@ void AstTyper::VisitAssignment(Assignment* expr) {
oracle()->AssignmentReceiverTypes(id, name, expr->GetReceiverTypes());
       } else {
         KeyedAccessStoreMode store_mode;
-        oracle()->KeyedAssignmentReceiverTypes(
-            id, expr->GetReceiverTypes(), &store_mode);
+        IcCheckType key_type;
+ oracle()->KeyedAssignmentReceiverTypes(id, expr->GetReceiverTypes(),
+                                               &store_mode, &key_type);
         expr->set_store_mode(store_mode);
+        expr->set_key_type(key_type);
       }
     }
   }
@@ -587,7 +589,11 @@ void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
 void AstTyper::VisitCountOperation(CountOperation* expr) {
   // Collect type feedback.
   TypeFeedbackId store_id = expr->CountStoreFeedbackId();
-  expr->set_store_mode(oracle()->GetStoreMode(store_id));
+  KeyedAccessStoreMode store_mode;
+  IcCheckType key_type;
+  oracle()->GetStoreModeAndKeyType(store_id, &store_mode, &key_type);
+  expr->set_store_mode(store_mode);
+  expr->set_key_type(key_type);
   oracle()->CountReceiverTypes(store_id, expr->GetReceiverTypes());
   expr->set_type(oracle()->CountType(expr->CountBinOpFeedbackId()));
   // TODO(rossberg): merge the count type with the generic expression type.


--
--
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