OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
6 | 6 |
7 #include "src/compiler/code-generator-impl.h" | 7 #include "src/compiler/code-generator-impl.h" |
8 #include "src/compiler/gap-resolver.h" | 8 #include "src/compiler/gap-resolver.h" |
9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
10 #include "src/scopes.h" | 10 #include "src/scopes.h" |
11 #include "src/x64/assembler-x64.h" | 11 #include "src/x64/assembler-x64.h" |
12 #include "src/x64/macro-assembler-x64.h" | 12 #include "src/x64/macro-assembler-x64.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 namespace compiler { | 16 namespace compiler { |
17 | 17 |
18 #define __ masm()-> | 18 #define __ masm()-> |
19 | 19 |
20 | 20 |
21 // Adds X64 specific methods for decoding operands. | 21 // Adds X64 specific methods for decoding operands. |
22 class X64OperandConverter : public InstructionOperandConverter { | 22 class X64OperandConverter : public InstructionOperandConverter { |
23 public: | 23 public: |
24 X64OperandConverter(CodeGenerator* gen, Instruction* instr) | 24 X64OperandConverter(CodeGenerator* gen, Instruction* instr) |
25 : InstructionOperandConverter(gen, instr) {} | 25 : InstructionOperandConverter(gen, instr) {} |
26 | 26 |
27 Immediate InputImmediate(int index) { | 27 Immediate InputImmediate(size_t index) { |
28 return ToImmediate(instr_->InputAt(index)); | 28 return ToImmediate(instr_->InputAt(index)); |
29 } | 29 } |
30 | 30 |
31 Operand InputOperand(int index) { return ToOperand(instr_->InputAt(index)); } | 31 Operand InputOperand(size_t index) { |
| 32 return ToOperand(instr_->InputAt(index)); |
| 33 } |
32 | 34 |
33 Operand OutputOperand() { return ToOperand(instr_->Output()); } | 35 Operand OutputOperand() { return ToOperand(instr_->Output()); } |
34 | 36 |
35 Immediate ToImmediate(InstructionOperand* operand) { | 37 Immediate ToImmediate(InstructionOperand* operand) { |
36 return Immediate(ToConstant(operand).ToInt32()); | 38 return Immediate(ToConstant(operand).ToInt32()); |
37 } | 39 } |
38 | 40 |
39 Operand ToOperand(InstructionOperand* op, int extra = 0) { | 41 Operand ToOperand(InstructionOperand* op, int extra = 0) { |
40 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); | 42 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); |
41 // The linkage computes where all spill slots are located. | 43 // The linkage computes where all spill slots are located. |
42 FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), extra); | 44 FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), extra); |
43 return Operand(offset.from_stack_pointer() ? rsp : rbp, offset.offset()); | 45 return Operand(offset.from_stack_pointer() ? rsp : rbp, offset.offset()); |
44 } | 46 } |
45 | 47 |
46 static int NextOffset(int* offset) { | 48 static size_t NextOffset(size_t* offset) { |
47 int i = *offset; | 49 size_t i = *offset; |
48 (*offset)++; | 50 (*offset)++; |
49 return i; | 51 return i; |
50 } | 52 } |
51 | 53 |
52 static ScaleFactor ScaleFor(AddressingMode one, AddressingMode mode) { | 54 static ScaleFactor ScaleFor(AddressingMode one, AddressingMode mode) { |
53 STATIC_ASSERT(0 == static_cast<int>(times_1)); | 55 STATIC_ASSERT(0 == static_cast<int>(times_1)); |
54 STATIC_ASSERT(1 == static_cast<int>(times_2)); | 56 STATIC_ASSERT(1 == static_cast<int>(times_2)); |
55 STATIC_ASSERT(2 == static_cast<int>(times_4)); | 57 STATIC_ASSERT(2 == static_cast<int>(times_4)); |
56 STATIC_ASSERT(3 == static_cast<int>(times_8)); | 58 STATIC_ASSERT(3 == static_cast<int>(times_8)); |
57 int scale = static_cast<int>(mode - one); | 59 int scale = static_cast<int>(mode - one); |
58 DCHECK(scale >= 0 && scale < 4); | 60 DCHECK(scale >= 0 && scale < 4); |
59 return static_cast<ScaleFactor>(scale); | 61 return static_cast<ScaleFactor>(scale); |
60 } | 62 } |
61 | 63 |
62 Operand MemoryOperand(int* offset) { | 64 Operand MemoryOperand(size_t* offset) { |
63 AddressingMode mode = AddressingModeField::decode(instr_->opcode()); | 65 AddressingMode mode = AddressingModeField::decode(instr_->opcode()); |
64 switch (mode) { | 66 switch (mode) { |
65 case kMode_MR: { | 67 case kMode_MR: { |
66 Register base = InputRegister(NextOffset(offset)); | 68 Register base = InputRegister(NextOffset(offset)); |
67 int32_t disp = 0; | 69 int32_t disp = 0; |
68 return Operand(base, disp); | 70 return Operand(base, disp); |
69 } | 71 } |
70 case kMode_MRI: { | 72 case kMode_MRI: { |
71 Register base = InputRegister(NextOffset(offset)); | 73 Register base = InputRegister(NextOffset(offset)); |
72 int32_t disp = InputInt32(NextOffset(offset)); | 74 int32_t disp = InputInt32(NextOffset(offset)); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 return Operand(index, scale, disp); | 119 return Operand(index, scale, disp); |
118 } | 120 } |
119 case kMode_None: | 121 case kMode_None: |
120 UNREACHABLE(); | 122 UNREACHABLE(); |
121 return Operand(no_reg, 0); | 123 return Operand(no_reg, 0); |
122 } | 124 } |
123 UNREACHABLE(); | 125 UNREACHABLE(); |
124 return Operand(no_reg, 0); | 126 return Operand(no_reg, 0); |
125 } | 127 } |
126 | 128 |
127 Operand MemoryOperand(int first_input = 0) { | 129 Operand MemoryOperand(size_t first_input = 0) { |
128 return MemoryOperand(&first_input); | 130 return MemoryOperand(&first_input); |
129 } | 131 } |
130 }; | 132 }; |
131 | 133 |
132 | 134 |
133 namespace { | 135 namespace { |
134 | 136 |
135 bool HasImmediateInput(Instruction* instr, int index) { | 137 bool HasImmediateInput(Instruction* instr, size_t index) { |
136 return instr->InputAt(index)->IsImmediate(); | 138 return instr->InputAt(index)->IsImmediate(); |
137 } | 139 } |
138 | 140 |
139 | 141 |
140 class OutOfLineLoadZero FINAL : public OutOfLineCode { | 142 class OutOfLineLoadZero FINAL : public OutOfLineCode { |
141 public: | 143 public: |
142 OutOfLineLoadZero(CodeGenerator* gen, Register result) | 144 OutOfLineLoadZero(CodeGenerator* gen, Register result) |
143 : OutOfLineCode(gen), result_(result) {} | 145 : OutOfLineCode(gen), result_(result) {} |
144 | 146 |
145 void Generate() FINAL { __ xorl(result_, result_); } | 147 void Generate() FINAL { __ xorl(result_, result_); } |
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
814 break; | 816 break; |
815 case kX64Movsxbl: | 817 case kX64Movsxbl: |
816 ASSEMBLE_MOVX(movsxbl); | 818 ASSEMBLE_MOVX(movsxbl); |
817 __ AssertZeroExtended(i.OutputRegister()); | 819 __ AssertZeroExtended(i.OutputRegister()); |
818 break; | 820 break; |
819 case kX64Movzxbl: | 821 case kX64Movzxbl: |
820 ASSEMBLE_MOVX(movzxbl); | 822 ASSEMBLE_MOVX(movzxbl); |
821 __ AssertZeroExtended(i.OutputRegister()); | 823 __ AssertZeroExtended(i.OutputRegister()); |
822 break; | 824 break; |
823 case kX64Movb: { | 825 case kX64Movb: { |
824 int index = 0; | 826 size_t index = 0; |
825 Operand operand = i.MemoryOperand(&index); | 827 Operand operand = i.MemoryOperand(&index); |
826 if (HasImmediateInput(instr, index)) { | 828 if (HasImmediateInput(instr, index)) { |
827 __ movb(operand, Immediate(i.InputInt8(index))); | 829 __ movb(operand, Immediate(i.InputInt8(index))); |
828 } else { | 830 } else { |
829 __ movb(operand, i.InputRegister(index)); | 831 __ movb(operand, i.InputRegister(index)); |
830 } | 832 } |
831 break; | 833 break; |
832 } | 834 } |
833 case kX64Movsxwl: | 835 case kX64Movsxwl: |
834 ASSEMBLE_MOVX(movsxwl); | 836 ASSEMBLE_MOVX(movsxwl); |
835 __ AssertZeroExtended(i.OutputRegister()); | 837 __ AssertZeroExtended(i.OutputRegister()); |
836 break; | 838 break; |
837 case kX64Movzxwl: | 839 case kX64Movzxwl: |
838 ASSEMBLE_MOVX(movzxwl); | 840 ASSEMBLE_MOVX(movzxwl); |
839 __ AssertZeroExtended(i.OutputRegister()); | 841 __ AssertZeroExtended(i.OutputRegister()); |
840 break; | 842 break; |
841 case kX64Movw: { | 843 case kX64Movw: { |
842 int index = 0; | 844 size_t index = 0; |
843 Operand operand = i.MemoryOperand(&index); | 845 Operand operand = i.MemoryOperand(&index); |
844 if (HasImmediateInput(instr, index)) { | 846 if (HasImmediateInput(instr, index)) { |
845 __ movw(operand, Immediate(i.InputInt16(index))); | 847 __ movw(operand, Immediate(i.InputInt16(index))); |
846 } else { | 848 } else { |
847 __ movw(operand, i.InputRegister(index)); | 849 __ movw(operand, i.InputRegister(index)); |
848 } | 850 } |
849 break; | 851 break; |
850 } | 852 } |
851 case kX64Movl: | 853 case kX64Movl: |
852 if (instr->HasOutput()) { | 854 if (instr->HasOutput()) { |
853 if (instr->addressing_mode() == kMode_None) { | 855 if (instr->addressing_mode() == kMode_None) { |
854 if (instr->InputAt(0)->IsRegister()) { | 856 if (instr->InputAt(0)->IsRegister()) { |
855 __ movl(i.OutputRegister(), i.InputRegister(0)); | 857 __ movl(i.OutputRegister(), i.InputRegister(0)); |
856 } else { | 858 } else { |
857 __ movl(i.OutputRegister(), i.InputOperand(0)); | 859 __ movl(i.OutputRegister(), i.InputOperand(0)); |
858 } | 860 } |
859 } else { | 861 } else { |
860 __ movl(i.OutputRegister(), i.MemoryOperand()); | 862 __ movl(i.OutputRegister(), i.MemoryOperand()); |
861 } | 863 } |
862 __ AssertZeroExtended(i.OutputRegister()); | 864 __ AssertZeroExtended(i.OutputRegister()); |
863 } else { | 865 } else { |
864 int index = 0; | 866 size_t index = 0; |
865 Operand operand = i.MemoryOperand(&index); | 867 Operand operand = i.MemoryOperand(&index); |
866 if (HasImmediateInput(instr, index)) { | 868 if (HasImmediateInput(instr, index)) { |
867 __ movl(operand, i.InputImmediate(index)); | 869 __ movl(operand, i.InputImmediate(index)); |
868 } else { | 870 } else { |
869 __ movl(operand, i.InputRegister(index)); | 871 __ movl(operand, i.InputRegister(index)); |
870 } | 872 } |
871 } | 873 } |
872 break; | 874 break; |
873 case kX64Movsxlq: | 875 case kX64Movsxlq: |
874 ASSEMBLE_MOVX(movsxlq); | 876 ASSEMBLE_MOVX(movsxlq); |
875 break; | 877 break; |
876 case kX64Movq: | 878 case kX64Movq: |
877 if (instr->HasOutput()) { | 879 if (instr->HasOutput()) { |
878 __ movq(i.OutputRegister(), i.MemoryOperand()); | 880 __ movq(i.OutputRegister(), i.MemoryOperand()); |
879 } else { | 881 } else { |
880 int index = 0; | 882 size_t index = 0; |
881 Operand operand = i.MemoryOperand(&index); | 883 Operand operand = i.MemoryOperand(&index); |
882 if (HasImmediateInput(instr, index)) { | 884 if (HasImmediateInput(instr, index)) { |
883 __ movq(operand, i.InputImmediate(index)); | 885 __ movq(operand, i.InputImmediate(index)); |
884 } else { | 886 } else { |
885 __ movq(operand, i.InputRegister(index)); | 887 __ movq(operand, i.InputRegister(index)); |
886 } | 888 } |
887 } | 889 } |
888 break; | 890 break; |
889 case kX64Movss: | 891 case kX64Movss: |
890 if (instr->HasOutput()) { | 892 if (instr->HasOutput()) { |
891 __ movss(i.OutputDoubleRegister(), i.MemoryOperand()); | 893 __ movss(i.OutputDoubleRegister(), i.MemoryOperand()); |
892 } else { | 894 } else { |
893 int index = 0; | 895 size_t index = 0; |
894 Operand operand = i.MemoryOperand(&index); | 896 Operand operand = i.MemoryOperand(&index); |
895 __ movss(operand, i.InputDoubleRegister(index)); | 897 __ movss(operand, i.InputDoubleRegister(index)); |
896 } | 898 } |
897 break; | 899 break; |
898 case kX64Movsd: | 900 case kX64Movsd: |
899 if (instr->HasOutput()) { | 901 if (instr->HasOutput()) { |
900 __ movsd(i.OutputDoubleRegister(), i.MemoryOperand()); | 902 __ movsd(i.OutputDoubleRegister(), i.MemoryOperand()); |
901 } else { | 903 } else { |
902 int index = 0; | 904 size_t index = 0; |
903 Operand operand = i.MemoryOperand(&index); | 905 Operand operand = i.MemoryOperand(&index); |
904 __ movsd(operand, i.InputDoubleRegister(index)); | 906 __ movsd(operand, i.InputDoubleRegister(index)); |
905 } | 907 } |
906 break; | 908 break; |
907 case kX64Lea32: { | 909 case kX64Lea32: { |
908 AddressingMode mode = AddressingModeField::decode(instr->opcode()); | 910 AddressingMode mode = AddressingModeField::decode(instr->opcode()); |
909 // Shorten "leal" to "addl", "subl" or "shll" if the register allocation | 911 // Shorten "leal" to "addl", "subl" or "shll" if the register allocation |
910 // and addressing mode just happens to work out. The "addl"/"subl" forms | 912 // and addressing mode just happens to work out. The "addl"/"subl" forms |
911 // in these cases are faster based on measurements. | 913 // in these cases are faster based on measurements. |
912 if (i.InputRegister(0).is(i.OutputRegister())) { | 914 if (i.InputRegister(0).is(i.OutputRegister())) { |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1071 | 1073 |
1072 // Assembles boolean materializations after this instruction. | 1074 // Assembles boolean materializations after this instruction. |
1073 void CodeGenerator::AssembleArchBoolean(Instruction* instr, | 1075 void CodeGenerator::AssembleArchBoolean(Instruction* instr, |
1074 FlagsCondition condition) { | 1076 FlagsCondition condition) { |
1075 X64OperandConverter i(this, instr); | 1077 X64OperandConverter i(this, instr); |
1076 Label done; | 1078 Label done; |
1077 | 1079 |
1078 // Materialize a full 64-bit 1 or 0 value. The result register is always the | 1080 // Materialize a full 64-bit 1 or 0 value. The result register is always the |
1079 // last output of the instruction. | 1081 // last output of the instruction. |
1080 Label check; | 1082 Label check; |
1081 DCHECK_NE(0, static_cast<int>(instr->OutputCount())); | 1083 DCHECK_NE(0u, instr->OutputCount()); |
1082 Register reg = i.OutputRegister(static_cast<int>(instr->OutputCount() - 1)); | 1084 Register reg = i.OutputRegister(instr->OutputCount() - 1); |
1083 Condition cc = no_condition; | 1085 Condition cc = no_condition; |
1084 switch (condition) { | 1086 switch (condition) { |
1085 case kUnorderedEqual: | 1087 case kUnorderedEqual: |
1086 __ j(parity_odd, &check, Label::kNear); | 1088 __ j(parity_odd, &check, Label::kNear); |
1087 __ movl(reg, Immediate(0)); | 1089 __ movl(reg, Immediate(0)); |
1088 __ jmp(&done, Label::kNear); | 1090 __ jmp(&done, Label::kNear); |
1089 // Fall through. | 1091 // Fall through. |
1090 case kEqual: | 1092 case kEqual: |
1091 cc = equal; | 1093 cc = equal; |
1092 break; | 1094 break; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1133 __ setcc(cc, reg); | 1135 __ setcc(cc, reg); |
1134 __ movzxbl(reg, reg); | 1136 __ movzxbl(reg, reg); |
1135 __ bind(&done); | 1137 __ bind(&done); |
1136 } | 1138 } |
1137 | 1139 |
1138 | 1140 |
1139 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { | 1141 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { |
1140 X64OperandConverter i(this, instr); | 1142 X64OperandConverter i(this, instr); |
1141 Register input = i.InputRegister(0); | 1143 Register input = i.InputRegister(0); |
1142 for (size_t index = 2; index < instr->InputCount(); index += 2) { | 1144 for (size_t index = 2; index < instr->InputCount(); index += 2) { |
1143 __ cmpl(input, Immediate(i.InputInt32(static_cast<int>(index + 0)))); | 1145 __ cmpl(input, Immediate(i.InputInt32(index + 0))); |
1144 __ j(equal, GetLabel(i.InputRpo(static_cast<int>(index + 1)))); | 1146 __ j(equal, GetLabel(i.InputRpo(index + 1))); |
1145 } | 1147 } |
1146 AssembleArchJump(i.InputRpo(1)); | 1148 AssembleArchJump(i.InputRpo(1)); |
1147 } | 1149 } |
1148 | 1150 |
1149 | 1151 |
1150 void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) { | 1152 void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) { |
1151 X64OperandConverter i(this, instr); | 1153 X64OperandConverter i(this, instr); |
1152 Register input = i.InputRegister(0); | 1154 Register input = i.InputRegister(0); |
1153 int32_t const case_count = static_cast<int32_t>(instr->InputCount() - 2); | 1155 int32_t const case_count = static_cast<int32_t>(instr->InputCount() - 2); |
1154 Label** cases = zone()->NewArray<Label*>(case_count); | 1156 Label** cases = zone()->NewArray<Label*>(case_count); |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1433 } | 1435 } |
1434 } | 1436 } |
1435 MarkLazyDeoptSite(); | 1437 MarkLazyDeoptSite(); |
1436 } | 1438 } |
1437 | 1439 |
1438 #undef __ | 1440 #undef __ |
1439 | 1441 |
1440 } // namespace internal | 1442 } // namespace internal |
1441 } // namespace compiler | 1443 } // namespace compiler |
1442 } // namespace v8 | 1444 } // namespace v8 |
OLD | NEW |