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/base/adapters.h" | 5 #include "src/base/adapters.h" |
6 #include "src/base/bits.h" | 6 #include "src/base/bits.h" |
7 #include "src/compiler/instruction-selector-impl.h" | 7 #include "src/compiler/instruction-selector-impl.h" |
8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
10 | 10 |
(...skipping 1092 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1103 void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { | 1103 void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { |
1104 VisitRR(this, kArmVrintzF64, node); | 1104 VisitRR(this, kArmVrintzF64, node); |
1105 } | 1105 } |
1106 | 1106 |
1107 | 1107 |
1108 void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) { | 1108 void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) { |
1109 VisitRR(this, kArmVrintaF64, node); | 1109 VisitRR(this, kArmVrintaF64, node); |
1110 } | 1110 } |
1111 | 1111 |
1112 | 1112 |
1113 void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { | 1113 void InstructionSelector::EmitPrepareArguments(NodeVector* arguments, |
| 1114 const CallDescriptor* descriptor, |
| 1115 Node* node) { |
1114 ArmOperandGenerator g(this); | 1116 ArmOperandGenerator g(this); |
1115 const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node); | |
1116 | |
1117 FrameStateDescriptor* frame_state_descriptor = nullptr; | |
1118 if (descriptor->NeedsFrameState()) { | |
1119 frame_state_descriptor = | |
1120 GetFrameStateDescriptor(node->InputAt(descriptor->InputCount())); | |
1121 } | |
1122 | |
1123 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | |
1124 | |
1125 // Compute InstructionOperands for inputs and outputs. | |
1126 // TODO(turbofan): on ARM it's probably better to use the code object in a | |
1127 // register if there are multiple uses of it. Improve constant pool and the | |
1128 // heuristics in the register allocator for where to emit constants. | |
1129 InitializeCallBuffer(node, &buffer, true, true); | |
1130 | 1117 |
1131 // Prepare for C function call. | 1118 // Prepare for C function call. |
1132 if (descriptor->IsCFunctionCall()) { | 1119 if (descriptor->IsCFunctionCall()) { |
1133 Emit(kArchPrepareCallCFunction | | 1120 Emit(kArchPrepareCallCFunction | |
1134 MiscField::encode(static_cast<int>(descriptor->CParameterCount())), | 1121 MiscField::encode(static_cast<int>(descriptor->CParameterCount())), |
1135 0, nullptr, 0, nullptr); | 1122 0, nullptr, 0, nullptr); |
1136 | 1123 |
1137 // Poke any stack arguments. | 1124 // Poke any stack arguments. |
1138 for (size_t n = 0; n < buffer.pushed_nodes.size(); ++n) { | 1125 for (size_t n = 0; n < arguments->size(); ++n) { |
1139 if (Node* input = buffer.pushed_nodes[n]) { | 1126 if (Node* input = (*arguments)[n]) { |
1140 int slot = static_cast<int>(n); | 1127 int slot = static_cast<int>(n); |
1141 Emit(kArmPoke | MiscField::encode(slot), g.NoOutput(), | 1128 Emit(kArmPoke | MiscField::encode(slot), g.NoOutput(), |
1142 g.UseRegister(input)); | 1129 g.UseRegister(input)); |
1143 } | 1130 } |
1144 } | 1131 } |
1145 } else { | 1132 } else { |
1146 // Push any stack arguments. | 1133 // Push any stack arguments. |
1147 for (Node* input : base::Reversed(buffer.pushed_nodes)) { | 1134 for (Node* input : base::Reversed(*arguments)) { |
1148 // Skip any alignment holes in pushed nodes. | 1135 // Skip any alignment holes in pushed nodes. |
1149 if (input == nullptr) continue; | 1136 if (input == nullptr) continue; |
1150 Emit(kArmPush, g.NoOutput(), g.UseRegister(input)); | 1137 Emit(kArmPush, g.NoOutput(), g.UseRegister(input)); |
1151 } | 1138 } |
1152 } | 1139 } |
1153 | |
1154 // Pass label of exception handler block. | |
1155 CallDescriptor::Flags flags = descriptor->flags(); | |
1156 if (handler) { | |
1157 DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode()); | |
1158 IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front()); | |
1159 if (hint == IfExceptionHint::kLocallyCaught) { | |
1160 flags |= CallDescriptor::kHasLocalCatchHandler; | |
1161 } | |
1162 flags |= CallDescriptor::kHasExceptionHandler; | |
1163 buffer.instruction_args.push_back(g.Label(handler)); | |
1164 } | |
1165 | |
1166 // Select the appropriate opcode based on the call type. | |
1167 InstructionCode opcode = kArchNop; | |
1168 switch (descriptor->kind()) { | |
1169 case CallDescriptor::kCallAddress: | |
1170 opcode = | |
1171 kArchCallCFunction | | |
1172 MiscField::encode(static_cast<int>(descriptor->CParameterCount())); | |
1173 break; | |
1174 case CallDescriptor::kCallCodeObject: | |
1175 opcode = kArchCallCodeObject | MiscField::encode(flags); | |
1176 break; | |
1177 case CallDescriptor::kCallJSFunction: | |
1178 opcode = kArchCallJSFunction | MiscField::encode(flags); | |
1179 break; | |
1180 case CallDescriptor::kLazyBailout: | |
1181 opcode = kArchLazyBailout | MiscField::encode(flags); | |
1182 break; | |
1183 } | |
1184 | |
1185 // Emit the call instruction. | |
1186 size_t const output_count = buffer.outputs.size(); | |
1187 auto* outputs = output_count ? &buffer.outputs.front() : nullptr; | |
1188 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), | |
1189 &buffer.instruction_args.front())->MarkAsCall(); | |
1190 } | 1140 } |
1191 | 1141 |
1192 | 1142 |
1193 void InstructionSelector::VisitTailCall(Node* node) { | 1143 void InstructionSelector::VisitTailCall(Node* node) { |
1194 ArmOperandGenerator g(this); | 1144 ArmOperandGenerator g(this); |
1195 CallDescriptor const* descriptor = OpParameter<CallDescriptor const*>(node); | 1145 CallDescriptor const* descriptor = OpParameter<CallDescriptor const*>(node); |
1196 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); | 1146 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); |
1197 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite); | 1147 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite); |
1198 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall); | 1148 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall); |
1199 | 1149 |
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1666 flags |= MachineOperatorBuilder::kFloat64RoundDown | | 1616 flags |= MachineOperatorBuilder::kFloat64RoundDown | |
1667 MachineOperatorBuilder::kFloat64RoundTruncate | | 1617 MachineOperatorBuilder::kFloat64RoundTruncate | |
1668 MachineOperatorBuilder::kFloat64RoundTiesAway; | 1618 MachineOperatorBuilder::kFloat64RoundTiesAway; |
1669 } | 1619 } |
1670 return flags; | 1620 return flags; |
1671 } | 1621 } |
1672 | 1622 |
1673 } // namespace compiler | 1623 } // namespace compiler |
1674 } // namespace internal | 1624 } // namespace internal |
1675 } // namespace v8 | 1625 } // namespace v8 |
OLD | NEW |