Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: src/compiler/instruction-selector.cc

Issue 1485183002: [turbofan] Deopt support for escape analysis (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@ea-local
Patch Set: Improve Unittest and guard printf behind --trace-turbo-escape Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 300
301 InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input, 301 InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input,
302 FrameStateInputKind kind) { 302 FrameStateInputKind kind) {
303 switch (input->opcode()) { 303 switch (input->opcode()) {
304 case IrOpcode::kInt32Constant: 304 case IrOpcode::kInt32Constant:
305 case IrOpcode::kNumberConstant: 305 case IrOpcode::kNumberConstant:
306 case IrOpcode::kFloat32Constant: 306 case IrOpcode::kFloat32Constant:
307 case IrOpcode::kFloat64Constant: 307 case IrOpcode::kFloat64Constant:
308 case IrOpcode::kHeapConstant: 308 case IrOpcode::kHeapConstant:
309 return g->UseImmediate(input); 309 return g->UseImmediate(input);
310 case IrOpcode::kObjectState:
311 UNREACHABLE();
312 break;
310 default: 313 default:
311 switch (kind) { 314 switch (kind) {
312 case FrameStateInputKind::kStackSlot: 315 case FrameStateInputKind::kStackSlot:
313 return g->UseUniqueSlot(input); 316 return g->UseUniqueSlot(input);
314 case FrameStateInputKind::kAny: 317 case FrameStateInputKind::kAny:
315 return g->UseAny(input); 318 return g->UseAny(input);
316 } 319 }
317 UNREACHABLE(); 320 }
318 return InstructionOperand(); 321 UNREACHABLE();
322 return InstructionOperand();
323 }
324
325
326 class StateObjectDeduplicator {
327 public:
328 explicit StateObjectDeduplicator(Zone* zone) : objects_(zone) {}
329 static const size_t kNotDuplicated = SIZE_MAX;
330
331 size_t GetObjectId(Node* node) {
332 for (size_t i = 0; i < objects_.size(); ++i) {
333 if (objects_[i] == node) {
334 return i;
335 }
336 }
337 return kNotDuplicated;
338 }
339
340 size_t InsertObject(Node* node) {
341 size_t id = objects_.size();
342 objects_.push_back(node);
343 return id;
344 }
345
346 private:
347 ZoneVector<Node*> objects_;
348 };
349
350
351 // Returns the number of instruction operands added to inputs.
352 size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor,
353 InstructionOperandVector* inputs,
354 OperandGenerator* g,
355 StateObjectDeduplicator* deduplicator,
356 Node* input, MachineType type,
357 FrameStateInputKind kind, Zone* zone) {
358 switch (input->opcode()) {
359 case IrOpcode::kObjectState: {
360 size_t id = deduplicator->GetObjectId(input);
361 if (id == StateObjectDeduplicator::kNotDuplicated) {
362 size_t entries = 0;
363 id = deduplicator->InsertObject(input);
364 descriptor->fields().push_back(
365 StateValueDescriptor::Recursive(zone, id));
366 StateValueDescriptor* new_desc = &descriptor->fields().back();
367 for (Edge edge : input->input_edges()) {
368 entries += AddOperandToStateValueDescriptor(
369 new_desc, inputs, g, deduplicator, edge.to(),
370 MachineType::AnyTagged(), kind, zone);
371 }
372 return entries;
373 } else {
374 // Crankshaft counts duplicate objects for the running id, so we have
375 // to push the input again.
376 deduplicator->InsertObject(input);
377 descriptor->fields().push_back(
378 StateValueDescriptor::Duplicate(zone, id));
379 return 0;
380 }
381 break;
382 }
383 default: {
384 inputs->push_back(OperandForDeopt(g, input, kind));
385 descriptor->fields().push_back(StateValueDescriptor::Plain(zone, type));
386 return 1;
387 }
319 } 388 }
320 } 389 }
321 390
322 391
323 void AddFrameStateInputs(Node* state, OperandGenerator* g, 392 // Returns the number of instruction operands added to inputs.
324 InstructionOperandVector* inputs, 393 size_t AddInputsToFrameStateDescriptor(FrameStateDescriptor* descriptor,
325 FrameStateDescriptor* descriptor, 394 Node* state, OperandGenerator* g,
326 FrameStateInputKind kind, Zone* zone) { 395 StateObjectDeduplicator* deduplicator,
396 InstructionOperandVector* inputs,
397 FrameStateInputKind kind, Zone* zone) {
327 DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode()); 398 DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode());
328 399
400 size_t entries = 0;
401 size_t initial_size = inputs->size();
402 USE(initial_size); // initial_size is only used for debug.
403
329 if (descriptor->outer_state()) { 404 if (descriptor->outer_state()) {
330 AddFrameStateInputs(state->InputAt(kFrameStateOuterStateInput), g, inputs, 405 entries += AddInputsToFrameStateDescriptor(
331 descriptor->outer_state(), kind, zone); 406 descriptor->outer_state(), state->InputAt(kFrameStateOuterStateInput),
407 g, deduplicator, inputs, kind, zone);
332 } 408 }
333 409
334 Node* parameters = state->InputAt(kFrameStateParametersInput); 410 Node* parameters = state->InputAt(kFrameStateParametersInput);
335 Node* locals = state->InputAt(kFrameStateLocalsInput); 411 Node* locals = state->InputAt(kFrameStateLocalsInput);
336 Node* stack = state->InputAt(kFrameStateStackInput); 412 Node* stack = state->InputAt(kFrameStateStackInput);
337 Node* context = state->InputAt(kFrameStateContextInput); 413 Node* context = state->InputAt(kFrameStateContextInput);
338 Node* function = state->InputAt(kFrameStateFunctionInput); 414 Node* function = state->InputAt(kFrameStateFunctionInput);
339 415
340 DCHECK_EQ(descriptor->parameters_count(), 416 DCHECK_EQ(descriptor->parameters_count(),
341 StateValuesAccess(parameters).size()); 417 StateValuesAccess(parameters).size());
342 DCHECK_EQ(descriptor->locals_count(), StateValuesAccess(locals).size()); 418 DCHECK_EQ(descriptor->locals_count(), StateValuesAccess(locals).size());
343 DCHECK_EQ(descriptor->stack_count(), StateValuesAccess(stack).size()); 419 DCHECK_EQ(descriptor->stack_count(), StateValuesAccess(stack).size());
344 420
345 ZoneVector<MachineType> types(zone); 421 StateValueDescriptor* values_descriptor =
346 types.reserve(descriptor->GetSize()); 422 descriptor->GetStateValueDescriptor();
347 423 entries += AddOperandToStateValueDescriptor(
348 size_t value_index = 0; 424 values_descriptor, inputs, g, deduplicator, function,
349 inputs->push_back( 425 MachineType::AnyTagged(), FrameStateInputKind::kStackSlot, zone);
350 OperandForDeopt(g, function, FrameStateInputKind::kStackSlot));
351 descriptor->SetType(value_index++, MachineType::AnyTagged());
352 for (StateValuesAccess::TypedNode input_node : 426 for (StateValuesAccess::TypedNode input_node :
353 StateValuesAccess(parameters)) { 427 StateValuesAccess(parameters)) {
354 inputs->push_back(OperandForDeopt(g, input_node.node, kind)); 428 entries += AddOperandToStateValueDescriptor(values_descriptor, inputs, g,
355 descriptor->SetType(value_index++, input_node.type); 429 deduplicator, input_node.node,
430 input_node.type, kind, zone);
356 } 431 }
357 if (descriptor->HasContext()) { 432 if (descriptor->HasContext()) {
358 inputs->push_back( 433 entries += AddOperandToStateValueDescriptor(
359 OperandForDeopt(g, context, FrameStateInputKind::kStackSlot)); 434 values_descriptor, inputs, g, deduplicator, context,
360 descriptor->SetType(value_index++, MachineType::AnyTagged()); 435 MachineType::AnyTagged(), FrameStateInputKind::kStackSlot, zone);
361 } 436 }
362 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(locals)) { 437 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(locals)) {
363 inputs->push_back(OperandForDeopt(g, input_node.node, kind)); 438 entries += AddOperandToStateValueDescriptor(values_descriptor, inputs, g,
364 descriptor->SetType(value_index++, input_node.type); 439 deduplicator, input_node.node,
440 input_node.type, kind, zone);
365 } 441 }
366 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(stack)) { 442 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(stack)) {
367 inputs->push_back(OperandForDeopt(g, input_node.node, kind)); 443 entries += AddOperandToStateValueDescriptor(values_descriptor, inputs, g,
368 descriptor->SetType(value_index++, input_node.type); 444 deduplicator, input_node.node,
445 input_node.type, kind, zone);
369 } 446 }
370 DCHECK(value_index == descriptor->GetSize()); 447 DCHECK_EQ(initial_size + entries, inputs->size());
448 return entries;
371 } 449 }
372 450
373 } // namespace 451 } // namespace
374 452
375 453
376 // An internal helper class for generating the operands to calls. 454 // An internal helper class for generating the operands to calls.
377 // TODO(bmeurer): Get rid of the CallBuffer business and make 455 // TODO(bmeurer): Get rid of the CallBuffer business and make
378 // InstructionSelector::VisitCall platform independent instead. 456 // InstructionSelector::VisitCall platform independent instead.
379 struct CallBuffer { 457 struct CallBuffer {
380 CallBuffer(Zone* zone, const CallDescriptor* descriptor, 458 CallBuffer(Zone* zone, const CallDescriptor* descriptor,
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 // The target is ignored, but we still need to pass a value here. 571 // The target is ignored, but we still need to pass a value here.
494 buffer->instruction_args.push_back(g.UseImmediate(callee)); 572 buffer->instruction_args.push_back(g.UseImmediate(callee));
495 break; 573 break;
496 } 574 }
497 DCHECK_EQ(1u, buffer->instruction_args.size()); 575 DCHECK_EQ(1u, buffer->instruction_args.size());
498 576
499 // If the call needs a frame state, we insert the state information as 577 // If the call needs a frame state, we insert the state information as
500 // follows (n is the number of value inputs to the frame state): 578 // follows (n is the number of value inputs to the frame state):
501 // arg 1 : deoptimization id. 579 // arg 1 : deoptimization id.
502 // arg 2 - arg (n + 1) : value inputs to the frame state. 580 // arg 2 - arg (n + 1) : value inputs to the frame state.
581 size_t frame_state_entries = 0;
582 USE(frame_state_entries); // frame_state_entries is only used for debug.
503 if (buffer->frame_state_descriptor != NULL) { 583 if (buffer->frame_state_descriptor != NULL) {
504 InstructionSequence::StateId state_id = 584 InstructionSequence::StateId state_id =
505 sequence()->AddFrameStateDescriptor(buffer->frame_state_descriptor); 585 sequence()->AddFrameStateDescriptor(buffer->frame_state_descriptor);
506 buffer->instruction_args.push_back(g.TempImmediate(state_id.ToInt())); 586 buffer->instruction_args.push_back(g.TempImmediate(state_id.ToInt()));
507 587
508 Node* frame_state = 588 Node* frame_state =
509 call->InputAt(static_cast<int>(buffer->descriptor->InputCount())); 589 call->InputAt(static_cast<int>(buffer->descriptor->InputCount()));
510 AddFrameStateInputs(frame_state, &g, &buffer->instruction_args, 590
511 buffer->frame_state_descriptor, 591 StateObjectDeduplicator deduplicator(instruction_zone());
512 FrameStateInputKind::kStackSlot, instruction_zone()); 592
593 frame_state_entries =
594 1 + AddInputsToFrameStateDescriptor(
595 buffer->frame_state_descriptor, frame_state, &g, &deduplicator,
596 &buffer->instruction_args, FrameStateInputKind::kStackSlot,
597 instruction_zone());
598
599 DCHECK_EQ(1 + frame_state_entries, buffer->instruction_args.size());
513 } 600 }
514 DCHECK(1 + buffer->frame_state_value_count() ==
515 buffer->instruction_args.size());
516 601
517 size_t input_count = static_cast<size_t>(buffer->input_count()); 602 size_t input_count = static_cast<size_t>(buffer->input_count());
518 603
519 // Split the arguments into pushed_nodes and instruction_args. Pushed 604 // Split the arguments into pushed_nodes and instruction_args. Pushed
520 // arguments require an explicit push instruction before the call and do 605 // arguments require an explicit push instruction before the call and do
521 // not appear as arguments to the call. Everything else ends up 606 // not appear as arguments to the call. Everything else ends up
522 // as an InstructionOperand argument to the call. 607 // as an InstructionOperand argument to the call.
523 auto iter(call->inputs().begin()); 608 auto iter(call->inputs().begin());
524 size_t pushed_count = 0; 609 size_t pushed_count = 0;
525 bool call_tail = (flags & kCallTail) != 0; 610 bool call_tail = (flags & kCallTail) != 0;
(...skipping 16 matching lines...) Expand all
542 buffer->pushed_nodes.resize(stack_index + 1); 627 buffer->pushed_nodes.resize(stack_index + 1);
543 } 628 }
544 PushParameter parameter(*iter, buffer->descriptor->GetInputType(index)); 629 PushParameter parameter(*iter, buffer->descriptor->GetInputType(index));
545 buffer->pushed_nodes[stack_index] = parameter; 630 buffer->pushed_nodes[stack_index] = parameter;
546 pushed_count++; 631 pushed_count++;
547 } else { 632 } else {
548 buffer->instruction_args.push_back(op); 633 buffer->instruction_args.push_back(op);
549 } 634 }
550 } 635 }
551 DCHECK_EQ(input_count, buffer->instruction_args.size() + pushed_count - 636 DCHECK_EQ(input_count, buffer->instruction_args.size() + pushed_count -
552 buffer->frame_state_value_count()); 637 frame_state_entries);
553 if (V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK && call_tail && 638 if (V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK && call_tail &&
554 stack_param_delta != 0) { 639 stack_param_delta != 0) {
555 // For tail calls that change the size of their parameter list and keep 640 // For tail calls that change the size of their parameter list and keep
556 // their return address on the stack, move the return address to just above 641 // their return address on the stack, move the return address to just above
557 // the parameters. 642 // the parameters.
558 LinkageLocation saved_return_location = 643 LinkageLocation saved_return_location =
559 LinkageLocation::ForSavedCallerReturnAddress(); 644 LinkageLocation::ForSavedCallerReturnAddress();
560 InstructionOperand return_address = 645 InstructionOperand return_address =
561 g.UsePointerLocation(LinkageLocation::ConvertToTailCallerLocation( 646 g.UsePointerLocation(LinkageLocation::ConvertToTailCallerLocation(
562 saved_return_location, stack_param_delta), 647 saved_return_location, stack_param_delta),
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 return MarkAsReference(node), VisitConstant(node); 830 return MarkAsReference(node), VisitConstant(node);
746 case IrOpcode::kNumberConstant: { 831 case IrOpcode::kNumberConstant: {
747 double value = OpParameter<double>(node); 832 double value = OpParameter<double>(node);
748 if (!IsSmiDouble(value)) MarkAsReference(node); 833 if (!IsSmiDouble(value)) MarkAsReference(node);
749 return VisitConstant(node); 834 return VisitConstant(node);
750 } 835 }
751 case IrOpcode::kCall: 836 case IrOpcode::kCall:
752 return VisitCall(node); 837 return VisitCall(node);
753 case IrOpcode::kFrameState: 838 case IrOpcode::kFrameState:
754 case IrOpcode::kStateValues: 839 case IrOpcode::kStateValues:
840 case IrOpcode::kObjectState:
755 return; 841 return;
756 case IrOpcode::kLoad: { 842 case IrOpcode::kLoad: {
757 LoadRepresentation type = LoadRepresentationOf(node->op()); 843 LoadRepresentation type = LoadRepresentationOf(node->op());
758 MarkAsRepresentation(type.representation(), node); 844 MarkAsRepresentation(type.representation(), node);
759 return VisitLoad(node); 845 return VisitLoad(node);
760 } 846 }
761 case IrOpcode::kStore: 847 case IrOpcode::kStore:
762 return VisitStore(node); 848 return VisitStore(node);
763 case IrOpcode::kWord32And: 849 case IrOpcode::kWord32And:
764 return MarkAsWord32(node), VisitWord32And(node); 850 return MarkAsWord32(node), VisitWord32And(node);
(...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after
1463 } 1549 }
1464 Emit(kArchRet, 0, nullptr, ret_count, value_locations); 1550 Emit(kArchRet, 0, nullptr, ret_count, value_locations);
1465 } 1551 }
1466 } 1552 }
1467 1553
1468 1554
1469 void InstructionSelector::VisitDeoptimize(DeoptimizeKind kind, Node* value) { 1555 void InstructionSelector::VisitDeoptimize(DeoptimizeKind kind, Node* value) {
1470 OperandGenerator g(this); 1556 OperandGenerator g(this);
1471 1557
1472 FrameStateDescriptor* desc = GetFrameStateDescriptor(value); 1558 FrameStateDescriptor* desc = GetFrameStateDescriptor(value);
1473 size_t arg_count = desc->GetTotalSize() + 1; // Include deopt id.
1474 1559
1475 InstructionOperandVector args(instruction_zone()); 1560 InstructionOperandVector args(instruction_zone());
1476 args.reserve(arg_count); 1561 args.reserve(desc->GetTotalSize() + 1); // Include deopt id.
1477 1562
1478 InstructionSequence::StateId state_id = 1563 InstructionSequence::StateId state_id =
1479 sequence()->AddFrameStateDescriptor(desc); 1564 sequence()->AddFrameStateDescriptor(desc);
1480 args.push_back(g.TempImmediate(state_id.ToInt())); 1565 args.push_back(g.TempImmediate(state_id.ToInt()));
1481 1566
1482 AddFrameStateInputs(value, &g, &args, desc, FrameStateInputKind::kAny, 1567 StateObjectDeduplicator deduplicator(instruction_zone());
1483 instruction_zone());
1484 1568
1485 DCHECK_EQ(args.size(), arg_count); 1569 AddInputsToFrameStateDescriptor(desc, value, &g, &deduplicator, &args,
1570 FrameStateInputKind::kAny,
1571 instruction_zone());
1486 1572
1487 InstructionCode opcode = kArchDeoptimize; 1573 InstructionCode opcode = kArchDeoptimize;
1488 switch (kind) { 1574 switch (kind) {
1489 case DeoptimizeKind::kEager: 1575 case DeoptimizeKind::kEager:
1490 opcode |= MiscField::encode(Deoptimizer::EAGER); 1576 opcode |= MiscField::encode(Deoptimizer::EAGER);
1491 break; 1577 break;
1492 case DeoptimizeKind::kSoft: 1578 case DeoptimizeKind::kSoft:
1493 opcode |= MiscField::encode(Deoptimizer::SOFT); 1579 opcode |= MiscField::encode(Deoptimizer::SOFT);
1494 break; 1580 break;
1495 } 1581 }
1496 Emit(opcode, 0, nullptr, arg_count, &args.front(), 0, nullptr); 1582 Emit(opcode, 0, nullptr, args.size(), &args.front(), 0, nullptr);
1497 } 1583 }
1498 1584
1499 1585
1500 void InstructionSelector::VisitThrow(Node* value) { 1586 void InstructionSelector::VisitThrow(Node* value) {
1501 OperandGenerator g(this); 1587 OperandGenerator g(this);
1502 Emit(kArchThrowTerminator, g.NoOutput()); // TODO(titzer) 1588 Emit(kArchThrowTerminator, g.NoOutput()); // TODO(titzer)
1503 } 1589 }
1504 1590
1505 1591
1506 FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor( 1592 FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor(
(...skipping 21 matching lines...) Expand all
1528 return new (instruction_zone()) FrameStateDescriptor( 1614 return new (instruction_zone()) FrameStateDescriptor(
1529 instruction_zone(), state_info.type(), state_info.bailout_id(), 1615 instruction_zone(), state_info.type(), state_info.bailout_id(),
1530 state_info.state_combine(), parameters, locals, stack, 1616 state_info.state_combine(), parameters, locals, stack,
1531 state_info.shared_info(), outer_state); 1617 state_info.shared_info(), outer_state);
1532 } 1618 }
1533 1619
1534 1620
1535 } // namespace compiler 1621 } // namespace compiler
1536 } // namespace internal 1622 } // namespace internal
1537 } // namespace v8 1623 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698