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.h" | 5 #include "src/compiler/instruction-selector.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "src/base/adapters.h" | 9 #include "src/base/adapters.h" |
10 #include "src/compiler/instruction-selector-impl.h" | 10 #include "src/compiler/instruction-selector-impl.h" |
(...skipping 1054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1065 | 1065 |
1066 // Emit the call instruction. | 1066 // Emit the call instruction. |
1067 size_t const output_count = buffer.outputs.size(); | 1067 size_t const output_count = buffer.outputs.size(); |
1068 auto* outputs = output_count ? &buffer.outputs.front() : nullptr; | 1068 auto* outputs = output_count ? &buffer.outputs.front() : nullptr; |
1069 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), | 1069 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), |
1070 &buffer.instruction_args.front()) | 1070 &buffer.instruction_args.front()) |
1071 ->MarkAsCall(); | 1071 ->MarkAsCall(); |
1072 } | 1072 } |
1073 | 1073 |
1074 | 1074 |
| 1075 void InstructionSelector::VisitTailCall(Node* node) { |
| 1076 OperandGenerator g(this); |
| 1077 CallDescriptor const* descriptor = OpParameter<CallDescriptor const*>(node); |
| 1078 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); |
| 1079 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite); |
| 1080 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall); |
| 1081 |
| 1082 // TODO(turbofan): Relax restriction for stack parameters. |
| 1083 |
| 1084 if (linkage()->GetIncomingDescriptor()->CanTailCall(node)) { |
| 1085 CallBuffer buffer(zone(), descriptor, nullptr); |
| 1086 |
| 1087 // Compute InstructionOperands for inputs and outputs. |
| 1088 InitializeCallBuffer(node, &buffer, true, true); |
| 1089 |
| 1090 // Select the appropriate opcode based on the call type. |
| 1091 InstructionCode opcode; |
| 1092 switch (descriptor->kind()) { |
| 1093 case CallDescriptor::kCallCodeObject: |
| 1094 opcode = kArchTailCallCodeObject; |
| 1095 break; |
| 1096 case CallDescriptor::kCallJSFunction: |
| 1097 opcode = kArchTailCallJSFunction; |
| 1098 break; |
| 1099 default: |
| 1100 UNREACHABLE(); |
| 1101 return; |
| 1102 } |
| 1103 opcode |= MiscField::encode(descriptor->flags()); |
| 1104 |
| 1105 // Emit the tailcall instruction. |
| 1106 Emit(opcode, 0, nullptr, buffer.instruction_args.size(), |
| 1107 &buffer.instruction_args.front()); |
| 1108 } else { |
| 1109 FrameStateDescriptor* frame_state_descriptor = |
| 1110 descriptor->NeedsFrameState() |
| 1111 ? GetFrameStateDescriptor( |
| 1112 node->InputAt(static_cast<int>(descriptor->InputCount()))) |
| 1113 : nullptr; |
| 1114 |
| 1115 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
| 1116 |
| 1117 // Compute InstructionOperands for inputs and outputs. |
| 1118 InitializeCallBuffer(node, &buffer, true, IsTailCallAddressImmediate()); |
| 1119 |
| 1120 EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node); |
| 1121 |
| 1122 // Select the appropriate opcode based on the call type. |
| 1123 InstructionCode opcode; |
| 1124 switch (descriptor->kind()) { |
| 1125 case CallDescriptor::kCallCodeObject: |
| 1126 opcode = kArchCallCodeObject; |
| 1127 break; |
| 1128 case CallDescriptor::kCallJSFunction: |
| 1129 opcode = kArchCallJSFunction; |
| 1130 break; |
| 1131 default: |
| 1132 UNREACHABLE(); |
| 1133 return; |
| 1134 } |
| 1135 opcode |= MiscField::encode(descriptor->flags()); |
| 1136 |
| 1137 // Emit the call instruction. |
| 1138 size_t output_count = buffer.outputs.size(); |
| 1139 auto* outputs = &buffer.outputs.front(); |
| 1140 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), |
| 1141 &buffer.instruction_args.front()) |
| 1142 ->MarkAsCall(); |
| 1143 Emit(kArchRet, 0, nullptr, output_count, outputs); |
| 1144 } |
| 1145 } |
| 1146 |
| 1147 |
1075 void InstructionSelector::VisitGoto(BasicBlock* target) { | 1148 void InstructionSelector::VisitGoto(BasicBlock* target) { |
1076 // jump to the next block. | 1149 // jump to the next block. |
1077 OperandGenerator g(this); | 1150 OperandGenerator g(this); |
1078 Emit(kArchJmp, g.NoOutput(), g.Label(target)); | 1151 Emit(kArchJmp, g.NoOutput(), g.Label(target)); |
1079 } | 1152 } |
1080 | 1153 |
1081 | 1154 |
1082 void InstructionSelector::VisitReturn(Node* ret) { | 1155 void InstructionSelector::VisitReturn(Node* ret) { |
1083 OperandGenerator g(this); | 1156 OperandGenerator g(this); |
1084 if (linkage()->GetIncomingDescriptor()->ReturnCount() == 0) { | 1157 if (linkage()->GetIncomingDescriptor()->ReturnCount() == 0) { |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1219 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(stack)) { | 1292 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(stack)) { |
1220 inputs->push_back(OperandForDeopt(&g, input_node.node, kind)); | 1293 inputs->push_back(OperandForDeopt(&g, input_node.node, kind)); |
1221 descriptor->SetType(value_index++, input_node.type); | 1294 descriptor->SetType(value_index++, input_node.type); |
1222 } | 1295 } |
1223 DCHECK(value_index == descriptor->GetSize()); | 1296 DCHECK(value_index == descriptor->GetSize()); |
1224 } | 1297 } |
1225 | 1298 |
1226 } // namespace compiler | 1299 } // namespace compiler |
1227 } // namespace internal | 1300 } // namespace internal |
1228 } // namespace v8 | 1301 } // namespace v8 |
OLD | NEW |