Merge polymorphic load/store handling
authorverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 5 Feb 2014 15:28:57 +0000 (15:28 +0000)
committerverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 5 Feb 2014 15:28:57 +0000 (15:28 +0000)
R=dcarney@chromium.org

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

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

src/hydrogen.cc
src/hydrogen.h

index 1593301..ce83d90 100644 (file)
@@ -5610,10 +5610,12 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreMonomorphic(
 }
 
 
-void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
+void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
+    PropertyAccessType access_type,
     BailoutId ast_id,
     BailoutId return_id,
     HValue* object,
+    HValue* value,
     SmallMapList* types,
     Handle<String> name) {
   // Something did not match; must use a polymorphic load.
@@ -5623,8 +5625,9 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
   bool handled_string = false;
 
   bool handle_smi = false;
+  STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
   for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
-    PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
+    PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name);
     if (info.type()->Is(Type::String())) {
       if (handled_string) continue;
       handled_string = true;
@@ -5643,7 +5646,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
   handled_string = false;
 
   for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
-    PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
+    PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name);
     if (info.type()->Is(Type::String())) {
       if (handled_string) continue;
       handled_string = true;
@@ -5692,16 +5695,28 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
 
     set_current_block(if_true);
 
-    HInstruction* load = BuildLoadMonomorphic(
-        &info, object, dependency, ast_id,
-        return_id, FLAG_polymorphic_inlining);
-    if (load == NULL) {
+    HInstruction* access = NULL;
+    HValue* result = NULL;
+    switch (access_type) {
+      case LOAD:
+        access = BuildLoadMonomorphic(
+            &info, object, dependency, ast_id,
+            return_id, FLAG_polymorphic_inlining);
+        result = access;
+        break;
+      case STORE:
+        access = BuildStoreMonomorphic(
+            &info, dependency, value, ast_id, return_id,
+            FLAG_polymorphic_inlining);
+        result = value;
+        break;
+    }
+
+    if (access == NULL) {
       if (HasStackOverflow()) return;
     } else {
-      if (!load->IsLinked()) {
-        AddInstruction(load);
-      }
-      if (!ast_context()->IsEffect()) Push(load);
+      if (!access->IsLinked()) AddInstruction(access);
+      if (!ast_context()->IsEffect()) Push(result);
     }
 
     if (current_block() != NULL) Goto(join);
@@ -5716,10 +5731,28 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
     // that the environment stack matches the depth on deopt that it otherwise
     // would have had after a successful load.
     if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
-    FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join);
+    const char* message = "";
+    switch (access_type) {
+      case LOAD:
+        message = "Unknown map in polymorphic load";
+        break;
+      case STORE:
+        message = "Unknown map in polymorphic store";
+        break;
+    }
+    FinishExitWithHardDeoptimization(message, join);
   } else {
-    HInstruction* load = Add<HLoadNamedGeneric>(object, name);
-    if (!ast_context()->IsEffect()) Push(load);
+    HValue* result = NULL;
+    switch (access_type) {
+      case LOAD:
+        result = Add<HLoadNamedGeneric>(object, name);
+        break;
+      case STORE:
+        AddInstruction(BuildStoreNamedGeneric(object, name, value));
+        result = value;
+        break;
+    }
+    if (!ast_context()->IsEffect()) Push(result);
 
     if (join != NULL) {
       Goto(join);
@@ -5737,90 +5770,6 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
 }
 
 
-void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
-    BailoutId assignment_id,
-    BailoutId return_id,
-    HValue* object,
-    HValue* value,
-    SmallMapList* types,
-    Handle<String> name) {
-  int count = 0;
-  HBasicBlock* join = NULL;
-  // TODO(verwaest): Unify with polymorphic load handling.
-  for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
-    PropertyAccessInfo info(this, STORE, ToType(types->at(i)), name);
-    if (info.CanAccessMonomorphic()) {
-      if (count == 0) {
-        BuildCheckHeapObject(object);
-        join = graph()->CreateBasicBlock();
-      }
-      ++count;
-      HBasicBlock* if_true = graph()->CreateBasicBlock();
-      HBasicBlock* if_false = graph()->CreateBasicBlock();
-      HCompareMap* compare = New<HCompareMap>(
-          object, info.map(),  if_true, if_false);
-      FinishCurrentBlock(compare);
-
-      set_current_block(if_true);
-
-      HInstruction* store;
-      store = BuildStoreMonomorphic(
-          &info, compare, value, assignment_id, return_id,
-          FLAG_polymorphic_inlining);
-
-      if (store == NULL) {
-        if (HasStackOverflow()) return;
-      } else {
-        ASSERT(!store->IsLinked());
-        AddInstruction(store);
-        if (!ast_context()->IsEffect()) Push(value);
-      }
-
-      if (current_block() != NULL) Goto(join);
-      set_current_block(if_false);
-    }
-  }
-
-  // Finish up.  Unconditionally deoptimize if we've handled all the maps we
-  // know about and do not want to handle ones we've never seen.  Otherwise
-  // use a generic IC.
-  if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
-    FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join);
-  } else {
-    HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
-    AddInstruction(instr);
-
-    if (join != NULL) {
-      if (!ast_context()->IsEffect()) {
-        Push(value);
-      }
-      Goto(join);
-    } else {
-      // The HSimulate for the store should not see the stored value in
-      // effect contexts (it is not materialized at expr->id() in the
-      // unoptimized code).
-      if (instr->HasObservableSideEffects()) {
-        if (ast_context()->IsEffect()) {
-          Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
-        } else {
-          Push(value);
-          Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
-          Drop(1);
-        }
-      }
-      return ast_context()->ReturnValue(value);
-    }
-  }
-
-  ASSERT(join != NULL);
-  join->SetJoinId(assignment_id);
-  set_current_block(join);
-  if (!ast_context()->IsEffect()) {
-    ast_context()->ReturnValue(Pop());
-  }
-}
-
-
 static bool ComputeReceiverTypes(Expression* expr,
                                  HValue* receiver,
                                  SmallMapList** t,
@@ -5882,8 +5831,8 @@ void HOptimizedGraphBuilder::BuildStore(Expression* expr,
   if (types->length() > 0) {
     PropertyAccessInfo info(this, STORE, ToType(types->first()), name);
     if (!info.CanAccessAsMonomorphic(types)) {
-      return HandlePolymorphicStoreNamedField(
-          ast_id, return_id, object, value, types, name);
+      return HandlePolymorphicNamedFieldAccess(
+          STORE, ast_id, return_id, object, value, types, name);
     }
 
     ASSERT(!info.type()->Is(Type::Number()));
@@ -6734,8 +6683,8 @@ void HOptimizedGraphBuilder::BuildLoad(Property* expr,
     if (types->length() > 0) {
       PropertyAccessInfo info(this, LOAD, ToType(types->first()), name);
       if (!info.CanAccessAsMonomorphic(types)) {
-        return HandlePolymorphicLoadNamedField(
-            ast_id, expr->LoadId(), object, types, name);
+        return HandlePolymorphicNamedFieldAccess(
+            LOAD, ast_id, expr->LoadId(), object, NULL, types, name);
       }
 
       HValue* checked_object;
index 7eb2c84..46cfa71 100644 (file)
@@ -2187,6 +2187,8 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
   Type* ToType(Handle<Map> map) { return IC::MapToType<Type>(map, zone()); }
 
  private:
+  enum PropertyAccessType { LOAD, STORE };
+
   // Helpers for flow graph construction.
   enum GlobalPropertyAccess {
     kUseCell,
@@ -2251,11 +2253,13 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
 
   void HandlePropertyAssignment(Assignment* expr);
   void HandleCompoundAssignment(Assignment* expr);
-  void HandlePolymorphicLoadNamedField(BailoutId ast_id,
-                                       BailoutId return_id,
-                                       HValue* object,
-                                       SmallMapList* types,
-                                       Handle<String> name);
+  void HandlePolymorphicNamedFieldAccess(PropertyAccessType access_type,
+                                         BailoutId ast_id,
+                                         BailoutId return_id,
+                                         HValue* object,
+                                         HValue* value,
+                                         SmallMapList* types,
+                                         Handle<String> name);
 
   void VisitTypedArrayInitialize(CallRuntime* expr);
 
@@ -2264,7 +2268,6 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
 
   void VisitDataViewInitialize(CallRuntime* expr);
 
-  enum PropertyAccessType { LOAD, STORE };
   class PropertyAccessInfo {
    public:
     PropertyAccessInfo(HOptimizedGraphBuilder* builder,
@@ -2390,12 +2393,6 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
                                       BailoutId return_id,
                                       bool can_inline_accessor = true);
 
-  void HandlePolymorphicStoreNamedField(BailoutId assignment_id,
-                                        BailoutId return_id,
-                                        HValue* object,
-                                        HValue* value,
-                                        SmallMapList* types,
-                                        Handle<String> name);
   void HandlePolymorphicCallNamed(Call* expr,
                                   HValue* receiver,
                                   SmallMapList* types,