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" |
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 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 } | 614 } |
614 | 615 |
615 | 616 |
616 void FlowGraphCompiler::CopyParameters() { | 617 void FlowGraphCompiler::CopyParameters() { |
617 __ Comment("Copy parameters"); | 618 __ Comment("Copy parameters"); |
618 const Function& function = parsed_function().function(); | 619 const Function& function = parsed_function().function(); |
619 const bool is_native_instance_closure = | 620 const bool is_native_instance_closure = |
620 function.is_native() && function.IsImplicitInstanceClosureFunction(); | 621 function.is_native() && function.IsImplicitInstanceClosureFunction(); |
621 LocalScope* scope = parsed_function().node_sequence()->scope(); | 622 LocalScope* scope = parsed_function().node_sequence()->scope(); |
622 const int num_fixed_params = function.num_fixed_parameters(); | 623 const int num_fixed_params = function.num_fixed_parameters(); |
623 const int num_opt_params = function.num_optional_parameters(); | 624 const int num_opt_pos_params = function.num_optional_positional_parameters(); |
| 625 int num_opt_named_params = function.num_optional_named_parameters(); |
| 626 const int num_params = |
| 627 num_fixed_params + num_opt_pos_params + num_opt_named_params; |
624 int implicit_this_param_pos = is_native_instance_closure ? -1 : 0; | 628 int implicit_this_param_pos = is_native_instance_closure ? -1 : 0; |
625 ASSERT(parsed_function().first_parameter_index() == | 629 ASSERT(parsed_function().first_parameter_index() == |
626 ParsedFunction::kFirstLocalSlotIndex + implicit_this_param_pos); | 630 ParsedFunction::kFirstLocalSlotIndex + implicit_this_param_pos); |
| 631 |
| 632 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args, |
| 633 // where num_pos_args is the number of positional arguments passed in. |
| 634 const int min_num_pos_args = num_fixed_params; |
| 635 const int max_num_pos_args = num_fixed_params + num_opt_pos_params + |
| 636 (FLAG_reject_named_argument_as_positional ? 0 : num_opt_named_params); |
| 637 |
| 638 // Number of positional args is the second Smi in descriptor array (EDX). |
| 639 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); |
| 640 // Check that min_num_pos_args <= num_pos_args. |
| 641 Label wrong_num_arguments; |
| 642 __ cmpl(ECX, Immediate(Smi::RawValue(min_num_pos_args))); |
| 643 __ j(LESS, &wrong_num_arguments); |
| 644 // Check that num_pos_args <= max_num_pos_args. |
| 645 __ cmpl(ECX, Immediate(Smi::RawValue(max_num_pos_args))); |
| 646 __ j(GREATER, &wrong_num_arguments); |
| 647 |
627 // Copy positional arguments. | 648 // Copy positional arguments. |
628 // Check that no fewer than num_fixed_params positional arguments are passed | 649 // Argument i passed at fp[1 + num_args - i] is copied |
629 // in and that no more than num_params arguments are passed in. | 650 // to fp[ParsedFunction::kFirstLocalSlotIndex - i]. |
630 // Passed argument i at fp[1 + argc - i] | |
631 // copied to fp[ParsedFunction::kFirstLocalSlotIndex - i]. | |
632 const int num_params = num_fixed_params + num_opt_params; | |
633 | 651 |
634 // Total number of args is the first Smi in args descriptor array (EDX). | 652 // Total number of args is the first Smi in args descriptor array (EDX). |
635 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); | 653 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); |
636 // Check that num_args <= num_params. | |
637 Label wrong_num_arguments; | |
638 __ cmpl(EBX, Immediate(Smi::RawValue(num_params))); | |
639 __ j(GREATER, &wrong_num_arguments); | |
640 // Number of positional args is the second Smi in descriptor array (EDX). | |
641 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); | |
642 // Check that num_pos_args >= num_fixed_params. | |
643 __ cmpl(ECX, Immediate(Smi::RawValue(num_fixed_params))); | |
644 __ j(LESS, &wrong_num_arguments); | |
645 | |
646 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4. | 654 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4. |
647 // Let EBX point to the last passed positional argument, i.e. to | 655 // Let EBX point to the last passed positional argument, i.e. to |
648 // fp[1 + num_args - (num_pos_args - 1)]. | 656 // fp[1 + num_args - (num_pos_args - 1)]. |
649 __ subl(EBX, ECX); | 657 __ subl(EBX, ECX); |
650 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize)); | 658 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize)); |
651 | 659 |
652 // Let EDI point to the last copied positional argument, i.e. to | 660 // Let EDI point to the last copied positional argument, i.e. to |
653 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)]. | 661 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)]. |
654 const int index = | 662 const int index = |
655 ParsedFunction::kFirstLocalSlotIndex + 1 + implicit_this_param_pos; | 663 ParsedFunction::kFirstLocalSlotIndex + 1 + implicit_this_param_pos; |
(...skipping 14 matching lines...) Expand all Loading... |
670 const Address argument_addr(EBX, ECX, TIMES_4, 0); | 678 const Address argument_addr(EBX, ECX, TIMES_4, 0); |
671 const Address copy_addr(EDI, ECX, TIMES_4, 0); | 679 const Address copy_addr(EDI, ECX, TIMES_4, 0); |
672 __ Bind(&loop); | 680 __ Bind(&loop); |
673 __ movl(EAX, argument_addr); | 681 __ movl(EAX, argument_addr); |
674 __ movl(copy_addr, EAX); | 682 __ movl(copy_addr, EAX); |
675 __ Bind(&loop_condition); | 683 __ Bind(&loop_condition); |
676 __ decl(ECX); | 684 __ decl(ECX); |
677 __ j(POSITIVE, &loop, Assembler::kNearJump); | 685 __ j(POSITIVE, &loop, Assembler::kNearJump); |
678 | 686 |
679 // Copy or initialize optional named arguments. | 687 // Copy or initialize optional named arguments. |
| 688 |
| 689 if (!FLAG_reject_named_argument_as_positional) { |
| 690 // Treat optional positional parameters as optional named parameters. |
| 691 num_opt_named_params += num_opt_pos_params; |
| 692 } |
680 const Immediate raw_null = | 693 const Immediate raw_null = |
681 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 694 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
682 Label all_arguments_processed; | 695 Label all_arguments_processed; |
683 if (num_opt_params > 0) { | 696 if (num_opt_named_params > 0) { |
684 // Start by alphabetically sorting the names of the optional parameters. | 697 // Start by alphabetically sorting the names of the optional parameters. |
685 LocalVariable** opt_param = new LocalVariable*[num_opt_params]; | 698 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params]; |
686 int* opt_param_position = new int[num_opt_params]; | 699 int* opt_param_position = new int[num_opt_named_params]; |
687 for (int pos = num_fixed_params; pos < num_params; pos++) { | 700 for (int pos = num_fixed_params; pos < num_params; pos++) { |
688 LocalVariable* parameter = scope->VariableAt(pos); | 701 LocalVariable* parameter = scope->VariableAt(pos); |
689 const String& opt_param_name = parameter->name(); | 702 const String& opt_param_name = parameter->name(); |
690 int i = pos - num_fixed_params; | 703 int i = pos - num_fixed_params; |
691 while (--i >= 0) { | 704 while (--i >= 0) { |
692 LocalVariable* param_i = opt_param[i]; | 705 LocalVariable* param_i = opt_param[i]; |
693 const intptr_t result = opt_param_name.CompareTo(param_i->name()); | 706 const intptr_t result = opt_param_name.CompareTo(param_i->name()); |
694 ASSERT(result != 0); | 707 ASSERT(result != 0); |
695 if (result > 0) break; | 708 if (result > 0) break; |
696 opt_param[i + 1] = opt_param[i]; | 709 opt_param[i + 1] = opt_param[i]; |
697 opt_param_position[i + 1] = opt_param_position[i]; | 710 opt_param_position[i + 1] = opt_param_position[i]; |
698 } | 711 } |
699 opt_param[i + 1] = parameter; | 712 opt_param[i + 1] = parameter; |
700 opt_param_position[i + 1] = pos; | 713 opt_param_position[i + 1] = pos; |
701 } | 714 } |
702 // Generate code handling each optional parameter in alphabetical order. | 715 // Generate code handling each optional parameter in alphabetical order. |
703 // Total number of args is the first Smi in args descriptor array (EDX). | 716 // Total number of args is the first Smi in args descriptor array (EDX). |
704 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); | 717 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); |
705 // Number of positional args is the second Smi in descriptor array (EDX). | 718 // Number of positional args is the second Smi in descriptor array (EDX). |
706 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); | 719 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); |
707 __ SmiUntag(ECX); | 720 __ SmiUntag(ECX); |
708 // Let EBX point to the first passed argument, i.e. to fp[1 + argc - 0]. | 721 // Let EBX point to the first passed argument, i.e. to fp[1 + argc - 0]. |
709 __ leal(EBX, Address(EBP, EBX, TIMES_2, kWordSize)); // EBX is Smi. | 722 __ leal(EBX, Address(EBP, EBX, TIMES_2, kWordSize)); // EBX is Smi. |
710 // Let EDI point to the name/pos pair of the first named argument. | 723 // Let EDI point to the name/pos pair of the first named argument. |
711 __ leal(EDI, FieldAddress(EDX, Array::data_offset() + (2 * kWordSize))); | 724 __ leal(EDI, FieldAddress(EDX, Array::data_offset() + (2 * kWordSize))); |
712 for (int i = 0; i < num_opt_params; i++) { | 725 for (int i = 0; i < num_opt_named_params; i++) { |
713 // Handle this optional parameter only if k or fewer positional arguments | |
714 // have been passed, where k is the position of this optional parameter in | |
715 // the formal parameter list. | |
716 Label load_default_value, assign_optional_parameter, next_parameter; | 726 Label load_default_value, assign_optional_parameter, next_parameter; |
717 const int param_pos = opt_param_position[i]; | 727 const int param_pos = opt_param_position[i]; |
718 __ cmpl(ECX, Immediate(param_pos)); | 728 if (!FLAG_reject_named_argument_as_positional) { |
719 __ j(GREATER, &next_parameter, Assembler::kNearJump); | 729 // Handle this optional parameter only if k or fewer positional |
| 730 // arguments have been passed, where k is the position of this optional |
| 731 // parameter in the formal parameter list. |
| 732 __ cmpl(ECX, Immediate(param_pos)); |
| 733 __ j(GREATER, &next_parameter, Assembler::kNearJump); |
| 734 } |
720 // Check if this named parameter was passed in. | 735 // Check if this named parameter was passed in. |
721 __ movl(EAX, Address(EDI, 0)); // Load EAX with the name of the argument. | 736 __ movl(EAX, Address(EDI, 0)); // Load EAX with the name of the argument. |
722 ASSERT(opt_param[i]->name().IsSymbol()); | 737 ASSERT(opt_param[i]->name().IsSymbol()); |
723 __ CompareObject(EAX, opt_param[i]->name()); | 738 __ CompareObject(EAX, opt_param[i]->name()); |
724 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump); | 739 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump); |
725 // Load EAX with passed-in argument at provided arg_pos, i.e. at | 740 // Load EAX with passed-in argument at provided arg_pos, i.e. at |
726 // fp[1 + argc - arg_pos]. | 741 // fp[1 + argc - arg_pos]. |
727 __ movl(EAX, Address(EDI, kWordSize)); // EAX is arg_pos as Smi. | 742 __ movl(EAX, Address(EDI, kWordSize)); // EAX is arg_pos as Smi. |
728 __ addl(EDI, Immediate(2 * kWordSize)); // Point to next name/pos pair. | 743 __ addl(EDI, Immediate(2 * kWordSize)); // Point to next name/pos pair. |
729 __ negl(EAX); | 744 __ negl(EAX); |
730 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi. | 745 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi. |
731 __ movl(EAX, argument_addr); | 746 __ movl(EAX, argument_addr); |
732 __ jmp(&assign_optional_parameter, Assembler::kNearJump); | 747 __ jmp(&assign_optional_parameter, Assembler::kNearJump); |
733 __ Bind(&load_default_value); | 748 __ Bind(&load_default_value); |
734 // Load EAX with default argument at pos. | 749 // Load EAX with default argument. |
735 const Object& value = Object::ZoneHandle( | 750 const Object& value = Object::ZoneHandle( |
736 parsed_function().default_parameter_values().At( | 751 parsed_function().default_parameter_values().At( |
737 param_pos - num_fixed_params)); | 752 param_pos - num_fixed_params)); |
738 __ LoadObject(EAX, value); | 753 __ LoadObject(EAX, value); |
739 __ Bind(&assign_optional_parameter); | 754 __ Bind(&assign_optional_parameter); |
740 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. | 755 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. |
741 // We do not use the final allocation index of the variable here, i.e. | 756 // We do not use the final allocation index of the variable here, i.e. |
742 // scope->VariableAt(i)->index(), because captured variables still need | 757 // scope->VariableAt(i)->index(), because captured variables still need |
743 // to be copied to the context that is not yet allocated. | 758 // to be copied to the context that is not yet allocated. |
744 intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex - | 759 intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex - |
745 param_pos + implicit_this_param_pos); | 760 param_pos + implicit_this_param_pos); |
746 const Address param_addr(EBP, (computed_param_pos * kWordSize)); | 761 const Address param_addr(EBP, (computed_param_pos * kWordSize)); |
747 __ movl(param_addr, EAX); | 762 __ movl(param_addr, EAX); |
748 __ Bind(&next_parameter); | 763 __ Bind(&next_parameter); |
749 } | 764 } |
750 delete[] opt_param; | 765 delete[] opt_param; |
751 delete[] opt_param_position; | 766 delete[] opt_param_position; |
752 // Check that EDI now points to the null terminator in the array descriptor. | 767 // Check that EDI now points to the null terminator in the array descriptor. |
753 __ cmpl(Address(EDI, 0), raw_null); | 768 __ cmpl(Address(EDI, 0), raw_null); |
754 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 769 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
| 770 } else if (num_opt_pos_params > 0) { |
| 771 ASSERT(FLAG_reject_named_argument_as_positional); |
| 772 // Number of positional args is the second Smi in descriptor array (EDX). |
| 773 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); |
| 774 __ SmiUntag(ECX); |
| 775 for (int i = 0; i < num_opt_pos_params; i++) { |
| 776 Label next_parameter; |
| 777 // Handle this optional positonal parameter only if k or fewer positional |
| 778 // arguments have been passed, where k is param_pos, the position of this |
| 779 // optional parameter in the formal parameter list. |
| 780 const int param_pos = num_fixed_params + i; |
| 781 __ cmpl(ECX, Immediate(param_pos)); |
| 782 __ j(GREATER, &next_parameter, Assembler::kNearJump); |
| 783 // Load RAX with default argument. |
| 784 const Object& value = Object::ZoneHandle( |
| 785 parsed_function().default_parameter_values().At(i)); |
| 786 __ LoadObject(EAX, value); |
| 787 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. |
| 788 // We do not use the final allocation index of the variable here, i.e. |
| 789 // scope->VariableAt(i)->index(), because captured variables still need |
| 790 // to be copied to the context that is not yet allocated. |
| 791 intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex - |
| 792 param_pos + implicit_this_param_pos); |
| 793 const Address param_addr(EBP, (computed_param_pos * kWordSize)); |
| 794 __ movl(param_addr, EAX); |
| 795 __ Bind(&next_parameter); |
| 796 } |
| 797 // Total number of args is the first Smi in args descriptor array (EDX). |
| 798 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); |
| 799 __ SmiUntag(EBX); |
| 800 // Check that ECX equals EBX, i.e. no named arguments passed. |
| 801 __ cmpl(ECX, EBX); |
| 802 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
755 } else { | 803 } else { |
756 ASSERT(is_native_instance_closure); | 804 ASSERT(is_native_instance_closure); |
757 __ jmp(&all_arguments_processed, Assembler::kNearJump); | 805 __ jmp(&all_arguments_processed, Assembler::kNearJump); |
758 } | 806 } |
759 | 807 |
760 __ Bind(&wrong_num_arguments); | 808 __ Bind(&wrong_num_arguments); |
761 if (StackSize() != 0) { | 809 if (StackSize() != 0) { |
762 // We need to unwind the space we reserved for locals and copied parameters. | 810 // We need to unwind the space we reserved for locals and copied parameters. |
763 // The NoSuchMethodFunction stub does not expect to see that area on the | 811 // The NoSuchMethodFunction stub does not expect to see that area on the |
764 // stack. | 812 // stack. |
765 __ addl(ESP, Immediate(StackSize() * kWordSize)); | 813 __ addl(ESP, Immediate(StackSize() * kWordSize)); |
766 } | 814 } |
767 // The calls below have empty stackmaps because we have just dropped the | 815 // The calls immediately below have empty stackmaps because we have just |
768 // spill slots. | 816 // dropped the spill slots. |
769 BitmapBuilder* empty_stack_bitmap = new BitmapBuilder(); | 817 BitmapBuilder* empty_stack_bitmap = new BitmapBuilder(); |
770 if (function.IsClosureFunction()) { | 818 if (function.IsClosureFunction()) { |
771 // We do not use GenerateCallRuntime because of the non-standard (empty) | 819 // We do not use GenerateCallRuntime because of the non-standard (empty) |
772 // stackmap used here. | 820 // stackmap used here. |
773 __ CallRuntime(kClosureArgumentMismatchRuntimeEntry); | 821 __ CallRuntime(kClosureArgumentMismatchRuntimeEntry); |
774 AddCurrentDescriptor(PcDescriptors::kOther, | 822 AddCurrentDescriptor(PcDescriptors::kOther, |
775 Isolate::kNoDeoptId, | 823 Isolate::kNoDeoptId, |
776 0); // No token position. | 824 0); // No token position. |
777 } else { | 825 } else { |
778 ASSERT(!IsLeaf()); | 826 ASSERT(!IsLeaf()); |
(...skipping 13 matching lines...) Expand all Loading... |
792 // ECX : ic-data. | 840 // ECX : ic-data. |
793 // EDX : arguments descriptor array. | 841 // EDX : arguments descriptor array. |
794 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); | 842 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); |
795 } | 843 } |
796 if (is_optimizing()) { | 844 if (is_optimizing()) { |
797 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), | 845 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), |
798 empty_stack_bitmap, | 846 empty_stack_bitmap, |
799 0); // No registers. | 847 0); // No registers. |
800 } | 848 } |
801 | 849 |
802 | |
803 if (FLAG_trace_functions) { | 850 if (FLAG_trace_functions) { |
804 __ pushl(EAX); // Preserve result. | 851 __ pushl(EAX); // Preserve result. |
805 __ PushObject(Function::ZoneHandle(function.raw())); | 852 __ PushObject(Function::ZoneHandle(function.raw())); |
806 // We do not use GenerateCallRuntime because of the non-standard (empty) | 853 // We do not use GenerateCallRuntime because of the non-standard (empty) |
807 // stackmap used here. | 854 // stackmap used here. |
808 __ CallRuntime(kTraceFunctionExitRuntimeEntry); | 855 __ CallRuntime(kTraceFunctionExitRuntimeEntry); |
809 AddCurrentDescriptor(PcDescriptors::kOther, | 856 AddCurrentDescriptor(PcDescriptors::kOther, |
810 Isolate::kNoDeoptId, | 857 Isolate::kNoDeoptId, |
811 0); // No token position. | 858 0); // No token position. |
812 if (is_optimizing()) { | 859 if (is_optimizing()) { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
899 // Although this intrinsified code will never be patched, it must satisfy | 946 // Although this intrinsified code will never be patched, it must satisfy |
900 // CodePatcher::CodeIsPatchable, which verifies that this code has a minimum | 947 // CodePatcher::CodeIsPatchable, which verifies that this code has a minimum |
901 // code size. | 948 // code size. |
902 __ int3(); | 949 __ int3(); |
903 __ jmp(&StubCode::FixCallersTargetLabel()); | 950 __ jmp(&StubCode::FixCallersTargetLabel()); |
904 return; | 951 return; |
905 } | 952 } |
906 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. | 953 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. |
907 const Function& function = parsed_function().function(); | 954 const Function& function = parsed_function().function(); |
908 | 955 |
909 const int parameter_count = function.num_fixed_parameters(); | 956 const int num_fixed_params = function.num_fixed_parameters(); |
910 const int copied_parameter_count = parsed_function().copied_parameter_count(); | 957 const int num_copied_params = parsed_function().num_copied_params(); |
911 const int local_count = parsed_function().stack_local_count(); | 958 const int num_locals = parsed_function().num_stack_locals(); |
912 __ Comment("Enter frame"); | 959 __ Comment("Enter frame"); |
913 if (IsLeaf()) { | 960 if (IsLeaf()) { |
914 AssemblerMacros::EnterDartLeafFrame(assembler(), (StackSize() * kWordSize)); | 961 AssemblerMacros::EnterDartLeafFrame(assembler(), (StackSize() * kWordSize)); |
915 } else { | 962 } else { |
916 AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize)); | 963 AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize)); |
917 } | 964 } |
918 | 965 |
919 // For optimized code, keep a bitmap of the frame in order to build | 966 // For optimized code, keep a bitmap of the frame in order to build |
920 // stackmaps for GC safepoints in the prologue. | 967 // stackmaps for GC safepoints in the prologue. |
921 LocationSummary* prologue_locs = NULL; | 968 LocationSummary* prologue_locs = NULL; |
922 if (is_optimizing()) { | 969 if (is_optimizing()) { |
923 // Spill slots are allocated but not initialized. | 970 // Spill slots are allocated but not initialized. |
924 prologue_locs = new LocationSummary(0, 0, LocationSummary::kCall); | 971 prologue_locs = new LocationSummary(0, 0, LocationSummary::kCall); |
925 prologue_locs->stack_bitmap()->SetLength(StackSize()); | 972 prologue_locs->stack_bitmap()->SetLength(StackSize()); |
926 } | 973 } |
927 | 974 |
928 // We check the number of passed arguments when we have to copy them due to | 975 // We check the number of passed arguments when we have to copy them due to |
929 // the presence of optional named parameters. | 976 // the presence of optional parameters. |
930 // No such checking code is generated if only fixed parameters are declared, | 977 // No such checking code is generated if only fixed parameters are declared, |
931 // unless we are debug mode or unless we are compiling a closure. | 978 // unless we are debug mode or unless we are compiling a closure. |
932 LocalVariable* saved_args_desc_var = | 979 LocalVariable* saved_args_desc_var = |
933 parsed_function().GetSavedArgumentsDescriptorVar(); | 980 parsed_function().GetSavedArgumentsDescriptorVar(); |
934 if (copied_parameter_count == 0) { | 981 if (num_copied_params == 0) { |
935 #ifdef DEBUG | 982 #ifdef DEBUG |
| 983 ASSERT(!parsed_function().function().HasOptionalParameters()); |
936 const bool check_arguments = true; | 984 const bool check_arguments = true; |
937 #else | 985 #else |
938 const bool check_arguments = function.IsClosureFunction(); | 986 const bool check_arguments = function.IsClosureFunction(); |
939 #endif | 987 #endif |
940 if (check_arguments) { | 988 if (check_arguments) { |
941 __ Comment("Check argument count"); | 989 __ Comment("Check argument count"); |
942 // Check that num_fixed <= argc <= num_params. | 990 // Check that num_fixed <= argc <= num_params. |
943 Label argc_in_range; | 991 Label argc_in_range; |
944 // Total number of args is the first Smi in args descriptor array (EDX). | 992 // Total number of args is the first Smi in args descriptor array (EDX). |
945 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 993 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
946 __ cmpl(EAX, Immediate(Smi::RawValue(parameter_count))); | 994 __ cmpl(EAX, Immediate(Smi::RawValue(num_fixed_params))); |
947 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); | 995 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); |
948 if (function.IsClosureFunction()) { | 996 if (function.IsClosureFunction()) { |
949 GenerateCallRuntime(function.token_pos(), | 997 GenerateCallRuntime(function.token_pos(), |
950 kClosureArgumentMismatchRuntimeEntry, | 998 kClosureArgumentMismatchRuntimeEntry, |
951 prologue_locs); | 999 prologue_locs); |
952 } else { | 1000 } else { |
953 __ Stop("Wrong number of arguments"); | 1001 __ Stop("Wrong number of arguments"); |
954 } | 1002 } |
955 __ Bind(&argc_in_range); | 1003 __ Bind(&argc_in_range); |
956 } | 1004 } |
(...skipping 10 matching lines...) Expand all Loading... |
967 // and later to the context, once the context is allocated. | 1015 // and later to the context, once the context is allocated. |
968 ASSERT(saved_args_desc_var->is_captured() || | 1016 ASSERT(saved_args_desc_var->is_captured() || |
969 (saved_args_desc_var->index() == slot)); | 1017 (saved_args_desc_var->index() == slot)); |
970 __ movl(Address(EBP, slot * kWordSize), kArgumentsDescriptorReg); | 1018 __ movl(Address(EBP, slot * kWordSize), kArgumentsDescriptorReg); |
971 } | 1019 } |
972 CopyParameters(); | 1020 CopyParameters(); |
973 } | 1021 } |
974 | 1022 |
975 // In unoptimized code, initialize (non-argument) stack allocated slots to | 1023 // In unoptimized code, initialize (non-argument) stack allocated slots to |
976 // null. This does not cover the saved_args_desc_var slot. | 1024 // null. This does not cover the saved_args_desc_var slot. |
977 if (!is_optimizing() && (local_count > 0)) { | 1025 if (!is_optimizing() && (num_locals > 0)) { |
978 __ Comment("Initialize spill slots"); | 1026 __ Comment("Initialize spill slots"); |
979 const intptr_t slot_base = parsed_function().first_stack_local_index(); | 1027 const intptr_t slot_base = parsed_function().first_stack_local_index(); |
980 const Immediate raw_null = | 1028 const Immediate raw_null = |
981 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1029 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
982 __ movl(EAX, raw_null); | 1030 __ movl(EAX, raw_null); |
983 for (intptr_t i = 0; i < local_count; ++i) { | 1031 for (intptr_t i = 0; i < num_locals; ++i) { |
984 // Subtract index i (locals lie at lower addresses than EBP). | 1032 // Subtract index i (locals lie at lower addresses than EBP). |
985 __ movl(Address(EBP, (slot_base - i) * kWordSize), EAX); | 1033 __ movl(Address(EBP, (slot_base - i) * kWordSize), EAX); |
986 } | 1034 } |
987 } | 1035 } |
988 | 1036 |
989 if (FLAG_print_scopes) { | 1037 if (FLAG_print_scopes) { |
990 // Print the function scope (again) after generating the prologue in order | 1038 // Print the function scope (again) after generating the prologue in order |
991 // to see annotations such as allocation indices of locals. | 1039 // to see annotations such as allocation indices of locals. |
992 if (FLAG_print_ast) { | 1040 if (FLAG_print_ast) { |
993 // Second printing. | 1041 // Second printing. |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1328 __ popl(ECX); | 1376 __ popl(ECX); |
1329 __ popl(EAX); | 1377 __ popl(EAX); |
1330 } | 1378 } |
1331 | 1379 |
1332 | 1380 |
1333 #undef __ | 1381 #undef __ |
1334 | 1382 |
1335 } // namespace dart | 1383 } // namespace dart |
1336 | 1384 |
1337 #endif // defined TARGET_ARCH_IA32 | 1385 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |