OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/effect-control-linearizer.h" | 5 #include "src/compiler/effect-control-linearizer.h" |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/compiler/access-builder.h" | 8 #include "src/compiler/access-builder.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 for (Node* const phi : phis) { | 258 for (Node* const phi : phis) { |
259 for (int index = 0; index < input_count; ++index) { | 259 for (int index = 0; index < input_count; ++index) { |
260 inputs[index] = phi->InputAt(index); | 260 inputs[index] = phi->InputAt(index); |
261 } | 261 } |
262 inputs[input_count] = merge_true; | 262 inputs[input_count] = merge_true; |
263 Node* phi_true = graph->NewNode(phi->op(), input_count + 1, inputs); | 263 Node* phi_true = graph->NewNode(phi->op(), input_count + 1, inputs); |
264 inputs[input_count] = merge_false; | 264 inputs[input_count] = merge_false; |
265 Node* phi_false = graph->NewNode(phi->op(), input_count + 1, inputs); | 265 Node* phi_false = graph->NewNode(phi->op(), input_count + 1, inputs); |
266 if (phi->UseCount() == 0) { | 266 if (phi->UseCount() == 0) { |
267 DCHECK_EQ(phi->opcode(), IrOpcode::kEffectPhi); | 267 DCHECK_EQ(phi->opcode(), IrOpcode::kEffectPhi); |
268 DCHECK_EQ(input_count, block->SuccessorCount()); | |
269 } else { | 268 } else { |
270 for (Edge edge : phi->use_edges()) { | 269 for (Edge edge : phi->use_edges()) { |
271 Node* control = NodeProperties::GetControlInput(edge.from()); | 270 Node* control = NodeProperties::GetControlInput(edge.from()); |
272 if (NodeProperties::IsPhi(edge.from())) { | 271 if (NodeProperties::IsPhi(edge.from())) { |
273 control = NodeProperties::GetControlInput(control, edge.index()); | 272 control = NodeProperties::GetControlInput(control, edge.index()); |
274 } | 273 } |
275 DCHECK(control == matcher.IfTrue() || control == matcher.IfFalse()); | 274 DCHECK(control == matcher.IfTrue() || control == matcher.IfFalse()); |
276 edge.UpdateTo((control == matcher.IfTrue()) ? phi_true : phi_false); | 275 edge.UpdateTo((control == matcher.IfTrue()) ? phi_true : phi_false); |
277 } | 276 } |
278 } | 277 } |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 break; | 608 break; |
610 case IrOpcode::kChangeTaggedToInt32: | 609 case IrOpcode::kChangeTaggedToInt32: |
611 state = LowerChangeTaggedToInt32(node, *effect, *control); | 610 state = LowerChangeTaggedToInt32(node, *effect, *control); |
612 break; | 611 break; |
613 case IrOpcode::kChangeTaggedToUint32: | 612 case IrOpcode::kChangeTaggedToUint32: |
614 state = LowerChangeTaggedToUint32(node, *effect, *control); | 613 state = LowerChangeTaggedToUint32(node, *effect, *control); |
615 break; | 614 break; |
616 case IrOpcode::kChangeTaggedToFloat64: | 615 case IrOpcode::kChangeTaggedToFloat64: |
617 state = LowerChangeTaggedToFloat64(node, *effect, *control); | 616 state = LowerChangeTaggedToFloat64(node, *effect, *control); |
618 break; | 617 break; |
| 618 case IrOpcode::kTruncateTaggedToBit: |
| 619 state = LowerTruncateTaggedToBit(node, *effect, *control); |
| 620 break; |
619 case IrOpcode::kTruncateTaggedToFloat64: | 621 case IrOpcode::kTruncateTaggedToFloat64: |
620 state = LowerTruncateTaggedToFloat64(node, *effect, *control); | 622 state = LowerTruncateTaggedToFloat64(node, *effect, *control); |
621 break; | 623 break; |
622 case IrOpcode::kCheckBounds: | 624 case IrOpcode::kCheckBounds: |
623 state = LowerCheckBounds(node, frame_state, *effect, *control); | 625 state = LowerCheckBounds(node, frame_state, *effect, *control); |
624 break; | 626 break; |
625 case IrOpcode::kCheckMaps: | 627 case IrOpcode::kCheckMaps: |
626 state = LowerCheckMaps(node, frame_state, *effect, *control); | 628 state = LowerCheckMaps(node, frame_state, *effect, *control); |
627 break; | 629 break; |
628 case IrOpcode::kCheckNumber: | 630 case IrOpcode::kCheckNumber: |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
935 EffectControlLinearizer::ValueEffectControl | 937 EffectControlLinearizer::ValueEffectControl |
936 EffectControlLinearizer::LowerChangeTaggedToBit(Node* node, Node* effect, | 938 EffectControlLinearizer::LowerChangeTaggedToBit(Node* node, Node* effect, |
937 Node* control) { | 939 Node* control) { |
938 Node* value = node->InputAt(0); | 940 Node* value = node->InputAt(0); |
939 value = graph()->NewNode(machine()->WordEqual(), value, | 941 value = graph()->NewNode(machine()->WordEqual(), value, |
940 jsgraph()->TrueConstant()); | 942 jsgraph()->TrueConstant()); |
941 return ValueEffectControl(value, effect, control); | 943 return ValueEffectControl(value, effect, control); |
942 } | 944 } |
943 | 945 |
944 EffectControlLinearizer::ValueEffectControl | 946 EffectControlLinearizer::ValueEffectControl |
| 947 EffectControlLinearizer::LowerTruncateTaggedToBit(Node* node, Node* effect, |
| 948 Node* control) { |
| 949 Node* value = node->InputAt(0); |
| 950 Node* one = jsgraph()->Int32Constant(1); |
| 951 Node* zero = jsgraph()->Int32Constant(0); |
| 952 Node* fzero = jsgraph()->Float64Constant(0.0); |
| 953 |
| 954 // Collect effect/control/value triples. |
| 955 int count = 0; |
| 956 Node* values[7]; |
| 957 Node* effects[7]; |
| 958 Node* controls[6]; |
| 959 |
| 960 // Check if {value} is a Smi. |
| 961 Node* check_smi = ObjectIsSmi(value); |
| 962 Node* branch_smi = graph()->NewNode(common()->Branch(BranchHint::kFalse), |
| 963 check_smi, control); |
| 964 |
| 965 // If {value} is a Smi, then we only need to check that it's not zero. |
| 966 Node* if_smi = graph()->NewNode(common()->IfTrue(), branch_smi); |
| 967 Node* esmi = effect; |
| 968 { |
| 969 controls[count] = if_smi; |
| 970 effects[count] = esmi; |
| 971 values[count] = |
| 972 graph()->NewNode(machine()->Word32Equal(), |
| 973 graph()->NewNode(machine()->WordEqual(), value, |
| 974 jsgraph()->ZeroConstant()), |
| 975 zero); |
| 976 count++; |
| 977 } |
| 978 control = graph()->NewNode(common()->IfFalse(), branch_smi); |
| 979 |
| 980 // Load the map instance type of {value}. |
| 981 Node* value_map = effect = graph()->NewNode( |
| 982 simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control); |
| 983 Node* value_instance_type = effect = graph()->NewNode( |
| 984 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map, |
| 985 effect, control); |
| 986 |
| 987 // Check if {value} is an Oddball. |
| 988 Node* check_oddball = |
| 989 graph()->NewNode(machine()->Word32Equal(), value_instance_type, |
| 990 jsgraph()->Int32Constant(ODDBALL_TYPE)); |
| 991 Node* branch_oddball = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
| 992 check_oddball, control); |
| 993 |
| 994 // The only Oddball {value} that is trueish is true itself. |
| 995 Node* if_oddball = graph()->NewNode(common()->IfTrue(), branch_oddball); |
| 996 Node* eoddball = effect; |
| 997 { |
| 998 controls[count] = if_oddball; |
| 999 effects[count] = eoddball; |
| 1000 values[count] = graph()->NewNode(machine()->WordEqual(), value, |
| 1001 jsgraph()->TrueConstant()); |
| 1002 count++; |
| 1003 } |
| 1004 control = graph()->NewNode(common()->IfFalse(), branch_oddball); |
| 1005 |
| 1006 // Check if {value} is a String. |
| 1007 Node* check_string = |
| 1008 graph()->NewNode(machine()->Int32LessThan(), value_instance_type, |
| 1009 jsgraph()->Int32Constant(FIRST_NONSTRING_TYPE)); |
| 1010 Node* branch_string = |
| 1011 graph()->NewNode(common()->Branch(), check_string, control); |
| 1012 |
| 1013 // For String {value}, we need to check that the length is not zero. |
| 1014 Node* if_string = graph()->NewNode(common()->IfTrue(), branch_string); |
| 1015 Node* estring = effect; |
| 1016 { |
| 1017 // Load the {value} length. |
| 1018 Node* value_length = estring = graph()->NewNode( |
| 1019 simplified()->LoadField(AccessBuilder::ForStringLength()), value, |
| 1020 estring, if_string); |
| 1021 |
| 1022 controls[count] = if_string; |
| 1023 effects[count] = estring; |
| 1024 values[count] = |
| 1025 graph()->NewNode(machine()->Word32Equal(), |
| 1026 graph()->NewNode(machine()->WordEqual(), value_length, |
| 1027 jsgraph()->ZeroConstant()), |
| 1028 zero); |
| 1029 count++; |
| 1030 } |
| 1031 control = graph()->NewNode(common()->IfFalse(), branch_string); |
| 1032 |
| 1033 // Check if {value} is a HeapNumber. |
| 1034 Node* check_heapnumber = |
| 1035 graph()->NewNode(machine()->Word32Equal(), value_instance_type, |
| 1036 jsgraph()->Int32Constant(HEAP_NUMBER_TYPE)); |
| 1037 Node* branch_heapnumber = |
| 1038 graph()->NewNode(common()->Branch(), check_heapnumber, control); |
| 1039 |
| 1040 // For HeapNumber {value}, just check that its value is not 0.0, -0.0 or NaN. |
| 1041 Node* if_heapnumber = graph()->NewNode(common()->IfTrue(), branch_heapnumber); |
| 1042 Node* eheapnumber = effect; |
| 1043 { |
| 1044 // Load the raw value of {value}. |
| 1045 Node* value_value = eheapnumber = graph()->NewNode( |
| 1046 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value, |
| 1047 eheapnumber, if_heapnumber); |
| 1048 |
| 1049 // Check if {value} is either less than 0.0 or greater than 0.0. |
| 1050 Node* check = |
| 1051 graph()->NewNode(machine()->Float64LessThan(), fzero, value_value); |
| 1052 Node* branch = graph()->NewNode(common()->Branch(), check, if_heapnumber); |
| 1053 |
| 1054 controls[count] = graph()->NewNode(common()->IfTrue(), branch); |
| 1055 effects[count] = eheapnumber; |
| 1056 values[count] = one; |
| 1057 count++; |
| 1058 |
| 1059 controls[count] = graph()->NewNode(common()->IfFalse(), branch); |
| 1060 effects[count] = eheapnumber; |
| 1061 values[count] = |
| 1062 graph()->NewNode(machine()->Float64LessThan(), value_value, fzero); |
| 1063 count++; |
| 1064 } |
| 1065 control = graph()->NewNode(common()->IfFalse(), branch_heapnumber); |
| 1066 |
| 1067 // The {value} is either a JSReceiver, a Symbol or some Simd128Value. In |
| 1068 // those cases we can just the undetectable bit on the map, which will only |
| 1069 // be set for certain JSReceivers, i.e. document.all. |
| 1070 { |
| 1071 // Load the {value} map bit field. |
| 1072 Node* value_map_bitfield = effect = graph()->NewNode( |
| 1073 simplified()->LoadField(AccessBuilder::ForMapBitField()), value_map, |
| 1074 effect, control); |
| 1075 |
| 1076 controls[count] = control; |
| 1077 effects[count] = effect; |
| 1078 values[count] = graph()->NewNode( |
| 1079 machine()->Word32Equal(), |
| 1080 graph()->NewNode(machine()->Word32And(), value_map_bitfield, |
| 1081 jsgraph()->Int32Constant(1 << Map::kIsUndetectable)), |
| 1082 zero); |
| 1083 count++; |
| 1084 } |
| 1085 |
| 1086 // Merge the different controls. |
| 1087 control = graph()->NewNode(common()->Merge(count), count, controls); |
| 1088 effects[count] = control; |
| 1089 effect = graph()->NewNode(common()->EffectPhi(count), count + 1, effects); |
| 1090 values[count] = control; |
| 1091 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, count), |
| 1092 count + 1, values); |
| 1093 |
| 1094 return ValueEffectControl(value, effect, control); |
| 1095 } |
| 1096 |
| 1097 EffectControlLinearizer::ValueEffectControl |
945 EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node, Node* effect, | 1098 EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node, Node* effect, |
946 Node* control) { | 1099 Node* control) { |
947 Node* value = node->InputAt(0); | 1100 Node* value = node->InputAt(0); |
948 | 1101 |
949 Node* check = ObjectIsSmi(value); | 1102 Node* check = ObjectIsSmi(value); |
950 Node* branch = | 1103 Node* branch = |
951 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | 1104 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); |
952 | 1105 |
953 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 1106 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
954 Node* etrue = effect; | 1107 Node* etrue = effect; |
(...skipping 2353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3308 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3461 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
3309 Operator::kEliminatable); | 3462 Operator::kEliminatable); |
3310 to_number_operator_.set(common()->Call(desc)); | 3463 to_number_operator_.set(common()->Call(desc)); |
3311 } | 3464 } |
3312 return to_number_operator_.get(); | 3465 return to_number_operator_.get(); |
3313 } | 3466 } |
3314 | 3467 |
3315 } // namespace compiler | 3468 } // namespace compiler |
3316 } // namespace internal | 3469 } // namespace internal |
3317 } // namespace v8 | 3470 } // namespace v8 |
OLD | NEW |