| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 | 23 |
| 24 FlowGraphCompiler::FlowGraphCompiler( | 24 FlowGraphCompiler::FlowGraphCompiler( |
| 25 Assembler* assembler, | 25 Assembler* assembler, |
| 26 const ParsedFunction& parsed_function, | 26 const ParsedFunction& parsed_function, |
| 27 const GrowableArray<BlockEntryInstr*>* blocks) | 27 const GrowableArray<BlockEntryInstr*>* blocks) |
| 28 : assembler_(assembler), | 28 : assembler_(assembler), |
| 29 parsed_function_(parsed_function), | 29 parsed_function_(parsed_function), |
| 30 blocks_(blocks), | 30 blocks_(blocks), |
| 31 block_info_(blocks->length()), | 31 block_info_(blocks->length()), |
| 32 current_block_(NULL), | 32 current_block_(NULL), |
| 33 pc_descriptors_list_(new CodeGenerator::DescriptorList()), | 33 pc_descriptors_list_(new CodeGenerator::DescriptorList()) { |
| 34 stack_local_count_(0) { | |
| 35 for (int i = 0; i < blocks->length(); ++i) { | 34 for (int i = 0; i < blocks->length(); ++i) { |
| 36 block_info_.Add(new BlockInfo()); | 35 block_info_.Add(new BlockInfo()); |
| 37 } | 36 } |
| 38 } | 37 } |
| 39 | 38 |
| 40 | 39 |
| 41 FlowGraphCompiler::~FlowGraphCompiler() { | 40 FlowGraphCompiler::~FlowGraphCompiler() { |
| 42 // BlockInfos are zone-allocated, so their destructors are not called. | 41 // BlockInfos are zone-allocated, so their destructors are not called. |
| 43 // Verify the labels explicitly here. | 42 // Verify the labels explicitly here. |
| 44 for (int i = 0; i < block_info_.length(); ++i) { | 43 for (int i = 0; i < block_info_.length(); ++i) { |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 default: | 157 default: |
| 159 UNIMPLEMENTED(); | 158 UNIMPLEMENTED(); |
| 160 } | 159 } |
| 161 ExternalLabel target_label("InlineCache", label_address); | 160 ExternalLabel target_label("InlineCache", label_address); |
| 162 __ call(&target_label); | 161 __ call(&target_label); |
| 163 AddCurrentDescriptor(PcDescriptors::kIcCall, node_id, token_index); | 162 AddCurrentDescriptor(PcDescriptors::kIcCall, node_id, token_index); |
| 164 __ addq(RSP, Immediate(argument_count * kWordSize)); | 163 __ addq(RSP, Immediate(argument_count * kWordSize)); |
| 165 } | 164 } |
| 166 | 165 |
| 167 | 166 |
| 167 void FlowGraphCompiler::VisitCurrentContext(CurrentContextComp* comp) { |
| 168 __ movq(RAX, CTX); |
| 169 } |
| 170 |
| 171 |
| 172 void FlowGraphCompiler::VisitClosureCall(ClosureCallComp* comp) { |
| 173 ASSERT(comp->context()->IsTemp()); |
| 174 ASSERT(VerifyCallComputation(comp)); |
| 175 // The arguments to the stub include the closure. The arguments |
| 176 // descriptor describes the closure's arguments (and so does not include |
| 177 // the closure). |
| 178 int argument_count = comp->ArgumentCount(); |
| 179 const Array& arguments_descriptor = |
| 180 CodeGenerator::ArgumentsDescriptor(argument_count - 1, |
| 181 comp->argument_names()); |
| 182 __ LoadObject(R10, arguments_descriptor); |
| 183 |
| 184 GenerateCall(comp->token_index(), |
| 185 &StubCode::CallClosureFunctionLabel(), |
| 186 PcDescriptors::kOther); |
| 187 __ addq(RSP, Immediate(argument_count * kWordSize)); |
| 188 __ popq(CTX); |
| 189 } |
| 190 |
| 191 |
| 168 void FlowGraphCompiler::VisitInstanceCall(InstanceCallComp* comp) { | 192 void FlowGraphCompiler::VisitInstanceCall(InstanceCallComp* comp) { |
| 169 ASSERT(VerifyCallComputation(comp)); | 193 ASSERT(VerifyCallComputation(comp)); |
| 170 EmitInstanceCall(comp->node_id(), | 194 EmitInstanceCall(comp->node_id(), |
| 171 comp->token_index(), | 195 comp->token_index(), |
| 172 comp->function_name(), | 196 comp->function_name(), |
| 173 comp->ArgumentCount(), | 197 comp->ArgumentCount(), |
| 174 comp->argument_names(), | 198 comp->argument_names(), |
| 175 comp->checked_argument_count()); | 199 comp->checked_argument_count()); |
| 176 } | 200 } |
| 177 | 201 |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 535 if (comp->ElementAt(i)->IsTemp()) { | 559 if (comp->ElementAt(i)->IsTemp()) { |
| 536 __ popq(Address(RCX, i * kWordSize)); | 560 __ popq(Address(RCX, i * kWordSize)); |
| 537 } else { | 561 } else { |
| 538 LoadValue(RDX, comp->ElementAt(i)); | 562 LoadValue(RDX, comp->ElementAt(i)); |
| 539 __ movq(Address(RCX, i * kWordSize), RDX); | 563 __ movq(Address(RCX, i * kWordSize), RDX); |
| 540 } | 564 } |
| 541 } | 565 } |
| 542 } | 566 } |
| 543 | 567 |
| 544 | 568 |
| 569 void FlowGraphCompiler::VisitCreateClosure(CreateClosureComp* comp) { |
| 570 const Function& function = comp->function(); |
| 571 const Code& stub = Code::Handle( |
| 572 StubCode::GetAllocationStubForClosure(function)); |
| 573 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); |
| 574 GenerateCall(comp->token_index(), &label, PcDescriptors::kOther); |
| 575 |
| 576 const Class& cls = Class::Handle(function.signature_class()); |
| 577 if (cls.HasTypeArguments()) { |
| 578 __ popq(RCX); // Discard type arguments. |
| 579 } |
| 580 if (function.IsImplicitInstanceClosureFunction()) { |
| 581 __ popq(RCX); // Discard receiver. |
| 582 } |
| 583 } |
| 584 |
| 585 |
| 545 void FlowGraphCompiler::VisitBlocks( | 586 void FlowGraphCompiler::VisitBlocks( |
| 546 const GrowableArray<BlockEntryInstr*>& blocks) { | 587 const GrowableArray<BlockEntryInstr*>& blocks) { |
| 547 for (intptr_t i = blocks.length() - 1; i >= 0; --i) { | 588 for (intptr_t i = blocks.length() - 1; i >= 0; --i) { |
| 548 // Compile the block entry. | 589 // Compile the block entry. |
| 549 current_block_ = blocks[i]; | 590 current_block_ = blocks[i]; |
| 550 Instruction* instr = current_block()->Accept(this); | 591 Instruction* instr = current_block()->Accept(this); |
| 551 // Compile all successors until an exit, branch, or a block entry. | 592 // Compile all successors until an exit, branch, or a block entry. |
| 552 while ((instr != NULL) && !instr->IsBlockEntry()) { | 593 while ((instr != NULL) && !instr->IsBlockEntry()) { |
| 553 instr = instr->Accept(this); | 594 instr = instr->Accept(this); |
| 554 } | 595 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 } | 650 } |
| 610 | 651 |
| 611 | 652 |
| 612 void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) { | 653 void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) { |
| 613 LoadValue(RAX, instr->value()); | 654 LoadValue(RAX, instr->value()); |
| 614 | 655 |
| 615 #ifdef DEBUG | 656 #ifdef DEBUG |
| 616 // Check that the entry stack size matches the exit stack size. | 657 // Check that the entry stack size matches the exit stack size. |
| 617 __ movq(R10, RBP); | 658 __ movq(R10, RBP); |
| 618 __ subq(R10, RSP); | 659 __ subq(R10, RSP); |
| 619 __ cmpq(R10, Immediate(stack_local_count() * kWordSize)); | 660 __ cmpq(R10, Immediate(parsed_function_.stack_local_count() * kWordSize)); |
| 620 Label stack_ok; | 661 Label stack_ok; |
| 621 __ j(EQUAL, &stack_ok, Assembler::kNearJump); | 662 __ j(EQUAL, &stack_ok, Assembler::kNearJump); |
| 622 __ Stop("Exit stack size does not match the entry stack size."); | 663 __ Stop("Exit stack size does not match the entry stack size."); |
| 623 __ Bind(&stack_ok); | 664 __ Bind(&stack_ok); |
| 624 #endif // DEBUG. | 665 #endif // DEBUG. |
| 625 | 666 |
| 626 if (FLAG_trace_functions) { | 667 if (FLAG_trace_functions) { |
| 627 __ pushq(RAX); // Preserve result. | 668 __ pushq(RAX); // Preserve result. |
| 628 const Function& function = | 669 const Function& function = |
| 629 Function::ZoneHandle(parsed_function_.function().raw()); | 670 Function::ZoneHandle(parsed_function_.function().raw()); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 669 if (negated) { | 710 if (negated) { |
| 670 __ j(EQUAL, &block_info_[instr->true_successor()->block_number()]->label); | 711 __ j(EQUAL, &block_info_[instr->true_successor()->block_number()]->label); |
| 671 } else { | 712 } else { |
| 672 __ j(NOT_EQUAL, | 713 __ j(NOT_EQUAL, |
| 673 &block_info_[instr->false_successor()->block_number()]->label); | 714 &block_info_[instr->false_successor()->block_number()]->label); |
| 674 } | 715 } |
| 675 } | 716 } |
| 676 | 717 |
| 677 | 718 |
| 678 void FlowGraphCompiler::CompileGraph() { | 719 void FlowGraphCompiler::CompileGraph() { |
| 720 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. |
| 679 const Function& function = parsed_function_.function(); | 721 const Function& function = parsed_function_.function(); |
| 680 if ((function.num_optional_parameters() != 0)) { | 722 |
| 681 Bailout("function has optional parameters"); | 723 // We don't implement copied parameters yet and should have bailed out |
| 682 } | 724 // from the graph builder. |
| 683 LocalScope* scope = parsed_function_.node_sequence()->scope(); | 725 ASSERT(function.num_optional_parameters() == 0); |
| 684 LocalScope* context_owner = NULL; | |
| 685 const int parameter_count = function.num_fixed_parameters(); | 726 const int parameter_count = function.num_fixed_parameters(); |
| 686 const int first_parameter_index = 1 + parameter_count; | 727 const int local_count = parsed_function_.stack_local_count(); |
| 687 const int first_local_index = -1; | 728 __ EnterFrame(local_count * kWordSize); |
| 688 int first_free_frame_index = | |
| 689 scope->AllocateVariables(first_parameter_index, | |
| 690 parameter_count, | |
| 691 first_local_index, | |
| 692 scope, | |
| 693 &context_owner); | |
| 694 set_stack_local_count(first_local_index - first_free_frame_index); | |
| 695 | |
| 696 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. | |
| 697 __ EnterFrame(stack_local_count() * kWordSize); | |
| 698 #ifdef DEBUG | 729 #ifdef DEBUG |
| 699 const bool check_arguments = true; | 730 const bool check_arguments = true; |
| 700 #else | 731 #else |
| 701 const bool check_arguments = function.IsClosureFunction(); | 732 const bool check_arguments = function.IsClosureFunction(); |
| 702 #endif | 733 #endif |
| 703 if (check_arguments) { | 734 if (check_arguments) { |
| 704 // Check that num_fixed <= argc <= num_params. | 735 // Check that num_fixed <= argc <= num_params. |
| 705 Label argc_in_range; | 736 Label argc_in_range; |
| 706 // Total number of args is the first Smi in args descriptor array (R10). | 737 // Total number of args is the first Smi in args descriptor array (R10). |
| 707 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | 738 __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| 708 __ cmpq(RAX, Immediate(Smi::RawValue(parameter_count))); | 739 __ cmpq(RAX, Immediate(Smi::RawValue(parameter_count))); |
| 709 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); | 740 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); |
| 710 if (function.IsClosureFunction()) { | 741 if (function.IsClosureFunction()) { |
| 711 GenerateCallRuntime(AstNode::kNoId, | 742 GenerateCallRuntime(AstNode::kNoId, |
| 712 function.token_index(), | 743 function.token_index(), |
| 713 kClosureArgumentMismatchRuntimeEntry); | 744 kClosureArgumentMismatchRuntimeEntry); |
| 714 } else { | 745 } else { |
| 715 __ Stop("Wrong number of arguments"); | 746 __ Stop("Wrong number of arguments"); |
| 716 } | 747 } |
| 717 __ Bind(&argc_in_range); | 748 __ Bind(&argc_in_range); |
| 718 } | 749 } |
| 719 | 750 |
| 720 // Initialize locals to null. | 751 // Initialize locals to null. |
| 721 if (stack_local_count() > 0) { | 752 if (local_count > 0) { |
| 722 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(Object::null()))); | 753 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(Object::null()))); |
| 723 for (int i = 0; i < stack_local_count(); ++i) { | 754 const int base = parsed_function_.first_stack_local_index(); |
| 755 for (int i = 0; i < local_count; ++i) { |
| 724 // Subtract index i (locals lie at lower addresses than RBP). | 756 // Subtract index i (locals lie at lower addresses than RBP). |
| 725 __ movq(Address(RBP, (first_local_index - i) * kWordSize), RAX); | 757 __ movq(Address(RBP, (base - i) * kWordSize), RAX); |
| 726 } | 758 } |
| 727 } | 759 } |
| 728 | 760 |
| 729 // Generate stack overflow check. | 761 // Generate stack overflow check. |
| 730 __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address())); | 762 __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address())); |
| 731 __ cmpq(RSP, Address(TMP, 0)); | 763 __ cmpq(RSP, Address(TMP, 0)); |
| 732 Label no_stack_overflow; | 764 Label no_stack_overflow; |
| 733 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); | 765 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); |
| 734 GenerateCallRuntime(AstNode::kNoId, | 766 GenerateCallRuntime(AstNode::kNoId, |
| 735 function.token_index(), | 767 function.token_index(), |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 808 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { | 840 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { |
| 809 // We don't compile exception handlers yet. | 841 // We don't compile exception handlers yet. |
| 810 code.set_exception_handlers( | 842 code.set_exception_handlers( |
| 811 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); | 843 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); |
| 812 } | 844 } |
| 813 | 845 |
| 814 | 846 |
| 815 } // namespace dart | 847 } // namespace dart |
| 816 | 848 |
| 817 #endif // defined TARGET_ARCH_X64 | 849 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |