| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/js-builtin-reducer.h" | 5 #include "src/compiler/js-builtin-reducer.h" |
| 6 #include "src/compiler/js-graph.h" | 6 #include "src/compiler/js-graph.h" |
| 7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
| 8 #include "src/compiler/node-properties.h" | 8 #include "src/compiler/node-properties.h" |
| 9 #include "src/compiler/simplified-operator.h" | 9 #include "src/compiler/simplified-operator.h" |
| 10 #include "src/objects-inl.h" | 10 #include "src/objects-inl.h" |
| 11 #include "src/type-cache.h" |
| 11 #include "src/types.h" | 12 #include "src/types.h" |
| 12 | 13 |
| 13 namespace v8 { | 14 namespace v8 { |
| 14 namespace internal { | 15 namespace internal { |
| 15 namespace compiler { | 16 namespace compiler { |
| 16 | 17 |
| 17 | 18 |
| 18 // Helper class to access JSCallFunction nodes that are potential candidates | 19 // Helper class to access JSCallFunction nodes that are potential candidates |
| 19 // for reduction when they have a BuiltinFunctionId associated with them. | 20 // for reduction when they have a BuiltinFunctionId associated with them. |
| 20 class JSCallReduction { | 21 class JSCallReduction { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 DCHECK_EQ(IrOpcode::kJSCallFunction, node_->opcode()); | 79 DCHECK_EQ(IrOpcode::kJSCallFunction, node_->opcode()); |
| 79 DCHECK_LT(index, GetJSCallArity()); | 80 DCHECK_LT(index, GetJSCallArity()); |
| 80 // Skip first (i.e. callee) and second (i.e. receiver) operand. | 81 // Skip first (i.e. callee) and second (i.e. receiver) operand. |
| 81 return NodeProperties::GetValueInput(node_, index + 2); | 82 return NodeProperties::GetValueInput(node_, index + 2); |
| 82 } | 83 } |
| 83 | 84 |
| 84 private: | 85 private: |
| 85 Node* node_; | 86 Node* node_; |
| 86 }; | 87 }; |
| 87 | 88 |
| 88 | |
| 89 JSBuiltinReducer::JSBuiltinReducer(Editor* editor, JSGraph* jsgraph) | 89 JSBuiltinReducer::JSBuiltinReducer(Editor* editor, JSGraph* jsgraph) |
| 90 : AdvancedReducer(editor), jsgraph_(jsgraph) {} | 90 : AdvancedReducer(editor), |
| 91 | 91 jsgraph_(jsgraph), |
| 92 type_cache_(TypeCache::Get()) {} |
| 92 | 93 |
| 93 // ECMA-262, section 15.8.2.11. | 94 // ECMA-262, section 15.8.2.11. |
| 94 Reduction JSBuiltinReducer::ReduceMathMax(Node* node) { | 95 Reduction JSBuiltinReducer::ReduceMathMax(Node* node) { |
| 95 JSCallReduction r(node); | 96 JSCallReduction r(node); |
| 96 if (r.InputsMatchZero()) { | 97 if (r.InputsMatchZero()) { |
| 97 // Math.max() -> -Infinity | 98 // Math.max() -> -Infinity |
| 98 return Replace(jsgraph()->Constant(-V8_INFINITY)); | 99 return Replace(jsgraph()->Constant(-V8_INFINITY)); |
| 99 } | 100 } |
| 100 if (r.InputsMatchOne(Type::Number())) { | 101 if (r.InputsMatchOne(Type::Number())) { |
| 101 // Math.max(a:number) -> a | 102 // Math.max(a:number) -> a |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 JSCallReduction r(node); | 135 JSCallReduction r(node); |
| 135 if (r.InputsMatchOne(Type::Number())) { | 136 if (r.InputsMatchOne(Type::Number())) { |
| 136 // Math.fround(a:number) -> TruncateFloat64ToFloat32(a) | 137 // Math.fround(a:number) -> TruncateFloat64ToFloat32(a) |
| 137 Node* value = | 138 Node* value = |
| 138 graph()->NewNode(machine()->TruncateFloat64ToFloat32(), r.left()); | 139 graph()->NewNode(machine()->TruncateFloat64ToFloat32(), r.left()); |
| 139 return Replace(value); | 140 return Replace(value); |
| 140 } | 141 } |
| 141 return NoChange(); | 142 return NoChange(); |
| 142 } | 143 } |
| 143 | 144 |
| 145 // ES6 section 20.2.2.28 Math.round ( x ) |
| 146 Reduction JSBuiltinReducer::ReduceMathRound(Node* node) { |
| 147 JSCallReduction r(node); |
| 148 if (r.InputsMatchOne(type_cache_.kIntegerOrMinusZeroOrNaN)) { |
| 149 // Math.round(a:integer \/ -0 \/ NaN) -> a |
| 150 return Replace(r.left()); |
| 151 } |
| 152 if (r.InputsMatchOne(Type::Number()) && |
| 153 machine()->Float64RoundUp().IsSupported()) { |
| 154 // Math.round(a:number) -> Select(Float64LessThan(#0.5, Float64Sub(i, a)), |
| 155 // Float64Sub(i, #1.0), i) |
| 156 // where i = Float64RoundUp(a) |
| 157 Node* value = r.left(); |
| 158 Node* integer = graph()->NewNode(machine()->Float64RoundUp().op(), value); |
| 159 Node* real = graph()->NewNode(machine()->Float64Sub(), integer, value); |
| 160 return Replace(graph()->NewNode( |
| 161 common()->Select(MachineRepresentation::kFloat64), |
| 162 graph()->NewNode(machine()->Float64LessThan(), |
| 163 jsgraph()->Float64Constant(0.5), real), |
| 164 graph()->NewNode(machine()->Float64Sub(), integer, |
| 165 jsgraph()->Float64Constant(1.0)), |
| 166 integer)); |
| 167 } |
| 168 return NoChange(); |
| 169 } |
| 144 | 170 |
| 145 Reduction JSBuiltinReducer::Reduce(Node* node) { | 171 Reduction JSBuiltinReducer::Reduce(Node* node) { |
| 146 Reduction reduction = NoChange(); | 172 Reduction reduction = NoChange(); |
| 147 JSCallReduction r(node); | 173 JSCallReduction r(node); |
| 148 | 174 |
| 149 // Dispatch according to the BuiltinFunctionId if present. | 175 // Dispatch according to the BuiltinFunctionId if present. |
| 150 if (!r.HasBuiltinFunctionId()) return NoChange(); | 176 if (!r.HasBuiltinFunctionId()) return NoChange(); |
| 151 switch (r.GetBuiltinFunctionId()) { | 177 switch (r.GetBuiltinFunctionId()) { |
| 152 case kMathMax: | 178 case kMathMax: |
| 153 reduction = ReduceMathMax(node); | 179 reduction = ReduceMathMax(node); |
| 154 break; | 180 break; |
| 155 case kMathImul: | 181 case kMathImul: |
| 156 reduction = ReduceMathImul(node); | 182 reduction = ReduceMathImul(node); |
| 157 break; | 183 break; |
| 158 case kMathFround: | 184 case kMathFround: |
| 159 reduction = ReduceMathFround(node); | 185 reduction = ReduceMathFround(node); |
| 160 break; | 186 break; |
| 187 case kMathRound: |
| 188 reduction = ReduceMathRound(node); |
| 189 break; |
| 161 default: | 190 default: |
| 162 break; | 191 break; |
| 163 } | 192 } |
| 164 | 193 |
| 165 // Replace builtin call assuming replacement nodes are pure values that don't | 194 // Replace builtin call assuming replacement nodes are pure values that don't |
| 166 // produce an effect. Replaces {node} with {reduction} and relaxes effects. | 195 // produce an effect. Replaces {node} with {reduction} and relaxes effects. |
| 167 if (reduction.Changed()) ReplaceWithValue(node, reduction.replacement()); | 196 if (reduction.Changed()) ReplaceWithValue(node, reduction.replacement()); |
| 168 | 197 |
| 169 return reduction; | 198 return reduction; |
| 170 } | 199 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 186 } | 215 } |
| 187 | 216 |
| 188 | 217 |
| 189 SimplifiedOperatorBuilder* JSBuiltinReducer::simplified() const { | 218 SimplifiedOperatorBuilder* JSBuiltinReducer::simplified() const { |
| 190 return jsgraph()->simplified(); | 219 return jsgraph()->simplified(); |
| 191 } | 220 } |
| 192 | 221 |
| 193 } // namespace compiler | 222 } // namespace compiler |
| 194 } // namespace internal | 223 } // namespace internal |
| 195 } // namespace v8 | 224 } // namespace v8 |
| OLD | NEW |