Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(397)

Side by Side Diff: runtime/vm/flow_graph_compiler_ia32.cc

Issue 10910119: Implement new optional parameters syntax in the vm (issue 4290). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_compiler.cc ('k') | runtime/vm/flow_graph_compiler_x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler.cc ('k') | runtime/vm/flow_graph_compiler_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698