inline api setters in crankshaft
authordcarney@chromium.org <dcarney@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 6 Feb 2014 07:31:08 +0000 (07:31 +0000)
committerdcarney@chromium.org <dcarney@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 6 Feb 2014 07:31:08 +0000 (07:31 +0000)
R=verwaest@chromium.org

BUG=

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

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

src/hydrogen.cc
src/hydrogen.h
test/cctest/test-api.cc

index 8caeab7..591f00f 100644 (file)
@@ -5585,7 +5585,8 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess(
     } else if (FLAG_inline_accessors && can_inline_accessor) {
       bool success = info->IsLoad()
           ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id)
-          : TryInlineSetter(info->accessor(), ast_id, return_id, value);
+          : TryInlineSetter(
+              info->accessor(), info->map(), ast_id, return_id, value);
       if (success) return NULL;
     }
 
@@ -7420,9 +7421,11 @@ bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
 
 
 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
+                                             Handle<Map> receiver_map,
                                              BailoutId id,
                                              BailoutId assignment_id,
                                              HValue* implicit_return_value) {
+  if (TryInlineApiSetter(setter, receiver_map, id)) return true;
   return TryInline(setter,
                    1,
                    implicit_return_value,
@@ -7733,6 +7736,20 @@ bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<JSFunction> function,
 }
 
 
+bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<JSFunction> function,
+                                                Handle<Map> receiver_map,
+                                                BailoutId ast_id) {
+  SmallMapList receiver_maps(1, zone());
+  receiver_maps.Add(receiver_map, zone());
+  return TryInlineApiCall(function,
+                          NULL,  // Receiver is on expression stack.
+                          &receiver_maps,
+                          1,
+                          ast_id,
+                          kCallApiSetter);
+}
+
+
 bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function,
                                                HValue* receiver,
                                                SmallMapList* receiver_maps,
@@ -7788,6 +7805,18 @@ bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function,
       receiver = Pop();
       Add<HPushArgument>(receiver);
       break;
+    case kCallApiSetter:
+      {
+        // Receiver and prototype chain cannot have changed.
+        ASSERT_EQ(1, argc);
+        ASSERT_EQ(NULL, receiver);
+        // Receiver and value are on expression stack.
+        HValue* value = Pop();
+        receiver = Pop();
+        Add<HPushArgument>(receiver);
+        Add<HPushArgument>(value);
+        break;
+     }
   }
 
   HValue* holder = NULL;
index aa2e171..2ee87e7 100644 (file)
@@ -2222,6 +2222,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
                        BailoutId ast_id,
                        BailoutId return_id);
   bool TryInlineSetter(Handle<JSFunction> setter,
+                       Handle<Map> receiver_map,
                        BailoutId id,
                        BailoutId assignment_id,
                        HValue* implicit_return_value);
@@ -2235,7 +2236,8 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
   enum ApiCallType {
     kCallApiFunction,
     kCallApiMethod,
-    kCallApiGetter
+    kCallApiGetter,
+    kCallApiSetter
   };
   bool TryInlineApiMethodCall(Call* expr,
                               HValue* receiver,
@@ -2244,6 +2246,9 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
   bool TryInlineApiGetter(Handle<JSFunction> function,
                           Handle<Map> receiver_map,
                           BailoutId ast_id);
+  bool TryInlineApiSetter(Handle<JSFunction> function,
+                          Handle<Map> receiver_map,
+                          BailoutId ast_id);
   bool TryInlineApiCall(Handle<JSFunction> function,
                          HValue* receiver,
                          SmallMapList* receiver_maps,
index 31fad53..fee0402 100644 (file)
@@ -21912,6 +21912,9 @@ class ApiCallOptimizationChecker {
     CHECK(callee == info.Callee());
     CHECK(data == info.Data());
     CHECK(receiver == info.This());
+    if (info.Length() == 1) {
+      CHECK_EQ(v8_num(1), info[0]);
+    }
     CHECK(holder == info.Holder());
     count++;
   }
@@ -21974,9 +21977,9 @@ class ApiCallOptimizationChecker {
       Local<Object> global_holder = Local<Object>::Cast(
           inner_global->GetPrototype());
       global_holder->Set(v8_str("g_f"), function);
-      SetAccessorProperty(global_holder, v8_str("g_p1"), function);
+      SetAccessorProperty(global_holder, v8_str("g_acc"), function, function);
       function_holder->Set(v8_str("f"), function);
-      SetAccessorProperty(function_holder, v8_str("p1"), function);
+      SetAccessorProperty(function_holder, v8_str("acc"), function, function);
       // Initialize expected values.
       callee = function;
       count = 0;
@@ -22007,14 +22010,16 @@ class ApiCallOptimizationChecker {
         i::OS::SNPrintF(
             wrap_function,
             "function wrap_f_%d() { var f = g_f; return f(); }\n"
-            "function wrap_p1_%d() { return this.g_p1; }\n",
-            key, key);
+            "function wrap_get_%d() { return this.g_acc; }\n"
+            "function wrap_set_%d() { this.g_acc = 1; }\n",
+            key, key, key);
       } else {
         i::OS::SNPrintF(
             wrap_function,
             "function wrap_f_%d() { return receiver_subclass.f(); }\n"
-            "function wrap_p1_%d() { return receiver_subclass.p1; }\n",
-            key, key);
+            "function wrap_get_%d() { return receiver_subclass.acc; }\n"
+            "function wrap_set_%d() { receiver_subclass.acc = 1; }\n",
+            key, key, key);
       }
       // build source string
       i::ScopedVector<char> source(500);
@@ -22022,20 +22027,28 @@ class ApiCallOptimizationChecker {
           source,
           "%s\n"  // wrap functions
           "function wrap_f() { wrap_f_%d(); }\n"
-          "function wrap_p1() { wrap_p1_%d(); }\n"
+          "function wrap_get() { wrap_get_%d(); }\n"
+          "function wrap_set() { wrap_set_%d(); }\n"
+          "\n"
           "wrap_f();\n"
           "wrap_f();\n"
           "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
           "wrap_f();\n"
-          "wrap_p1();\n"
-          "wrap_p1();\n"
-          "%%OptimizeFunctionOnNextCall(wrap_p1_%d);\n"
-          "wrap_p1();\n",
-          wrap_function.start(), key, key, key, key);
+          "\n"
+          "wrap_get();\n"
+          "wrap_get();\n"
+          "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
+          "wrap_get();\n"
+          "\n"
+          "wrap_set();\n"
+          "wrap_set();\n"
+          "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
+          "wrap_set();\n",
+          wrap_function.start(), key, key, key, key, key, key);
       v8::TryCatch try_catch;
       CompileRun(source.start());
       ASSERT(!try_catch.HasCaught());
-      CHECK_EQ(6, count);
+      CHECK_EQ(9, count);
     }
 };