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 | 6 |
7 #include "src/compilation-dependencies.h" | 7 #include "src/compilation-dependencies.h" |
8 #include "src/compiler/access-builder.h" | 8 #include "src/compiler/access-builder.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 } | 228 } |
229 | 229 |
230 Reduction JSBuiltinReducer::ReduceArrayIterator(Handle<Map> receiver_map, | 230 Reduction JSBuiltinReducer::ReduceArrayIterator(Handle<Map> receiver_map, |
231 Node* node, IterationKind kind, | 231 Node* node, IterationKind kind, |
232 ArrayIteratorKind iter_kind) { | 232 ArrayIteratorKind iter_kind) { |
233 Node* receiver = NodeProperties::GetValueInput(node, 1); | 233 Node* receiver = NodeProperties::GetValueInput(node, 1); |
234 Node* effect = NodeProperties::GetEffectInput(node); | 234 Node* effect = NodeProperties::GetEffectInput(node); |
235 Node* control = NodeProperties::GetControlInput(node); | 235 Node* control = NodeProperties::GetControlInput(node); |
236 | 236 |
237 if (iter_kind == ArrayIteratorKind::kTypedArray) { | 237 if (iter_kind == ArrayIteratorKind::kTypedArray) { |
238 // For JSTypedArray iterator methods, deopt if the buffer is neutered. This | 238 // See if we can skip the neutering check. |
239 // is potentially a deopt loop, but should be extremely unlikely. | 239 if (isolate()->IsArrayBufferNeuteringIntact()) { |
240 DCHECK_EQ(JS_TYPED_ARRAY_TYPE, receiver_map->instance_type()); | 240 // Add a code dependency so we are deoptimized in case an ArrayBuffer |
241 Node* buffer = effect = graph()->NewNode( | 241 // gets neutered. |
242 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()), | 242 dependencies()->AssumePropertyCell( |
243 receiver, effect, control); | 243 factory()->array_buffer_neutering_protector()); |
| 244 } else { |
| 245 // For JSTypedArray iterator methods, deopt if the buffer is neutered. |
| 246 // This is potentially a deopt loop, but should be extremely unlikely. |
| 247 DCHECK_EQ(JS_TYPED_ARRAY_TYPE, receiver_map->instance_type()); |
| 248 Node* buffer = effect = graph()->NewNode( |
| 249 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()), |
| 250 receiver, effect, control); |
244 | 251 |
245 Node* check = effect = graph()->NewNode( | 252 // Deoptimize if the {buffer} has been neutered. |
246 simplified()->ArrayBufferWasNeutered(), buffer, effect, control); | 253 Node* check = effect = graph()->NewNode( |
247 check = graph()->NewNode(simplified()->BooleanNot(), check); | 254 simplified()->ArrayBufferWasNeutered(), buffer, effect, control); |
248 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); | 255 check = graph()->NewNode(simplified()->BooleanNot(), check); |
| 256 effect = |
| 257 graph()->NewNode(simplified()->CheckIf(), check, effect, control); |
| 258 } |
249 } | 259 } |
250 | 260 |
251 int map_index = -1; | 261 int map_index = -1; |
252 Node* object_map = jsgraph()->UndefinedConstant(); | 262 Node* object_map = jsgraph()->UndefinedConstant(); |
253 switch (receiver_map->instance_type()) { | 263 switch (receiver_map->instance_type()) { |
254 case JS_ARRAY_TYPE: | 264 case JS_ARRAY_TYPE: |
255 if (kind == IterationKind::kKeys) { | 265 if (kind == IterationKind::kKeys) { |
256 map_index = Context::FAST_ARRAY_KEY_ITERATOR_MAP_INDEX; | 266 map_index = Context::FAST_ARRAY_KEY_ITERATOR_MAP_INDEX; |
257 } else { | 267 } else { |
258 map_index = kind == IterationKind::kValues | 268 map_index = kind == IterationKind::kValues |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 Node* index = efalse0 = graph()->NewNode( | 538 Node* index = efalse0 = graph()->NewNode( |
529 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorIndex( | 539 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorIndex( |
530 JS_TYPED_ARRAY_TYPE, elements_kind)), | 540 JS_TYPED_ARRAY_TYPE, elements_kind)), |
531 iterator, efalse0, if_false0); | 541 iterator, efalse0, if_false0); |
532 | 542 |
533 // typedarray.[[ViewedArrayBuffer]] | 543 // typedarray.[[ViewedArrayBuffer]] |
534 Node* buffer = efalse0 = graph()->NewNode( | 544 Node* buffer = efalse0 = graph()->NewNode( |
535 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()), | 545 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()), |
536 array, efalse0, if_false0); | 546 array, efalse0, if_false0); |
537 | 547 |
538 Node* check1 = efalse0 = graph()->NewNode( | 548 // See if we can skip the neutering check. |
539 simplified()->ArrayBufferWasNeutered(), buffer, efalse0, if_false0); | 549 if (isolate()->IsArrayBufferNeuteringIntact()) { |
540 check1 = graph()->NewNode(simplified()->BooleanNot(), check1); | 550 // Add a code dependency so we are deoptimized in case an ArrayBuffer |
541 efalse0 = | 551 // gets neutered. |
542 graph()->NewNode(simplified()->CheckIf(), check1, efalse0, if_false0); | 552 dependencies()->AssumePropertyCell( |
| 553 factory()->array_buffer_neutering_protector()); |
| 554 } else { |
| 555 // Deoptimize if the array byuffer was neutered. |
| 556 Node* check1 = efalse0 = graph()->NewNode( |
| 557 simplified()->ArrayBufferWasNeutered(), buffer, efalse0, if_false0); |
| 558 check1 = graph()->NewNode(simplified()->BooleanNot(), check1); |
| 559 efalse0 = |
| 560 graph()->NewNode(simplified()->CheckIf(), check1, efalse0, if_false0); |
| 561 } |
543 | 562 |
544 Node* length = efalse0 = graph()->NewNode( | 563 Node* length = efalse0 = graph()->NewNode( |
545 simplified()->LoadField(AccessBuilder::ForJSTypedArrayLength()), array, | 564 simplified()->LoadField(AccessBuilder::ForJSTypedArrayLength()), array, |
546 efalse0, if_false0); | 565 efalse0, if_false0); |
547 | 566 |
548 Node* check2 = | 567 Node* check2 = |
549 graph()->NewNode(simplified()->NumberLessThan(), index, length); | 568 graph()->NewNode(simplified()->NumberLessThan(), index, length); |
550 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue), | 569 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
551 check2, if_false0); | 570 check2, if_false0); |
552 | 571 |
(...skipping 1215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1768 return NoChange(); | 1787 return NoChange(); |
1769 } | 1788 } |
1770 | 1789 |
1771 Reduction JSBuiltinReducer::ReduceArrayBufferViewAccessor( | 1790 Reduction JSBuiltinReducer::ReduceArrayBufferViewAccessor( |
1772 Node* node, InstanceType instance_type, FieldAccess const& access) { | 1791 Node* node, InstanceType instance_type, FieldAccess const& access) { |
1773 Node* receiver = NodeProperties::GetValueInput(node, 1); | 1792 Node* receiver = NodeProperties::GetValueInput(node, 1); |
1774 Node* effect = NodeProperties::GetEffectInput(node); | 1793 Node* effect = NodeProperties::GetEffectInput(node); |
1775 Node* control = NodeProperties::GetControlInput(node); | 1794 Node* control = NodeProperties::GetControlInput(node); |
1776 if (HasInstanceTypeWitness(receiver, effect, instance_type)) { | 1795 if (HasInstanceTypeWitness(receiver, effect, instance_type)) { |
1777 // Load the {receiver}s field. | 1796 // Load the {receiver}s field. |
1778 Node* receiver_value = effect = graph()->NewNode( | 1797 Node* value = effect = graph()->NewNode(simplified()->LoadField(access), |
1779 simplified()->LoadField(access), receiver, effect, control); | 1798 receiver, effect, control); |
1780 | 1799 |
1781 // Check if the {receiver}s buffer was neutered. | 1800 // See if we can skip the neutering check. |
1782 Node* receiver_buffer = effect = graph()->NewNode( | 1801 if (isolate()->IsArrayBufferNeuteringIntact()) { |
1783 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()), | 1802 // Add a code dependency so we are deoptimized in case an ArrayBuffer |
1784 receiver, effect, control); | 1803 // gets neutered. |
1785 Node* check = effect = | 1804 dependencies()->AssumePropertyCell( |
1786 graph()->NewNode(simplified()->ArrayBufferWasNeutered(), | 1805 factory()->array_buffer_neutering_protector()); |
1787 receiver_buffer, effect, control); | 1806 } else { |
| 1807 // Check if the {receiver}s buffer was neutered. |
| 1808 Node* receiver_buffer = effect = graph()->NewNode( |
| 1809 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()), |
| 1810 receiver, effect, control); |
| 1811 Node* check = effect = |
| 1812 graph()->NewNode(simplified()->ArrayBufferWasNeutered(), |
| 1813 receiver_buffer, effect, control); |
1788 | 1814 |
1789 // Default to zero if the {receiver}s buffer was neutered. | 1815 // Default to zero if the {receiver}s buffer was neutered. |
1790 Node* value = graph()->NewNode( | 1816 value = graph()->NewNode( |
1791 common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse), | 1817 common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse), |
1792 check, jsgraph()->ZeroConstant(), receiver_value); | 1818 check, jsgraph()->ZeroConstant(), value); |
| 1819 } |
1793 | 1820 |
1794 ReplaceWithValue(node, value, effect, control); | 1821 ReplaceWithValue(node, value, effect, control); |
1795 return Replace(value); | 1822 return Replace(value); |
1796 } | 1823 } |
1797 return NoChange(); | 1824 return NoChange(); |
1798 } | 1825 } |
1799 | 1826 |
1800 Reduction JSBuiltinReducer::Reduce(Node* node) { | 1827 Reduction JSBuiltinReducer::Reduce(Node* node) { |
1801 Reduction reduction = NoChange(); | 1828 Reduction reduction = NoChange(); |
1802 JSCallReduction r(node); | 1829 JSCallReduction r(node); |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2014 return jsgraph()->simplified(); | 2041 return jsgraph()->simplified(); |
2015 } | 2042 } |
2016 | 2043 |
2017 JSOperatorBuilder* JSBuiltinReducer::javascript() const { | 2044 JSOperatorBuilder* JSBuiltinReducer::javascript() const { |
2018 return jsgraph()->javascript(); | 2045 return jsgraph()->javascript(); |
2019 } | 2046 } |
2020 | 2047 |
2021 } // namespace compiler | 2048 } // namespace compiler |
2022 } // namespace internal | 2049 } // namespace internal |
2023 } // namespace v8 | 2050 } // namespace v8 |
OLD | NEW |