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 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 sequence()->MarkAsRepresentation(rep, unalloc.virtual_register()); | 247 sequence()->MarkAsRepresentation(rep, unalloc.virtual_register()); |
248 } | 248 } |
249 | 249 |
250 | 250 |
251 void InstructionSelector::MarkAsRepresentation(MachineType rep, Node* node) { | 251 void InstructionSelector::MarkAsRepresentation(MachineType rep, Node* node) { |
252 rep = RepresentationOf(rep); | 252 rep = RepresentationOf(rep); |
253 sequence()->MarkAsRepresentation(rep, GetVirtualRegister(node)); | 253 sequence()->MarkAsRepresentation(rep, GetVirtualRegister(node)); |
254 } | 254 } |
255 | 255 |
256 | 256 |
257 // TODO(bmeurer): Get rid of the CallBuffer business and make | 257 namespace { |
258 // InstructionSelector::VisitCall platform independent instead. | 258 |
259 CallBuffer::CallBuffer(Zone* zone, const CallDescriptor* d, | 259 enum class FrameStateInputKind { kAny, kStackSlot }; |
260 FrameStateDescriptor* frame_desc) | 260 |
261 : descriptor(d), | 261 |
262 frame_state_descriptor(frame_desc), | 262 InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input, |
263 output_nodes(zone), | 263 FrameStateInputKind kind) { |
264 outputs(zone), | 264 switch (input->opcode()) { |
265 instruction_args(zone), | 265 case IrOpcode::kInt32Constant: |
266 pushed_nodes(zone) { | 266 case IrOpcode::kNumberConstant: |
267 output_nodes.reserve(d->ReturnCount()); | 267 case IrOpcode::kFloat32Constant: |
268 outputs.reserve(d->ReturnCount()); | 268 case IrOpcode::kFloat64Constant: |
269 pushed_nodes.reserve(input_count()); | 269 case IrOpcode::kHeapConstant: |
270 instruction_args.reserve(input_count() + frame_state_value_count()); | 270 return g->UseImmediate(input); |
| 271 default: |
| 272 switch (kind) { |
| 273 case FrameStateInputKind::kStackSlot: |
| 274 return g->UseUniqueSlot(input); |
| 275 case FrameStateInputKind::kAny: |
| 276 return g->UseAny(input); |
| 277 } |
| 278 UNREACHABLE(); |
| 279 return InstructionOperand(); |
| 280 } |
271 } | 281 } |
272 | 282 |
273 | 283 |
| 284 void AddFrameStateInputs(Node* state, OperandGenerator* g, |
| 285 InstructionOperandVector* inputs, |
| 286 FrameStateDescriptor* descriptor, |
| 287 FrameStateInputKind kind, Zone* zone) { |
| 288 DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode()); |
| 289 |
| 290 if (descriptor->outer_state()) { |
| 291 AddFrameStateInputs(state->InputAt(kFrameStateOuterStateInput), g, inputs, |
| 292 descriptor->outer_state(), kind, zone); |
| 293 } |
| 294 |
| 295 Node* parameters = state->InputAt(kFrameStateParametersInput); |
| 296 Node* locals = state->InputAt(kFrameStateLocalsInput); |
| 297 Node* stack = state->InputAt(kFrameStateStackInput); |
| 298 Node* context = state->InputAt(kFrameStateContextInput); |
| 299 Node* function = state->InputAt(kFrameStateFunctionInput); |
| 300 |
| 301 DCHECK_EQ(descriptor->parameters_count(), |
| 302 StateValuesAccess(parameters).size()); |
| 303 DCHECK_EQ(descriptor->locals_count(), StateValuesAccess(locals).size()); |
| 304 DCHECK_EQ(descriptor->stack_count(), StateValuesAccess(stack).size()); |
| 305 |
| 306 ZoneVector<MachineType> types(zone); |
| 307 types.reserve(descriptor->GetSize()); |
| 308 |
| 309 size_t value_index = 0; |
| 310 inputs->push_back(OperandForDeopt(g, function, kind)); |
| 311 descriptor->SetType(value_index++, kMachAnyTagged); |
| 312 for (StateValuesAccess::TypedNode input_node : |
| 313 StateValuesAccess(parameters)) { |
| 314 inputs->push_back(OperandForDeopt(g, input_node.node, kind)); |
| 315 descriptor->SetType(value_index++, input_node.type); |
| 316 } |
| 317 if (descriptor->HasContext()) { |
| 318 inputs->push_back(OperandForDeopt(g, context, kind)); |
| 319 descriptor->SetType(value_index++, kMachAnyTagged); |
| 320 } |
| 321 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(locals)) { |
| 322 inputs->push_back(OperandForDeopt(g, input_node.node, kind)); |
| 323 descriptor->SetType(value_index++, input_node.type); |
| 324 } |
| 325 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(stack)) { |
| 326 inputs->push_back(OperandForDeopt(g, input_node.node, kind)); |
| 327 descriptor->SetType(value_index++, input_node.type); |
| 328 } |
| 329 DCHECK(value_index == descriptor->GetSize()); |
| 330 } |
| 331 |
| 332 } // namespace |
| 333 |
| 334 |
| 335 // An internal helper class for generating the operands to calls. |
274 // TODO(bmeurer): Get rid of the CallBuffer business and make | 336 // TODO(bmeurer): Get rid of the CallBuffer business and make |
| 337 // InstructionSelector::VisitCall platform independent instead. |
| 338 struct CallBuffer { |
| 339 CallBuffer(Zone* zone, const CallDescriptor* descriptor, |
| 340 FrameStateDescriptor* frame_state) |
| 341 : descriptor(descriptor), |
| 342 frame_state_descriptor(frame_state), |
| 343 output_nodes(zone), |
| 344 outputs(zone), |
| 345 instruction_args(zone), |
| 346 pushed_nodes(zone) { |
| 347 output_nodes.reserve(descriptor->ReturnCount()); |
| 348 outputs.reserve(descriptor->ReturnCount()); |
| 349 pushed_nodes.reserve(input_count()); |
| 350 instruction_args.reserve(input_count() + frame_state_value_count()); |
| 351 } |
| 352 |
| 353 |
| 354 const CallDescriptor* descriptor; |
| 355 FrameStateDescriptor* frame_state_descriptor; |
| 356 NodeVector output_nodes; |
| 357 InstructionOperandVector outputs; |
| 358 InstructionOperandVector instruction_args; |
| 359 NodeVector pushed_nodes; |
| 360 |
| 361 size_t input_count() const { return descriptor->InputCount(); } |
| 362 |
| 363 size_t frame_state_count() const { return descriptor->FrameStateCount(); } |
| 364 |
| 365 size_t frame_state_value_count() const { |
| 366 return (frame_state_descriptor == NULL) |
| 367 ? 0 |
| 368 : (frame_state_descriptor->GetTotalSize() + |
| 369 1); // Include deopt id. |
| 370 } |
| 371 }; |
| 372 |
| 373 |
| 374 // TODO(bmeurer): Get rid of the CallBuffer business and make |
275 // InstructionSelector::VisitCall platform independent instead. | 375 // InstructionSelector::VisitCall platform independent instead. |
276 void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, | 376 void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, |
277 bool call_code_immediate, | 377 bool call_code_immediate, |
278 bool call_address_immediate) { | 378 bool call_address_immediate) { |
279 OperandGenerator g(this); | 379 OperandGenerator g(this); |
280 DCHECK_LE(call->op()->ValueOutputCount(), | 380 DCHECK_LE(call->op()->ValueOutputCount(), |
281 static_cast<int>(buffer->descriptor->ReturnCount())); | 381 static_cast<int>(buffer->descriptor->ReturnCount())); |
282 DCHECK_EQ( | 382 DCHECK_EQ( |
283 call->op()->ValueInputCount(), | 383 call->op()->ValueInputCount(), |
284 static_cast<int>(buffer->input_count() + buffer->frame_state_count())); | 384 static_cast<int>(buffer->input_count() + buffer->frame_state_count())); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 // follows (n is the number of value inputs to the frame state): | 456 // follows (n is the number of value inputs to the frame state): |
357 // arg 1 : deoptimization id. | 457 // arg 1 : deoptimization id. |
358 // arg 2 - arg (n + 1) : value inputs to the frame state. | 458 // arg 2 - arg (n + 1) : value inputs to the frame state. |
359 if (buffer->frame_state_descriptor != NULL) { | 459 if (buffer->frame_state_descriptor != NULL) { |
360 InstructionSequence::StateId state_id = | 460 InstructionSequence::StateId state_id = |
361 sequence()->AddFrameStateDescriptor(buffer->frame_state_descriptor); | 461 sequence()->AddFrameStateDescriptor(buffer->frame_state_descriptor); |
362 buffer->instruction_args.push_back(g.TempImmediate(state_id.ToInt())); | 462 buffer->instruction_args.push_back(g.TempImmediate(state_id.ToInt())); |
363 | 463 |
364 Node* frame_state = | 464 Node* frame_state = |
365 call->InputAt(static_cast<int>(buffer->descriptor->InputCount())); | 465 call->InputAt(static_cast<int>(buffer->descriptor->InputCount())); |
366 AddFrameStateInputs(frame_state, &buffer->instruction_args, | 466 AddFrameStateInputs(frame_state, &g, &buffer->instruction_args, |
367 buffer->frame_state_descriptor, | 467 buffer->frame_state_descriptor, |
368 FrameStateInputKind::kStackSlot); | 468 FrameStateInputKind::kStackSlot, instruction_zone()); |
369 } | 469 } |
370 DCHECK(1 + buffer->frame_state_value_count() == | 470 DCHECK(1 + buffer->frame_state_value_count() == |
371 buffer->instruction_args.size()); | 471 buffer->instruction_args.size()); |
372 | 472 |
373 size_t input_count = static_cast<size_t>(buffer->input_count()); | 473 size_t input_count = static_cast<size_t>(buffer->input_count()); |
374 | 474 |
375 // Split the arguments into pushed_nodes and instruction_args. Pushed | 475 // Split the arguments into pushed_nodes and instruction_args. Pushed |
376 // arguments require an explicit push instruction before the call and do | 476 // arguments require an explicit push instruction before the call and do |
377 // not appear as arguments to the call. Everything else ends up | 477 // not appear as arguments to the call. Everything else ends up |
378 // as an InstructionOperand argument to the call. | 478 // as an InstructionOperand argument to the call. |
(...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1175 FrameStateDescriptor* desc = GetFrameStateDescriptor(value); | 1275 FrameStateDescriptor* desc = GetFrameStateDescriptor(value); |
1176 size_t arg_count = desc->GetTotalSize() + 1; // Include deopt id. | 1276 size_t arg_count = desc->GetTotalSize() + 1; // Include deopt id. |
1177 | 1277 |
1178 InstructionOperandVector args(instruction_zone()); | 1278 InstructionOperandVector args(instruction_zone()); |
1179 args.reserve(arg_count); | 1279 args.reserve(arg_count); |
1180 | 1280 |
1181 InstructionSequence::StateId state_id = | 1281 InstructionSequence::StateId state_id = |
1182 sequence()->AddFrameStateDescriptor(desc); | 1282 sequence()->AddFrameStateDescriptor(desc); |
1183 args.push_back(g.TempImmediate(state_id.ToInt())); | 1283 args.push_back(g.TempImmediate(state_id.ToInt())); |
1184 | 1284 |
1185 AddFrameStateInputs(value, &args, desc, FrameStateInputKind::kAny); | 1285 AddFrameStateInputs(value, &g, &args, desc, FrameStateInputKind::kAny, |
| 1286 instruction_zone()); |
1186 | 1287 |
1187 DCHECK_EQ(args.size(), arg_count); | 1288 DCHECK_EQ(args.size(), arg_count); |
1188 | 1289 |
1189 Emit(kArchDeoptimize, 0, nullptr, arg_count, &args.front(), 0, nullptr); | 1290 Emit(kArchDeoptimize, 0, nullptr, arg_count, &args.front(), 0, nullptr); |
1190 } | 1291 } |
1191 | 1292 |
1192 | 1293 |
1193 void InstructionSelector::VisitThrow(Node* value) { | 1294 void InstructionSelector::VisitThrow(Node* value) { |
1194 OperandGenerator g(this); | 1295 OperandGenerator g(this); |
1195 Emit(kArchNop, g.NoOutput()); // TODO(titzer) | 1296 Emit(kArchNop, g.NoOutput()); // TODO(titzer) |
(...skipping 22 matching lines...) Expand all Loading... |
1218 outer_state = GetFrameStateDescriptor(outer_node); | 1319 outer_state = GetFrameStateDescriptor(outer_node); |
1219 } | 1320 } |
1220 | 1321 |
1221 return new (instruction_zone()) FrameStateDescriptor( | 1322 return new (instruction_zone()) FrameStateDescriptor( |
1222 instruction_zone(), state_info.type(), state_info.bailout_id(), | 1323 instruction_zone(), state_info.type(), state_info.bailout_id(), |
1223 state_info.state_combine(), parameters, locals, stack, | 1324 state_info.state_combine(), parameters, locals, stack, |
1224 state_info.shared_info(), outer_state); | 1325 state_info.shared_info(), outer_state); |
1225 } | 1326 } |
1226 | 1327 |
1227 | 1328 |
1228 InstructionOperand InstructionSelector::OperandForDeopt( | |
1229 OperandGenerator* g, Node* input, FrameStateInputKind kind) { | |
1230 switch (input->opcode()) { | |
1231 case IrOpcode::kInt32Constant: | |
1232 case IrOpcode::kNumberConstant: | |
1233 case IrOpcode::kFloat32Constant: | |
1234 case IrOpcode::kFloat64Constant: | |
1235 case IrOpcode::kHeapConstant: | |
1236 return g->UseImmediate(input); | |
1237 default: | |
1238 switch (kind) { | |
1239 case FrameStateInputKind::kStackSlot: | |
1240 return g->UseUniqueSlot(input); | |
1241 case FrameStateInputKind::kAny: | |
1242 return g->UseAny(input); | |
1243 } | |
1244 UNREACHABLE(); | |
1245 return InstructionOperand(); | |
1246 } | |
1247 } | |
1248 | |
1249 | |
1250 void InstructionSelector::AddFrameStateInputs(Node* state, | |
1251 InstructionOperandVector* inputs, | |
1252 FrameStateDescriptor* descriptor, | |
1253 FrameStateInputKind kind) { | |
1254 DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode()); | |
1255 | |
1256 if (descriptor->outer_state()) { | |
1257 AddFrameStateInputs(state->InputAt(kFrameStateOuterStateInput), inputs, | |
1258 descriptor->outer_state(), kind); | |
1259 } | |
1260 | |
1261 Node* parameters = state->InputAt(kFrameStateParametersInput); | |
1262 Node* locals = state->InputAt(kFrameStateLocalsInput); | |
1263 Node* stack = state->InputAt(kFrameStateStackInput); | |
1264 Node* context = state->InputAt(kFrameStateContextInput); | |
1265 Node* function = state->InputAt(kFrameStateFunctionInput); | |
1266 | |
1267 DCHECK_EQ(descriptor->parameters_count(), | |
1268 StateValuesAccess(parameters).size()); | |
1269 DCHECK_EQ(descriptor->locals_count(), StateValuesAccess(locals).size()); | |
1270 DCHECK_EQ(descriptor->stack_count(), StateValuesAccess(stack).size()); | |
1271 | |
1272 ZoneVector<MachineType> types(instruction_zone()); | |
1273 types.reserve(descriptor->GetSize()); | |
1274 | |
1275 OperandGenerator g(this); | |
1276 size_t value_index = 0; | |
1277 inputs->push_back(OperandForDeopt(&g, function, kind)); | |
1278 descriptor->SetType(value_index++, kMachAnyTagged); | |
1279 for (StateValuesAccess::TypedNode input_node : | |
1280 StateValuesAccess(parameters)) { | |
1281 inputs->push_back(OperandForDeopt(&g, input_node.node, kind)); | |
1282 descriptor->SetType(value_index++, input_node.type); | |
1283 } | |
1284 if (descriptor->HasContext()) { | |
1285 inputs->push_back(OperandForDeopt(&g, context, kind)); | |
1286 descriptor->SetType(value_index++, kMachAnyTagged); | |
1287 } | |
1288 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(locals)) { | |
1289 inputs->push_back(OperandForDeopt(&g, input_node.node, kind)); | |
1290 descriptor->SetType(value_index++, input_node.type); | |
1291 } | |
1292 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(stack)) { | |
1293 inputs->push_back(OperandForDeopt(&g, input_node.node, kind)); | |
1294 descriptor->SetType(value_index++, input_node.type); | |
1295 } | |
1296 DCHECK(value_index == descriptor->GetSize()); | |
1297 } | |
1298 | |
1299 } // namespace compiler | 1329 } // namespace compiler |
1300 } // namespace internal | 1330 } // namespace internal |
1301 } // namespace v8 | 1331 } // namespace v8 |
OLD | NEW |