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