Fix bug in inlining call-as-function when inlining multiple levels deep.
authorfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 26 Oct 2011 10:31:06 +0000 (10:31 +0000)
committerfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 26 Oct 2011 10:31:06 +0000 (10:31 +0000)
This change fixes a off-by-one level error when dropping the
function from the environment. The function of the outermost
environment was not dropped.

BUG=v8:1785
TEST=test/mjsunit/compiler/regress-inline-callfunctionstub.js
Review URL: http://codereview.chromium.org/8341019

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

src/hydrogen.cc
src/hydrogen.h
test/mjsunit/compiler/regress-inline-callfunctionstub.js [new file with mode: 0644]
test/mjsunit/mjsunit.status

index 05d460970e44897f7f91e1ffed5b8b69f8752e1b..3a4d172f51db236758d2c4aaee21684b1ab2c867 100644 (file)
@@ -4713,7 +4713,10 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
       Handle<Code>(target_shared->code()),
       Handle<Context>(target->context()->global_context()),
       isolate());
-  FunctionState target_state(this, &target_info, &target_oracle, drop_extra);
+  // The function state is new-allocated because we need to delete it
+  // in two different places.
+  FunctionState* target_state =
+      new FunctionState(this, &target_info, &target_oracle, drop_extra);
 
   HConstant* undefined = graph()->GetConstantUndefined();
   HEnvironment* inner_env =
@@ -4747,6 +4750,7 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
     TraceInline(target, caller, "inline graph construction failed");
     target_shared->DisableOptimization(*target);
     inline_bailout_ = true;
+    delete target_state;
     return true;
   }
 
@@ -4793,19 +4797,21 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
     // Pop the return test context from the expression context stack.
     ASSERT(ast_context() == inlined_test_context());
     ClearInlinedTestContext();
+    delete target_state;
 
     // Forward to the real test context.
     if (if_true->HasPredecessor()) {
       if_true->SetJoinId(expr->id());
       HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
-      if_true->Goto(true_target, drop_extra);
+      if_true->Goto(true_target, function_state()->drop_extra());
     }
     if (if_false->HasPredecessor()) {
       if_false->SetJoinId(expr->id());
       HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
-      if_false->Goto(false_target, drop_extra);
+      if_false->Goto(false_target, function_state()->drop_extra());
     }
     set_current_block(NULL);
+    return true;
 
   } else if (function_return()->HasPredecessor()) {
     function_return()->SetJoinId(expr->id());
@@ -4813,7 +4819,7 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
   } else {
     set_current_block(NULL);
   }
-
+  delete target_state;
   return true;
 }
 
index 1ef8d9106c6bf5e56ae9b56b3e03174c97c236ae..2d08dc8e79ee7faa8435a687722711107d384adc 100644 (file)
@@ -605,7 +605,7 @@ class TestContext: public AstContext {
 };
 
 
-class FunctionState BASE_EMBEDDED {
+class FunctionState {
  public:
   FunctionState(HGraphBuilder* owner,
                 CompilationInfo* info,
diff --git a/test/mjsunit/compiler/regress-inline-callfunctionstub.js b/test/mjsunit/compiler/regress-inline-callfunctionstub.js
new file mode 100644 (file)
index 0000000..a39d26d
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+// Test inlined of calls-as-function two levels deep.
+function f() { return 42; }
+
+var o = {g : function () { return f(); } }
+function main(func) {
+  var v=0;
+  for (var i=0; i<1; i++) {
+    if (func()) v = 42;
+  }
+}
+
+main(o.g);
+main(o.g);
+main(o.g);
+%OptimizeFunctionOnNextCall(main);
+main(o.g);
+
index a6bcba931a4d7db7fcd416672151cbc00cb47448..941e0e8cc5be94580c002afbb6dda988fd32d0ad 100644 (file)
@@ -30,9 +30,6 @@ prefix mjsunit
 # All tests in the bug directory are expected to fail.
 bugs: FAIL
 
-# BUG(1785): Temporarily disabled until fixed.
-tools/tickprocessor: SKIP
-
 ##############################################################################
 # Fails.
 regress/regress-1119: FAIL