| 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-typed-lowering.h" | 5 #include "src/compiler/js-typed-lowering.h" |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/compilation-dependencies.h" | 8 #include "src/compilation-dependencies.h" |
| 9 #include "src/compiler/access-builder.h" | 9 #include "src/compiler/access-builder.h" |
| 10 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/js-graph.h" |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 the_hole_type_( | 379 the_hole_type_( |
| 380 Type::Constant(factory()->the_hole_value(), graph()->zone())), | 380 Type::Constant(factory()->the_hole_value(), graph()->zone())), |
| 381 type_cache_(TypeCache::Get()) { | 381 type_cache_(TypeCache::Get()) { |
| 382 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { | 382 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { |
| 383 double min = kMinInt / (1 << k); | 383 double min = kMinInt / (1 << k); |
| 384 double max = kMaxInt / (1 << k); | 384 double max = kMaxInt / (1 << k); |
| 385 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); | 385 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); |
| 386 } | 386 } |
| 387 } | 387 } |
| 388 | 388 |
| 389 | |
| 390 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { | 389 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { |
| 391 JSBinopReduction r(this, node); | 390 JSBinopReduction r(this, node); |
| 392 NumberOperationHint hint; | 391 NumberOperationHint hint; |
| 393 if (r.GetBinaryNumberOperationHint(&hint)) { | 392 if (r.GetBinaryNumberOperationHint(&hint)) { |
| 394 if (hint == NumberOperationHint::kNumberOrOddball && | 393 if (hint == NumberOperationHint::kNumberOrOddball && |
| 395 r.BothInputsAre(Type::PlainPrimitive()) && | 394 r.BothInputsAre(Type::PlainPrimitive()) && |
| 396 r.NeitherInputCanBe(Type::StringOrReceiver())) { | 395 r.NeitherInputCanBe(Type::StringOrReceiver())) { |
| 397 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) | 396 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) |
| 398 r.ConvertInputsToNumber(); | 397 r.ConvertInputsToNumber(); |
| 399 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); | 398 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 734 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
| 736 } else if (r.GetCompareNumberOperationHint(&hint)) { | 735 } else if (r.GetCompareNumberOperationHint(&hint)) { |
| 737 return r.ChangeToSpeculativeOperator( | 736 return r.ChangeToSpeculativeOperator( |
| 738 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); | 737 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); |
| 739 } else if (r.BothInputsAre(Type::Number())) { | 738 } else if (r.BothInputsAre(Type::Number())) { |
| 740 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 739 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
| 741 } | 740 } |
| 742 return NoChange(); | 741 return NoChange(); |
| 743 } | 742 } |
| 744 | 743 |
| 745 | |
| 746 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { | 744 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { |
| 747 JSBinopReduction r(this, node); | 745 JSBinopReduction r(this, node); |
| 748 if (r.left() == r.right()) { | 746 if (r.left() == r.right()) { |
| 749 // x === x is always true if x != NaN | 747 // x === x is always true if x != NaN |
| 750 if (!r.left_type()->Maybe(Type::NaN())) { | 748 if (!r.left_type()->Maybe(Type::NaN())) { |
| 751 Node* replacement = jsgraph()->BooleanConstant(!invert); | 749 Node* replacement = jsgraph()->BooleanConstant(!invert); |
| 752 ReplaceWithValue(node, replacement); | 750 ReplaceWithValue(node, replacement); |
| 753 return Replace(replacement); | 751 return Replace(replacement); |
| 754 } | 752 } |
| 755 } | 753 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 798 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 796 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
| 799 } else if (r.GetCompareNumberOperationHint(&hint)) { | 797 } else if (r.GetCompareNumberOperationHint(&hint)) { |
| 800 return r.ChangeToSpeculativeOperator( | 798 return r.ChangeToSpeculativeOperator( |
| 801 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); | 799 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); |
| 802 } else if (r.BothInputsAre(Type::Number())) { | 800 } else if (r.BothInputsAre(Type::Number())) { |
| 803 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 801 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
| 804 } | 802 } |
| 805 return NoChange(); | 803 return NoChange(); |
| 806 } | 804 } |
| 807 | 805 |
| 808 | |
| 809 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { | 806 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { |
| 810 Node* const input = node->InputAt(0); | 807 Node* const input = node->InputAt(0); |
| 811 Type* const input_type = NodeProperties::GetType(input); | 808 Type* const input_type = NodeProperties::GetType(input); |
| 812 if (input_type->Is(Type::Boolean())) { | 809 if (input_type->Is(Type::Boolean())) { |
| 813 // JSToBoolean(x:boolean) => x | 810 // JSToBoolean(x:boolean) => x |
| 814 return Replace(input); | 811 return Replace(input); |
| 815 } else if (input_type->Is(Type::OrderedNumber())) { | 812 } else if (input_type->Is(Type::OrderedNumber())) { |
| 816 // JSToBoolean(x:ordered-number) => BooleanNot(NumberEqual(x,#0)) | 813 // JSToBoolean(x:ordered-number) => BooleanNot(NumberEqual(x,#0)) |
| 817 RelaxEffectsAndControls(node); | 814 RelaxEffectsAndControls(node); |
| 818 node->ReplaceInput(0, graph()->NewNode(simplified()->NumberEqual(), input, | 815 node->ReplaceInput(0, graph()->NewNode(simplified()->NumberEqual(), input, |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 909 // JSToNumber(undefined) => #NaN | 906 // JSToNumber(undefined) => #NaN |
| 910 return Replace(jsgraph()->NaNConstant()); | 907 return Replace(jsgraph()->NaNConstant()); |
| 911 } | 908 } |
| 912 if (input_type->Is(Type::Null())) { | 909 if (input_type->Is(Type::Null())) { |
| 913 // JSToNumber(null) => #0 | 910 // JSToNumber(null) => #0 |
| 914 return Replace(jsgraph()->ZeroConstant()); | 911 return Replace(jsgraph()->ZeroConstant()); |
| 915 } | 912 } |
| 916 return NoChange(); | 913 return NoChange(); |
| 917 } | 914 } |
| 918 | 915 |
| 919 | |
| 920 Reduction JSTypedLowering::ReduceJSToNumber(Node* node) { | 916 Reduction JSTypedLowering::ReduceJSToNumber(Node* node) { |
| 921 // Try to reduce the input first. | 917 // Try to reduce the input first. |
| 922 Node* const input = node->InputAt(0); | 918 Node* const input = node->InputAt(0); |
| 923 Reduction reduction = ReduceJSToNumberInput(input); | 919 Reduction reduction = ReduceJSToNumberInput(input); |
| 924 if (reduction.Changed()) { | 920 if (reduction.Changed()) { |
| 925 ReplaceWithValue(node, reduction.replacement()); | 921 ReplaceWithValue(node, reduction.replacement()); |
| 926 return reduction; | 922 return reduction; |
| 927 } | 923 } |
| 928 Type* const input_type = NodeProperties::GetType(input); | 924 Type* const input_type = NodeProperties::GetType(input); |
| 929 if (input_type->Is(Type::PlainPrimitive())) { | 925 if (input_type->Is(Type::PlainPrimitive())) { |
| 930 RelaxEffectsAndControls(node); | 926 RelaxEffectsAndControls(node); |
| 931 node->TrimInputCount(1); | 927 node->TrimInputCount(1); |
| 932 NodeProperties::ChangeOp(node, simplified()->PlainPrimitiveToNumber()); | 928 NodeProperties::ChangeOp(node, simplified()->PlainPrimitiveToNumber()); |
| 933 return Changed(node); | 929 return Changed(node); |
| 934 } | 930 } |
| 935 return NoChange(); | 931 return NoChange(); |
| 936 } | 932 } |
| 937 | 933 |
| 938 | |
| 939 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) { | 934 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) { |
| 940 if (input->opcode() == IrOpcode::kJSToString) { | 935 if (input->opcode() == IrOpcode::kJSToString) { |
| 941 // Recursively try to reduce the input first. | 936 // Recursively try to reduce the input first. |
| 942 Reduction result = ReduceJSToString(input); | 937 Reduction result = ReduceJSToString(input); |
| 943 if (result.Changed()) return result; | 938 if (result.Changed()) return result; |
| 944 return Changed(input); // JSToString(JSToString(x)) => JSToString(x) | 939 return Changed(input); // JSToString(JSToString(x)) => JSToString(x) |
| 945 } | 940 } |
| 946 Type* input_type = NodeProperties::GetType(input); | 941 Type* input_type = NodeProperties::GetType(input); |
| 947 if (input_type->Is(Type::String())) { | 942 if (input_type->Is(Type::String())) { |
| 948 return Changed(input); // JSToString(x:string) => x | 943 return Changed(input); // JSToString(x:string) => x |
| 949 } | 944 } |
| 950 if (input_type->Is(Type::Boolean())) { | 945 if (input_type->Is(Type::Boolean())) { |
| 951 return Replace(graph()->NewNode( | 946 return Replace(graph()->NewNode( |
| 952 common()->Select(MachineRepresentation::kTagged), input, | 947 common()->Select(MachineRepresentation::kTagged), input, |
| 953 jsgraph()->HeapConstant(factory()->true_string()), | 948 jsgraph()->HeapConstant(factory()->true_string()), |
| 954 jsgraph()->HeapConstant(factory()->false_string()))); | 949 jsgraph()->HeapConstant(factory()->false_string()))); |
| 955 } | 950 } |
| 956 if (input_type->Is(Type::Undefined())) { | 951 if (input_type->Is(Type::Undefined())) { |
| 957 return Replace(jsgraph()->HeapConstant(factory()->undefined_string())); | 952 return Replace(jsgraph()->HeapConstant(factory()->undefined_string())); |
| 958 } | 953 } |
| 959 if (input_type->Is(Type::Null())) { | 954 if (input_type->Is(Type::Null())) { |
| 960 return Replace(jsgraph()->HeapConstant(factory()->null_string())); | 955 return Replace(jsgraph()->HeapConstant(factory()->null_string())); |
| 961 } | 956 } |
| 962 // TODO(turbofan): js-typed-lowering of ToString(x:number) | 957 // TODO(turbofan): js-typed-lowering of ToString(x:number) |
| 963 return NoChange(); | 958 return NoChange(); |
| 964 } | 959 } |
| 965 | 960 |
| 966 | |
| 967 Reduction JSTypedLowering::ReduceJSToString(Node* node) { | 961 Reduction JSTypedLowering::ReduceJSToString(Node* node) { |
| 968 // Try to reduce the input first. | 962 // Try to reduce the input first. |
| 969 Node* const input = node->InputAt(0); | 963 Node* const input = node->InputAt(0); |
| 970 Reduction reduction = ReduceJSToStringInput(input); | 964 Reduction reduction = ReduceJSToStringInput(input); |
| 971 if (reduction.Changed()) { | 965 if (reduction.Changed()) { |
| 972 ReplaceWithValue(node, reduction.replacement()); | 966 ReplaceWithValue(node, reduction.replacement()); |
| 973 return reduction; | 967 return reduction; |
| 974 } | 968 } |
| 975 return NoChange(); | 969 return NoChange(); |
| 976 } | 970 } |
| 977 | 971 |
| 978 | |
| 979 Reduction JSTypedLowering::ReduceJSToObject(Node* node) { | 972 Reduction JSTypedLowering::ReduceJSToObject(Node* node) { |
| 980 DCHECK_EQ(IrOpcode::kJSToObject, node->opcode()); | 973 DCHECK_EQ(IrOpcode::kJSToObject, node->opcode()); |
| 981 Node* receiver = NodeProperties::GetValueInput(node, 0); | 974 Node* receiver = NodeProperties::GetValueInput(node, 0); |
| 982 Type* receiver_type = NodeProperties::GetType(receiver); | 975 Type* receiver_type = NodeProperties::GetType(receiver); |
| 983 Node* context = NodeProperties::GetContextInput(node); | 976 Node* context = NodeProperties::GetContextInput(node); |
| 984 Node* frame_state = NodeProperties::GetFrameStateInput(node); | 977 Node* frame_state = NodeProperties::GetFrameStateInput(node); |
| 985 Node* effect = NodeProperties::GetEffectInput(node); | 978 Node* effect = NodeProperties::GetEffectInput(node); |
| 986 Node* control = NodeProperties::GetControlInput(node); | 979 Node* control = NodeProperties::GetControlInput(node); |
| 987 if (receiver_type->Is(Type::Receiver())) { | 980 if (receiver_type->Is(Type::Receiver())) { |
| 988 ReplaceWithValue(node, receiver, effect, control); | 981 ReplaceWithValue(node, receiver, effect, control); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1046 receiver_type->Is(Type::String())) { | 1039 receiver_type->Is(Type::String())) { |
| 1047 Node* value = effect = graph()->NewNode( | 1040 Node* value = effect = graph()->NewNode( |
| 1048 simplified()->LoadField(AccessBuilder::ForStringLength()), receiver, | 1041 simplified()->LoadField(AccessBuilder::ForStringLength()), receiver, |
| 1049 effect, control); | 1042 effect, control); |
| 1050 ReplaceWithValue(node, value, effect); | 1043 ReplaceWithValue(node, value, effect); |
| 1051 return Replace(value); | 1044 return Replace(value); |
| 1052 } | 1045 } |
| 1053 return NoChange(); | 1046 return NoChange(); |
| 1054 } | 1047 } |
| 1055 | 1048 |
| 1056 | |
| 1057 Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) { | 1049 Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) { |
| 1058 Node* key = NodeProperties::GetValueInput(node, 1); | 1050 Node* key = NodeProperties::GetValueInput(node, 1); |
| 1059 Node* base = NodeProperties::GetValueInput(node, 0); | 1051 Node* base = NodeProperties::GetValueInput(node, 0); |
| 1060 Type* key_type = NodeProperties::GetType(key); | 1052 Type* key_type = NodeProperties::GetType(key); |
| 1061 HeapObjectMatcher mbase(base); | 1053 HeapObjectMatcher mbase(base); |
| 1062 if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) { | 1054 if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) { |
| 1063 Handle<JSTypedArray> const array = | 1055 Handle<JSTypedArray> const array = |
| 1064 Handle<JSTypedArray>::cast(mbase.Value()); | 1056 Handle<JSTypedArray>::cast(mbase.Value()); |
| 1065 if (!array->GetBuffer()->was_neutered()) { | 1057 if (!array->GetBuffer()->was_neutered()) { |
| 1066 array->GetBuffer()->set_is_neuterable(false); | 1058 array->GetBuffer()->set_is_neuterable(false); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1094 Node* load = graph()->NewNode(simplified()->LoadBuffer(access), buffer, | 1086 Node* load = graph()->NewNode(simplified()->LoadBuffer(access), buffer, |
| 1095 offset, length, effect, control); | 1087 offset, length, effect, control); |
| 1096 ReplaceWithValue(node, load, load); | 1088 ReplaceWithValue(node, load, load); |
| 1097 return Replace(load); | 1089 return Replace(load); |
| 1098 } | 1090 } |
| 1099 } | 1091 } |
| 1100 } | 1092 } |
| 1101 return NoChange(); | 1093 return NoChange(); |
| 1102 } | 1094 } |
| 1103 | 1095 |
| 1104 | |
| 1105 Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) { | 1096 Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) { |
| 1106 Node* key = NodeProperties::GetValueInput(node, 1); | 1097 Node* key = NodeProperties::GetValueInput(node, 1); |
| 1107 Node* base = NodeProperties::GetValueInput(node, 0); | 1098 Node* base = NodeProperties::GetValueInput(node, 0); |
| 1108 Node* value = NodeProperties::GetValueInput(node, 2); | 1099 Node* value = NodeProperties::GetValueInput(node, 2); |
| 1109 Type* key_type = NodeProperties::GetType(key); | 1100 Type* key_type = NodeProperties::GetType(key); |
| 1110 Type* value_type = NodeProperties::GetType(value); | 1101 Type* value_type = NodeProperties::GetType(value); |
| 1111 HeapObjectMatcher mbase(base); | 1102 HeapObjectMatcher mbase(base); |
| 1112 if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) { | 1103 if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) { |
| 1113 Handle<JSTypedArray> const array = | 1104 Handle<JSTypedArray> const array = |
| 1114 Handle<JSTypedArray>::cast(mbase.Value()); | 1105 Handle<JSTypedArray>::cast(mbase.Value()); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1172 node->ReplaceInput(5, control); | 1163 node->ReplaceInput(5, control); |
| 1173 node->TrimInputCount(6); | 1164 node->TrimInputCount(6); |
| 1174 NodeProperties::ChangeOp(node, simplified()->StoreBuffer(access)); | 1165 NodeProperties::ChangeOp(node, simplified()->StoreBuffer(access)); |
| 1175 return Changed(node); | 1166 return Changed(node); |
| 1176 } | 1167 } |
| 1177 } | 1168 } |
| 1178 } | 1169 } |
| 1179 return NoChange(); | 1170 return NoChange(); |
| 1180 } | 1171 } |
| 1181 | 1172 |
| 1182 | |
| 1183 Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) { | 1173 Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) { |
| 1184 DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode()); | 1174 DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode()); |
| 1185 Node* const context = NodeProperties::GetContextInput(node); | 1175 Node* const context = NodeProperties::GetContextInput(node); |
| 1186 Node* const frame_state = NodeProperties::GetFrameStateInput(node); | 1176 Node* const frame_state = NodeProperties::GetFrameStateInput(node); |
| 1187 | 1177 |
| 1188 // If deoptimization is disabled, we cannot optimize. | 1178 // If deoptimization is disabled, we cannot optimize. |
| 1189 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | 1179 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); |
| 1190 | 1180 |
| 1191 // If we are in a try block, don't optimize since the runtime call | 1181 // If we are in a try block, don't optimize since the runtime call |
| 1192 // in the proxy case can throw. | 1182 // in the proxy case can throw. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1275 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), | 1265 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), |
| 1276 loop_object_map, loop_effect, control); | 1266 loop_object_map, loop_effect, control); |
| 1277 Node* is_proxy = | 1267 Node* is_proxy = |
| 1278 graph()->NewNode(simplified()->NumberEqual(), map_instance_type, | 1268 graph()->NewNode(simplified()->NumberEqual(), map_instance_type, |
| 1279 jsgraph()->Constant(JS_PROXY_TYPE)); | 1269 jsgraph()->Constant(JS_PROXY_TYPE)); |
| 1280 Node* branch_is_proxy = | 1270 Node* branch_is_proxy = |
| 1281 graph()->NewNode(common()->Branch(BranchHint::kFalse), is_proxy, control); | 1271 graph()->NewNode(common()->Branch(BranchHint::kFalse), is_proxy, control); |
| 1282 Node* if_is_proxy = graph()->NewNode(common()->IfTrue(), branch_is_proxy); | 1272 Node* if_is_proxy = graph()->NewNode(common()->IfTrue(), branch_is_proxy); |
| 1283 Node* e_is_proxy = effect; | 1273 Node* e_is_proxy = effect; |
| 1284 | 1274 |
| 1285 | |
| 1286 Node* runtime_has_in_proto_chain = control = graph()->NewNode( | 1275 Node* runtime_has_in_proto_chain = control = graph()->NewNode( |
| 1287 common()->Merge(2), if_is_access_check_needed, if_is_proxy); | 1276 common()->Merge(2), if_is_access_check_needed, if_is_proxy); |
| 1288 effect = graph()->NewNode(common()->EffectPhi(2), e_is_access_check_needed, | 1277 effect = graph()->NewNode(common()->EffectPhi(2), e_is_access_check_needed, |
| 1289 e_is_proxy, control); | 1278 e_is_proxy, control); |
| 1290 | 1279 |
| 1291 // If we need an access check or the object is a Proxy, make a runtime call | 1280 // If we need an access check or the object is a Proxy, make a runtime call |
| 1292 // to finish the lowering. | 1281 // to finish the lowering. |
| 1293 Node* bool_result_runtime_has_in_proto_chain_case = graph()->NewNode( | 1282 Node* bool_result_runtime_has_in_proto_chain_case = graph()->NewNode( |
| 1294 javascript()->CallRuntime(Runtime::kHasInPrototypeChain), r.left(), | 1283 javascript()->CallRuntime(Runtime::kHasInPrototypeChain), r.left(), |
| 1295 prototype, context, frame_state, effect, control); | 1284 prototype, context, frame_state, effect, control); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1346 effect = | 1335 effect = |
| 1347 graph()->NewNode(common()->EffectPhi(2), e_is_smi, effect, control); | 1336 graph()->NewNode(common()->EffectPhi(2), e_is_smi, effect, control); |
| 1348 result = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | 1337 result = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), |
| 1349 jsgraph()->FalseConstant(), result, control); | 1338 jsgraph()->FalseConstant(), result, control); |
| 1350 } | 1339 } |
| 1351 | 1340 |
| 1352 ReplaceWithValue(node, result, effect, control); | 1341 ReplaceWithValue(node, result, effect, control); |
| 1353 return Changed(result); | 1342 return Changed(result); |
| 1354 } | 1343 } |
| 1355 | 1344 |
| 1356 | |
| 1357 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) { | 1345 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) { |
| 1358 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); | 1346 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); |
| 1359 ContextAccess const& access = ContextAccessOf(node->op()); | 1347 ContextAccess const& access = ContextAccessOf(node->op()); |
| 1360 Node* effect = NodeProperties::GetEffectInput(node); | 1348 Node* effect = NodeProperties::GetEffectInput(node); |
| 1361 Node* control = graph()->start(); | 1349 Node* control = graph()->start(); |
| 1362 for (size_t i = 0; i < access.depth(); ++i) { | 1350 for (size_t i = 0; i < access.depth(); ++i) { |
| 1363 Node* previous = effect = graph()->NewNode( | 1351 Node* previous = effect = graph()->NewNode( |
| 1364 simplified()->LoadField( | 1352 simplified()->LoadField( |
| 1365 AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)), | 1353 AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)), |
| 1366 NodeProperties::GetValueInput(node, 0), effect, control); | 1354 NodeProperties::GetValueInput(node, 0), effect, control); |
| 1367 node->ReplaceInput(0, previous); | 1355 node->ReplaceInput(0, previous); |
| 1368 } | 1356 } |
| 1369 node->ReplaceInput(1, effect); | 1357 node->ReplaceInput(1, effect); |
| 1370 node->ReplaceInput(2, control); | 1358 node->ReplaceInput(2, control); |
| 1371 NodeProperties::ChangeOp( | 1359 NodeProperties::ChangeOp( |
| 1372 node, | 1360 node, |
| 1373 simplified()->LoadField(AccessBuilder::ForContextSlot(access.index()))); | 1361 simplified()->LoadField(AccessBuilder::ForContextSlot(access.index()))); |
| 1374 return Changed(node); | 1362 return Changed(node); |
| 1375 } | 1363 } |
| 1376 | 1364 |
| 1377 | |
| 1378 Reduction JSTypedLowering::ReduceJSStoreContext(Node* node) { | 1365 Reduction JSTypedLowering::ReduceJSStoreContext(Node* node) { |
| 1379 DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode()); | 1366 DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode()); |
| 1380 ContextAccess const& access = ContextAccessOf(node->op()); | 1367 ContextAccess const& access = ContextAccessOf(node->op()); |
| 1381 Node* effect = NodeProperties::GetEffectInput(node); | 1368 Node* effect = NodeProperties::GetEffectInput(node); |
| 1382 Node* control = graph()->start(); | 1369 Node* control = graph()->start(); |
| 1383 for (size_t i = 0; i < access.depth(); ++i) { | 1370 for (size_t i = 0; i < access.depth(); ++i) { |
| 1384 Node* previous = effect = graph()->NewNode( | 1371 Node* previous = effect = graph()->NewNode( |
| 1385 simplified()->LoadField( | 1372 simplified()->LoadField( |
| 1386 AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)), | 1373 AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)), |
| 1387 NodeProperties::GetValueInput(node, 0), effect, control); | 1374 NodeProperties::GetValueInput(node, 0), effect, control); |
| 1388 node->ReplaceInput(0, previous); | 1375 node->ReplaceInput(0, previous); |
| 1389 } | 1376 } |
| 1390 node->RemoveInput(2); | 1377 node->RemoveInput(2); |
| 1391 node->ReplaceInput(2, effect); | 1378 node->ReplaceInput(2, effect); |
| 1392 NodeProperties::ChangeOp( | 1379 NodeProperties::ChangeOp( |
| 1393 node, | 1380 node, |
| 1394 simplified()->StoreField(AccessBuilder::ForContextSlot(access.index()))); | 1381 simplified()->StoreField(AccessBuilder::ForContextSlot(access.index()))); |
| 1395 return Changed(node); | 1382 return Changed(node); |
| 1396 } | 1383 } |
| 1397 | 1384 |
| 1398 | |
| 1399 Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) { | 1385 Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) { |
| 1400 DCHECK_EQ(IrOpcode::kJSConvertReceiver, node->opcode()); | 1386 DCHECK_EQ(IrOpcode::kJSConvertReceiver, node->opcode()); |
| 1401 ConvertReceiverMode mode = ConvertReceiverModeOf(node->op()); | 1387 ConvertReceiverMode mode = ConvertReceiverModeOf(node->op()); |
| 1402 Node* receiver = NodeProperties::GetValueInput(node, 0); | 1388 Node* receiver = NodeProperties::GetValueInput(node, 0); |
| 1403 Type* receiver_type = NodeProperties::GetType(receiver); | 1389 Type* receiver_type = NodeProperties::GetType(receiver); |
| 1404 Node* context = NodeProperties::GetContextInput(node); | 1390 Node* context = NodeProperties::GetContextInput(node); |
| 1405 Type* context_type = NodeProperties::GetType(context); | 1391 Type* context_type = NodeProperties::GetType(context); |
| 1406 Node* frame_state = NodeProperties::GetFrameStateInput(node); | 1392 Node* frame_state = NodeProperties::GetFrameStateInput(node); |
| 1407 Node* effect = NodeProperties::GetEffectInput(node); | 1393 Node* effect = NodeProperties::GetEffectInput(node); |
| 1408 Node* control = NodeProperties::GetControlInput(node); | 1394 Node* control = NodeProperties::GetControlInput(node); |
| 1409 if (!receiver_type->Is(Type::Receiver())) { | 1395 |
| 1410 if (receiver_type->Is(Type::NullOrUndefined()) || | 1396 // Check if {receiver} is known to be a receiver. |
| 1411 mode == ConvertReceiverMode::kNullOrUndefined) { | 1397 if (receiver_type->Is(Type::Receiver())) { |
| 1412 if (context_type->IsConstant()) { | 1398 ReplaceWithValue(node, receiver, effect, control); |
| 1413 Handle<JSObject> global_proxy( | 1399 return Replace(receiver); |
| 1414 Handle<Context>::cast(context_type->AsConstant()->Value()) | 1400 } |
| 1415 ->global_proxy(), | 1401 |
| 1416 isolate()); | 1402 // If the {receiver} is known to be null or undefined, we can just replace it |
| 1417 receiver = jsgraph()->Constant(global_proxy); | 1403 // with the global proxy unconditionally. |
| 1418 } else { | 1404 if (receiver_type->Is(Type::NullOrUndefined()) || |
| 1419 Node* native_context = effect = graph()->NewNode( | 1405 mode == ConvertReceiverMode::kNullOrUndefined) { |
| 1420 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | 1406 if (context_type->IsConstant()) { |
| 1421 context, context, effect); | 1407 Handle<JSObject> global_proxy( |
| 1422 receiver = effect = graph()->NewNode( | 1408 Handle<Context>::cast(context_type->AsConstant()->Value()) |
| 1423 javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true), | 1409 ->global_proxy(), |
| 1424 native_context, native_context, effect); | 1410 isolate()); |
| 1425 } | 1411 receiver = jsgraph()->Constant(global_proxy); |
| 1426 } else if (!receiver_type->Maybe(Type::NullOrUndefined()) || | |
| 1427 mode == ConvertReceiverMode::kNotNullOrUndefined) { | |
| 1428 receiver = effect = | |
| 1429 graph()->NewNode(javascript()->ToObject(), receiver, context, | |
| 1430 frame_state, effect, control); | |
| 1431 } else { | 1412 } else { |
| 1432 // Check {receiver} for undefined. | 1413 Node* native_context = effect = graph()->NewNode( |
| 1433 Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(), receiver, | 1414 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), |
| 1434 jsgraph()->UndefinedConstant()); | 1415 context, context, effect); |
| 1435 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kFalse), | 1416 receiver = effect = graph()->NewNode( |
| 1436 check0, control); | 1417 javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true), |
| 1437 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | 1418 native_context, native_context, effect); |
| 1438 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | 1419 } |
| 1420 ReplaceWithValue(node, receiver, effect, control); |
| 1421 return Replace(receiver); |
| 1422 } |
| 1439 | 1423 |
| 1440 // Check {receiver} for null. | 1424 // If {receiver} cannot be null or undefined we can skip a few checks. |
| 1441 Node* check1 = graph()->NewNode(simplified()->ReferenceEqual(), receiver, | 1425 if (!receiver_type->Maybe(Type::NullOrUndefined()) || |
| 1442 jsgraph()->NullConstant()); | 1426 mode == ConvertReceiverMode::kNotNullOrUndefined) { |
| 1443 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse), | 1427 Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), receiver); |
| 1444 check1, if_false0); | 1428 Node* branch = |
| 1445 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | 1429 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); |
| 1446 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 1447 | 1430 |
| 1448 // Convert {receiver} using ToObject. | 1431 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
| 1449 Node* if_convert = if_false1; | 1432 Node* etrue = effect; |
| 1450 Node* econvert = effect; | 1433 Node* rtrue = receiver; |
| 1451 Node* rconvert; | |
| 1452 { | |
| 1453 rconvert = econvert = | |
| 1454 graph()->NewNode(javascript()->ToObject(), receiver, context, | |
| 1455 frame_state, econvert, if_convert); | |
| 1456 } | |
| 1457 | 1434 |
| 1458 // Replace {receiver} with global proxy of {context}. | 1435 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
| 1459 Node* if_global = | 1436 Node* efalse = effect; |
| 1460 graph()->NewNode(common()->Merge(2), if_true0, if_true1); | 1437 Node* rfalse; |
| 1461 Node* eglobal = effect; | 1438 { |
| 1462 Node* rglobal; | 1439 // Convert {receiver} using the ToObjectStub. |
| 1463 { | 1440 Callable callable = CodeFactory::ToObject(isolate()); |
| 1464 if (context_type->IsConstant()) { | 1441 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor( |
| 1465 Handle<JSObject> global_proxy( | 1442 isolate(), graph()->zone(), callable.descriptor(), 0, |
| 1466 Handle<Context>::cast(context_type->AsConstant()->Value()) | 1443 CallDescriptor::kNeedsFrameState, node->op()->properties()); |
| 1467 ->global_proxy(), | 1444 rfalse = efalse = graph()->NewNode( |
| 1468 isolate()); | 1445 common()->Call(desc), jsgraph()->HeapConstant(callable.code()), |
| 1469 rglobal = jsgraph()->Constant(global_proxy); | 1446 receiver, context, frame_state, efalse); |
| 1470 } else { | 1447 } |
| 1471 Node* native_context = eglobal = graph()->NewNode( | |
| 1472 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | |
| 1473 context, context, eglobal); | |
| 1474 rglobal = eglobal = graph()->NewNode( | |
| 1475 javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true), | |
| 1476 native_context, native_context, eglobal); | |
| 1477 } | |
| 1478 } | |
| 1479 | 1448 |
| 1480 control = graph()->NewNode(common()->Merge(2), if_convert, if_global); | 1449 control = graph()->NewNode(common()->Merge(2), if_true, if_false); |
| 1481 effect = | 1450 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); |
| 1482 graph()->NewNode(common()->EffectPhi(2), econvert, eglobal, control); | 1451 |
| 1483 receiver = | 1452 // Morph the {node} into an appropriate Phi. |
| 1484 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | 1453 ReplaceWithValue(node, node, effect, control); |
| 1485 rconvert, rglobal, control); | 1454 node->ReplaceInput(0, rtrue); |
| 1455 node->ReplaceInput(1, rfalse); |
| 1456 node->ReplaceInput(2, control); |
| 1457 node->TrimInputCount(3); |
| 1458 NodeProperties::ChangeOp(node, |
| 1459 common()->Phi(MachineRepresentation::kTagged, 2)); |
| 1460 return Changed(node); |
| 1461 } |
| 1462 |
| 1463 // Check if {receiver} is already a JSReceiver. |
| 1464 Node* check0 = graph()->NewNode(simplified()->ObjectIsReceiver(), receiver); |
| 1465 Node* branch0 = |
| 1466 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); |
| 1467 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
| 1468 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); |
| 1469 |
| 1470 // Check {receiver} for undefined. |
| 1471 Node* check1 = graph()->NewNode(simplified()->ReferenceEqual(), receiver, |
| 1472 jsgraph()->UndefinedConstant()); |
| 1473 Node* branch1 = |
| 1474 graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, if_false0); |
| 1475 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 1476 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 1477 |
| 1478 // Check {receiver} for null. |
| 1479 Node* check2 = graph()->NewNode(simplified()->ReferenceEqual(), receiver, |
| 1480 jsgraph()->NullConstant()); |
| 1481 Node* branch2 = |
| 1482 graph()->NewNode(common()->Branch(BranchHint::kFalse), check2, if_false1); |
| 1483 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); |
| 1484 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); |
| 1485 |
| 1486 // We just use {receiver} directly. |
| 1487 Node* if_noop = if_true0; |
| 1488 Node* enoop = effect; |
| 1489 Node* rnoop = receiver; |
| 1490 |
| 1491 // Convert {receiver} using ToObject. |
| 1492 Node* if_convert = if_false2; |
| 1493 Node* econvert = effect; |
| 1494 Node* rconvert; |
| 1495 { |
| 1496 // Convert {receiver} using the ToObjectStub. |
| 1497 Callable callable = CodeFactory::ToObject(isolate()); |
| 1498 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor( |
| 1499 isolate(), graph()->zone(), callable.descriptor(), 0, |
| 1500 CallDescriptor::kNeedsFrameState, node->op()->properties()); |
| 1501 rconvert = econvert = graph()->NewNode( |
| 1502 common()->Call(desc), jsgraph()->HeapConstant(callable.code()), |
| 1503 receiver, context, frame_state, econvert); |
| 1504 } |
| 1505 |
| 1506 // Replace {receiver} with global proxy of {context}. |
| 1507 Node* if_global = graph()->NewNode(common()->Merge(2), if_true1, if_true2); |
| 1508 Node* eglobal = effect; |
| 1509 Node* rglobal; |
| 1510 { |
| 1511 if (context_type->IsConstant()) { |
| 1512 Handle<JSObject> global_proxy( |
| 1513 Handle<Context>::cast(context_type->AsConstant()->Value()) |
| 1514 ->global_proxy(), |
| 1515 isolate()); |
| 1516 rglobal = jsgraph()->Constant(global_proxy); |
| 1517 } else { |
| 1518 Node* native_context = eglobal = graph()->NewNode( |
| 1519 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), |
| 1520 context, context, eglobal); |
| 1521 rglobal = eglobal = graph()->NewNode( |
| 1522 javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true), |
| 1523 native_context, native_context, eglobal); |
| 1486 } | 1524 } |
| 1487 } | 1525 } |
| 1488 ReplaceWithValue(node, receiver, effect, control); | 1526 |
| 1489 return Changed(receiver); | 1527 control = |
| 1528 graph()->NewNode(common()->Merge(3), if_noop, if_convert, if_global); |
| 1529 effect = graph()->NewNode(common()->EffectPhi(3), enoop, econvert, eglobal, |
| 1530 control); |
| 1531 // Morph the {node} into an appropriate Phi. |
| 1532 ReplaceWithValue(node, node, effect, control); |
| 1533 node->ReplaceInput(0, rnoop); |
| 1534 node->ReplaceInput(1, rconvert); |
| 1535 node->ReplaceInput(2, rglobal); |
| 1536 node->ReplaceInput(3, control); |
| 1537 node->TrimInputCount(4); |
| 1538 NodeProperties::ChangeOp(node, |
| 1539 common()->Phi(MachineRepresentation::kTagged, 3)); |
| 1540 return Changed(node); |
| 1490 } | 1541 } |
| 1491 | 1542 |
| 1492 | |
| 1493 Reduction JSTypedLowering::ReduceJSCallConstruct(Node* node) { | 1543 Reduction JSTypedLowering::ReduceJSCallConstruct(Node* node) { |
| 1494 DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode()); | 1544 DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode()); |
| 1495 CallConstructParameters const& p = CallConstructParametersOf(node->op()); | 1545 CallConstructParameters const& p = CallConstructParametersOf(node->op()); |
| 1496 DCHECK_LE(2u, p.arity()); | 1546 DCHECK_LE(2u, p.arity()); |
| 1497 int const arity = static_cast<int>(p.arity() - 2); | 1547 int const arity = static_cast<int>(p.arity() - 2); |
| 1498 Node* target = NodeProperties::GetValueInput(node, 0); | 1548 Node* target = NodeProperties::GetValueInput(node, 0); |
| 1499 Type* target_type = NodeProperties::GetType(target); | 1549 Type* target_type = NodeProperties::GetType(target); |
| 1500 Node* new_target = NodeProperties::GetValueInput(node, arity + 1); | 1550 Node* new_target = NodeProperties::GetValueInput(node, arity + 1); |
| 1501 | 1551 |
| 1502 // Check if {target} is a known JSFunction. | 1552 // Check if {target} is a known JSFunction. |
| (...skipping 611 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2114 } | 2164 } |
| 2115 | 2165 |
| 2116 | 2166 |
| 2117 CompilationDependencies* JSTypedLowering::dependencies() const { | 2167 CompilationDependencies* JSTypedLowering::dependencies() const { |
| 2118 return dependencies_; | 2168 return dependencies_; |
| 2119 } | 2169 } |
| 2120 | 2170 |
| 2121 } // namespace compiler | 2171 } // namespace compiler |
| 2122 } // namespace internal | 2172 } // namespace internal |
| 2123 } // namespace v8 | 2173 } // namespace v8 |
| OLD | NEW |