| 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 "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 __ pushq(defn->locs()->out().reg()); | 622 __ pushq(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 (R10). | 645 // Number of positional args is the second Smi in descriptor array (R10). |
| 648 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize))); | 646 __ movq(RCX, FieldAddress(R10, 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 (R10). | 659 // Total number of args is the first Smi in args descriptor array (R10). |
| 662 __ movq(RBX, FieldAddress(R10, Array::data_offset())); | 660 __ movq(RBX, FieldAddress(R10, Array::data_offset())); |
| 663 // Since RBX and RCX are Smi, use TIMES_4 instead of TIMES_8. | 661 // Since RBX and RCX are Smi, use TIMES_4 instead of TIMES_8. |
| 664 // Let RBX point to the last passed positional argument, i.e. to | 662 // Let RBX 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 __ subq(RBX, RCX); | 664 __ subq(RBX, RCX); |
| 667 __ leaq(RBX, Address(RBP, RBX, TIMES_4, 2 * kWordSize)); | 665 __ leaq(RBX, Address(RBP, RBX, TIMES_4, 2 * kWordSize)); |
| 668 | 666 |
| 669 // Let RDI point to the last copied positional argument, i.e. to | 667 // Let RDI 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 __ movq(RAX, FieldAddress(CTX, Context::variable_offset(0))); | |
| 676 __ movq(Address(RBP, (index * kWordSize)), RAX); | |
| 677 } | |
| 678 __ SmiUntag(RCX); | 670 __ SmiUntag(RCX); |
| 679 __ movq(RAX, RCX); | 671 __ movq(RAX, RCX); |
| 680 __ negq(RAX); | 672 __ negq(RAX); |
| 681 // -num_pos_args is in RAX. | 673 // -num_pos_args is in RAX. |
| 682 // (ParsedFunction::kFirstLocalSlotIndex + 1 + implicit_this_param_pos) | 674 // (ParsedFunction::kFirstLocalSlotIndex + 1) is in index. |
| 683 // is in index. | |
| 684 __ leaq(RDI, Address(RBP, RAX, TIMES_8, (index * kWordSize))); | 675 __ leaq(RDI, Address(RBP, RAX, TIMES_8, (index * kWordSize))); |
| 685 Label loop, loop_condition; | 676 Label loop, loop_condition; |
| 686 __ jmp(&loop_condition, Assembler::kNearJump); | 677 __ jmp(&loop_condition, Assembler::kNearJump); |
| 687 // We do not use the final allocation index of the variable here, i.e. | 678 // We do not use the final allocation index of the variable here, i.e. |
| 688 // scope->VariableAt(i)->index(), because captured variables still need | 679 // scope->VariableAt(i)->index(), because captured variables still need |
| 689 // to be copied to the context that is not yet allocated. | 680 // to be copied to the context that is not yet allocated. |
| 690 const Address argument_addr(RBX, RCX, TIMES_8, 0); | 681 const Address argument_addr(RBX, RCX, TIMES_8, 0); |
| 691 const Address copy_addr(RDI, RCX, TIMES_8, 0); | 682 const Address copy_addr(RDI, RCX, TIMES_8, 0); |
| 692 __ Bind(&loop); | 683 __ Bind(&loop); |
| 693 __ movq(RAX, argument_addr); | 684 __ movq(RAX, argument_addr); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 // Load RAX with default argument. | 740 // Load RAX with default argument. |
| 750 const Object& value = Object::ZoneHandle( | 741 const Object& value = Object::ZoneHandle( |
| 751 parsed_function().default_parameter_values().At( | 742 parsed_function().default_parameter_values().At( |
| 752 param_pos - num_fixed_params)); | 743 param_pos - num_fixed_params)); |
| 753 __ LoadObject(RAX, value); | 744 __ LoadObject(RAX, value); |
| 754 __ Bind(&assign_optional_parameter); | 745 __ Bind(&assign_optional_parameter); |
| 755 // Assign RAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. | 746 // Assign RAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. |
| 756 // We do not use the final allocation index of the variable here, i.e. | 747 // We do not use the final allocation index of the variable here, i.e. |
| 757 // scope->VariableAt(i)->index(), because captured variables still need | 748 // scope->VariableAt(i)->index(), because captured variables still need |
| 758 // to be copied to the context that is not yet allocated. | 749 // to be copied to the context that is not yet allocated. |
| 759 intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex - | 750 const intptr_t computed_param_pos = |
| 760 param_pos + implicit_this_param_pos); | 751 ParsedFunction::kFirstLocalSlotIndex - param_pos; |
| 761 const Address param_addr(RBP, (computed_param_pos * kWordSize)); | 752 const Address param_addr(RBP, (computed_param_pos * kWordSize)); |
| 762 __ movq(param_addr, RAX); | 753 __ movq(param_addr, RAX); |
| 763 __ Bind(&next_parameter); | 754 __ Bind(&next_parameter); |
| 764 } | 755 } |
| 765 delete[] opt_param; | 756 delete[] opt_param; |
| 766 delete[] opt_param_position; | 757 delete[] opt_param_position; |
| 767 // Check that RDI now points to the null terminator in the array descriptor. | 758 // Check that RDI now points to the null terminator in the array descriptor. |
| 768 __ cmpq(Address(RDI, 0), raw_null); | 759 __ cmpq(Address(RDI, 0), raw_null); |
| 769 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 760 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
| 770 } else if (num_opt_pos_params > 0) { | 761 } else { |
| 762 ASSERT(num_opt_pos_params > 0); |
| 771 // Number of positional args is the second Smi in descriptor array (R10). | 763 // Number of positional args is the second Smi in descriptor array (R10). |
| 772 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize))); | 764 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize))); |
| 773 __ SmiUntag(RCX); | 765 __ SmiUntag(RCX); |
| 774 for (int i = 0; i < num_opt_pos_params; i++) { | 766 for (int i = 0; i < num_opt_pos_params; i++) { |
| 775 Label next_parameter; | 767 Label next_parameter; |
| 776 // Handle this optional positonal parameter only if k or fewer positional | 768 // Handle this optional positonal parameter only if k or fewer positional |
| 777 // arguments have been passed, where k is param_pos, the position of this | 769 // arguments have been passed, where k is param_pos, the position of this |
| 778 // optional parameter in the formal parameter list. | 770 // optional parameter in the formal parameter list. |
| 779 const int param_pos = num_fixed_params + i; | 771 const int param_pos = num_fixed_params + i; |
| 780 __ cmpq(RCX, Immediate(param_pos)); | 772 __ cmpq(RCX, Immediate(param_pos)); |
| 781 __ j(GREATER, &next_parameter, Assembler::kNearJump); | 773 __ j(GREATER, &next_parameter, Assembler::kNearJump); |
| 782 // Load RAX with default argument. | 774 // Load RAX with default argument. |
| 783 const Object& value = Object::ZoneHandle( | 775 const Object& value = Object::ZoneHandle( |
| 784 parsed_function().default_parameter_values().At(i)); | 776 parsed_function().default_parameter_values().At(i)); |
| 785 __ LoadObject(RAX, value); | 777 __ LoadObject(RAX, value); |
| 786 // Assign RAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. | 778 // Assign RAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. |
| 787 // We do not use the final allocation index of the variable here, i.e. | 779 // We do not use the final allocation index of the variable here, i.e. |
| 788 // scope->VariableAt(i)->index(), because captured variables still need | 780 // scope->VariableAt(i)->index(), because captured variables still need |
| 789 // to be copied to the context that is not yet allocated. | 781 // to be copied to the context that is not yet allocated. |
| 790 intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex - | 782 const intptr_t computed_param_pos = |
| 791 param_pos + implicit_this_param_pos); | 783 ParsedFunction::kFirstLocalSlotIndex - param_pos; |
| 792 const Address param_addr(RBP, (computed_param_pos * kWordSize)); | 784 const Address param_addr(RBP, (computed_param_pos * kWordSize)); |
| 793 __ movq(param_addr, RAX); | 785 __ movq(param_addr, RAX); |
| 794 __ Bind(&next_parameter); | 786 __ Bind(&next_parameter); |
| 795 } | 787 } |
| 796 // Total number of args is the first Smi in args descriptor array (R10). | 788 // Total number of args is the first Smi in args descriptor array (R10). |
| 797 __ movq(RBX, FieldAddress(R10, Array::data_offset())); | 789 __ movq(RBX, FieldAddress(R10, Array::data_offset())); |
| 798 __ SmiUntag(RBX); | 790 __ SmiUntag(RBX); |
| 799 // Check that RCX equals RBX, i.e. no named arguments passed. | 791 // Check that RCX equals RBX, i.e. no named arguments passed. |
| 800 __ cmpq(RCX, RBX); | 792 __ cmpq(RCX, RBX); |
| 801 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 793 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
| 802 } else { | |
| 803 ASSERT(is_native_instance_closure); | |
| 804 __ jmp(&all_arguments_processed, Assembler::kNearJump); | |
| 805 } | 794 } |
| 806 | 795 |
| 807 __ Bind(&wrong_num_arguments); | 796 __ Bind(&wrong_num_arguments); |
| 808 if (StackSize() != 0) { | 797 if (StackSize() != 0) { |
| 809 // We need to unwind the space we reserved for locals and copied parameters. | 798 // We need to unwind the space we reserved for locals and copied parameters. |
| 810 // The NoSuchMethodFunction stub does not expect to see that area on the | 799 // The NoSuchMethodFunction stub does not expect to see that area on the |
| 811 // stack. | 800 // stack. |
| 812 __ addq(RSP, Immediate(StackSize() * kWordSize)); | 801 __ addq(RSP, Immediate(StackSize() * kWordSize)); |
| 813 } | 802 } |
| 814 // The calls immediately below have empty stackmaps because we have just | 803 // The calls immediately below have empty stackmaps because we have just |
| (...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1366 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { | 1355 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { |
| 1367 __ Exchange(mem1, mem2); | 1356 __ Exchange(mem1, mem2); |
| 1368 } | 1357 } |
| 1369 | 1358 |
| 1370 | 1359 |
| 1371 #undef __ | 1360 #undef __ |
| 1372 | 1361 |
| 1373 } // namespace dart | 1362 } // namespace dart |
| 1374 | 1363 |
| 1375 #endif // defined TARGET_ARCH_X64 | 1364 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |