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 |