OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
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" |
(...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
662 void FlowGraphCompiler::CopyParameters() { | 662 void FlowGraphCompiler::CopyParameters() { |
663 __ Comment("Copy parameters"); | 663 __ Comment("Copy parameters"); |
664 const Function& function = parsed_function().function(); | 664 const Function& function = parsed_function().function(); |
665 LocalScope* scope = parsed_function().node_sequence()->scope(); | 665 LocalScope* scope = parsed_function().node_sequence()->scope(); |
666 const int num_fixed_params = function.num_fixed_parameters(); | 666 const int num_fixed_params = function.num_fixed_parameters(); |
667 const int num_opt_pos_params = function.NumOptionalPositionalParameters(); | 667 const int num_opt_pos_params = function.NumOptionalPositionalParameters(); |
668 const int num_opt_named_params = function.NumOptionalNamedParameters(); | 668 const int num_opt_named_params = function.NumOptionalNamedParameters(); |
669 const int num_params = | 669 const int num_params = |
670 num_fixed_params + num_opt_pos_params + num_opt_named_params; | 670 num_fixed_params + num_opt_pos_params + num_opt_named_params; |
671 ASSERT(function.NumParameters() == num_params); | 671 ASSERT(function.NumParameters() == num_params); |
672 ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotIndex); | 672 ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotFromFp); |
673 | 673 |
674 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args, | 674 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args, |
675 // where num_pos_args is the number of positional arguments passed in. | 675 // where num_pos_args is the number of positional arguments passed in. |
676 const int min_num_pos_args = num_fixed_params; | 676 const int min_num_pos_args = num_fixed_params; |
677 const int max_num_pos_args = num_fixed_params + num_opt_pos_params; | 677 const int max_num_pos_args = num_fixed_params + num_opt_pos_params; |
678 | 678 |
679 __ movl(ECX, | 679 __ movl(ECX, |
680 FieldAddress(EDX, ArgumentsDescriptor::positional_count_offset())); | 680 FieldAddress(EDX, ArgumentsDescriptor::positional_count_offset())); |
681 // Check that min_num_pos_args <= num_pos_args. | 681 // Check that min_num_pos_args <= num_pos_args. |
682 Label wrong_num_arguments; | 682 Label wrong_num_arguments; |
683 __ cmpl(ECX, Immediate(Smi::RawValue(min_num_pos_args))); | 683 __ cmpl(ECX, Immediate(Smi::RawValue(min_num_pos_args))); |
684 __ j(LESS, &wrong_num_arguments); | 684 __ j(LESS, &wrong_num_arguments); |
685 // Check that num_pos_args <= max_num_pos_args. | 685 // Check that num_pos_args <= max_num_pos_args. |
686 __ cmpl(ECX, Immediate(Smi::RawValue(max_num_pos_args))); | 686 __ cmpl(ECX, Immediate(Smi::RawValue(max_num_pos_args))); |
687 __ j(GREATER, &wrong_num_arguments); | 687 __ j(GREATER, &wrong_num_arguments); |
688 | 688 |
689 // Copy positional arguments. | 689 // Copy positional arguments. |
690 // Argument i passed at fp[kLastParamSlotIndex + num_args - 1 - i] is copied | 690 // Argument i passed at fp[kParamEndSlotFromFp + num_args - i] is copied |
691 // to fp[kFirstLocalSlotIndex - i]. | 691 // to fp[kFirstLocalSlotFromFp - i]. |
692 | 692 |
693 __ movl(EBX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 693 __ movl(EBX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
694 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4. | 694 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4. |
695 // Let EBX point to the last passed positional argument, i.e. to | 695 // Let EBX point to the last passed positional argument, i.e. to |
696 // fp[kLastParamSlotIndex + num_args - 1 - (num_pos_args - 1)]. | 696 // fp[kParamEndSlotFromFp + num_args - (num_pos_args - 1)]. |
697 __ subl(EBX, ECX); | 697 __ subl(EBX, ECX); |
698 __ leal(EBX, Address(EBP, EBX, TIMES_2, kLastParamSlotIndex * kWordSize)); | 698 __ leal(EBX, Address(EBP, EBX, TIMES_2, |
| 699 (kParamEndSlotFromFp + 1) * kWordSize)); |
699 | 700 |
700 // Let EDI point to the last copied positional argument, i.e. to | 701 // Let EDI point to the last copied positional argument, i.e. to |
701 // fp[kFirstLocalSlotIndex - (num_pos_args - 1)]. | 702 // fp[kFirstLocalSlotFromFp - (num_pos_args - 1)]. |
702 __ leal(EDI, Address(EBP, (kFirstLocalSlotIndex + 1) * kWordSize)); | 703 __ leal(EDI, Address(EBP, (kFirstLocalSlotFromFp + 1) * kWordSize)); |
703 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling. | 704 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling. |
704 __ subl(EDI, ECX); | 705 __ subl(EDI, ECX); |
705 __ SmiUntag(ECX); | 706 __ SmiUntag(ECX); |
706 Label loop, loop_condition; | 707 Label loop, loop_condition; |
707 __ jmp(&loop_condition, Assembler::kNearJump); | 708 __ jmp(&loop_condition, Assembler::kNearJump); |
708 // We do not use the final allocation index of the variable here, i.e. | 709 // We do not use the final allocation index of the variable here, i.e. |
709 // scope->VariableAt(i)->index(), because captured variables still need | 710 // scope->VariableAt(i)->index(), because captured variables still need |
710 // to be copied to the context that is not yet allocated. | 711 // to be copied to the context that is not yet allocated. |
711 const Address argument_addr(EBX, ECX, TIMES_4, 0); | 712 const Address argument_addr(EBX, ECX, TIMES_4, 0); |
712 const Address copy_addr(EDI, ECX, TIMES_4, 0); | 713 const Address copy_addr(EDI, ECX, TIMES_4, 0); |
(...skipping 26 matching lines...) Expand all Loading... |
739 } | 740 } |
740 opt_param[i + 1] = parameter; | 741 opt_param[i + 1] = parameter; |
741 opt_param_position[i + 1] = pos; | 742 opt_param_position[i + 1] = pos; |
742 } | 743 } |
743 // Generate code handling each optional parameter in alphabetical order. | 744 // Generate code handling each optional parameter in alphabetical order. |
744 __ movl(EBX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 745 __ movl(EBX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
745 __ movl(ECX, | 746 __ movl(ECX, |
746 FieldAddress(EDX, ArgumentsDescriptor::positional_count_offset())); | 747 FieldAddress(EDX, ArgumentsDescriptor::positional_count_offset())); |
747 __ SmiUntag(ECX); | 748 __ SmiUntag(ECX); |
748 // Let EBX point to the first passed argument, i.e. to | 749 // Let EBX point to the first passed argument, i.e. to |
749 // fp[kLastParamSlotIndex + num_args - 1 - 0]; num_args (EBX) is Smi. | 750 // fp[kParamEndSlotFromFp + num_args - 0]; num_args (EBX) is Smi. |
750 __ leal(EBX, | 751 __ leal(EBX, |
751 Address(EBP, EBX, TIMES_2, (kLastParamSlotIndex - 1) * kWordSize)); | 752 Address(EBP, EBX, TIMES_2, kParamEndSlotFromFp * kWordSize)); |
752 // Let EDI point to the entry of the first named argument. | 753 // Let EDI point to the entry of the first named argument. |
753 __ leal(EDI, | 754 __ leal(EDI, |
754 FieldAddress(EDX, ArgumentsDescriptor::first_named_entry_offset())); | 755 FieldAddress(EDX, ArgumentsDescriptor::first_named_entry_offset())); |
755 for (int i = 0; i < num_opt_named_params; i++) { | 756 for (int i = 0; i < num_opt_named_params; i++) { |
756 Label load_default_value, assign_optional_parameter; | 757 Label load_default_value, assign_optional_parameter; |
757 const int param_pos = opt_param_position[i]; | 758 const int param_pos = opt_param_position[i]; |
758 // Check if this named parameter was passed in. | 759 // Check if this named parameter was passed in. |
759 // Load EAX with the name of the argument. | 760 // Load EAX with the name of the argument. |
760 __ movl(EAX, Address(EDI, ArgumentsDescriptor::name_offset())); | 761 __ movl(EAX, Address(EDI, ArgumentsDescriptor::name_offset())); |
761 ASSERT(opt_param[i]->name().IsSymbol()); | 762 ASSERT(opt_param[i]->name().IsSymbol()); |
762 __ CompareObject(EAX, opt_param[i]->name()); | 763 __ CompareObject(EAX, opt_param[i]->name()); |
763 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump); | 764 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump); |
764 // Load EAX with passed-in argument at provided arg_pos, i.e. at | 765 // Load EAX with passed-in argument at provided arg_pos, i.e. at |
765 // fp[kLastParamSlotIndex + num_args - 1 - arg_pos]. | 766 // fp[kParamEndSlotFromFp + num_args - arg_pos]. |
766 __ movl(EAX, Address(EDI, ArgumentsDescriptor::position_offset())); | 767 __ movl(EAX, Address(EDI, ArgumentsDescriptor::position_offset())); |
767 // EAX is arg_pos as Smi. | 768 // EAX is arg_pos as Smi. |
768 // Point to next named entry. | 769 // Point to next named entry. |
769 __ addl(EDI, Immediate(ArgumentsDescriptor::named_entry_size())); | 770 __ addl(EDI, Immediate(ArgumentsDescriptor::named_entry_size())); |
770 __ negl(EAX); | 771 __ negl(EAX); |
771 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi. | 772 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi. |
772 __ movl(EAX, argument_addr); | 773 __ movl(EAX, argument_addr); |
773 __ jmp(&assign_optional_parameter, Assembler::kNearJump); | 774 __ jmp(&assign_optional_parameter, Assembler::kNearJump); |
774 __ Bind(&load_default_value); | 775 __ Bind(&load_default_value); |
775 // Load EAX with default argument. | 776 // Load EAX with default argument. |
776 const Object& value = Object::ZoneHandle( | 777 const Object& value = Object::ZoneHandle( |
777 parsed_function().default_parameter_values().At( | 778 parsed_function().default_parameter_values().At( |
778 param_pos - num_fixed_params)); | 779 param_pos - num_fixed_params)); |
779 __ LoadObject(EAX, value); | 780 __ LoadObject(EAX, value); |
780 __ Bind(&assign_optional_parameter); | 781 __ Bind(&assign_optional_parameter); |
781 // Assign EAX to fp[kFirstLocalSlotIndex - param_pos]. | 782 // Assign EAX to fp[kFirstLocalSlotFromFp - param_pos]. |
782 // We do not use the final allocation index of the variable here, i.e. | 783 // We do not use the final allocation index of the variable here, i.e. |
783 // scope->VariableAt(i)->index(), because captured variables still need | 784 // scope->VariableAt(i)->index(), because captured variables still need |
784 // to be copied to the context that is not yet allocated. | 785 // to be copied to the context that is not yet allocated. |
785 const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos; | 786 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; |
786 const Address param_addr(EBP, computed_param_pos * kWordSize); | 787 const Address param_addr(EBP, computed_param_pos * kWordSize); |
787 __ movl(param_addr, EAX); | 788 __ movl(param_addr, EAX); |
788 } | 789 } |
789 delete[] opt_param; | 790 delete[] opt_param; |
790 delete[] opt_param_position; | 791 delete[] opt_param_position; |
791 // Check that EDI now points to the null terminator in the array descriptor. | 792 // Check that EDI now points to the null terminator in the array descriptor. |
792 __ cmpl(Address(EDI, 0), raw_null); | 793 __ cmpl(Address(EDI, 0), raw_null); |
793 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 794 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
794 } else { | 795 } else { |
795 ASSERT(num_opt_pos_params > 0); | 796 ASSERT(num_opt_pos_params > 0); |
796 __ movl(ECX, | 797 __ movl(ECX, |
797 FieldAddress(EDX, ArgumentsDescriptor::positional_count_offset())); | 798 FieldAddress(EDX, ArgumentsDescriptor::positional_count_offset())); |
798 __ SmiUntag(ECX); | 799 __ SmiUntag(ECX); |
799 for (int i = 0; i < num_opt_pos_params; i++) { | 800 for (int i = 0; i < num_opt_pos_params; i++) { |
800 Label next_parameter; | 801 Label next_parameter; |
801 // Handle this optional positional parameter only if k or fewer positional | 802 // Handle this optional positional parameter only if k or fewer positional |
802 // arguments have been passed, where k is param_pos, the position of this | 803 // arguments have been passed, where k is param_pos, the position of this |
803 // optional parameter in the formal parameter list. | 804 // optional parameter in the formal parameter list. |
804 const int param_pos = num_fixed_params + i; | 805 const int param_pos = num_fixed_params + i; |
805 __ cmpl(ECX, Immediate(param_pos)); | 806 __ cmpl(ECX, Immediate(param_pos)); |
806 __ j(GREATER, &next_parameter, Assembler::kNearJump); | 807 __ j(GREATER, &next_parameter, Assembler::kNearJump); |
807 // Load EAX with default argument. | 808 // Load EAX with default argument. |
808 const Object& value = Object::ZoneHandle( | 809 const Object& value = Object::ZoneHandle( |
809 parsed_function().default_parameter_values().At(i)); | 810 parsed_function().default_parameter_values().At(i)); |
810 __ LoadObject(EAX, value); | 811 __ LoadObject(EAX, value); |
811 // Assign EAX to fp[kFirstLocalSlotIndex - param_pos]. | 812 // Assign EAX to fp[kFirstLocalSlotFromFp - param_pos]. |
812 // We do not use the final allocation index of the variable here, i.e. | 813 // We do not use the final allocation index of the variable here, i.e. |
813 // scope->VariableAt(i)->index(), because captured variables still need | 814 // scope->VariableAt(i)->index(), because captured variables still need |
814 // to be copied to the context that is not yet allocated. | 815 // to be copied to the context that is not yet allocated. |
815 const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos; | 816 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; |
816 const Address param_addr(EBP, computed_param_pos * kWordSize); | 817 const Address param_addr(EBP, computed_param_pos * kWordSize); |
817 __ movl(param_addr, EAX); | 818 __ movl(param_addr, EAX); |
818 __ Bind(&next_parameter); | 819 __ Bind(&next_parameter); |
819 } | 820 } |
820 __ movl(EBX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 821 __ movl(EBX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
821 __ SmiUntag(EBX); | 822 __ SmiUntag(EBX); |
822 // Check that ECX equals EBX, i.e. no named arguments passed. | 823 // Check that ECX equals EBX, i.e. no named arguments passed. |
823 __ cmpl(ECX, EBX); | 824 __ cmpl(ECX, EBX); |
824 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 825 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
825 } | 826 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
868 // This step can be skipped in case we decide that formal parameters are | 869 // This step can be skipped in case we decide that formal parameters are |
869 // implicitly final, since garbage collecting the unmodified value is not | 870 // implicitly final, since garbage collecting the unmodified value is not |
870 // an issue anymore. | 871 // an issue anymore. |
871 | 872 |
872 // EDX : arguments descriptor array. | 873 // EDX : arguments descriptor array. |
873 __ movl(ECX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 874 __ movl(ECX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
874 __ SmiUntag(ECX); | 875 __ SmiUntag(ECX); |
875 Label null_args_loop, null_args_loop_condition; | 876 Label null_args_loop, null_args_loop_condition; |
876 __ jmp(&null_args_loop_condition, Assembler::kNearJump); | 877 __ jmp(&null_args_loop_condition, Assembler::kNearJump); |
877 const Address original_argument_addr( | 878 const Address original_argument_addr( |
878 EBP, ECX, TIMES_4, kLastParamSlotIndex * kWordSize); | 879 EBP, ECX, TIMES_4, (kParamEndSlotFromFp + 1) * kWordSize); |
879 __ Bind(&null_args_loop); | 880 __ Bind(&null_args_loop); |
880 __ movl(original_argument_addr, raw_null); | 881 __ movl(original_argument_addr, raw_null); |
881 __ Bind(&null_args_loop_condition); | 882 __ Bind(&null_args_loop_condition); |
882 __ decl(ECX); | 883 __ decl(ECX); |
883 __ j(POSITIVE, &null_args_loop, Assembler::kNearJump); | 884 __ j(POSITIVE, &null_args_loop, Assembler::kNearJump); |
884 } | 885 } |
885 | 886 |
886 | 887 |
887 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { | 888 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { |
888 // TOS: return address. | 889 // TOS: return address. |
(...skipping 892 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1781 __ movups(reg, Address(ESP, 0)); | 1782 __ movups(reg, Address(ESP, 0)); |
1782 __ addl(ESP, Immediate(kFpuRegisterSize)); | 1783 __ addl(ESP, Immediate(kFpuRegisterSize)); |
1783 } | 1784 } |
1784 | 1785 |
1785 | 1786 |
1786 #undef __ | 1787 #undef __ |
1787 | 1788 |
1788 } // namespace dart | 1789 } // namespace dart |
1789 | 1790 |
1790 #endif // defined TARGET_ARCH_IA32 | 1791 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |