Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: src/compiler/js-typed-lowering.cc

Issue 2228783003: [turbofan] Fix typed lowering of JSConvertReceiver. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/js-operator.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/js-operator.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698