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/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
10 #include "src/compiler/access-builder.h" | 10 #include "src/compiler/access-builder.h" |
(...skipping 894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
905 } | 905 } |
906 | 906 |
907 ReplaceWithValue(node, value, effect, control); | 907 ReplaceWithValue(node, value, effect, control); |
908 return Replace(value); | 908 return Replace(value); |
909 } | 909 } |
910 return NoChange(); | 910 return NoChange(); |
911 } | 911 } |
912 | 912 |
913 // ES6 section 22.1.3.18 Array.prototype.push ( ) | 913 // ES6 section 22.1.3.18 Array.prototype.push ( ) |
914 Reduction JSBuiltinReducer::ReduceArrayPush(Node* node) { | 914 Reduction JSBuiltinReducer::ReduceArrayPush(Node* node) { |
915 Handle<Map> receiver_map; | |
916 // We need exactly target, receiver and value parameters. | 915 // We need exactly target, receiver and value parameters. |
917 if (node->op()->ValueInputCount() != 3) return NoChange(); | 916 if (node->op()->ValueInputCount() != 3) return NoChange(); |
918 Node* receiver = NodeProperties::GetValueInput(node, 1); | 917 Node* receiver = NodeProperties::GetValueInput(node, 1); |
919 Node* effect = NodeProperties::GetEffectInput(node); | 918 Node* effect = NodeProperties::GetEffectInput(node); |
920 Node* control = NodeProperties::GetControlInput(node); | 919 Node* control = NodeProperties::GetControlInput(node); |
921 Node* value = NodeProperties::GetValueInput(node, 2); | 920 Node* value = NodeProperties::GetValueInput(node, 2); |
922 if (GetMapWitness(node).ToHandle(&receiver_map) && | 921 ZoneHandleSet<Map> receiver_maps; |
923 CanInlineArrayResizeOperation(receiver_map)) { | 922 NodeProperties::InferReceiverMapsResult result = |
| 923 NodeProperties::InferReceiverMaps(receiver, effect, &receiver_maps); |
| 924 if (receiver_maps.size() != 1) return NoChange(); |
| 925 DCHECK_NE(NodeProperties::kNoReceiverMaps, result); |
| 926 |
| 927 // TODO(turbofan): Relax this to deal with multiple {receiver} maps. |
| 928 Handle<Map> receiver_map = receiver_maps[0]; |
| 929 if (CanInlineArrayResizeOperation(receiver_map)) { |
924 // Install code dependencies on the {receiver} prototype maps and the | 930 // Install code dependencies on the {receiver} prototype maps and the |
925 // global array protector cell. | 931 // global array protector cell. |
926 dependencies()->AssumePropertyCell(factory()->array_protector()); | 932 dependencies()->AssumePropertyCell(factory()->array_protector()); |
927 dependencies()->AssumePrototypeMapsStable(receiver_map); | 933 dependencies()->AssumePrototypeMapsStable(receiver_map); |
928 | 934 |
| 935 // If the {receiver_maps} information is not reliable, we need |
| 936 // to check that the {receiver} still has one of these maps. |
| 937 if (result == NodeProperties::kUnreliableReceiverMaps) { |
| 938 if (receiver_map->is_stable()) { |
| 939 dependencies()->AssumeMapStable(receiver_map); |
| 940 } else { |
| 941 // TODO(turbofan): This is a potential - yet unlikely - deoptimization |
| 942 // loop, since we might not learn from this deoptimization in baseline |
| 943 // code. We need a way to learn from deoptimizations in optimized to |
| 944 // address these problems. |
| 945 effect = graph()->NewNode( |
| 946 simplified()->CheckMaps(CheckMapsFlag::kNone, receiver_maps), |
| 947 receiver, effect, control); |
| 948 } |
| 949 } |
| 950 |
929 // TODO(turbofan): Perform type checks on the {value}. We are not guaranteed | 951 // TODO(turbofan): Perform type checks on the {value}. We are not guaranteed |
930 // to learn from these checks in case they fail, as the witness (i.e. the | 952 // to learn from these checks in case they fail, as the witness (i.e. the |
931 // map check from the LoadIC for a.push) might not be executed in baseline | 953 // map check from the LoadIC for a.push) might not be executed in baseline |
932 // code (after we stored the value in the builtin and thereby changed the | 954 // code (after we stored the value in the builtin and thereby changed the |
933 // elements kind of a) before be decide to optimize this function again. We | 955 // elements kind of a) before be decide to optimize this function again. We |
934 // currently don't have a proper way to deal with this; the proper solution | 956 // currently don't have a proper way to deal with this; the proper solution |
935 // here is to learn on deopt, i.e. disable Array.prototype.push inlining | 957 // here is to learn on deopt, i.e. disable Array.prototype.push inlining |
936 // for this function. | 958 // for this function. |
937 if (IsFastSmiElementsKind(receiver_map->elements_kind())) { | 959 if (IsFastSmiElementsKind(receiver_map->elements_kind())) { |
938 value = effect = | 960 value = effect = |
(...skipping 1371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2310 return jsgraph()->simplified(); | 2332 return jsgraph()->simplified(); |
2311 } | 2333 } |
2312 | 2334 |
2313 JSOperatorBuilder* JSBuiltinReducer::javascript() const { | 2335 JSOperatorBuilder* JSBuiltinReducer::javascript() const { |
2314 return jsgraph()->javascript(); | 2336 return jsgraph()->javascript(); |
2315 } | 2337 } |
2316 | 2338 |
2317 } // namespace compiler | 2339 } // namespace compiler |
2318 } // namespace internal | 2340 } // namespace internal |
2319 } // namespace v8 | 2341 } // namespace v8 |
OLD | NEW |