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/access-builder.h" |
5 #include "src/compiler/diamond.h" | 6 #include "src/compiler/diamond.h" |
6 #include "src/compiler/js-builtin-reducer.h" | 7 #include "src/compiler/js-builtin-reducer.h" |
7 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
8 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
9 #include "src/compiler/node-properties.h" | 10 #include "src/compiler/node-properties.h" |
10 #include "src/types.h" | 11 #include "src/types.h" |
11 | 12 |
12 namespace v8 { | 13 namespace v8 { |
13 namespace internal { | 14 namespace internal { |
14 namespace compiler { | 15 namespace compiler { |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 if (r.InputsMatchOne(Type::Number())) { | 146 if (r.InputsMatchOne(Type::Number())) { |
146 // Math.fround(a:number) -> TruncateFloat64ToFloat32(a) | 147 // Math.fround(a:number) -> TruncateFloat64ToFloat32(a) |
147 Node* value = | 148 Node* value = |
148 graph()->NewNode(machine()->TruncateFloat64ToFloat32(), r.left()); | 149 graph()->NewNode(machine()->TruncateFloat64ToFloat32(), r.left()); |
149 return Replace(value); | 150 return Replace(value); |
150 } | 151 } |
151 return NoChange(); | 152 return NoChange(); |
152 } | 153 } |
153 | 154 |
154 | 155 |
| 156 Reduction JSBuiltinReducer::ReduceAtomicsLoad(Node* node) { |
| 157 JSCallReduction r(node); |
| 158 if (r.GetJSCallArity() == 2) { |
| 159 // TODO(binji): copy-pasta from JSTypedLowering::ReduceJSLoadProperty |
| 160 Node* base = r.GetJSCallInput(0); |
| 161 Node* index = r.GetJSCallInput(1); |
| 162 Type* index_type = NodeProperties::GetBounds(index).upper; |
| 163 HeapObjectMatcher<Object> mbase(base); |
| 164 if (mbase.HasValue() && mbase.Value().handle()->IsJSTypedArray()) { |
| 165 Handle<JSTypedArray> array = |
| 166 Handle<JSTypedArray>::cast(mbase.Value().handle()); |
| 167 if (array->is_shared()) { |
| 168 bool const is_external = true; |
| 169 ElementAccess const access = |
| 170 AccessBuilder::ForTypedArrayElement(array->type(), is_external); |
| 171 size_t const k = ElementSizeLog2Of(access.machine_type); |
| 172 double const byte_length = array->byte_length()->Number(); |
| 173 DCHECK(IsExternalArrayElementsKind(array->map()->elements_kind())); |
| 174 Handle<ExternalArray> elements = |
| 175 Handle<ExternalArray>::cast(handle(array->elements())); |
| 176 Node* buffer = jsgraph()->PointerConstant(elements->external_pointer()); |
| 177 Node* effect = NodeProperties::GetEffectInput(node); |
| 178 Node* control = NodeProperties::GetControlInput(node); |
| 179 |
| 180 // TODO(binji): reuse from js-typed-lowering.cc? |
| 181 Type* shifted_int32_range = Type::Range( |
| 182 kMinInt / (1 << k), kMaxInt / (1 << k), graph()->zone()); |
| 183 if (index_type->Is(shifted_int32_range) && byte_length <= kMaxInt) { |
| 184 // Check if we can avoid the bounds check. |
| 185 if (index_type->Min() >= 0 && |
| 186 index_type->Max() < array->length()->Number()) { |
| 187 Node* load = |
| 188 graph()->NewNode(simplified()->LoadElementAtomic(access), |
| 189 buffer, index, effect, control); |
| 190 NodeProperties::ReplaceWithValue(node, load, load); |
| 191 return Changed(node); |
| 192 } |
| 193 } |
| 194 |
| 195 // Copy-pasta from SimplifiedLowering::DoLoadBuffer |
| 196 Node* offset = |
| 197 graph()->NewNode(machine()->Word32Shl(), index, |
| 198 jsgraph()->Int32Constant(static_cast<int>(k))); |
| 199 Node* length = jsgraph()->Constant(byte_length); |
| 200 Node* check = |
| 201 graph()->NewNode(machine()->Uint32LessThan(), offset, length); |
| 202 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
| 203 check, control); |
| 204 |
| 205 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
| 206 Node* etrue = graph()->NewNode(simplified()->LoadElementAtomic(access), |
| 207 buffer, index, effect, if_true); |
| 208 Node* vtrue = etrue; |
| 209 |
| 210 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
| 211 Node* efalse = effect; |
| 212 Node* vfalse = jsgraph()->UndefinedConstant(); |
| 213 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
| 214 Node* ephi = |
| 215 graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge); |
| 216 |
| 217 // Replace effect uses of {node} with the {ephi}. |
| 218 NodeProperties::ReplaceWithValue(node, node, ephi); |
| 219 |
| 220 // Turn the {node} into a Phi. |
| 221 node->set_op(common()->Phi(kMachAnyTagged, 2)); |
| 222 node->ReplaceInput(0, vtrue); |
| 223 node->ReplaceInput(1, vfalse); |
| 224 node->ReplaceInput(2, merge); |
| 225 node->TrimInputCount(3); |
| 226 return Changed(node); |
| 227 } |
| 228 } |
| 229 } |
| 230 |
| 231 return NoChange(); |
| 232 } |
| 233 |
| 234 |
155 Reduction JSBuiltinReducer::Reduce(Node* node) { | 235 Reduction JSBuiltinReducer::Reduce(Node* node) { |
156 JSCallReduction r(node); | 236 JSCallReduction r(node); |
157 | 237 |
158 // Dispatch according to the BuiltinFunctionId if present. | 238 // Dispatch according to the BuiltinFunctionId if present. |
159 if (!r.HasBuiltinFunctionId()) return NoChange(); | 239 if (!r.HasBuiltinFunctionId()) return NoChange(); |
160 switch (r.GetBuiltinFunctionId()) { | 240 switch (r.GetBuiltinFunctionId()) { |
161 case kMathMax: | 241 case kMathMax: |
162 return ReplaceWithPureReduction(node, ReduceMathMax(node)); | 242 return ReplaceWithPureReduction(node, ReduceMathMax(node)); |
163 case kMathImul: | 243 case kMathImul: |
164 return ReplaceWithPureReduction(node, ReduceMathImul(node)); | 244 return ReplaceWithPureReduction(node, ReduceMathImul(node)); |
165 case kMathFround: | 245 case kMathFround: |
166 return ReplaceWithPureReduction(node, ReduceMathFround(node)); | 246 return ReplaceWithPureReduction(node, ReduceMathFround(node)); |
| 247 case kAtomicsLoad: |
| 248 return ReduceAtomicsLoad(node); |
167 default: | 249 default: |
168 break; | 250 break; |
169 } | 251 } |
170 return NoChange(); | 252 return NoChange(); |
171 } | 253 } |
172 | 254 |
173 | 255 |
174 Graph* JSBuiltinReducer::graph() const { return jsgraph()->graph(); } | 256 Graph* JSBuiltinReducer::graph() const { return jsgraph()->graph(); } |
175 | 257 |
176 | 258 |
177 CommonOperatorBuilder* JSBuiltinReducer::common() const { | 259 CommonOperatorBuilder* JSBuiltinReducer::common() const { |
178 return jsgraph()->common(); | 260 return jsgraph()->common(); |
179 } | 261 } |
180 | 262 |
181 | 263 |
182 MachineOperatorBuilder* JSBuiltinReducer::machine() const { | 264 MachineOperatorBuilder* JSBuiltinReducer::machine() const { |
183 return jsgraph()->machine(); | 265 return jsgraph()->machine(); |
184 } | 266 } |
185 | 267 |
186 } // namespace compiler | 268 } // namespace compiler |
187 } // namespace internal | 269 } // namespace internal |
188 } // namespace v8 | 270 } // namespace v8 |
OLD | NEW |