| 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 { | 
|    11 namespace compiler { |    11 namespace compiler { | 
|    12  |    12  | 
|    13 // Adds IA32-specific methods for generating operands. |    13 // Adds IA32-specific methods for generating operands. | 
|    14 class IA32OperandGenerator FINAL : public OperandGenerator { |    14 class IA32OperandGenerator FINAL : public OperandGenerator { | 
|    15  public: |    15  public: | 
|    16   explicit IA32OperandGenerator(InstructionSelector* selector) |    16   explicit IA32OperandGenerator(InstructionSelector* selector) | 
|    17       : OperandGenerator(selector) {} |    17       : OperandGenerator(selector) {} | 
|    18  |    18  | 
|    19   InstructionOperand UseByteRegister(Node* node) { |    19   InstructionOperand UseByteRegister(Node* node) { | 
|    20     // TODO(dcarney): relax constraint. |    20     // TODO(titzer): encode byte register use constraints. | 
|    21     return UseFixed(node, edx); |    21     return UseFixed(node, edx); | 
|    22   } |    22   } | 
|    23  |    23  | 
 |    24   InstructionOperand DefineAsByteRegister(Node* node) { | 
 |    25     // TODO(titzer): encode byte register def constraints. | 
 |    26     return DefineAsRegister(node); | 
 |    27   } | 
 |    28  | 
|    24   bool CanBeImmediate(Node* node) { |    29   bool CanBeImmediate(Node* node) { | 
|    25     switch (node->opcode()) { |    30     switch (node->opcode()) { | 
|    26       case IrOpcode::kInt32Constant: |    31       case IrOpcode::kInt32Constant: | 
|    27       case IrOpcode::kNumberConstant: |    32       case IrOpcode::kNumberConstant: | 
|    28       case IrOpcode::kExternalConstant: |    33       case IrOpcode::kExternalConstant: | 
|    29         return true; |    34         return true; | 
|    30       case IrOpcode::kHeapConstant: { |    35       case IrOpcode::kHeapConstant: { | 
|    31         // Constants in new space cannot be used as immediates in V8 because |    36         // Constants in new space cannot be used as immediates in V8 because | 
|    32         // the GC does not scan code objects when collecting the new generation. |    37         // the GC does not scan code objects when collecting the new generation. | 
|    33         Unique<HeapObject> value = OpParameter<Unique<HeapObject> >(node); |    38         Unique<HeapObject> value = OpParameter<Unique<HeapObject> >(node); | 
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   125   selector->Emit(opcode, g.DefineAsRegister(node), |   130   selector->Emit(opcode, g.DefineAsRegister(node), | 
|   126                  g.UseRegister(node->InputAt(0))); |   131                  g.UseRegister(node->InputAt(0))); | 
|   127 } |   132 } | 
|   128  |   133  | 
|   129  |   134  | 
|   130 void InstructionSelector::VisitLoad(Node* node) { |   135 void InstructionSelector::VisitLoad(Node* node) { | 
|   131   MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); |   136   MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); | 
|   132   MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); |   137   MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); | 
|   133  |   138  | 
|   134   ArchOpcode opcode; |   139   ArchOpcode opcode; | 
|   135   // TODO(titzer): signed/unsigned small loads |  | 
|   136   switch (rep) { |   140   switch (rep) { | 
|   137     case kRepFloat32: |   141     case kRepFloat32: | 
|   138       opcode = kIA32Movss; |   142       opcode = kIA32Movss; | 
|   139       break; |   143       break; | 
|   140     case kRepFloat64: |   144     case kRepFloat64: | 
|   141       opcode = kIA32Movsd; |   145       opcode = kIA32Movsd; | 
|   142       break; |   146       break; | 
|   143     case kRepBit:  // Fall through. |   147     case kRepBit:  // Fall through. | 
|   144     case kRepWord8: |   148     case kRepWord8: | 
|   145       opcode = typ == kTypeInt32 ? kIA32Movsxbl : kIA32Movzxbl; |   149       opcode = typ == kTypeInt32 ? kIA32Movsxbl : kIA32Movzxbl; | 
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   359     inputs[input_count++] = g.Use(right); |   363     inputs[input_count++] = g.Use(right); | 
|   360   } |   364   } | 
|   361  |   365  | 
|   362   if (cont->IsBranch()) { |   366   if (cont->IsBranch()) { | 
|   363     inputs[input_count++] = g.Label(cont->true_block()); |   367     inputs[input_count++] = g.Label(cont->true_block()); | 
|   364     inputs[input_count++] = g.Label(cont->false_block()); |   368     inputs[input_count++] = g.Label(cont->false_block()); | 
|   365   } |   369   } | 
|   366  |   370  | 
|   367   outputs[output_count++] = g.DefineSameAsFirst(node); |   371   outputs[output_count++] = g.DefineSameAsFirst(node); | 
|   368   if (cont->IsSet()) { |   372   if (cont->IsSet()) { | 
|   369     // TODO(turbofan): Use byte register here. |   373     outputs[output_count++] = g.DefineAsByteRegister(cont->result()); | 
|   370     outputs[output_count++] = g.DefineAsRegister(cont->result()); |  | 
|   371   } |   374   } | 
|   372  |   375  | 
|   373   DCHECK_NE(0u, input_count); |   376   DCHECK_NE(0u, input_count); | 
|   374   DCHECK_NE(0u, output_count); |   377   DCHECK_NE(0u, output_count); | 
|   375   DCHECK_GE(arraysize(inputs), input_count); |   378   DCHECK_GE(arraysize(inputs), input_count); | 
|   376   DCHECK_GE(arraysize(outputs), output_count); |   379   DCHECK_GE(arraysize(outputs), output_count); | 
|   377  |   380  | 
|   378   Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, |   381   Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, | 
|   379                                       outputs, input_count, inputs); |   382                                       outputs, input_count, inputs); | 
|   380   if (cont->IsBranch()) instr->MarkAsControl(); |   383   if (cont->IsBranch()) instr->MarkAsControl(); | 
| (...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   820 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |   823 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 
|   821                   InstructionOperand left, InstructionOperand right, |   824                   InstructionOperand left, InstructionOperand right, | 
|   822                   FlagsContinuation* cont) { |   825                   FlagsContinuation* cont) { | 
|   823   IA32OperandGenerator g(selector); |   826   IA32OperandGenerator g(selector); | 
|   824   if (cont->IsBranch()) { |   827   if (cont->IsBranch()) { | 
|   825     selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right, |   828     selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right, | 
|   826                    g.Label(cont->true_block()), |   829                    g.Label(cont->true_block()), | 
|   827                    g.Label(cont->false_block()))->MarkAsControl(); |   830                    g.Label(cont->false_block()))->MarkAsControl(); | 
|   828   } else { |   831   } else { | 
|   829     DCHECK(cont->IsSet()); |   832     DCHECK(cont->IsSet()); | 
|   830     // TODO(titzer): Needs byte register. |   833     selector->Emit(cont->Encode(opcode), g.DefineAsByteRegister(cont->result()), | 
|   831     selector->Emit(cont->Encode(opcode), g.DefineAsRegister(cont->result()), |  | 
|   832                    left, right); |   834                    left, right); | 
|   833   } |   835   } | 
|   834 } |   836 } | 
|   835  |   837  | 
|   836  |   838  | 
|   837 // Shared routine for multiple compare operations. |   839 // Shared routine for multiple compare operations. | 
|   838 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |   840 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 
|   839                   Node* left, Node* right, FlagsContinuation* cont, |   841                   Node* left, Node* right, FlagsContinuation* cont, | 
|   840                   bool commutative) { |   842                   bool commutative) { | 
|   841   IA32OperandGenerator g(selector); |   843   IA32OperandGenerator g(selector); | 
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1171   if (CpuFeatures::IsSupported(SSE4_1)) { |  1173   if (CpuFeatures::IsSupported(SSE4_1)) { | 
|  1172     flags |= MachineOperatorBuilder::kFloat64RoundDown | |  1174     flags |= MachineOperatorBuilder::kFloat64RoundDown | | 
|  1173              MachineOperatorBuilder::kFloat64RoundTruncate; |  1175              MachineOperatorBuilder::kFloat64RoundTruncate; | 
|  1174   } |  1176   } | 
|  1175   return flags; |  1177   return flags; | 
|  1176 } |  1178 } | 
|  1177  |  1179  | 
|  1178 }  // namespace compiler |  1180 }  // namespace compiler | 
|  1179 }  // namespace internal |  1181 }  // namespace internal | 
|  1180 }  // namespace v8 |  1182 }  // namespace v8 | 
| OLD | NEW |