| 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;
|
| }
|
|
|