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 |