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/compiler-source-position-table.h" | 10 #include "src/compiler/compiler-source-position-table.h" |
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 UnallocatedOperand unalloc = UnallocatedOperand::cast(op); | 407 UnallocatedOperand unalloc = UnallocatedOperand::cast(op); |
408 sequence()->MarkAsRepresentation(rep, unalloc.virtual_register()); | 408 sequence()->MarkAsRepresentation(rep, unalloc.virtual_register()); |
409 } | 409 } |
410 | 410 |
411 | 411 |
412 void InstructionSelector::MarkAsRepresentation(MachineRepresentation rep, | 412 void InstructionSelector::MarkAsRepresentation(MachineRepresentation rep, |
413 Node* node) { | 413 Node* node) { |
414 sequence()->MarkAsRepresentation(rep, GetVirtualRegister(node)); | 414 sequence()->MarkAsRepresentation(rep, GetVirtualRegister(node)); |
415 } | 415 } |
416 | 416 |
417 | |
418 namespace { | 417 namespace { |
419 | 418 |
420 enum class FrameStateInputKind { kAny, kStackSlot }; | |
421 | |
422 InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input, | 419 InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input, |
423 FrameStateInputKind kind, | 420 FrameStateInputKind kind, |
424 MachineRepresentation rep) { | 421 MachineRepresentation rep) { |
425 if (rep == MachineRepresentation::kNone) { | 422 if (rep == MachineRepresentation::kNone) { |
426 return g->TempImmediate(FrameStateDescriptor::kImpossibleValue); | 423 return g->TempImmediate(FrameStateDescriptor::kImpossibleValue); |
427 } | 424 } |
428 | 425 |
429 switch (input->opcode()) { | 426 switch (input->opcode()) { |
430 case IrOpcode::kInt32Constant: | 427 case IrOpcode::kInt32Constant: |
431 case IrOpcode::kInt64Constant: | 428 case IrOpcode::kInt64Constant: |
(...skipping 13 matching lines...) Expand all Loading... |
445 case FrameStateInputKind::kAny: | 442 case FrameStateInputKind::kAny: |
446 // Currently deopts "wrap" other operations, so the deopt's inputs | 443 // Currently deopts "wrap" other operations, so the deopt's inputs |
447 // are potentially needed untill the end of the deoptimising code. | 444 // are potentially needed untill the end of the deoptimising code. |
448 return g->UseAnyAtEnd(input); | 445 return g->UseAnyAtEnd(input); |
449 } | 446 } |
450 } | 447 } |
451 UNREACHABLE(); | 448 UNREACHABLE(); |
452 return InstructionOperand(); | 449 return InstructionOperand(); |
453 } | 450 } |
454 | 451 |
| 452 } // namespace |
455 | 453 |
456 class StateObjectDeduplicator { | 454 class StateObjectDeduplicator { |
457 public: | 455 public: |
458 explicit StateObjectDeduplicator(Zone* zone) : objects_(zone) {} | 456 explicit StateObjectDeduplicator(Zone* zone) : objects_(zone) {} |
459 static const size_t kNotDuplicated = SIZE_MAX; | 457 static const size_t kNotDuplicated = SIZE_MAX; |
460 | 458 |
461 size_t GetObjectId(Node* node) { | 459 size_t GetObjectId(Node* node) { |
462 for (size_t i = 0; i < objects_.size(); ++i) { | 460 for (size_t i = 0; i < objects_.size(); ++i) { |
463 if (objects_[i] == node) { | 461 if (objects_[i] == node) { |
464 return i; | 462 return i; |
465 } | 463 } |
466 } | 464 } |
467 return kNotDuplicated; | 465 return kNotDuplicated; |
468 } | 466 } |
469 | 467 |
470 size_t InsertObject(Node* node) { | 468 size_t InsertObject(Node* node) { |
471 size_t id = objects_.size(); | 469 size_t id = objects_.size(); |
472 objects_.push_back(node); | 470 objects_.push_back(node); |
473 return id; | 471 return id; |
474 } | 472 } |
475 | 473 |
476 private: | 474 private: |
477 ZoneVector<Node*> objects_; | 475 ZoneVector<Node*> objects_; |
478 }; | 476 }; |
479 | 477 |
480 | |
481 // Returns the number of instruction operands added to inputs. | 478 // Returns the number of instruction operands added to inputs. |
482 size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor, | 479 size_t InstructionSelector::AddOperandToStateValueDescriptor( |
483 InstructionOperandVector* inputs, | 480 StateValueList* values, InstructionOperandVector* inputs, |
484 OperandGenerator* g, | 481 OperandGenerator* g, StateObjectDeduplicator* deduplicator, Node* input, |
485 StateObjectDeduplicator* deduplicator, | 482 MachineType type, FrameStateInputKind kind, Zone* zone) { |
486 Node* input, MachineType type, | |
487 FrameStateInputKind kind, Zone* zone) { | |
488 switch (input->opcode()) { | 483 switch (input->opcode()) { |
489 case IrOpcode::kObjectState: { | 484 case IrOpcode::kObjectState: { |
490 UNREACHABLE(); | 485 UNREACHABLE(); |
491 return 0; | 486 return 0; |
492 } | 487 } |
493 case IrOpcode::kTypedObjectState: { | 488 case IrOpcode::kTypedObjectState: { |
494 size_t id = deduplicator->GetObjectId(input); | 489 size_t id = deduplicator->GetObjectId(input); |
495 if (id == StateObjectDeduplicator::kNotDuplicated) { | 490 if (id == StateObjectDeduplicator::kNotDuplicated) { |
496 size_t entries = 0; | 491 size_t entries = 0; |
497 id = deduplicator->InsertObject(input); | 492 id = deduplicator->InsertObject(input); |
498 descriptor->fields().push_back( | 493 StateValueList* nested = values->PushRecursiveField(zone, id); |
499 StateValueDescriptor::Recursive(zone, id)); | |
500 StateValueDescriptor* new_desc = &descriptor->fields().back(); | |
501 int const input_count = input->op()->ValueInputCount(); | 494 int const input_count = input->op()->ValueInputCount(); |
502 ZoneVector<MachineType> const* types = MachineTypesOf(input->op()); | 495 ZoneVector<MachineType> const* types = MachineTypesOf(input->op()); |
503 for (int i = 0; i < input_count; ++i) { | 496 for (int i = 0; i < input_count; ++i) { |
504 entries += AddOperandToStateValueDescriptor( | 497 entries += AddOperandToStateValueDescriptor( |
505 new_desc, inputs, g, deduplicator, input->InputAt(i), | 498 nested, inputs, g, deduplicator, input->InputAt(i), types->at(i), |
506 types->at(i), kind, zone); | 499 kind, zone); |
507 } | 500 } |
508 return entries; | 501 return entries; |
509 } else { | 502 } else { |
510 // Crankshaft counts duplicate objects for the running id, so we have | 503 // Crankshaft counts duplicate objects for the running id, so we have |
511 // to push the input again. | 504 // to push the input again. |
512 deduplicator->InsertObject(input); | 505 deduplicator->InsertObject(input); |
513 descriptor->fields().push_back( | 506 values->PushDuplicate(id); |
514 StateValueDescriptor::Duplicate(zone, id)); | |
515 return 0; | 507 return 0; |
516 } | 508 } |
517 } | 509 } |
518 default: { | 510 default: { |
| 511 Heap* const heap = isolate()->heap(); |
| 512 if (input->opcode() == IrOpcode::kHeapConstant) { |
| 513 Handle<HeapObject> constant = OpParameter<Handle<HeapObject>>(input); |
| 514 Heap::RootListIndex root_index; |
| 515 if (heap->IsRootHandle(constant, &root_index) && |
| 516 root_index == Heap::kOptimizedOutRootIndex) { |
| 517 values->PushOptimizedOut(); |
| 518 return 0; |
| 519 } |
| 520 } |
519 inputs->push_back(OperandForDeopt(g, input, kind, type.representation())); | 521 inputs->push_back(OperandForDeopt(g, input, kind, type.representation())); |
520 descriptor->fields().push_back(StateValueDescriptor::Plain(zone, type)); | 522 values->PushPlain(type); |
521 return 1; | 523 return 1; |
522 } | 524 } |
523 } | 525 } |
524 } | 526 } |
525 | 527 |
526 | 528 |
527 // Returns the number of instruction operands added to inputs. | 529 // Returns the number of instruction operands added to inputs. |
528 size_t AddInputsToFrameStateDescriptor(FrameStateDescriptor* descriptor, | 530 size_t InstructionSelector::AddInputsToFrameStateDescriptor( |
529 Node* state, OperandGenerator* g, | 531 FrameStateDescriptor* descriptor, Node* state, OperandGenerator* g, |
530 StateObjectDeduplicator* deduplicator, | 532 StateObjectDeduplicator* deduplicator, InstructionOperandVector* inputs, |
531 InstructionOperandVector* inputs, | 533 FrameStateInputKind kind, Zone* zone) { |
532 FrameStateInputKind kind, Zone* zone) { | |
533 DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode()); | 534 DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode()); |
534 | 535 |
535 size_t entries = 0; | 536 size_t entries = 0; |
536 size_t initial_size = inputs->size(); | 537 size_t initial_size = inputs->size(); |
537 USE(initial_size); // initial_size is only used for debug. | 538 USE(initial_size); // initial_size is only used for debug. |
538 | 539 |
539 if (descriptor->outer_state()) { | 540 if (descriptor->outer_state()) { |
540 entries += AddInputsToFrameStateDescriptor( | 541 entries += AddInputsToFrameStateDescriptor( |
541 descriptor->outer_state(), state->InputAt(kFrameStateOuterStateInput), | 542 descriptor->outer_state(), state->InputAt(kFrameStateOuterStateInput), |
542 g, deduplicator, inputs, kind, zone); | 543 g, deduplicator, inputs, kind, zone); |
543 } | 544 } |
544 | 545 |
545 Node* parameters = state->InputAt(kFrameStateParametersInput); | 546 Node* parameters = state->InputAt(kFrameStateParametersInput); |
546 Node* locals = state->InputAt(kFrameStateLocalsInput); | 547 Node* locals = state->InputAt(kFrameStateLocalsInput); |
547 Node* stack = state->InputAt(kFrameStateStackInput); | 548 Node* stack = state->InputAt(kFrameStateStackInput); |
548 Node* context = state->InputAt(kFrameStateContextInput); | 549 Node* context = state->InputAt(kFrameStateContextInput); |
549 Node* function = state->InputAt(kFrameStateFunctionInput); | 550 Node* function = state->InputAt(kFrameStateFunctionInput); |
550 | 551 |
551 DCHECK_EQ(descriptor->parameters_count(), | 552 DCHECK_EQ(descriptor->parameters_count(), |
552 StateValuesAccess(parameters).size()); | 553 StateValuesAccess(parameters).size()); |
553 DCHECK_EQ(descriptor->locals_count(), StateValuesAccess(locals).size()); | 554 DCHECK_EQ(descriptor->locals_count(), StateValuesAccess(locals).size()); |
554 DCHECK_EQ(descriptor->stack_count(), StateValuesAccess(stack).size()); | 555 DCHECK_EQ(descriptor->stack_count(), StateValuesAccess(stack).size()); |
555 | 556 |
556 StateValueDescriptor* values_descriptor = | 557 StateValueList* values_descriptor = descriptor->GetStateValueDescriptors(); |
557 descriptor->GetStateValueDescriptor(); | |
558 entries += AddOperandToStateValueDescriptor( | 558 entries += AddOperandToStateValueDescriptor( |
559 values_descriptor, inputs, g, deduplicator, function, | 559 values_descriptor, inputs, g, deduplicator, function, |
560 MachineType::AnyTagged(), FrameStateInputKind::kStackSlot, zone); | 560 MachineType::AnyTagged(), FrameStateInputKind::kStackSlot, zone); |
561 for (StateValuesAccess::TypedNode input_node : | 561 for (StateValuesAccess::TypedNode input_node : |
562 StateValuesAccess(parameters)) { | 562 StateValuesAccess(parameters)) { |
563 entries += AddOperandToStateValueDescriptor(values_descriptor, inputs, g, | 563 entries += AddOperandToStateValueDescriptor(values_descriptor, inputs, g, |
564 deduplicator, input_node.node, | 564 deduplicator, input_node.node, |
565 input_node.type, kind, zone); | 565 input_node.type, kind, zone); |
566 } | 566 } |
567 if (descriptor->HasContext()) { | 567 if (descriptor->HasContext()) { |
568 entries += AddOperandToStateValueDescriptor( | 568 entries += AddOperandToStateValueDescriptor( |
569 values_descriptor, inputs, g, deduplicator, context, | 569 values_descriptor, inputs, g, deduplicator, context, |
570 MachineType::AnyTagged(), FrameStateInputKind::kStackSlot, zone); | 570 MachineType::AnyTagged(), FrameStateInputKind::kStackSlot, zone); |
571 } | 571 } |
572 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(locals)) { | 572 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(locals)) { |
573 entries += AddOperandToStateValueDescriptor(values_descriptor, inputs, g, | 573 entries += AddOperandToStateValueDescriptor(values_descriptor, inputs, g, |
574 deduplicator, input_node.node, | 574 deduplicator, input_node.node, |
575 input_node.type, kind, zone); | 575 input_node.type, kind, zone); |
576 } | 576 } |
577 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(stack)) { | 577 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(stack)) { |
578 entries += AddOperandToStateValueDescriptor(values_descriptor, inputs, g, | 578 entries += AddOperandToStateValueDescriptor(values_descriptor, inputs, g, |
579 deduplicator, input_node.node, | 579 deduplicator, input_node.node, |
580 input_node.type, kind, zone); | 580 input_node.type, kind, zone); |
581 } | 581 } |
582 DCHECK_EQ(initial_size + entries, inputs->size()); | 582 DCHECK_EQ(initial_size + entries, inputs->size()); |
583 return entries; | 583 return entries; |
584 } | 584 } |
585 | 585 |
586 } // namespace | |
587 | |
588 | 586 |
589 // An internal helper class for generating the operands to calls. | 587 // An internal helper class for generating the operands to calls. |
590 // TODO(bmeurer): Get rid of the CallBuffer business and make | 588 // TODO(bmeurer): Get rid of the CallBuffer business and make |
591 // InstructionSelector::VisitCall platform independent instead. | 589 // InstructionSelector::VisitCall platform independent instead. |
592 struct CallBuffer { | 590 struct CallBuffer { |
593 CallBuffer(Zone* zone, const CallDescriptor* descriptor, | 591 CallBuffer(Zone* zone, const CallDescriptor* descriptor, |
594 FrameStateDescriptor* frame_state) | 592 FrameStateDescriptor* frame_state) |
595 : descriptor(descriptor), | 593 : descriptor(descriptor), |
596 frame_state_descriptor(frame_state), | 594 frame_state_descriptor(frame_state), |
597 output_nodes(zone), | 595 output_nodes(zone), |
(...skipping 1514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2112 return new (instruction_zone()) FrameStateDescriptor( | 2110 return new (instruction_zone()) FrameStateDescriptor( |
2113 instruction_zone(), state_info.type(), state_info.bailout_id(), | 2111 instruction_zone(), state_info.type(), state_info.bailout_id(), |
2114 state_info.state_combine(), parameters, locals, stack, | 2112 state_info.state_combine(), parameters, locals, stack, |
2115 state_info.shared_info(), outer_state); | 2113 state_info.shared_info(), outer_state); |
2116 } | 2114 } |
2117 | 2115 |
2118 | 2116 |
2119 } // namespace compiler | 2117 } // namespace compiler |
2120 } // namespace internal | 2118 } // namespace internal |
2121 } // namespace v8 | 2119 } // namespace v8 |
OLD | NEW |