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 13 matching lines...) Expand all Loading... |
24 const int64_t value = OpParameter<int64_t>(node); | 24 const int64_t value = OpParameter<int64_t>(node); |
25 return value == static_cast<int64_t>(static_cast<int32_t>(value)); | 25 return value == static_cast<int64_t>(static_cast<int32_t>(value)); |
26 } | 26 } |
27 default: | 27 default: |
28 return false; | 28 return false; |
29 } | 29 } |
30 } | 30 } |
31 | 31 |
32 AddressingMode GenerateMemoryOperandInputs(Node* index, int scale_exponent, | 32 AddressingMode GenerateMemoryOperandInputs(Node* index, int scale_exponent, |
33 Node* base, Node* displacement, | 33 Node* base, Node* displacement, |
34 InstructionOperand* inputs[], | 34 InstructionOperand inputs[], |
35 size_t* input_count) { | 35 size_t* input_count) { |
36 AddressingMode mode = kMode_MRI; | 36 AddressingMode mode = kMode_MRI; |
37 if (base != NULL) { | 37 if (base != NULL) { |
38 inputs[(*input_count)++] = UseRegister(base); | 38 inputs[(*input_count)++] = UseRegister(base); |
39 if (index != NULL) { | 39 if (index != NULL) { |
40 DCHECK(scale_exponent >= 0 && scale_exponent <= 3); | 40 DCHECK(scale_exponent >= 0 && scale_exponent <= 3); |
41 inputs[(*input_count)++] = UseRegister(index); | 41 inputs[(*input_count)++] = UseRegister(index); |
42 if (displacement != NULL) { | 42 if (displacement != NULL) { |
43 inputs[(*input_count)++] = UseImmediate(displacement); | 43 inputs[(*input_count)++] = UseImmediate(displacement); |
44 static const AddressingMode kMRnI_modes[] = {kMode_MR1I, kMode_MR2I, | 44 static const AddressingMode kMRnI_modes[] = {kMode_MR1I, kMode_MR2I, |
(...skipping 28 matching lines...) Expand all Loading... |
73 if (mode == kMode_MR1) { | 73 if (mode == kMode_MR1) { |
74 // [%r1 + %r1*1] has a smaller encoding than [%r1*2+0] | 74 // [%r1 + %r1*1] has a smaller encoding than [%r1*2+0] |
75 inputs[(*input_count)++] = UseRegister(index); | 75 inputs[(*input_count)++] = UseRegister(index); |
76 } | 76 } |
77 } | 77 } |
78 } | 78 } |
79 return mode; | 79 return mode; |
80 } | 80 } |
81 | 81 |
82 AddressingMode GetEffectiveAddressMemoryOperand(Node* operand, | 82 AddressingMode GetEffectiveAddressMemoryOperand(Node* operand, |
83 InstructionOperand* inputs[], | 83 InstructionOperand inputs[], |
84 size_t* input_count) { | 84 size_t* input_count) { |
85 BaseWithIndexAndDisplacement64Matcher m(operand, true); | 85 BaseWithIndexAndDisplacement64Matcher m(operand, true); |
86 DCHECK(m.matches()); | 86 DCHECK(m.matches()); |
87 if ((m.displacement() == NULL || CanBeImmediate(m.displacement()))) { | 87 if ((m.displacement() == NULL || CanBeImmediate(m.displacement()))) { |
88 return GenerateMemoryOperandInputs(m.index(), m.scale(), m.base(), | 88 return GenerateMemoryOperandInputs(m.index(), m.scale(), m.base(), |
89 m.displacement(), inputs, input_count); | 89 m.displacement(), inputs, input_count); |
90 } else { | 90 } else { |
91 inputs[(*input_count)++] = UseRegister(operand->InputAt(0)); | 91 inputs[(*input_count)++] = UseRegister(operand->InputAt(0)); |
92 inputs[(*input_count)++] = UseRegister(operand->InputAt(1)); | 92 inputs[(*input_count)++] = UseRegister(operand->InputAt(1)); |
93 return kMode_MR1; | 93 return kMode_MR1; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 break; | 125 break; |
126 case kRepTagged: // Fall through. | 126 case kRepTagged: // Fall through. |
127 case kRepWord64: | 127 case kRepWord64: |
128 opcode = kX64Movq; | 128 opcode = kX64Movq; |
129 break; | 129 break; |
130 default: | 130 default: |
131 UNREACHABLE(); | 131 UNREACHABLE(); |
132 return; | 132 return; |
133 } | 133 } |
134 | 134 |
135 InstructionOperand* outputs[1]; | 135 InstructionOperand outputs[1]; |
136 outputs[0] = g.DefineAsRegister(node); | 136 outputs[0] = g.DefineAsRegister(node); |
137 InstructionOperand* inputs[3]; | 137 InstructionOperand inputs[3]; |
138 size_t input_count = 0; | 138 size_t input_count = 0; |
139 AddressingMode mode = | 139 AddressingMode mode = |
140 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); | 140 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); |
141 InstructionCode code = opcode | AddressingModeField::encode(mode); | 141 InstructionCode code = opcode | AddressingModeField::encode(mode); |
142 Emit(code, 1, outputs, input_count, inputs); | 142 Emit(code, 1, outputs, input_count, inputs); |
143 } | 143 } |
144 | 144 |
145 | 145 |
146 void InstructionSelector::VisitStore(Node* node) { | 146 void InstructionSelector::VisitStore(Node* node) { |
147 X64OperandGenerator g(this); | 147 X64OperandGenerator g(this); |
148 Node* base = node->InputAt(0); | 148 Node* base = node->InputAt(0); |
149 Node* index = node->InputAt(1); | 149 Node* index = node->InputAt(1); |
150 Node* value = node->InputAt(2); | 150 Node* value = node->InputAt(2); |
151 | 151 |
152 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); | 152 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); |
153 MachineType rep = RepresentationOf(store_rep.machine_type()); | 153 MachineType rep = RepresentationOf(store_rep.machine_type()); |
154 if (store_rep.write_barrier_kind() == kFullWriteBarrier) { | 154 if (store_rep.write_barrier_kind() == kFullWriteBarrier) { |
155 DCHECK(rep == kRepTagged); | 155 DCHECK(rep == kRepTagged); |
156 // TODO(dcarney): refactor RecordWrite function to take temp registers | 156 // TODO(dcarney): refactor RecordWrite function to take temp registers |
157 // and pass them here instead of using fixed regs | 157 // and pass them here instead of using fixed regs |
158 // TODO(dcarney): handle immediate indices. | 158 // TODO(dcarney): handle immediate indices. |
159 InstructionOperand* temps[] = {g.TempRegister(rcx), g.TempRegister(rdx)}; | 159 InstructionOperand temps[] = {g.TempRegister(rcx), g.TempRegister(rdx)}; |
160 Emit(kX64StoreWriteBarrier, NULL, g.UseFixed(base, rbx), | 160 Emit(kX64StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, rbx), |
161 g.UseFixed(index, rcx), g.UseFixed(value, rdx), arraysize(temps), | 161 g.UseFixed(index, rcx), g.UseFixed(value, rdx), arraysize(temps), |
162 temps); | 162 temps); |
163 return; | 163 return; |
164 } | 164 } |
165 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind()); | 165 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind()); |
166 ArchOpcode opcode; | 166 ArchOpcode opcode; |
167 switch (rep) { | 167 switch (rep) { |
168 case kRepFloat32: | 168 case kRepFloat32: |
169 opcode = kX64Movss; | 169 opcode = kX64Movss; |
170 break; | 170 break; |
(...skipping 11 matching lines...) Expand all Loading... |
182 opcode = kX64Movl; | 182 opcode = kX64Movl; |
183 break; | 183 break; |
184 case kRepTagged: // Fall through. | 184 case kRepTagged: // Fall through. |
185 case kRepWord64: | 185 case kRepWord64: |
186 opcode = kX64Movq; | 186 opcode = kX64Movq; |
187 break; | 187 break; |
188 default: | 188 default: |
189 UNREACHABLE(); | 189 UNREACHABLE(); |
190 return; | 190 return; |
191 } | 191 } |
192 InstructionOperand* inputs[4]; | 192 InstructionOperand inputs[4]; |
193 size_t input_count = 0; | 193 size_t input_count = 0; |
194 AddressingMode mode = | 194 AddressingMode mode = |
195 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); | 195 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); |
196 InstructionCode code = opcode | AddressingModeField::encode(mode); | 196 InstructionCode code = opcode | AddressingModeField::encode(mode); |
197 InstructionOperand* value_operand = | 197 InstructionOperand value_operand = |
198 g.CanBeImmediate(value) ? g.UseImmediate(value) : g.UseRegister(value); | 198 g.CanBeImmediate(value) ? g.UseImmediate(value) : g.UseRegister(value); |
199 inputs[input_count++] = value_operand; | 199 inputs[input_count++] = value_operand; |
200 Emit(code, 0, static_cast<InstructionOperand**>(NULL), input_count, inputs); | 200 Emit(code, 0, static_cast<InstructionOperand*>(NULL), input_count, inputs); |
201 } | 201 } |
202 | 202 |
203 | 203 |
204 void InstructionSelector::VisitCheckedLoad(Node* node) { | 204 void InstructionSelector::VisitCheckedLoad(Node* node) { |
205 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 205 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
206 MachineType typ = TypeOf(OpParameter<MachineType>(node)); | 206 MachineType typ = TypeOf(OpParameter<MachineType>(node)); |
207 X64OperandGenerator g(this); | 207 X64OperandGenerator g(this); |
208 Node* const buffer = node->InputAt(0); | 208 Node* const buffer = node->InputAt(0); |
209 Node* const offset = node->InputAt(1); | 209 Node* const offset = node->InputAt(1); |
210 Node* const length = node->InputAt(2); | 210 Node* const length = node->InputAt(2); |
(...skipping 23 matching lines...) Expand all Loading... |
234 Int32BinopMatcher moffset(offset); | 234 Int32BinopMatcher moffset(offset); |
235 if (mlength.HasValue() && moffset.right().HasValue() && | 235 if (mlength.HasValue() && moffset.right().HasValue() && |
236 moffset.right().Value() >= 0 && | 236 moffset.right().Value() >= 0 && |
237 mlength.Value() >= moffset.right().Value()) { | 237 mlength.Value() >= moffset.right().Value()) { |
238 Emit(opcode, g.DefineAsRegister(node), g.UseRegister(buffer), | 238 Emit(opcode, g.DefineAsRegister(node), g.UseRegister(buffer), |
239 g.UseRegister(moffset.left().node()), | 239 g.UseRegister(moffset.left().node()), |
240 g.UseImmediate(moffset.right().node()), g.UseImmediate(length)); | 240 g.UseImmediate(moffset.right().node()), g.UseImmediate(length)); |
241 return; | 241 return; |
242 } | 242 } |
243 } | 243 } |
244 InstructionOperand* length_operand = | 244 InstructionOperand length_operand = |
245 g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length); | 245 g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length); |
246 Emit(opcode, g.DefineAsRegister(node), g.UseRegister(buffer), | 246 Emit(opcode, g.DefineAsRegister(node), g.UseRegister(buffer), |
247 g.UseRegister(offset), g.TempImmediate(0), length_operand); | 247 g.UseRegister(offset), g.TempImmediate(0), length_operand); |
248 } | 248 } |
249 | 249 |
250 | 250 |
251 void InstructionSelector::VisitCheckedStore(Node* node) { | 251 void InstructionSelector::VisitCheckedStore(Node* node) { |
252 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 252 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
253 X64OperandGenerator g(this); | 253 X64OperandGenerator g(this); |
254 Node* const buffer = node->InputAt(0); | 254 Node* const buffer = node->InputAt(0); |
(...skipping 14 matching lines...) Expand all Loading... |
269 case kRepFloat32: | 269 case kRepFloat32: |
270 opcode = kCheckedStoreFloat32; | 270 opcode = kCheckedStoreFloat32; |
271 break; | 271 break; |
272 case kRepFloat64: | 272 case kRepFloat64: |
273 opcode = kCheckedStoreFloat64; | 273 opcode = kCheckedStoreFloat64; |
274 break; | 274 break; |
275 default: | 275 default: |
276 UNREACHABLE(); | 276 UNREACHABLE(); |
277 return; | 277 return; |
278 } | 278 } |
279 InstructionOperand* value_operand = | 279 InstructionOperand value_operand = |
280 g.CanBeImmediate(value) ? g.UseImmediate(value) : g.UseRegister(value); | 280 g.CanBeImmediate(value) ? g.UseImmediate(value) : g.UseRegister(value); |
281 if (offset->opcode() == IrOpcode::kInt32Add && CanCover(node, offset)) { | 281 if (offset->opcode() == IrOpcode::kInt32Add && CanCover(node, offset)) { |
282 Int32Matcher mlength(length); | 282 Int32Matcher mlength(length); |
283 Int32BinopMatcher moffset(offset); | 283 Int32BinopMatcher moffset(offset); |
284 if (mlength.HasValue() && moffset.right().HasValue() && | 284 if (mlength.HasValue() && moffset.right().HasValue() && |
285 moffset.right().Value() >= 0 && | 285 moffset.right().Value() >= 0 && |
286 mlength.Value() >= moffset.right().Value()) { | 286 mlength.Value() >= moffset.right().Value()) { |
287 Emit(opcode, nullptr, g.UseRegister(buffer), | 287 Emit(opcode, g.NoOutput(), g.UseRegister(buffer), |
288 g.UseRegister(moffset.left().node()), | 288 g.UseRegister(moffset.left().node()), |
289 g.UseImmediate(moffset.right().node()), g.UseImmediate(length), | 289 g.UseImmediate(moffset.right().node()), g.UseImmediate(length), |
290 value_operand); | 290 value_operand); |
291 return; | 291 return; |
292 } | 292 } |
293 } | 293 } |
294 InstructionOperand* length_operand = | 294 InstructionOperand length_operand = |
295 g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length); | 295 g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length); |
296 Emit(opcode, nullptr, g.UseRegister(buffer), g.UseRegister(offset), | 296 Emit(opcode, g.NoOutput(), g.UseRegister(buffer), g.UseRegister(offset), |
297 g.TempImmediate(0), length_operand, value_operand); | 297 g.TempImmediate(0), length_operand, value_operand); |
298 } | 298 } |
299 | 299 |
300 | 300 |
301 // Shared routine for multiple binary operations. | 301 // Shared routine for multiple binary operations. |
302 static void VisitBinop(InstructionSelector* selector, Node* node, | 302 static void VisitBinop(InstructionSelector* selector, Node* node, |
303 InstructionCode opcode, FlagsContinuation* cont) { | 303 InstructionCode opcode, FlagsContinuation* cont) { |
304 X64OperandGenerator g(selector); | 304 X64OperandGenerator g(selector); |
305 Int32BinopMatcher m(node); | 305 Int32BinopMatcher m(node); |
306 Node* left = m.left().node(); | 306 Node* left = m.left().node(); |
307 Node* right = m.right().node(); | 307 Node* right = m.right().node(); |
308 InstructionOperand* inputs[4]; | 308 InstructionOperand inputs[4]; |
309 size_t input_count = 0; | 309 size_t input_count = 0; |
310 InstructionOperand* outputs[2]; | 310 InstructionOperand outputs[2]; |
311 size_t output_count = 0; | 311 size_t output_count = 0; |
312 | 312 |
313 // TODO(turbofan): match complex addressing modes. | 313 // TODO(turbofan): match complex addressing modes. |
314 if (left == right) { | 314 if (left == right) { |
315 // If both inputs refer to the same operand, enforce allocating a register | 315 // If both inputs refer to the same operand, enforce allocating a register |
316 // for both of them to ensure that we don't end up generating code like | 316 // for both of them to ensure that we don't end up generating code like |
317 // this: | 317 // this: |
318 // | 318 // |
319 // mov rax, [rbp-0x10] | 319 // mov rax, [rbp-0x10] |
320 // add rax, [rbp-0x10] | 320 // add rax, [rbp-0x10] |
321 // jo label | 321 // jo label |
322 InstructionOperand* const input = g.UseRegister(left); | 322 InstructionOperand const input = g.UseRegister(left); |
323 inputs[input_count++] = input; | 323 inputs[input_count++] = input; |
324 inputs[input_count++] = input; | 324 inputs[input_count++] = input; |
325 } else if (g.CanBeImmediate(right)) { | 325 } else if (g.CanBeImmediate(right)) { |
326 inputs[input_count++] = g.UseRegister(left); | 326 inputs[input_count++] = g.UseRegister(left); |
327 inputs[input_count++] = g.UseImmediate(right); | 327 inputs[input_count++] = g.UseImmediate(right); |
328 } else { | 328 } else { |
329 if (node->op()->HasProperty(Operator::kCommutative) && | 329 if (node->op()->HasProperty(Operator::kCommutative) && |
330 g.CanBeBetterLeftOperand(right)) { | 330 g.CanBeBetterLeftOperand(right)) { |
331 std::swap(left, right); | 331 std::swap(left, right); |
332 } | 332 } |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 g.UseFixed(right, rcx)); | 449 g.UseFixed(right, rcx)); |
450 } | 450 } |
451 } | 451 } |
452 | 452 |
453 | 453 |
454 void EmitLea(InstructionSelector* selector, InstructionCode opcode, | 454 void EmitLea(InstructionSelector* selector, InstructionCode opcode, |
455 Node* result, Node* index, int scale, Node* base, | 455 Node* result, Node* index, int scale, Node* base, |
456 Node* displacement) { | 456 Node* displacement) { |
457 X64OperandGenerator g(selector); | 457 X64OperandGenerator g(selector); |
458 | 458 |
459 InstructionOperand* inputs[4]; | 459 InstructionOperand inputs[4]; |
460 size_t input_count = 0; | 460 size_t input_count = 0; |
461 AddressingMode mode = g.GenerateMemoryOperandInputs( | 461 AddressingMode mode = g.GenerateMemoryOperandInputs( |
462 index, scale, base, displacement, inputs, &input_count); | 462 index, scale, base, displacement, inputs, &input_count); |
463 | 463 |
464 DCHECK_NE(0, static_cast<int>(input_count)); | 464 DCHECK_NE(0, static_cast<int>(input_count)); |
465 DCHECK_GE(arraysize(inputs), input_count); | 465 DCHECK_GE(arraysize(inputs), input_count); |
466 | 466 |
467 InstructionOperand* outputs[1]; | 467 InstructionOperand outputs[1]; |
468 outputs[0] = g.DefineAsRegister(result); | 468 outputs[0] = g.DefineAsRegister(result); |
469 | 469 |
470 opcode = AddressingModeField::encode(mode) | opcode; | 470 opcode = AddressingModeField::encode(mode) | opcode; |
471 | 471 |
472 selector->Emit(opcode, 1, outputs, input_count, inputs); | 472 selector->Emit(opcode, 1, outputs, input_count, inputs); |
473 } | 473 } |
474 | 474 |
475 } // namespace | 475 } // namespace |
476 | 476 |
477 | 477 |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
627 } | 627 } |
628 // TODO(turbofan): We use UseUniqueRegister here to improve register | 628 // TODO(turbofan): We use UseUniqueRegister here to improve register |
629 // allocation. | 629 // allocation. |
630 selector->Emit(opcode, g.DefineAsFixed(node, rdx), g.UseFixed(left, rax), | 630 selector->Emit(opcode, g.DefineAsFixed(node, rdx), g.UseFixed(left, rax), |
631 g.UseUniqueRegister(right)); | 631 g.UseUniqueRegister(right)); |
632 } | 632 } |
633 | 633 |
634 | 634 |
635 void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) { | 635 void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) { |
636 X64OperandGenerator g(selector); | 636 X64OperandGenerator g(selector); |
637 InstructionOperand* temps[] = {g.TempRegister(rdx)}; | 637 InstructionOperand temps[] = {g.TempRegister(rdx)}; |
638 selector->Emit( | 638 selector->Emit( |
639 opcode, g.DefineAsFixed(node, rax), g.UseFixed(node->InputAt(0), rax), | 639 opcode, g.DefineAsFixed(node, rax), g.UseFixed(node->InputAt(0), rax), |
640 g.UseUniqueRegister(node->InputAt(1)), arraysize(temps), temps); | 640 g.UseUniqueRegister(node->InputAt(1)), arraysize(temps), temps); |
641 } | 641 } |
642 | 642 |
643 | 643 |
644 void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) { | 644 void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) { |
645 X64OperandGenerator g(selector); | 645 X64OperandGenerator g(selector); |
646 selector->Emit(opcode, g.DefineAsFixed(node, rdx), | 646 selector->Emit(opcode, g.DefineAsFixed(node, rdx), |
647 g.UseFixed(node->InputAt(0), rax), | 647 g.UseFixed(node->InputAt(0), rax), |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
863 g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1))); | 863 g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1))); |
864 } else { | 864 } else { |
865 Emit(kSSEFloat64Div, g.DefineSameAsFirst(node), | 865 Emit(kSSEFloat64Div, g.DefineSameAsFirst(node), |
866 g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1))); | 866 g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1))); |
867 } | 867 } |
868 } | 868 } |
869 | 869 |
870 | 870 |
871 void InstructionSelector::VisitFloat64Mod(Node* node) { | 871 void InstructionSelector::VisitFloat64Mod(Node* node) { |
872 X64OperandGenerator g(this); | 872 X64OperandGenerator g(this); |
873 InstructionOperand* temps[] = {g.TempRegister(rax)}; | 873 InstructionOperand temps[] = {g.TempRegister(rax)}; |
874 Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node), | 874 Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node), |
875 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)), 1, | 875 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)), 1, |
876 temps); | 876 temps); |
877 } | 877 } |
878 | 878 |
879 | 879 |
880 void InstructionSelector::VisitFloat64Sqrt(Node* node) { | 880 void InstructionSelector::VisitFloat64Sqrt(Node* node) { |
881 X64OperandGenerator g(this); | 881 X64OperandGenerator g(this); |
882 Emit(kSSEFloat64Sqrt, g.DefineAsRegister(node), g.Use(node->InputAt(0))); | 882 Emit(kSSEFloat64Sqrt, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
883 } | 883 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
930 | 930 |
931 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | 931 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
932 | 932 |
933 // Compute InstructionOperands for inputs and outputs. | 933 // Compute InstructionOperands for inputs and outputs. |
934 InitializeCallBuffer(node, &buffer, true, true); | 934 InitializeCallBuffer(node, &buffer, true, true); |
935 | 935 |
936 // Push any stack arguments. | 936 // Push any stack arguments. |
937 for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend(); | 937 for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend(); |
938 ++i) { | 938 ++i) { |
939 // TODO(titzer): handle pushing double parameters. | 939 // TODO(titzer): handle pushing double parameters. |
940 InstructionOperand* value = | 940 InstructionOperand value = |
941 g.CanBeImmediate(*i) ? g.UseImmediate(*i) : IsSupported(ATOM) | 941 g.CanBeImmediate(*i) ? g.UseImmediate(*i) : IsSupported(ATOM) |
942 ? g.UseRegister(*i) | 942 ? g.UseRegister(*i) |
943 : g.Use(*i); | 943 : g.Use(*i); |
944 Emit(kX64Push, nullptr, value); | 944 Emit(kX64Push, g.NoOutput(), value); |
945 } | 945 } |
946 | 946 |
947 // Select the appropriate opcode based on the call type. | 947 // Select the appropriate opcode based on the call type. |
948 InstructionCode opcode; | 948 InstructionCode opcode; |
949 switch (descriptor->kind()) { | 949 switch (descriptor->kind()) { |
950 case CallDescriptor::kCallCodeObject: { | 950 case CallDescriptor::kCallCodeObject: { |
951 opcode = kArchCallCodeObject; | 951 opcode = kArchCallCodeObject; |
952 break; | 952 break; |
953 } | 953 } |
954 case CallDescriptor::kCallJSFunction: | 954 case CallDescriptor::kCallJSFunction: |
955 opcode = kArchCallJSFunction; | 955 opcode = kArchCallJSFunction; |
956 break; | 956 break; |
957 default: | 957 default: |
958 UNREACHABLE(); | 958 UNREACHABLE(); |
959 return; | 959 return; |
960 } | 960 } |
961 opcode |= MiscField::encode(descriptor->flags()); | 961 opcode |= MiscField::encode(descriptor->flags()); |
962 | 962 |
963 // Emit the call instruction. | 963 // Emit the call instruction. |
964 InstructionOperand** first_output = | 964 InstructionOperand* first_output = |
965 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL; | 965 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL; |
966 Instruction* call_instr = | 966 Instruction* call_instr = |
967 Emit(opcode, buffer.outputs.size(), first_output, | 967 Emit(opcode, buffer.outputs.size(), first_output, |
968 buffer.instruction_args.size(), &buffer.instruction_args.front()); | 968 buffer.instruction_args.size(), &buffer.instruction_args.front()); |
969 call_instr->MarkAsCall(); | 969 call_instr->MarkAsCall(); |
970 } | 970 } |
971 | 971 |
972 | 972 |
973 // Shared routine for multiple compare operations. | 973 // Shared routine for multiple compare operations. |
974 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 974 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
975 InstructionOperand* left, InstructionOperand* right, | 975 InstructionOperand left, InstructionOperand right, |
976 FlagsContinuation* cont) { | 976 FlagsContinuation* cont) { |
977 X64OperandGenerator g(selector); | 977 X64OperandGenerator g(selector); |
978 opcode = cont->Encode(opcode); | 978 opcode = cont->Encode(opcode); |
979 if (cont->IsBranch()) { | 979 if (cont->IsBranch()) { |
980 selector->Emit(opcode, NULL, left, right, g.Label(cont->true_block()), | 980 selector->Emit(opcode, g.NoOutput(), left, right, |
| 981 g.Label(cont->true_block()), |
981 g.Label(cont->false_block()))->MarkAsControl(); | 982 g.Label(cont->false_block()))->MarkAsControl(); |
982 } else { | 983 } else { |
983 DCHECK(cont->IsSet()); | 984 DCHECK(cont->IsSet()); |
984 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 985 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
985 } | 986 } |
986 } | 987 } |
987 | 988 |
988 | 989 |
989 // Shared routine for multiple compare operations. | 990 // Shared routine for multiple compare operations. |
990 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 991 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1310 MachineOperatorBuilder::kFloat64Ceil | | 1311 MachineOperatorBuilder::kFloat64Ceil | |
1311 MachineOperatorBuilder::kFloat64RoundTruncate | | 1312 MachineOperatorBuilder::kFloat64RoundTruncate | |
1312 MachineOperatorBuilder::kWord32ShiftIsSafe; | 1313 MachineOperatorBuilder::kWord32ShiftIsSafe; |
1313 } | 1314 } |
1314 return MachineOperatorBuilder::kNoFlags; | 1315 return MachineOperatorBuilder::kNoFlags; |
1315 } | 1316 } |
1316 | 1317 |
1317 } // namespace compiler | 1318 } // namespace compiler |
1318 } // namespace internal | 1319 } // namespace internal |
1319 } // namespace v8 | 1320 } // namespace v8 |
OLD | NEW |