| 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()); |
| 268 } else { | 269 } else { |
| 269 for (Edge edge : phi->use_edges()) { | 270 for (Edge edge : phi->use_edges()) { |
| 270 Node* control = NodeProperties::GetControlInput(edge.from()); | 271 Node* control = NodeProperties::GetControlInput(edge.from()); |
| 271 if (NodeProperties::IsPhi(edge.from())) { | 272 if (NodeProperties::IsPhi(edge.from())) { |
| 272 control = NodeProperties::GetControlInput(control, edge.index()); | 273 control = NodeProperties::GetControlInput(control, edge.index()); |
| 273 } | 274 } |
| 274 DCHECK(control == matcher.IfTrue() || control == matcher.IfFalse()); | 275 DCHECK(control == matcher.IfTrue() || control == matcher.IfFalse()); |
| 275 edge.UpdateTo((control == matcher.IfTrue()) ? phi_true : phi_false); | 276 edge.UpdateTo((control == matcher.IfTrue()) ? phi_true : phi_false); |
| 276 } | 277 } |
| 277 } | 278 } |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 break; | 609 break; |
| 609 case IrOpcode::kChangeTaggedToInt32: | 610 case IrOpcode::kChangeTaggedToInt32: |
| 610 state = LowerChangeTaggedToInt32(node, *effect, *control); | 611 state = LowerChangeTaggedToInt32(node, *effect, *control); |
| 611 break; | 612 break; |
| 612 case IrOpcode::kChangeTaggedToUint32: | 613 case IrOpcode::kChangeTaggedToUint32: |
| 613 state = LowerChangeTaggedToUint32(node, *effect, *control); | 614 state = LowerChangeTaggedToUint32(node, *effect, *control); |
| 614 break; | 615 break; |
| 615 case IrOpcode::kChangeTaggedToFloat64: | 616 case IrOpcode::kChangeTaggedToFloat64: |
| 616 state = LowerChangeTaggedToFloat64(node, *effect, *control); | 617 state = LowerChangeTaggedToFloat64(node, *effect, *control); |
| 617 break; | 618 break; |
| 618 case IrOpcode::kTruncateTaggedToBit: | |
| 619 state = LowerTruncateTaggedToBit(node, *effect, *control); | |
| 620 break; | |
| 621 case IrOpcode::kTruncateTaggedToFloat64: | 619 case IrOpcode::kTruncateTaggedToFloat64: |
| 622 state = LowerTruncateTaggedToFloat64(node, *effect, *control); | 620 state = LowerTruncateTaggedToFloat64(node, *effect, *control); |
| 623 break; | 621 break; |
| 624 case IrOpcode::kCheckBounds: | 622 case IrOpcode::kCheckBounds: |
| 625 state = LowerCheckBounds(node, frame_state, *effect, *control); | 623 state = LowerCheckBounds(node, frame_state, *effect, *control); |
| 626 break; | 624 break; |
| 627 case IrOpcode::kCheckNumber: | 625 case IrOpcode::kCheckNumber: |
| 628 state = LowerCheckNumber(node, frame_state, *effect, *control); | 626 state = LowerCheckNumber(node, frame_state, *effect, *control); |
| 629 break; | 627 break; |
| 630 case IrOpcode::kCheckIf: | 628 case IrOpcode::kCheckIf: |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 888 | 886 |
| 889 EffectControlLinearizer::ValueEffectControl | 887 EffectControlLinearizer::ValueEffectControl |
| 890 EffectControlLinearizer::LowerChangeTaggedToBit(Node* node, Node* effect, | 888 EffectControlLinearizer::LowerChangeTaggedToBit(Node* node, Node* effect, |
| 891 Node* control) { | 889 Node* control) { |
| 892 Node* value = node->InputAt(0); | 890 Node* value = node->InputAt(0); |
| 893 value = graph()->NewNode(machine()->WordEqual(), value, | 891 value = graph()->NewNode(machine()->WordEqual(), value, |
| 894 jsgraph()->TrueConstant()); | 892 jsgraph()->TrueConstant()); |
| 895 return ValueEffectControl(value, effect, control); | 893 return ValueEffectControl(value, effect, control); |
| 896 } | 894 } |
| 897 | 895 |
| 898 EffectControlLinearizer::ValueEffectControl | |
| 899 EffectControlLinearizer::LowerTruncateTaggedToBit(Node* node, Node* effect, | |
| 900 Node* control) { | |
| 901 Node* value = node->InputAt(0); | |
| 902 Node* one = jsgraph()->Int32Constant(1); | |
| 903 Node* zero = jsgraph()->Int32Constant(0); | |
| 904 Node* fzero = jsgraph()->Float64Constant(0.0); | |
| 905 | |
| 906 // Collect effect/control/value triples. | |
| 907 int count = 0; | |
| 908 Node* values[7]; | |
| 909 Node* effects[7]; | |
| 910 Node* controls[6]; | |
| 911 | |
| 912 // Check if {value} is a Smi. | |
| 913 Node* check_smi = ObjectIsSmi(value); | |
| 914 Node* branch_smi = graph()->NewNode(common()->Branch(BranchHint::kFalse), | |
| 915 check_smi, control); | |
| 916 | |
| 917 // If {value} is a Smi, then we only need to check that it's not zero. | |
| 918 Node* if_smi = graph()->NewNode(common()->IfTrue(), branch_smi); | |
| 919 Node* esmi = effect; | |
| 920 { | |
| 921 controls[count] = if_smi; | |
| 922 effects[count] = esmi; | |
| 923 values[count] = | |
| 924 graph()->NewNode(machine()->Word32Equal(), | |
| 925 graph()->NewNode(machine()->WordEqual(), value, | |
| 926 jsgraph()->ZeroConstant()), | |
| 927 zero); | |
| 928 count++; | |
| 929 } | |
| 930 control = graph()->NewNode(common()->IfFalse(), branch_smi); | |
| 931 | |
| 932 // Load the map instance type of {value}. | |
| 933 Node* value_map = effect = graph()->NewNode( | |
| 934 simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control); | |
| 935 Node* value_instance_type = effect = graph()->NewNode( | |
| 936 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map, | |
| 937 effect, control); | |
| 938 | |
| 939 // Check if {value} is an Oddball. | |
| 940 Node* check_oddball = | |
| 941 graph()->NewNode(machine()->Word32Equal(), value_instance_type, | |
| 942 jsgraph()->Int32Constant(ODDBALL_TYPE)); | |
| 943 Node* branch_oddball = graph()->NewNode(common()->Branch(BranchHint::kTrue), | |
| 944 check_oddball, control); | |
| 945 | |
| 946 // The only Oddball {value} that is trueish is true itself. | |
| 947 Node* if_oddball = graph()->NewNode(common()->IfTrue(), branch_oddball); | |
| 948 Node* eoddball = effect; | |
| 949 { | |
| 950 controls[count] = if_oddball; | |
| 951 effects[count] = eoddball; | |
| 952 values[count] = graph()->NewNode(machine()->WordEqual(), value, | |
| 953 jsgraph()->TrueConstant()); | |
| 954 count++; | |
| 955 } | |
| 956 control = graph()->NewNode(common()->IfFalse(), branch_oddball); | |
| 957 | |
| 958 // Check if {value} is a String. | |
| 959 Node* check_string = | |
| 960 graph()->NewNode(machine()->Int32LessThan(), value_instance_type, | |
| 961 jsgraph()->Int32Constant(FIRST_NONSTRING_TYPE)); | |
| 962 Node* branch_string = | |
| 963 graph()->NewNode(common()->Branch(), check_string, control); | |
| 964 | |
| 965 // For String {value}, we need to check that the length is not zero. | |
| 966 Node* if_string = graph()->NewNode(common()->IfTrue(), branch_string); | |
| 967 Node* estring = effect; | |
| 968 { | |
| 969 // Load the {value} length. | |
| 970 Node* value_length = estring = graph()->NewNode( | |
| 971 simplified()->LoadField(AccessBuilder::ForStringLength()), value, | |
| 972 estring, if_string); | |
| 973 | |
| 974 controls[count] = if_string; | |
| 975 effects[count] = estring; | |
| 976 values[count] = | |
| 977 graph()->NewNode(machine()->Word32Equal(), | |
| 978 graph()->NewNode(machine()->WordEqual(), value_length, | |
| 979 jsgraph()->ZeroConstant()), | |
| 980 zero); | |
| 981 count++; | |
| 982 } | |
| 983 control = graph()->NewNode(common()->IfFalse(), branch_string); | |
| 984 | |
| 985 // Check if {value} is a HeapNumber. | |
| 986 Node* check_heapnumber = | |
| 987 graph()->NewNode(machine()->Word32Equal(), value_instance_type, | |
| 988 jsgraph()->Int32Constant(HEAP_NUMBER_TYPE)); | |
| 989 Node* branch_heapnumber = | |
| 990 graph()->NewNode(common()->Branch(), check_heapnumber, control); | |
| 991 | |
| 992 // For HeapNumber {value}, just check that its value is not 0.0, -0.0 or NaN. | |
| 993 Node* if_heapnumber = graph()->NewNode(common()->IfTrue(), branch_heapnumber); | |
| 994 Node* eheapnumber = effect; | |
| 995 { | |
| 996 // Load the raw value of {value}. | |
| 997 Node* value_value = eheapnumber = graph()->NewNode( | |
| 998 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value, | |
| 999 eheapnumber, if_heapnumber); | |
| 1000 | |
| 1001 // Check if {value} is either less than 0.0 or greater than 0.0. | |
| 1002 Node* check = | |
| 1003 graph()->NewNode(machine()->Float64LessThan(), fzero, value_value); | |
| 1004 Node* branch = graph()->NewNode(common()->Branch(), check, if_heapnumber); | |
| 1005 | |
| 1006 controls[count] = graph()->NewNode(common()->IfTrue(), branch); | |
| 1007 effects[count] = eheapnumber; | |
| 1008 values[count] = one; | |
| 1009 count++; | |
| 1010 | |
| 1011 controls[count] = graph()->NewNode(common()->IfFalse(), branch); | |
| 1012 effects[count] = eheapnumber; | |
| 1013 values[count] = | |
| 1014 graph()->NewNode(machine()->Float64LessThan(), value_value, fzero); | |
| 1015 count++; | |
| 1016 } | |
| 1017 control = graph()->NewNode(common()->IfFalse(), branch_heapnumber); | |
| 1018 | |
| 1019 // The {value} is either a JSReceiver, a Symbol or some Simd128Value. In | |
| 1020 // those cases we can just the undetectable bit on the map, which will only | |
| 1021 // be set for certain JSReceivers, i.e. document.all. | |
| 1022 { | |
| 1023 // Load the {value} map bit field. | |
| 1024 Node* value_map_bitfield = effect = graph()->NewNode( | |
| 1025 simplified()->LoadField(AccessBuilder::ForMapBitField()), value_map, | |
| 1026 effect, control); | |
| 1027 | |
| 1028 controls[count] = control; | |
| 1029 effects[count] = effect; | |
| 1030 values[count] = graph()->NewNode( | |
| 1031 machine()->Word32Equal(), | |
| 1032 graph()->NewNode(machine()->Word32And(), value_map_bitfield, | |
| 1033 jsgraph()->Int32Constant(1 << Map::kIsUndetectable)), | |
| 1034 zero); | |
| 1035 count++; | |
| 1036 } | |
| 1037 | |
| 1038 // Merge the different controls. | |
| 1039 control = graph()->NewNode(common()->Merge(count), count, controls); | |
| 1040 effects[count] = control; | |
| 1041 effect = graph()->NewNode(common()->EffectPhi(count), count + 1, effects); | |
| 1042 values[count] = control; | |
| 1043 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, count), | |
| 1044 count + 1, values); | |
| 1045 | |
| 1046 return ValueEffectControl(value, effect, control); | |
| 1047 } | |
| 1048 | |
| 1049 EffectControlLinearizer::ValueEffectControl | 896 EffectControlLinearizer::ValueEffectControl |
| 1050 EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node, Node* effect, | 897 EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node, Node* effect, |
| 1051 Node* control) { | 898 Node* control) { |
| 1052 Node* value = node->InputAt(0); | 899 Node* value = node->InputAt(0); |
| 1053 | 900 |
| 1054 Node* check = ObjectIsSmi(value); | 901 Node* check = ObjectIsSmi(value); |
| 1055 Node* branch = | 902 Node* branch = |
| 1056 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | 903 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); |
| 1057 | 904 |
| 1058 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 905 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
| (...skipping 1293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2352 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 2199 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
| 2353 Operator::kNoThrow); | 2200 Operator::kNoThrow); |
| 2354 to_number_operator_.set(common()->Call(desc)); | 2201 to_number_operator_.set(common()->Call(desc)); |
| 2355 } | 2202 } |
| 2356 return to_number_operator_.get(); | 2203 return to_number_operator_.get(); |
| 2357 } | 2204 } |
| 2358 | 2205 |
| 2359 } // namespace compiler | 2206 } // namespace compiler |
| 2360 } // namespace internal | 2207 } // namespace internal |
| 2361 } // namespace v8 | 2208 } // namespace v8 |
| OLD | NEW |