| 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 |