Reviewers: Michael Starzinger,

Message:
PTAL.

Description:
Add inlined implementation of Math.round.

[email protected]

Please review this at https://codereview.chromium.org/681983003/

Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+75, -6 lines):
  M src/compiler/js-builtin-reducer.h
  M src/compiler/js-builtin-reducer.cc
  A + test/mjsunit/asm/math-round.js


Index: src/compiler/js-builtin-reducer.cc
diff --git a/src/compiler/js-builtin-reducer.cc b/src/compiler/js-builtin-reducer.cc index dbaa2930046b3039b3499841f7b3cbfb0c1480e8..adf6b84b4ee5e71bb308a191b1d6f95bc517785e 100644
--- a/src/compiler/js-builtin-reducer.cc
+++ b/src/compiler/js-builtin-reducer.cc
@@ -217,6 +217,69 @@ Reduction JSBuiltinReducer::ReduceMathCeil(Node* node) {
 }


+// ES6 draft 10-14-14, section 20.2.2.28.
+Reduction JSBuiltinReducer::ReduceMathRound(Node* node) {
+ if (machine()->HasFloat64Floor() && machine()->HasFloat64RoundTiesAway()) {
+    JSCallReduction r(node);
+    if (r.InputsMatchOne(Type::Number())) {
+      // This is based on the implementation from Crankshaft,
+      // see lithium-codegen-arm64.cc:LCodeGen::DoMathRoundD.
+      // Implementation will be selected for 32bit ARMv8, too.
+      // Math.round(a:number) ->
+      //   double res = Float64RoundTiesAway(a);
+      //   if (a >= 0.0 || a == res) {
+      //     return res;
+      //   } else {
+      //     return -abs(Float64Floor(a + 0.5))
+      //   }
+      Node* p = r.GetJSCallInput(0);
+      Node* control = graph()->start();
+      Node* rounded_away =
+          graph()->NewNode(machine()->Float64RoundTiesAway(), p);
+
+ Node* ge_zero = graph()->NewNode(simplified()->NumberLessThanOrEqual(),
+                                       jsgraph()->ZeroConstant(), p);
+      Node* eq_rounded =
+          graph()->NewNode(machine()->Float64Equal(), p, rounded_away);
+
+      Node* condition =
+          graph()->NewNode(machine()->WordOr(), eq_rounded, ge_zero);
+
+ Node* branch = graph()->NewNode(common()->Branch(), condition, control);
+      Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+      Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+
+      Node* sum = graph()->NewNode(machine()->Float64Add(), p,
+                                   jsgraph()->Constant(0.5));
+      Node* floored = graph()->NewNode(machine()->Float64Floor(), sum);
+
+      // Now ensure negative sign.
+      // TODO(turbofan): use FNEG(FABS(x)) instructions here; they are
+      // available on ARM (which this implementation is targeted at).
+      Node* zero = jsgraph()->Constant(-0.0);
+ Node* tag = graph()->NewNode(machine()->Float64LessThan(), floored, zero);
+
+      Node* branch2 = graph()->NewNode(common()->Branch(), tag, control);
+      Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
+      Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
+ Node* merge2 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
+
+      Node* neg =
+          graph()->NewNode(simplified()->NumberSubtract(), zero, floored);
+ Node* value = graph()->NewNode(common()->Phi(kMachFloat64, 2), floored,
+                                     neg, merge2);
+
+ Node* res = graph()->NewNode(common()->Phi(kMachFloat64, 2), rounded_away,
+                                   value, merge);
+
+      return Replace(res);
+    }
+  }
+  return NoChange();
+}
+
+
 Reduction JSBuiltinReducer::Reduce(Node* node) {
   JSCallReduction r(node);

@@ -237,6 +300,8 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
       return ReplaceWithPureReduction(node, ReduceMathFloor(node));
     case kMathCeil:
       return ReplaceWithPureReduction(node, ReduceMathCeil(node));
+    case kMathRound:
+      return ReplaceWithPureReduction(node, ReduceMathRound(node));
     default:
       break;
   }
Index: src/compiler/js-builtin-reducer.h
diff --git a/src/compiler/js-builtin-reducer.h b/src/compiler/js-builtin-reducer.h index 4b3be29caae7fd2be3387149d51a18ffab959829..7a5854c2ab53da0370e429f8036c1f47d2e8ae6a 100644
--- a/src/compiler/js-builtin-reducer.h
+++ b/src/compiler/js-builtin-reducer.h
@@ -37,6 +37,7 @@ class JSBuiltinReducer FINAL : public Reducer {
   Reduction ReduceMathFround(Node* node);
   Reduction ReduceMathFloor(Node* node);
   Reduction ReduceMathCeil(Node* node);
+  Reduction ReduceMathRound(Node* node);

   JSGraph* jsgraph_;
   SimplifiedOperatorBuilder simplified_;
Index: test/mjsunit/asm/math-round.js
diff --git a/test/mjsunit/asm/math-floor.js b/test/mjsunit/asm/math-round.js
similarity index 68%
copy from test/mjsunit/asm/math-floor.js
copy to test/mjsunit/asm/math-round.js
index e8c3f341bbd7998849a6c10c60185cfa9d8904b6..4837c89991407f03975728aa99d0f5c0db261ee3 100644
--- a/test/mjsunit/asm/math-floor.js
+++ b/test/mjsunit/asm/math-round.js
@@ -5,12 +5,12 @@
 function Module(stdlib) {
   "use asm";

-  var floor = stdlib.Math.floor;
+  var round = stdlib.Math.round;

   // f: double -> float
   function f(a) {
     a = +a;
-    return floor(a);
+    return round(a);
   }

   return { f: f };
@@ -26,13 +26,16 @@ assertEquals(0,                   f(0));
 assertEquals(+0,                  f(+0));
 assertEquals(-0,                  f(-0));
 assertEquals(0,                   f(0.49999));
-assertEquals(+0,                  f(0.6));
-assertEquals(+0,                  f(0.5));
-assertEquals(-1,                  f(-0.1));
-assertEquals(-1,                  f(-0.5));
+assertEquals(1,                   f(0.6));
+assertEquals(1,                   f(0.5));
+assertEquals(-0,                  f(-0.1));
+assertEquals(-0,                  f(-0.5));
 assertEquals(-1,                  f(-0.6));
 assertEquals(-2,                  f(-1.6));
 assertEquals(-1,                  f(-0.50001));
+assertEquals(0,                   f(0.49999999999999994));

+assertEquals("Infinity", String(1/f(0)));
+assertEquals("-Infinity", String(1/f(-0)));
 assertEquals("Infinity", String(f(Infinity)));
 assertEquals("-Infinity", String(f(-Infinity)));


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to