[turbofan] Avoid ToNumber conversions if they could deoptimize.
authorjarin <jarin@chromium.org>
Mon, 16 Feb 2015 12:59:12 +0000 (04:59 -0800)
committerCommit bot <commit-bot@chromium.org>
Mon, 16 Feb 2015 12:59:20 +0000 (12:59 +0000)
BUG=chromium:454158
LOG=n
R=bmeurer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#26661}

src/compiler/js-typed-lowering.cc
test/mjsunit/compiler/regress-to-number-binop-deopt.js [new file with mode: 0644]

index 5352c53..bbe46fb 100644 (file)
@@ -271,13 +271,15 @@ Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
 
 Reduction JSTypedLowering::ReduceJSBitwiseOr(Node* node) {
   JSBinopReduction r(this, node);
-  if (r.BothInputsAre(Type::Primitive()) || r.OneInputIs(zero_range_)) {
-    // TODO(jarin): Propagate frame state input from non-primitive input node to
-    // JSToNumber node.
+
+  // We can only reduce to Word32Or if we are sure the to-number conversions
+  // cannot lazily deoptimize.
+  bool shortcut_or_zero =
+      !FLAG_turbo_deoptimization && r.OneInputIs(zero_range_);
+  if (r.BothInputsAre(Type::Primitive()) || shortcut_or_zero) {
     // TODO(titzer): some Smi bitwise operations don't really require going
     // all the way to int32, which can save tagging/untagging for some
-    // operations
-    // on some platforms.
+    // operations on some platforms.
     // TODO(turbofan): make this heuristic configurable for code size.
     r.ConvertInputsToUI32(kSigned, kSigned);
     return r.ChangeToPureOperator(machine()->Word32Or(), Type::Integral32());
@@ -288,9 +290,13 @@ Reduction JSTypedLowering::ReduceJSBitwiseOr(Node* node) {
 
 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) {
   JSBinopReduction r(this, node);
-  if (r.BothInputsAre(Type::Primitive()) || r.OneInputIs(one_range_)) {
-    // TODO(jarin): Propagate frame state input from non-primitive input node to
-    // JSToNumber node.
+
+  // We can only reduce to NumberMultiply if we are sure the to-number
+  // conversions cannot lazily deoptimize.
+  bool shortcut_multiply_one =
+      !FLAG_turbo_deoptimization && r.OneInputIs(one_range_);
+
+  if (r.BothInputsAre(Type::Primitive()) || shortcut_multiply_one) {
     r.ConvertInputsToNumber();
     return r.ChangeToPureOperator(simplified()->NumberMultiply(),
                                   Type::Number());
diff --git a/test/mjsunit/compiler/regress-to-number-binop-deopt.js b/test/mjsunit/compiler/regress-to-number-binop-deopt.js
new file mode 100644 (file)
index 0000000..f6b77d9
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function deopt(f) {
+  return { valueOf : function() { %DeoptimizeFunction(f); return 1.1; } };
+}
+
+function or_zero(o) {
+  return o|0;
+}
+
+function multiply_one(o) {
+  return +o;
+}
+
+function multiply_one_symbol() {
+  return +Symbol();
+}
+
+assertThrows(multiply_one_symbol, TypeError);
+assertEquals(1, or_zero(deopt(or_zero)));
+assertEquals(1.1, multiply_one(deopt(multiply_one)));