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/generic-node-inl.h" | 5 #include "src/compiler/generic-node-inl.h" |
6 #include "src/compiler/instruction-selector-impl.h" | 6 #include "src/compiler/instruction-selector-impl.h" |
7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
11 namespace compiler { | 11 namespace compiler { |
12 | 12 |
13 // Adds X64-specific methods for generating operands. | 13 // Adds X64-specific methods for generating operands. |
14 class X64OperandGenerator FINAL : public OperandGenerator { | 14 class X64OperandGenerator FINAL : public OperandGenerator { |
15 public: | 15 public: |
16 explicit X64OperandGenerator(InstructionSelector* selector) | 16 explicit X64OperandGenerator(InstructionSelector* selector) |
17 : OperandGenerator(selector) {} | 17 : OperandGenerator(selector) {} |
18 | 18 |
19 InstructionOperand* TempRegister(Register reg) { | 19 InstructionOperand* TempRegister(Register reg) { |
20 return new (zone()) UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, | 20 return new (zone()) UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, |
21 Register::ToAllocationIndex(reg)); | 21 Register::ToAllocationIndex(reg)); |
22 } | 22 } |
23 | 23 |
24 InstructionOperand* UseImmediate64(Node* node) { return UseImmediate(node); } | |
25 | |
26 bool CanBeImmediate(Node* node) { | 24 bool CanBeImmediate(Node* node) { |
27 switch (node->opcode()) { | 25 switch (node->opcode()) { |
28 case IrOpcode::kInt32Constant: | 26 case IrOpcode::kInt32Constant: |
29 return true; | 27 return true; |
30 default: | 28 default: |
31 return false; | 29 return false; |
32 } | 30 } |
33 } | 31 } |
34 | 32 |
35 bool CanBeImmediate64(Node* node) { | |
36 switch (node->opcode()) { | |
37 case IrOpcode::kInt32Constant: | |
38 return true; | |
39 case IrOpcode::kNumberConstant: | |
40 return true; | |
41 case IrOpcode::kHeapConstant: { | |
42 // Constants in new space cannot be used as immediates in V8 because | |
43 // the GC does not scan code objects when collecting the new generation. | |
44 Unique<HeapObject> value = OpParameter<Unique<HeapObject> >(node); | |
45 return !isolate()->heap()->InNewSpace(*value.handle()); | |
46 } | |
47 default: | |
48 return false; | |
49 } | |
50 } | |
51 | |
52 bool CanBeBetterLeftOperand(Node* node) const { | 33 bool CanBeBetterLeftOperand(Node* node) const { |
53 return !selector()->IsLive(node); | 34 return !selector()->IsLive(node); |
54 } | 35 } |
55 }; | 36 }; |
56 | 37 |
57 | 38 |
58 // Get the AddressingMode of scale factor N from the AddressingMode of scale | 39 // Get the AddressingMode of scale factor N from the AddressingMode of scale |
59 // factor 1. | 40 // factor 1. |
60 static AddressingMode AdjustAddressingMode(AddressingMode base_mode, | 41 static AddressingMode AdjustAddressingMode(AddressingMode base_mode, |
61 int power) { | 42 int power) { |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 // Shared routine for multiple 32-bit shift operations. | 326 // Shared routine for multiple 32-bit shift operations. |
346 // TODO(bmeurer): Merge this with VisitWord64Shift using template magic? | 327 // TODO(bmeurer): Merge this with VisitWord64Shift using template magic? |
347 static void VisitWord32Shift(InstructionSelector* selector, Node* node, | 328 static void VisitWord32Shift(InstructionSelector* selector, Node* node, |
348 ArchOpcode opcode) { | 329 ArchOpcode opcode) { |
349 X64OperandGenerator g(selector); | 330 X64OperandGenerator g(selector); |
350 Node* left = node->InputAt(0); | 331 Node* left = node->InputAt(0); |
351 Node* right = node->InputAt(1); | 332 Node* right = node->InputAt(1); |
352 | 333 |
353 // TODO(turbofan): assembler only supports some addressing modes for shifts. | 334 // TODO(turbofan): assembler only supports some addressing modes for shifts. |
354 if (g.CanBeImmediate(right)) { | 335 if (g.CanBeImmediate(right)) { |
355 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), | 336 selector->Emit(opcode, g.DefineSameAsFirst(node), g.Use(left), |
356 g.UseImmediate(right)); | 337 g.UseImmediate(right)); |
357 } else { | 338 } else { |
358 Int32BinopMatcher m(node); | 339 Int32BinopMatcher m(node); |
359 if (m.right().IsWord32And()) { | 340 if (m.right().IsWord32And()) { |
360 Int32BinopMatcher mright(right); | 341 Int32BinopMatcher mright(right); |
361 if (mright.right().Is(0x1F)) { | 342 if (mright.right().Is(0x1F)) { |
362 right = mright.left().node(); | 343 right = mright.left().node(); |
363 } | 344 } |
364 } | 345 } |
365 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), | 346 selector->Emit(opcode, g.DefineSameAsFirst(node), g.Use(left), |
366 g.UseFixed(right, rcx)); | 347 g.UseFixed(right, rcx)); |
367 } | 348 } |
368 } | 349 } |
369 | 350 |
370 | 351 |
371 // Shared routine for multiple 64-bit shift operations. | 352 // Shared routine for multiple 64-bit shift operations. |
372 // TODO(bmeurer): Merge this with VisitWord32Shift using template magic? | 353 // TODO(bmeurer): Merge this with VisitWord32Shift using template magic? |
373 static void VisitWord64Shift(InstructionSelector* selector, Node* node, | 354 static void VisitWord64Shift(InstructionSelector* selector, Node* node, |
374 ArchOpcode opcode) { | 355 ArchOpcode opcode) { |
375 X64OperandGenerator g(selector); | 356 X64OperandGenerator g(selector); |
376 Node* left = node->InputAt(0); | 357 Node* left = node->InputAt(0); |
377 Node* right = node->InputAt(1); | 358 Node* right = node->InputAt(1); |
378 | 359 |
379 // TODO(turbofan): assembler only supports some addressing modes for shifts. | 360 // TODO(turbofan): assembler only supports some addressing modes for shifts. |
380 if (g.CanBeImmediate(right)) { | 361 if (g.CanBeImmediate(right)) { |
381 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), | 362 selector->Emit(opcode, g.DefineSameAsFirst(node), g.Use(left), |
382 g.UseImmediate(right)); | 363 g.UseImmediate(right)); |
383 } else { | 364 } else { |
384 Int64BinopMatcher m(node); | 365 Int64BinopMatcher m(node); |
385 if (m.right().IsWord64And()) { | 366 if (m.right().IsWord64And()) { |
386 Int64BinopMatcher mright(right); | 367 Int64BinopMatcher mright(right); |
387 if (mright.right().Is(0x3F)) { | 368 if (mright.right().Is(0x3F)) { |
388 right = mright.left().node(); | 369 right = mright.left().node(); |
389 } | 370 } |
390 } | 371 } |
391 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), | 372 selector->Emit(opcode, g.DefineSameAsFirst(node), g.Use(left), |
392 g.UseFixed(right, rcx)); | 373 g.UseFixed(right, rcx)); |
393 } | 374 } |
394 } | 375 } |
395 | 376 |
396 | 377 |
397 void InstructionSelector::VisitWord32Shl(Node* node) { | 378 void InstructionSelector::VisitWord32Shl(Node* node) { |
398 VisitWord32Shift(this, node, kX64Shl32); | 379 VisitWord32Shift(this, node, kX64Shl32); |
399 } | 380 } |
400 | 381 |
401 | 382 |
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
873 call_instr->MarkAsCall(); | 854 call_instr->MarkAsCall(); |
874 if (deoptimization != NULL) { | 855 if (deoptimization != NULL) { |
875 DCHECK(continuation != NULL); | 856 DCHECK(continuation != NULL); |
876 call_instr->MarkAsControl(); | 857 call_instr->MarkAsControl(); |
877 } | 858 } |
878 } | 859 } |
879 | 860 |
880 } // namespace compiler | 861 } // namespace compiler |
881 } // namespace internal | 862 } // namespace internal |
882 } // namespace v8 | 863 } // namespace v8 |
OLD | NEW |