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" |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |