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.