| 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 |