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

Side by Side Diff: runtime/vm/flow_graph_compiler_x64.cc

Issue 10910119: Implement new optional parameters syntax in the vm (issue 4290). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_compiler_ia32.cc ('k') | runtime/vm/flow_graph_inliner.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "lib/error.h" 10 #include "lib/error.h"
11 #include "vm/ast_printer.h" 11 #include "vm/ast_printer.h"
12 #include "vm/il_printer.h" 12 #include "vm/il_printer.h"
13 #include "vm/locations.h" 13 #include "vm/locations.h"
14 #include "vm/object_store.h" 14 #include "vm/object_store.h"
15 #include "vm/parser.h" 15 #include "vm/parser.h"
16 #include "vm/stub_code.h" 16 #include "vm/stub_code.h"
17 #include "vm/symbols.h" 17 #include "vm/symbols.h"
18 18
19 namespace dart { 19 namespace dart {
20 20
21 DECLARE_FLAG(bool, enable_type_checks); 21 DECLARE_FLAG(bool, enable_type_checks);
22 DECLARE_FLAG(bool, print_ast); 22 DECLARE_FLAG(bool, print_ast);
23 DECLARE_FLAG(bool, print_scopes); 23 DECLARE_FLAG(bool, print_scopes);
24 DECLARE_FLAG(bool, reject_named_argument_as_positional);
24 DECLARE_FLAG(bool, trace_functions); 25 DECLARE_FLAG(bool, trace_functions);
25 26
26 27
27 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, 28 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
28 intptr_t stub_ix) { 29 intptr_t stub_ix) {
29 // Calls do not need stubs, they share a deoptimization trampoline. 30 // Calls do not need stubs, they share a deoptimization trampoline.
30 ASSERT(reason() != kDeoptAtCall); 31 ASSERT(reason() != kDeoptAtCall);
31 Assembler* assem = compiler->assembler(); 32 Assembler* assem = compiler->assembler();
32 #define __ assem-> 33 #define __ assem->
33 __ Comment("Deopt stub for id %"Pd"", deopt_id()); 34 __ Comment("Deopt stub for id %"Pd"", deopt_id());
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. 583 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments.
583 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. 584 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator.
584 __ PushObject(Object::ZoneHandle()); // Make room for the result. 585 __ PushObject(Object::ZoneHandle()); // Make room for the result.
585 __ pushq(RAX); // Push the source object. 586 __ pushq(RAX); // Push the source object.
586 __ PushObject(dst_type); // Push the type of the destination. 587 __ PushObject(dst_type); // Push the type of the destination.
587 __ pushq(RCX); // Instantiator. 588 __ pushq(RCX); // Instantiator.
588 __ pushq(RDX); // Instantiator type arguments. 589 __ pushq(RDX); // Instantiator type arguments.
589 __ PushObject(dst_name); // Push the name of the destination. 590 __ PushObject(dst_name); // Push the name of the destination.
590 __ LoadObject(RAX, test_cache); 591 __ LoadObject(RAX, test_cache);
591 __ pushq(RAX); 592 __ pushq(RAX);
592 GenerateCallRuntime(token_pos, 593 GenerateCallRuntime(token_pos, kTypeCheckRuntimeEntry, locs);
593 kTypeCheckRuntimeEntry,
594 locs);
595 // Pop the parameters supplied to the runtime entry. The result of the 594 // Pop the parameters supplied to the runtime entry. The result of the
596 // type check runtime call is the checked value. 595 // type check runtime call is the checked value.
597 __ Drop(6); 596 __ Drop(6);
598 __ popq(RAX); 597 __ popq(RAX);
599 598
600 __ Bind(&is_assignable); 599 __ Bind(&is_assignable);
601 __ popq(RDX); // Remove pushed instantiator type arguments. 600 __ popq(RDX); // Remove pushed instantiator type arguments.
602 __ popq(RCX); // Remove pushed instantiator. 601 __ popq(RCX); // Remove pushed instantiator.
603 } 602 }
604 603
(...skipping 14 matching lines...) Expand all
619 } 618 }
620 619
621 620
622 void FlowGraphCompiler::CopyParameters() { 621 void FlowGraphCompiler::CopyParameters() {
623 __ Comment("Copy parameters"); 622 __ Comment("Copy parameters");
624 const Function& function = parsed_function().function(); 623 const Function& function = parsed_function().function();
625 const bool is_native_instance_closure = 624 const bool is_native_instance_closure =
626 function.is_native() && function.IsImplicitInstanceClosureFunction(); 625 function.is_native() && function.IsImplicitInstanceClosureFunction();
627 LocalScope* scope = parsed_function().node_sequence()->scope(); 626 LocalScope* scope = parsed_function().node_sequence()->scope();
628 const int num_fixed_params = function.num_fixed_parameters(); 627 const int num_fixed_params = function.num_fixed_parameters();
629 const int num_opt_params = function.num_optional_parameters(); 628 const int num_opt_pos_params = function.num_optional_positional_parameters();
629 int num_opt_named_params = function.num_optional_named_parameters();
630 const int num_params =
631 num_fixed_params + num_opt_pos_params + num_opt_named_params;
630 int implicit_this_param_pos = is_native_instance_closure ? -1 : 0; 632 int implicit_this_param_pos = is_native_instance_closure ? -1 : 0;
631 ASSERT(parsed_function().first_parameter_index() == 633 ASSERT(parsed_function().first_parameter_index() ==
632 ParsedFunction::kFirstLocalSlotIndex + implicit_this_param_pos); 634 ParsedFunction::kFirstLocalSlotIndex + implicit_this_param_pos);
635
636 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args,
637 // where num_pos_args is the number of positional arguments passed in.
638 const int min_num_pos_args = num_fixed_params;
639 const int max_num_pos_args = num_fixed_params + num_opt_pos_params +
640 (FLAG_reject_named_argument_as_positional ? 0 : num_opt_named_params);
641
642 // Number of positional args is the second Smi in descriptor array (R10).
643 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize)));
644 // Check that min_num_pos_args <= num_pos_args.
645 Label wrong_num_arguments;
646 __ cmpq(RCX, Immediate(Smi::RawValue(min_num_pos_args)));
647 __ j(LESS, &wrong_num_arguments);
648 // Check that num_pos_args <= max_num_pos_args.
649 __ cmpq(RCX, Immediate(Smi::RawValue(max_num_pos_args)));
650 __ j(GREATER, &wrong_num_arguments);
651
633 // Copy positional arguments. 652 // Copy positional arguments.
634 // Check that no fewer than num_fixed_params positional arguments are passed 653 // Argument i passed at fp[1 + num_args - i] is copied
635 // in and that no more than num_params arguments are passed in. 654 // to fp[ParsedFunction::kFirstLocalSlotIndex - i].
636 // Passed argument i at fp[1 + argc - i]
637 // copied to fp[ParsedFunction::kFirstLocalSlotIndex - i].
638 const int num_params = num_fixed_params + num_opt_params;
639 655
640 // Total number of args is the first Smi in args descriptor array (R10). 656 // Total number of args is the first Smi in args descriptor array (R10).
641 __ movq(RBX, FieldAddress(R10, Array::data_offset())); 657 __ movq(RBX, FieldAddress(R10, Array::data_offset()));
642 // Check that num_args <= num_params.
643 Label wrong_num_arguments;
644 __ cmpq(RBX, Immediate(Smi::RawValue(num_params)));
645 __ j(GREATER, &wrong_num_arguments);
646 // Number of positional args is the second Smi in descriptor array (R10).
647 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize)));
648 // Check that num_pos_args >= num_fixed_params.
649 __ cmpq(RCX, Immediate(Smi::RawValue(num_fixed_params)));
650 __ j(LESS, &wrong_num_arguments);
651
652 // Since RBX and RCX are Smi, use TIMES_4 instead of TIMES_8. 658 // Since RBX and RCX are Smi, use TIMES_4 instead of TIMES_8.
653 // Let RBX point to the last passed positional argument, i.e. to 659 // Let RBX point to the last passed positional argument, i.e. to
654 // fp[1 + num_args - (num_pos_args - 1)]. 660 // fp[1 + num_args - (num_pos_args - 1)].
655 __ subq(RBX, RCX); 661 __ subq(RBX, RCX);
656 __ leaq(RBX, Address(RBP, RBX, TIMES_4, 2 * kWordSize)); 662 __ leaq(RBX, Address(RBP, RBX, TIMES_4, 2 * kWordSize));
657 663
658 // Let RDI point to the last copied positional argument, i.e. to 664 // Let RDI point to the last copied positional argument, i.e. to
659 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)]. 665 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)].
660 const int index = 666 const int index =
661 ParsedFunction::kFirstLocalSlotIndex + 1 + implicit_this_param_pos; 667 ParsedFunction::kFirstLocalSlotIndex + 1 + implicit_this_param_pos;
(...skipping 17 matching lines...) Expand all
679 const Address argument_addr(RBX, RCX, TIMES_8, 0); 685 const Address argument_addr(RBX, RCX, TIMES_8, 0);
680 const Address copy_addr(RDI, RCX, TIMES_8, 0); 686 const Address copy_addr(RDI, RCX, TIMES_8, 0);
681 __ Bind(&loop); 687 __ Bind(&loop);
682 __ movq(RAX, argument_addr); 688 __ movq(RAX, argument_addr);
683 __ movq(copy_addr, RAX); 689 __ movq(copy_addr, RAX);
684 __ Bind(&loop_condition); 690 __ Bind(&loop_condition);
685 __ decq(RCX); 691 __ decq(RCX);
686 __ j(POSITIVE, &loop, Assembler::kNearJump); 692 __ j(POSITIVE, &loop, Assembler::kNearJump);
687 693
688 // Copy or initialize optional named arguments. 694 // Copy or initialize optional named arguments.
695
696 if (!FLAG_reject_named_argument_as_positional) {
697 // Treat optional positional parameters as optional named parameters.
698 num_opt_named_params += num_opt_pos_params;
699 }
689 const Immediate raw_null = 700 const Immediate raw_null =
690 Immediate(reinterpret_cast<intptr_t>(Object::null())); 701 Immediate(reinterpret_cast<intptr_t>(Object::null()));
691 Label all_arguments_processed; 702 Label all_arguments_processed;
692 if (num_opt_params > 0) { 703 if (num_opt_named_params > 0) {
693 // Start by alphabetically sorting the names of the optional parameters. 704 // Start by alphabetically sorting the names of the optional parameters.
694 LocalVariable** opt_param = new LocalVariable*[num_opt_params]; 705 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params];
695 int* opt_param_position = new int[num_opt_params]; 706 int* opt_param_position = new int[num_opt_named_params];
696 for (int pos = num_fixed_params; pos < num_params; pos++) { 707 for (int pos = num_fixed_params; pos < num_params; pos++) {
697 LocalVariable* parameter = scope->VariableAt(pos); 708 LocalVariable* parameter = scope->VariableAt(pos);
698 const String& opt_param_name = parameter->name(); 709 const String& opt_param_name = parameter->name();
699 int i = pos - num_fixed_params; 710 int i = pos - num_fixed_params;
700 while (--i >= 0) { 711 while (--i >= 0) {
701 LocalVariable* param_i = opt_param[i]; 712 LocalVariable* param_i = opt_param[i];
702 const intptr_t result = opt_param_name.CompareTo(param_i->name()); 713 const intptr_t result = opt_param_name.CompareTo(param_i->name());
703 ASSERT(result != 0); 714 ASSERT(result != 0);
704 if (result > 0) break; 715 if (result > 0) break;
705 opt_param[i + 1] = opt_param[i]; 716 opt_param[i + 1] = opt_param[i];
706 opt_param_position[i + 1] = opt_param_position[i]; 717 opt_param_position[i + 1] = opt_param_position[i];
707 } 718 }
708 opt_param[i + 1] = parameter; 719 opt_param[i + 1] = parameter;
709 opt_param_position[i + 1] = pos; 720 opt_param_position[i + 1] = pos;
710 } 721 }
711 // Generate code handling each optional parameter in alphabetical order. 722 // Generate code handling each optional parameter in alphabetical order.
712 // Total number of args is the first Smi in args descriptor array (R10). 723 // Total number of args is the first Smi in args descriptor array (R10).
713 __ movq(RBX, FieldAddress(R10, Array::data_offset())); 724 __ movq(RBX, FieldAddress(R10, Array::data_offset()));
714 // Number of positional args is the second Smi in descriptor array (R10). 725 // Number of positional args is the second Smi in descriptor array (R10).
715 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize))); 726 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize)));
716 __ SmiUntag(RCX); 727 __ SmiUntag(RCX);
717 // Let RBX point to the first passed argument, i.e. to fp[1 + argc - 0]. 728 // Let RBX point to the first passed argument, i.e. to fp[1 + argc - 0].
718 __ leaq(RBX, Address(RBP, RBX, TIMES_4, kWordSize)); // RBX is Smi. 729 __ leaq(RBX, Address(RBP, RBX, TIMES_4, kWordSize)); // RBX is Smi.
719 // Let EDI point to the name/pos pair of the first named argument. 730 // Let EDI point to the name/pos pair of the first named argument.
720 __ leaq(RDI, FieldAddress(R10, Array::data_offset() + (2 * kWordSize))); 731 __ leaq(RDI, FieldAddress(R10, Array::data_offset() + (2 * kWordSize)));
721 for (int i = 0; i < num_opt_params; i++) { 732 for (int i = 0; i < num_opt_named_params; i++) {
722 // Handle this optional parameter only if k or fewer positional arguments
723 // have been passed, where k is the position of this optional parameter in
724 // the formal parameter list.
725 Label load_default_value, assign_optional_parameter, next_parameter; 733 Label load_default_value, assign_optional_parameter, next_parameter;
726 const int param_pos = opt_param_position[i]; 734 const int param_pos = opt_param_position[i];
727 __ cmpq(RCX, Immediate(param_pos)); 735 if (!FLAG_reject_named_argument_as_positional) {
728 __ j(GREATER, &next_parameter, Assembler::kNearJump); 736 // Handle this optional parameter only if k or fewer positional
737 // arguments have been passed, where k is the position of this optional
738 // parameter in the formal parameter list.
739 __ cmpq(RCX, Immediate(param_pos));
740 __ j(GREATER, &next_parameter, Assembler::kNearJump);
741 }
729 // Check if this named parameter was passed in. 742 // Check if this named parameter was passed in.
730 __ movq(RAX, Address(RDI, 0)); // Load RAX with the name of the argument. 743 __ movq(RAX, Address(RDI, 0)); // Load RAX with the name of the argument.
744 ASSERT(opt_param[i]->name().IsSymbol());
731 __ CompareObject(RAX, opt_param[i]->name()); 745 __ CompareObject(RAX, opt_param[i]->name());
732 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump); 746 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
733 // Load RAX with passed-in argument at provided arg_pos, i.e. at 747 // Load RAX with passed-in argument at provided arg_pos, i.e. at
734 // fp[1 + argc - arg_pos]. 748 // fp[1 + argc - arg_pos].
735 __ movq(RAX, Address(RDI, kWordSize)); // RAX is arg_pos as Smi. 749 __ movq(RAX, Address(RDI, kWordSize)); // RAX is arg_pos as Smi.
736 __ addq(RDI, Immediate(2 * kWordSize)); // Point to next name/pos pair. 750 __ addq(RDI, Immediate(2 * kWordSize)); // Point to next name/pos pair.
737 __ negq(RAX); 751 __ negq(RAX);
738 Address argument_addr(RBX, RAX, TIMES_4, 0); // RAX is a negative Smi. 752 Address argument_addr(RBX, RAX, TIMES_4, 0); // RAX is a negative Smi.
739 __ movq(RAX, argument_addr); 753 __ movq(RAX, argument_addr);
740 __ jmp(&assign_optional_parameter, Assembler::kNearJump); 754 __ jmp(&assign_optional_parameter, Assembler::kNearJump);
741 __ Bind(&load_default_value); 755 __ Bind(&load_default_value);
742 // Load RAX with default argument at pos. 756 // Load RAX with default argument.
743 const Object& value = Object::ZoneHandle( 757 const Object& value = Object::ZoneHandle(
744 parsed_function().default_parameter_values().At( 758 parsed_function().default_parameter_values().At(
745 param_pos - num_fixed_params)); 759 param_pos - num_fixed_params));
746 __ LoadObject(RAX, value); 760 __ LoadObject(RAX, value);
747 __ Bind(&assign_optional_parameter); 761 __ Bind(&assign_optional_parameter);
748 // Assign RAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. 762 // Assign RAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos].
749 // We do not use the final allocation index of the variable here, i.e. 763 // We do not use the final allocation index of the variable here, i.e.
750 // scope->VariableAt(i)->index(), because captured variables still need 764 // scope->VariableAt(i)->index(), because captured variables still need
751 // to be copied to the context that is not yet allocated. 765 // to be copied to the context that is not yet allocated.
752 intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex - 766 intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex -
753 param_pos + implicit_this_param_pos); 767 param_pos + implicit_this_param_pos);
754 const Address param_addr(RBP, (computed_param_pos * kWordSize)); 768 const Address param_addr(RBP, (computed_param_pos * kWordSize));
755 __ movq(param_addr, RAX); 769 __ movq(param_addr, RAX);
756 __ Bind(&next_parameter); 770 __ Bind(&next_parameter);
757 } 771 }
758 delete[] opt_param; 772 delete[] opt_param;
759 delete[] opt_param_position; 773 delete[] opt_param_position;
760 // Check that RDI now points to the null terminator in the array descriptor. 774 // Check that RDI now points to the null terminator in the array descriptor.
761 __ cmpq(Address(RDI, 0), raw_null); 775 __ cmpq(Address(RDI, 0), raw_null);
762 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); 776 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
777 } else if (num_opt_pos_params > 0) {
778 ASSERT(FLAG_reject_named_argument_as_positional);
779 // Number of positional args is the second Smi in descriptor array (R10).
780 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize)));
781 __ SmiUntag(RCX);
782 for (int i = 0; i < num_opt_pos_params; i++) {
783 Label next_parameter;
784 // Handle this optional positonal parameter only if k or fewer positional
785 // arguments have been passed, where k is param_pos, the position of this
786 // optional parameter in the formal parameter list.
787 const int param_pos = num_fixed_params + i;
788 __ cmpq(RCX, Immediate(param_pos));
789 __ j(GREATER, &next_parameter, Assembler::kNearJump);
790 // Load RAX with default argument.
791 const Object& value = Object::ZoneHandle(
792 parsed_function().default_parameter_values().At(i));
793 __ LoadObject(RAX, value);
794 // Assign RAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos].
795 // We do not use the final allocation index of the variable here, i.e.
796 // scope->VariableAt(i)->index(), because captured variables still need
797 // to be copied to the context that is not yet allocated.
798 intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex -
799 param_pos + implicit_this_param_pos);
800 const Address param_addr(RBP, (computed_param_pos * kWordSize));
801 __ movq(param_addr, RAX);
802 __ Bind(&next_parameter);
803 }
804 // Total number of args is the first Smi in args descriptor array (R10).
805 __ movq(RBX, FieldAddress(R10, Array::data_offset()));
806 __ SmiUntag(RBX);
807 // Check that RCX equals RBX, i.e. no named arguments passed.
808 __ cmpq(RCX, RBX);
809 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
763 } else { 810 } else {
764 ASSERT(is_native_instance_closure); 811 ASSERT(is_native_instance_closure);
765 __ jmp(&all_arguments_processed, Assembler::kNearJump); 812 __ jmp(&all_arguments_processed, Assembler::kNearJump);
766 } 813 }
767 814
768 __ Bind(&wrong_num_arguments); 815 __ Bind(&wrong_num_arguments);
769 if (StackSize() != 0) { 816 if (StackSize() != 0) {
770 // We need to unwind the space we reserved for locals and copied parameters. 817 // We need to unwind the space we reserved for locals and copied parameters.
771 // The NoSuchMethodFunction stub does not expect to see that area on the 818 // The NoSuchMethodFunction stub does not expect to see that area on the
772 // stack. 819 // stack.
(...skipping 24 matching lines...) Expand all
797 // RBP + 8 : points to return address. 844 // RBP + 8 : points to return address.
798 // RBP + 16 : address of last argument (arg n-1). 845 // RBP + 16 : address of last argument (arg n-1).
799 // RSP + 16 + 8*(n-1) : address of first argument (arg 0). 846 // RSP + 16 + 8*(n-1) : address of first argument (arg 0).
800 // RBX : ic-data. 847 // RBX : ic-data.
801 // R10 : arguments descriptor array. 848 // R10 : arguments descriptor array.
802 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); 849 __ call(&StubCode::CallNoSuchMethodFunctionLabel());
803 } 850 }
804 if (is_optimizing()) { 851 if (is_optimizing()) {
805 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), 852 stackmap_table_builder_->AddEntry(assembler()->CodeSize(),
806 empty_stack_bitmap, 853 empty_stack_bitmap,
807 0); 854 0); // No registers.
808 } 855 }
809 856
810 if (FLAG_trace_functions) { 857 if (FLAG_trace_functions) {
811 __ pushq(RAX); // Preserve result. 858 __ pushq(RAX); // Preserve result.
812 __ PushObject(Function::ZoneHandle(function.raw())); 859 __ PushObject(Function::ZoneHandle(function.raw()));
813 // We do not use GenerateCallRuntime because of the non-standard (empty) 860 // We do not use GenerateCallRuntime because of the non-standard (empty)
814 // stackmap used here. 861 // stackmap used here.
815 __ CallRuntime(kTraceFunctionExitRuntimeEntry); 862 __ CallRuntime(kTraceFunctionExitRuntimeEntry);
816 AddCurrentDescriptor(PcDescriptors::kOther, 863 AddCurrentDescriptor(PcDescriptors::kOther,
817 Isolate::kNoDeoptId, 864 Isolate::kNoDeoptId,
818 0); // No token position. 865 0); // No token position.
819 if (is_optimizing()) { 866 if (is_optimizing()) {
820 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), 867 stackmap_table_builder_->AddEntry(assembler()->CodeSize(),
821 empty_stack_bitmap, 868 empty_stack_bitmap,
822 0); 869 0); // No registers.
823 } 870 }
824 __ popq(RAX); // Remove argument. 871 __ popq(RAX); // Remove argument.
825 __ popq(RAX); // Restore result. 872 __ popq(RAX); // Restore result.
826 } 873 }
827 __ LeaveFrame(); 874 __ LeaveFrame();
828 __ ret(); 875 __ ret();
829 876
830 __ Bind(&all_arguments_processed); 877 __ Bind(&all_arguments_processed);
831 // Nullify originally passed arguments only after they have been copied and 878 // Nullify originally passed arguments only after they have been copied and
832 // checked, otherwise noSuchMethod would not see their original values. 879 // checked, otherwise noSuchMethod would not see their original values.
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
907 // CodePatcher::CodeIsPatchable, which verifies that this code has a minimum 954 // CodePatcher::CodeIsPatchable, which verifies that this code has a minimum
908 // code size, and nop(2) increases the minimum code size appropriately. 955 // code size, and nop(2) increases the minimum code size appropriately.
909 __ nop(2); 956 __ nop(2);
910 __ int3(); 957 __ int3();
911 __ jmp(&StubCode::FixCallersTargetLabel()); 958 __ jmp(&StubCode::FixCallersTargetLabel());
912 return; 959 return;
913 } 960 }
914 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. 961 // Specialized version of entry code from CodeGenerator::GenerateEntryCode.
915 const Function& function = parsed_function().function(); 962 const Function& function = parsed_function().function();
916 963
917 const int parameter_count = function.num_fixed_parameters(); 964 const int num_fixed_params = function.num_fixed_parameters();
918 const int copied_parameter_count = parsed_function().copied_parameter_count(); 965 const int num_copied_params = parsed_function().num_copied_params();
919 const int local_count = parsed_function().stack_local_count(); 966 const int num_locals = parsed_function().num_stack_locals();
920 __ Comment("Enter frame"); 967 __ Comment("Enter frame");
921 if (IsLeaf()) { 968 if (IsLeaf()) {
922 AssemblerMacros::EnterDartLeafFrame(assembler(), (StackSize() * kWordSize)); 969 AssemblerMacros::EnterDartLeafFrame(assembler(), (StackSize() * kWordSize));
923 } else { 970 } else {
924 AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize)); 971 AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize));
925 } 972 }
926 973
927 // For optimized code, keep a bitmap of the frame in order to build 974 // For optimized code, keep a bitmap of the frame in order to build
928 // stackmaps for GC safepoints in the prologue. 975 // stackmaps for GC safepoints in the prologue.
929 LocationSummary* prologue_locs = NULL; 976 LocationSummary* prologue_locs = NULL;
930 if (is_optimizing()) { 977 if (is_optimizing()) {
931 // Spill slots are allocated but not initialized. 978 // Spill slots are allocated but not initialized.
932 prologue_locs = new LocationSummary(0, 0, LocationSummary::kCall); 979 prologue_locs = new LocationSummary(0, 0, LocationSummary::kCall);
933 prologue_locs->stack_bitmap()->SetLength(StackSize()); 980 prologue_locs->stack_bitmap()->SetLength(StackSize());
934 } 981 }
935 982
936 // We check the number of passed arguments when we have to copy them due to 983 // We check the number of passed arguments when we have to copy them due to
937 // the presence of optional named parameters. 984 // the presence of optional parameters.
938 // No such checking code is generated if only fixed parameters are declared, 985 // No such checking code is generated if only fixed parameters are declared,
939 // unless we are debug mode or unless we are compiling a closure. 986 // unless we are debug mode or unless we are compiling a closure.
940 LocalVariable* saved_args_desc_var = 987 LocalVariable* saved_args_desc_var =
941 parsed_function().GetSavedArgumentsDescriptorVar(); 988 parsed_function().GetSavedArgumentsDescriptorVar();
942 if (copied_parameter_count == 0) { 989 if (num_copied_params == 0) {
943 #ifdef DEBUG 990 #ifdef DEBUG
991 ASSERT(!parsed_function().function().HasOptionalParameters());
944 const bool check_arguments = true; 992 const bool check_arguments = true;
945 #else 993 #else
946 const bool check_arguments = function.IsClosureFunction(); 994 const bool check_arguments = function.IsClosureFunction();
947 #endif 995 #endif
948 if (check_arguments) { 996 if (check_arguments) {
949 __ Comment("Check argument count"); 997 __ Comment("Check argument count");
950 // Check that num_fixed <= argc <= num_params. 998 // Check that num_fixed <= argc <= num_params.
951 Label argc_in_range; 999 Label argc_in_range;
952 // Total number of args is the first Smi in args descriptor array (R10). 1000 // Total number of args is the first Smi in args descriptor array (R10).
953 __ movq(RAX, FieldAddress(R10, Array::data_offset())); 1001 __ movq(RAX, FieldAddress(R10, Array::data_offset()));
954 __ cmpq(RAX, Immediate(Smi::RawValue(parameter_count))); 1002 __ cmpq(RAX, Immediate(Smi::RawValue(num_fixed_params)));
955 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); 1003 __ j(EQUAL, &argc_in_range, Assembler::kNearJump);
956 if (function.IsClosureFunction()) { 1004 if (function.IsClosureFunction()) {
957 GenerateCallRuntime(function.token_pos(), 1005 GenerateCallRuntime(function.token_pos(),
958 kClosureArgumentMismatchRuntimeEntry, 1006 kClosureArgumentMismatchRuntimeEntry,
959 prologue_locs); 1007 prologue_locs);
960 } else { 1008 } else {
961 __ Stop("Wrong number of arguments"); 1009 __ Stop("Wrong number of arguments");
962 } 1010 }
963 __ Bind(&argc_in_range); 1011 __ Bind(&argc_in_range);
964 } 1012 }
(...skipping 10 matching lines...) Expand all
975 // and later to the context, once the context is allocated. 1023 // and later to the context, once the context is allocated.
976 ASSERT(saved_args_desc_var->is_captured() || 1024 ASSERT(saved_args_desc_var->is_captured() ||
977 (saved_args_desc_var->index() == slot)); 1025 (saved_args_desc_var->index() == slot));
978 __ movq(Address(RBP, slot * kWordSize), kArgumentsDescriptorReg); 1026 __ movq(Address(RBP, slot * kWordSize), kArgumentsDescriptorReg);
979 } 1027 }
980 CopyParameters(); 1028 CopyParameters();
981 } 1029 }
982 1030
983 // In unoptimized code, initialize (non-argument) stack allocated slots to 1031 // In unoptimized code, initialize (non-argument) stack allocated slots to
984 // null. This does not cover the saved_args_desc_var slot. 1032 // null. This does not cover the saved_args_desc_var slot.
985 if (!is_optimizing() && (local_count > 0)) { 1033 if (!is_optimizing() && (num_locals > 0)) {
986 __ Comment("Initialize spill slots"); 1034 __ Comment("Initialize spill slots");
987 const intptr_t slot_base = parsed_function().first_stack_local_index(); 1035 const intptr_t slot_base = parsed_function().first_stack_local_index();
988 const Immediate raw_null = 1036 const Immediate raw_null =
989 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1037 Immediate(reinterpret_cast<intptr_t>(Object::null()));
990 __ movq(RAX, raw_null); 1038 __ movq(RAX, raw_null);
991 for (intptr_t i = 0; i < local_count; ++i) { 1039 for (intptr_t i = 0; i < num_locals; ++i) {
992 // Subtract index i (locals lie at lower addresses than RBP). 1040 // Subtract index i (locals lie at lower addresses than RBP).
993 __ movq(Address(RBP, (slot_base - i) * kWordSize), RAX); 1041 __ movq(Address(RBP, (slot_base - i) * kWordSize), RAX);
994 } 1042 }
995 } 1043 }
996 1044
997 if (FLAG_print_scopes) { 1045 if (FLAG_print_scopes) {
998 // Print the function scope (again) after generating the prologue in order 1046 // Print the function scope (again) after generating the prologue in order
999 // to see annotations such as allocation indices of locals. 1047 // to see annotations such as allocation indices of locals.
1000 if (FLAG_print_ast) { 1048 if (FLAG_print_ast) {
1001 // Second printing. 1049 // Second printing.
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
1317 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { 1365 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) {
1318 __ Exchange(mem1, mem2); 1366 __ Exchange(mem1, mem2);
1319 } 1367 }
1320 1368
1321 1369
1322 #undef __ 1370 #undef __
1323 1371
1324 } // namespace dart 1372 } // namespace dart
1325 1373
1326 #endif // defined TARGET_ARCH_X64 1374 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_ia32.cc ('k') | runtime/vm/flow_graph_inliner.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698