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/instruction-selector-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
7 #include "src/compiler/node-properties.h" | 7 #include "src/compiler/node-properties.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 if (cont->IsSet()) { | 368 if (cont->IsSet()) { |
369 // TODO(turbofan): Use byte register here. | 369 // TODO(turbofan): Use byte register here. |
370 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 370 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
371 } | 371 } |
372 | 372 |
373 DCHECK_NE(0u, input_count); | 373 DCHECK_NE(0u, input_count); |
374 DCHECK_NE(0u, output_count); | 374 DCHECK_NE(0u, output_count); |
375 DCHECK_GE(arraysize(inputs), input_count); | 375 DCHECK_GE(arraysize(inputs), input_count); |
376 DCHECK_GE(arraysize(outputs), output_count); | 376 DCHECK_GE(arraysize(outputs), output_count); |
377 | 377 |
378 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, | 378 selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, |
379 outputs, input_count, inputs); | 379 inputs); |
380 if (cont->IsBranch()) instr->MarkAsControl(); | |
381 } | 380 } |
382 | 381 |
383 | 382 |
384 // Shared routine for multiple binary operations. | 383 // Shared routine for multiple binary operations. |
385 static void VisitBinop(InstructionSelector* selector, Node* node, | 384 static void VisitBinop(InstructionSelector* selector, Node* node, |
386 InstructionCode opcode) { | 385 InstructionCode opcode) { |
387 FlagsContinuation cont; | 386 FlagsContinuation cont; |
388 VisitBinop(selector, node, opcode, &cont); | 387 VisitBinop(selector, node, opcode, &cont); |
389 } | 388 } |
390 | 389 |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 | 815 |
817 namespace { | 816 namespace { |
818 | 817 |
819 // Shared routine for multiple compare operations. | 818 // Shared routine for multiple compare operations. |
820 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 819 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
821 InstructionOperand left, InstructionOperand right, | 820 InstructionOperand left, InstructionOperand right, |
822 FlagsContinuation* cont) { | 821 FlagsContinuation* cont) { |
823 IA32OperandGenerator g(selector); | 822 IA32OperandGenerator g(selector); |
824 if (cont->IsBranch()) { | 823 if (cont->IsBranch()) { |
825 selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right, | 824 selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right, |
826 g.Label(cont->true_block()), | 825 g.Label(cont->true_block()), g.Label(cont->false_block())); |
827 g.Label(cont->false_block()))->MarkAsControl(); | |
828 } else { | 826 } else { |
829 DCHECK(cont->IsSet()); | 827 DCHECK(cont->IsSet()); |
830 // TODO(titzer): Needs byte register. | 828 // TODO(titzer): Needs byte register. |
831 selector->Emit(cont->Encode(opcode), g.DefineAsRegister(cont->result()), | 829 selector->Emit(cont->Encode(opcode), g.DefineAsRegister(cont->result()), |
832 left, right); | 830 left, right); |
833 } | 831 } |
834 } | 832 } |
835 | 833 |
836 | 834 |
837 // Shared routine for multiple compare operations. | 835 // Shared routine for multiple compare operations. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
882 if (m.left().IsLoad() && m.right().IsLoadStackPointer()) { | 880 if (m.left().IsLoad() && m.right().IsLoadStackPointer()) { |
883 LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node()); | 881 LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node()); |
884 ExternalReference js_stack_limit = | 882 ExternalReference js_stack_limit = |
885 ExternalReference::address_of_stack_limit(selector->isolate()); | 883 ExternalReference::address_of_stack_limit(selector->isolate()); |
886 if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) { | 884 if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) { |
887 // Compare(Load(js_stack_limit), LoadStackPointer) | 885 // Compare(Load(js_stack_limit), LoadStackPointer) |
888 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); | 886 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); |
889 InstructionCode opcode = cont->Encode(kIA32StackCheck); | 887 InstructionCode opcode = cont->Encode(kIA32StackCheck); |
890 if (cont->IsBranch()) { | 888 if (cont->IsBranch()) { |
891 selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()), | 889 selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()), |
892 g.Label(cont->false_block()))->MarkAsControl(); | 890 g.Label(cont->false_block())); |
893 } else { | 891 } else { |
894 DCHECK(cont->IsSet()); | 892 DCHECK(cont->IsSet()); |
895 selector->Emit(opcode, g.DefineAsRegister(cont->result())); | 893 selector->Emit(opcode, g.DefineAsRegister(cont->result())); |
896 } | 894 } |
897 return; | 895 return; |
898 } | 896 } |
899 } | 897 } |
900 VisitWordCompare(selector, node, kIA32Cmp, cont); | 898 VisitWordCompare(selector, node, kIA32Cmp, cont); |
901 } | 899 } |
902 | 900 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1024 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); | 1022 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); |
1025 inputs[0] = index_operand; | 1023 inputs[0] = index_operand; |
1026 std::fill(&inputs[1], &inputs[input_count], default_operand); | 1024 std::fill(&inputs[1], &inputs[input_count], default_operand); |
1027 for (size_t index = 0; index < case_count; ++index) { | 1025 for (size_t index = 0; index < case_count; ++index) { |
1028 size_t value = case_values[index] - min_value; | 1026 size_t value = case_values[index] - min_value; |
1029 BasicBlock* branch = case_branches[index]; | 1027 BasicBlock* branch = case_branches[index]; |
1030 DCHECK_LE(0u, value); | 1028 DCHECK_LE(0u, value); |
1031 DCHECK_LT(value + 2, input_count); | 1029 DCHECK_LT(value + 2, input_count); |
1032 inputs[value + 2] = g.Label(branch); | 1030 inputs[value + 2] = g.Label(branch); |
1033 } | 1031 } |
1034 Emit(kArchTableSwitch, 0, nullptr, input_count, inputs, 0, nullptr) | 1032 Emit(kArchTableSwitch, 0, nullptr, input_count, inputs, 0, nullptr); |
1035 ->MarkAsControl(); | |
1036 return; | 1033 return; |
1037 } | 1034 } |
1038 | 1035 |
1039 // Generate a sequence of conditional jumps. | 1036 // Generate a sequence of conditional jumps. |
1040 size_t input_count = 2 + case_count * 2; | 1037 size_t input_count = 2 + case_count * 2; |
1041 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); | 1038 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); |
1042 inputs[0] = value_operand; | 1039 inputs[0] = value_operand; |
1043 inputs[1] = default_operand; | 1040 inputs[1] = default_operand; |
1044 for (size_t index = 0; index < case_count; ++index) { | 1041 for (size_t index = 0; index < case_count; ++index) { |
1045 int32_t value = case_values[index]; | 1042 int32_t value = case_values[index]; |
1046 BasicBlock* branch = case_branches[index]; | 1043 BasicBlock* branch = case_branches[index]; |
1047 inputs[index * 2 + 2 + 0] = g.TempImmediate(value); | 1044 inputs[index * 2 + 2 + 0] = g.TempImmediate(value); |
1048 inputs[index * 2 + 2 + 1] = g.Label(branch); | 1045 inputs[index * 2 + 2 + 1] = g.Label(branch); |
1049 } | 1046 } |
1050 Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr) | 1047 Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr); |
1051 ->MarkAsControl(); | |
1052 } | 1048 } |
1053 | 1049 |
1054 | 1050 |
1055 void InstructionSelector::VisitWord32Equal(Node* const node) { | 1051 void InstructionSelector::VisitWord32Equal(Node* const node) { |
1056 FlagsContinuation cont(kEqual, node); | 1052 FlagsContinuation cont(kEqual, node); |
1057 Int32BinopMatcher m(node); | 1053 Int32BinopMatcher m(node); |
1058 if (m.right().Is(0)) { | 1054 if (m.right().Is(0)) { |
1059 return VisitWordCompareZero(this, m.node(), m.left().node(), &cont); | 1055 return VisitWordCompareZero(this, m.node(), m.left().node(), &cont); |
1060 } | 1056 } |
1061 VisitWordCompare(this, node, &cont); | 1057 VisitWordCompare(this, node, &cont); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1171 if (CpuFeatures::IsSupported(SSE4_1)) { | 1167 if (CpuFeatures::IsSupported(SSE4_1)) { |
1172 flags |= MachineOperatorBuilder::kFloat64RoundDown | | 1168 flags |= MachineOperatorBuilder::kFloat64RoundDown | |
1173 MachineOperatorBuilder::kFloat64RoundTruncate; | 1169 MachineOperatorBuilder::kFloat64RoundTruncate; |
1174 } | 1170 } |
1175 return flags; | 1171 return flags; |
1176 } | 1172 } |
1177 | 1173 |
1178 } // namespace compiler | 1174 } // namespace compiler |
1179 } // namespace internal | 1175 } // namespace internal |
1180 } // namespace v8 | 1176 } // namespace v8 |
OLD | NEW |