Inline simple getter calls.
authorsvenpanne@chromium.org <svenpanne@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 30 Jul 2012 10:42:21 +0000 (10:42 +0000)
committersvenpanne@chromium.org <svenpanne@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 30 Jul 2012 10:42:21 +0000 (10:42 +0000)
Currently only simple getter calls are handled (i.e. no calls in count
operations or compound assignments), and deoptimization in the getter is not
handled at all. Because of the latter, we temporarily hide this feature behind a
new flag --inline-accessors, which is false by default.

Review URL: https://chromiumcodereview.appspot.com/10828066

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

src/arm/full-codegen-arm.cc
src/ast.h
src/flag-definitions.h
src/hydrogen.cc
src/hydrogen.h
src/ia32/full-codegen-ia32.cc
src/mips/full-codegen-mips.cc
src/x64/full-codegen-x64.cc

index d2325f708295c8da759dfb7fa688d3dfcc784e24..9bac93d4946ef68ef40c44c0e3a7d829ba2d9ab4 100644 (file)
@@ -2275,6 +2275,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
   if (key->IsPropertyName()) {
     VisitForAccumulatorValue(expr->obj());
     EmitNamedPropertyLoad(expr);
+    PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
     context()->Plug(r0);
   } else {
     VisitForStackValue(expr->obj());
index 8c9606a2db92da928fcab1f1aa131adea5423e78..63ee29ae0e80af35b73a11c94314364d9a11b8a8 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -1513,6 +1513,9 @@ class Property: public Expression {
   Expression* key() const { return key_; }
   virtual int position() const { return pos_; }
 
+  // Bailout support.
+  int ReturnId() const { return return_id_; }
+
   bool IsStringLength() const { return is_string_length_; }
   bool IsStringAccess() const { return is_string_access_; }
   bool IsFunctionPrototype() const { return is_function_prototype_; }
@@ -1535,6 +1538,7 @@ class Property: public Expression {
         obj_(obj),
         key_(key),
         pos_(pos),
+        return_id_(GetNextId(isolate)),
         is_monomorphic_(false),
         is_uninitialized_(false),
         is_array_length_(false),
@@ -1546,6 +1550,7 @@ class Property: public Expression {
   Expression* obj_;
   Expression* key_;
   int pos_;
+  const int return_id_;
 
   SmallMapList receiver_types_;
   bool is_monomorphic_ : 1;
index 51918a505d2ad8c5f2cb4cd568649bacec63dff4..19d7d37c3ef1bfe530ff5a4ea00d3088499488a4 100644 (file)
@@ -213,6 +213,7 @@ DEFINE_bool(cache_optimized_code, true,
             "cache optimized code for closures")
 DEFINE_bool(inline_construct, true, "inline constructor calls")
 DEFINE_bool(inline_arguments, true, "inline functions with arguments object")
+DEFINE_bool(inline_accessors, false, "inline JavaScript accessors")
 DEFINE_int(loop_weight, 1, "loop weight for representation inference")
 
 DEFINE_bool(optimize_for_in, true,
index f61485040a9a5e5f27dd07da33958cf9f1112f24..73c9173c70257941c094dfa6de1872033f454452 100644 (file)
@@ -6352,7 +6352,11 @@ void HGraphBuilder::VisitProperty(Property* expr) {
       Handle<AccessorPair> accessors;
       Handle<JSObject> holder;
       if (LookupAccessorPair(map, name, &accessors, &holder)) {
-        instr = BuildCallGetter(Pop(), map, accessors, holder);
+        AddCheckConstantFunction(holder, Top(), map, true);
+        Handle<JSFunction> getter(JSFunction::cast(accessors->getter()));
+        if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return;
+        AddInstruction(new(zone()) HPushArgument(Pop()));
+        instr = new(zone()) HCallConstantFunction(getter, 1);
       } else {
         instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map);
       }
@@ -6920,6 +6924,18 @@ bool HGraphBuilder::TryInlineConstruct(CallNew* expr, HValue* receiver) {
 }
 
 
+bool HGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
+                                    Property* prop) {
+  return TryInline(CALL_AS_METHOD,
+                   getter,
+                   0,
+                   NULL,
+                   prop->id(),
+                   prop->ReturnId(),
+                   NORMAL_RETURN);
+}
+
+
 bool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) {
   if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
   BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
index 3cdd7f8a312a0aef93a3b1d3ff06c83dc2a49358..61d792f1dc9cbf02540adcf76b7a55b3e76e6dfb 100644 (file)
@@ -1040,6 +1040,7 @@ class HGraphBuilder: public AstVisitor {
 
   bool TryInlineCall(Call* expr, bool drop_extra = false);
   bool TryInlineConstruct(CallNew* expr, HValue* receiver);
+  bool TryInlineGetter(Handle<JSFunction> getter, Property* prop);
   bool TryInlineBuiltinMethodCall(Call* expr,
                                   HValue* receiver,
                                   Handle<Map> receiver_map,
index 75253c07a462c60b461e7d0d32498fc667870762..ceee56af25aea6e73c879b41c4e4cf8944f2f23f 100644 (file)
@@ -2214,6 +2214,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
     VisitForAccumulatorValue(expr->obj());
     __ mov(edx, result_register());
     EmitNamedPropertyLoad(expr);
+    PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
     context()->Plug(eax);
   } else {
     VisitForStackValue(expr->obj());
index 4a19d6c8764b3ce4151bab394d77e7fbd3f07ab0..a5e7dcf02b19035b444e537864537d18d8ead612 100644 (file)
@@ -2299,6 +2299,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
   if (key->IsPropertyName()) {
     VisitForAccumulatorValue(expr->obj());
     EmitNamedPropertyLoad(expr);
+    PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
     context()->Plug(v0);
   } else {
     VisitForStackValue(expr->obj());
index 344905e212081be287fdbd33d692ebefc9361399..702ee29f638c0c58538f048a6e271fe9b8bb60a9 100644 (file)
@@ -2188,6 +2188,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
   if (key->IsPropertyName()) {
     VisitForAccumulatorValue(expr->obj());
     EmitNamedPropertyLoad(expr);
+    PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
     context()->Plug(rax);
   } else {
     VisitForStackValue(expr->obj());