| 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_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 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 620 Definition* defn = instr->AsDefinition(); | 620 Definition* defn = instr->AsDefinition(); |
| 621 if ((defn != NULL) && defn->is_used()) { | 621 if ((defn != NULL) && defn->is_used()) { |
| 622 __ pushl(defn->locs()->out().reg()); | 622 __ pushl(defn->locs()->out().reg()); |
| 623 } | 623 } |
| 624 } | 624 } |
| 625 | 625 |
| 626 | 626 |
| 627 void FlowGraphCompiler::CopyParameters() { | 627 void FlowGraphCompiler::CopyParameters() { |
| 628 __ Comment("Copy parameters"); | 628 __ Comment("Copy parameters"); |
| 629 const Function& function = parsed_function().function(); | 629 const Function& function = parsed_function().function(); |
| 630 const bool is_native_instance_closure = | |
| 631 function.is_native() && function.IsImplicitInstanceClosureFunction(); | |
| 632 LocalScope* scope = parsed_function().node_sequence()->scope(); | 630 LocalScope* scope = parsed_function().node_sequence()->scope(); |
| 633 const int num_fixed_params = function.num_fixed_parameters(); | 631 const int num_fixed_params = function.num_fixed_parameters(); |
| 634 const int num_opt_pos_params = function.NumOptionalPositionalParameters(); | 632 const int num_opt_pos_params = function.NumOptionalPositionalParameters(); |
| 635 int num_opt_named_params = function.NumOptionalNamedParameters(); | 633 const int num_opt_named_params = function.NumOptionalNamedParameters(); |
| 636 const int num_params = | 634 const int num_params = |
| 637 num_fixed_params + num_opt_pos_params + num_opt_named_params; | 635 num_fixed_params + num_opt_pos_params + num_opt_named_params; |
| 638 int implicit_this_param_pos = is_native_instance_closure ? -1 : 0; | 636 ASSERT(function.NumParameters() == num_params); |
| 639 ASSERT(parsed_function().first_parameter_index() == | 637 ASSERT(parsed_function().first_parameter_index() == |
| 640 ParsedFunction::kFirstLocalSlotIndex + implicit_this_param_pos); | 638 ParsedFunction::kFirstLocalSlotIndex); |
| 641 | 639 |
| 642 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args, | 640 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args, |
| 643 // where num_pos_args is the number of positional arguments passed in. | 641 // where num_pos_args is the number of positional arguments passed in. |
| 644 const int min_num_pos_args = num_fixed_params; | 642 const int min_num_pos_args = num_fixed_params; |
| 645 const int max_num_pos_args = num_fixed_params + num_opt_pos_params; | 643 const int max_num_pos_args = num_fixed_params + num_opt_pos_params; |
| 646 | 644 |
| 647 // Number of positional args is the second Smi in descriptor array (EDX). | 645 // Number of positional args is the second Smi in descriptor array (EDX). |
| 648 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); | 646 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); |
| 649 // Check that min_num_pos_args <= num_pos_args. | 647 // Check that min_num_pos_args <= num_pos_args. |
| 650 Label wrong_num_arguments; | 648 Label wrong_num_arguments; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 661 // Total number of args is the first Smi in args descriptor array (EDX). | 659 // Total number of args is the first Smi in args descriptor array (EDX). |
| 662 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); | 660 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); |
| 663 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4. | 661 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4. |
| 664 // Let EBX point to the last passed positional argument, i.e. to | 662 // Let EBX point to the last passed positional argument, i.e. to |
| 665 // fp[1 + num_args - (num_pos_args - 1)]. | 663 // fp[1 + num_args - (num_pos_args - 1)]. |
| 666 __ subl(EBX, ECX); | 664 __ subl(EBX, ECX); |
| 667 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize)); | 665 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize)); |
| 668 | 666 |
| 669 // Let EDI point to the last copied positional argument, i.e. to | 667 // Let EDI point to the last copied positional argument, i.e. to |
| 670 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)]. | 668 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)]. |
| 671 const int index = | 669 const int index = ParsedFunction::kFirstLocalSlotIndex + 1; |
| 672 ParsedFunction::kFirstLocalSlotIndex + 1 + implicit_this_param_pos; | |
| 673 // First copy captured receiver if function is an implicit native closure. | |
| 674 if (is_native_instance_closure) { | |
| 675 __ movl(EAX, FieldAddress(CTX, Context::variable_offset(0))); | |
| 676 __ movl(Address(EBP, (index * kWordSize)), EAX); | |
| 677 } | |
| 678 __ leal(EDI, Address(EBP, (index * kWordSize))); | 670 __ leal(EDI, Address(EBP, (index * kWordSize))); |
| 679 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling. | 671 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling. |
| 680 __ subl(EDI, ECX); | 672 __ subl(EDI, ECX); |
| 681 __ SmiUntag(ECX); | 673 __ SmiUntag(ECX); |
| 682 Label loop, loop_condition; | 674 Label loop, loop_condition; |
| 683 __ jmp(&loop_condition, Assembler::kNearJump); | 675 __ jmp(&loop_condition, Assembler::kNearJump); |
| 684 // We do not use the final allocation index of the variable here, i.e. | 676 // We do not use the final allocation index of the variable here, i.e. |
| 685 // scope->VariableAt(i)->index(), because captured variables still need | 677 // scope->VariableAt(i)->index(), because captured variables still need |
| 686 // to be copied to the context that is not yet allocated. | 678 // to be copied to the context that is not yet allocated. |
| 687 const Address argument_addr(EBX, ECX, TIMES_4, 0); | 679 const Address argument_addr(EBX, ECX, TIMES_4, 0); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 746 // Load EAX with default argument. | 738 // Load EAX with default argument. |
| 747 const Object& value = Object::ZoneHandle( | 739 const Object& value = Object::ZoneHandle( |
| 748 parsed_function().default_parameter_values().At( | 740 parsed_function().default_parameter_values().At( |
| 749 param_pos - num_fixed_params)); | 741 param_pos - num_fixed_params)); |
| 750 __ LoadObject(EAX, value); | 742 __ LoadObject(EAX, value); |
| 751 __ Bind(&assign_optional_parameter); | 743 __ Bind(&assign_optional_parameter); |
| 752 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. | 744 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. |
| 753 // We do not use the final allocation index of the variable here, i.e. | 745 // We do not use the final allocation index of the variable here, i.e. |
| 754 // scope->VariableAt(i)->index(), because captured variables still need | 746 // scope->VariableAt(i)->index(), because captured variables still need |
| 755 // to be copied to the context that is not yet allocated. | 747 // to be copied to the context that is not yet allocated. |
| 756 intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex - | 748 const intptr_t computed_param_pos = |
| 757 param_pos + implicit_this_param_pos); | 749 ParsedFunction::kFirstLocalSlotIndex - param_pos; |
| 758 const Address param_addr(EBP, (computed_param_pos * kWordSize)); | 750 const Address param_addr(EBP, (computed_param_pos * kWordSize)); |
| 759 __ movl(param_addr, EAX); | 751 __ movl(param_addr, EAX); |
| 760 __ Bind(&next_parameter); | 752 __ Bind(&next_parameter); |
| 761 } | 753 } |
| 762 delete[] opt_param; | 754 delete[] opt_param; |
| 763 delete[] opt_param_position; | 755 delete[] opt_param_position; |
| 764 // Check that EDI now points to the null terminator in the array descriptor. | 756 // Check that EDI now points to the null terminator in the array descriptor. |
| 765 __ cmpl(Address(EDI, 0), raw_null); | 757 __ cmpl(Address(EDI, 0), raw_null); |
| 766 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 758 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
| 767 } else if (num_opt_pos_params > 0) { | 759 } else { |
| 760 ASSERT(num_opt_pos_params > 0); |
| 768 // Number of positional args is the second Smi in descriptor array (EDX). | 761 // Number of positional args is the second Smi in descriptor array (EDX). |
| 769 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); | 762 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); |
| 770 __ SmiUntag(ECX); | 763 __ SmiUntag(ECX); |
| 771 for (int i = 0; i < num_opt_pos_params; i++) { | 764 for (int i = 0; i < num_opt_pos_params; i++) { |
| 772 Label next_parameter; | 765 Label next_parameter; |
| 773 // Handle this optional positonal parameter only if k or fewer positional | 766 // Handle this optional positonal parameter only if k or fewer positional |
| 774 // arguments have been passed, where k is param_pos, the position of this | 767 // arguments have been passed, where k is param_pos, the position of this |
| 775 // optional parameter in the formal parameter list. | 768 // optional parameter in the formal parameter list. |
| 776 const int param_pos = num_fixed_params + i; | 769 const int param_pos = num_fixed_params + i; |
| 777 __ cmpl(ECX, Immediate(param_pos)); | 770 __ cmpl(ECX, Immediate(param_pos)); |
| 778 __ j(GREATER, &next_parameter, Assembler::kNearJump); | 771 __ j(GREATER, &next_parameter, Assembler::kNearJump); |
| 779 // Load RAX with default argument. | 772 // Load RAX with default argument. |
| 780 const Object& value = Object::ZoneHandle( | 773 const Object& value = Object::ZoneHandle( |
| 781 parsed_function().default_parameter_values().At(i)); | 774 parsed_function().default_parameter_values().At(i)); |
| 782 __ LoadObject(EAX, value); | 775 __ LoadObject(EAX, value); |
| 783 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. | 776 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. |
| 784 // We do not use the final allocation index of the variable here, i.e. | 777 // We do not use the final allocation index of the variable here, i.e. |
| 785 // scope->VariableAt(i)->index(), because captured variables still need | 778 // scope->VariableAt(i)->index(), because captured variables still need |
| 786 // to be copied to the context that is not yet allocated. | 779 // to be copied to the context that is not yet allocated. |
| 787 intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex - | 780 const intptr_t computed_param_pos = |
| 788 param_pos + implicit_this_param_pos); | 781 ParsedFunction::kFirstLocalSlotIndex - param_pos; |
| 789 const Address param_addr(EBP, (computed_param_pos * kWordSize)); | 782 const Address param_addr(EBP, (computed_param_pos * kWordSize)); |
| 790 __ movl(param_addr, EAX); | 783 __ movl(param_addr, EAX); |
| 791 __ Bind(&next_parameter); | 784 __ Bind(&next_parameter); |
| 792 } | 785 } |
| 793 // Total number of args is the first Smi in args descriptor array (EDX). | 786 // Total number of args is the first Smi in args descriptor array (EDX). |
| 794 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); | 787 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); |
| 795 __ SmiUntag(EBX); | 788 __ SmiUntag(EBX); |
| 796 // Check that ECX equals EBX, i.e. no named arguments passed. | 789 // Check that ECX equals EBX, i.e. no named arguments passed. |
| 797 __ cmpl(ECX, EBX); | 790 __ cmpl(ECX, EBX); |
| 798 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 791 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
| 799 } else { | |
| 800 ASSERT(is_native_instance_closure); | |
| 801 __ jmp(&all_arguments_processed, Assembler::kNearJump); | |
| 802 } | 792 } |
| 803 | 793 |
| 804 __ Bind(&wrong_num_arguments); | 794 __ Bind(&wrong_num_arguments); |
| 805 if (StackSize() != 0) { | 795 if (StackSize() != 0) { |
| 806 // We need to unwind the space we reserved for locals and copied parameters. | 796 // We need to unwind the space we reserved for locals and copied parameters. |
| 807 // The NoSuchMethodFunction stub does not expect to see that area on the | 797 // The NoSuchMethodFunction stub does not expect to see that area on the |
| 808 // stack. | 798 // stack. |
| 809 __ addl(ESP, Immediate(StackSize() * kWordSize)); | 799 __ addl(ESP, Immediate(StackSize() * kWordSize)); |
| 810 } | 800 } |
| 811 // The calls immediately below have empty stackmaps because we have just | 801 // The calls immediately below have empty stackmaps because we have just |
| (...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1387 __ popl(ECX); | 1377 __ popl(ECX); |
| 1388 __ popl(EAX); | 1378 __ popl(EAX); |
| 1389 } | 1379 } |
| 1390 | 1380 |
| 1391 | 1381 |
| 1392 #undef __ | 1382 #undef __ |
| 1393 | 1383 |
| 1394 } // namespace dart | 1384 } // namespace dart |
| 1395 | 1385 |
| 1396 #endif // defined TARGET_ARCH_IA32 | 1386 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |