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

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

Issue 9693020: Optional arguments in new compiler. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 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_x64.h ('k') | no next file » | 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_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 "vm/ast_printer.h" 10 #include "vm/ast_printer.h"
(...skipping 29 matching lines...) Expand all
40 FlowGraphCompiler::~FlowGraphCompiler() { 40 FlowGraphCompiler::~FlowGraphCompiler() {
41 // BlockInfos are zone-allocated, so their destructors are not called. 41 // BlockInfos are zone-allocated, so their destructors are not called.
42 // Verify the labels explicitly here. 42 // Verify the labels explicitly here.
43 for (int i = 0; i < block_info_.length(); ++i) { 43 for (int i = 0; i < block_info_.length(); ++i) {
44 ASSERT(!block_info_[i]->label.IsLinked()); 44 ASSERT(!block_info_[i]->label.IsLinked());
45 ASSERT(!block_info_[i]->label.HasNear()); 45 ASSERT(!block_info_[i]->label.HasNear());
46 } 46 }
47 } 47 }
48 48
49 49
50 intptr_t FlowGraphCompiler::StackSize() const {
51 return parsed_function_.stack_local_count() +
52 parsed_function_.copied_parameter_count();
53 }
54
55
50 void FlowGraphCompiler::Bailout(const char* reason) { 56 void FlowGraphCompiler::Bailout(const char* reason) {
51 const char* kFormat = "FlowGraphCompiler Bailout: %s %s."; 57 const char* kFormat = "FlowGraphCompiler Bailout: %s %s.";
52 const char* function_name = parsed_function_.function().ToCString(); 58 const char* function_name = parsed_function_.function().ToCString();
53 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 59 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
54 char* chars = reinterpret_cast<char*>( 60 char* chars = reinterpret_cast<char*>(
55 Isolate::Current()->current_zone()->Allocate(len)); 61 Isolate::Current()->current_zone()->Allocate(len));
56 OS::SNPrint(chars, len, kFormat, function_name, reason); 62 OS::SNPrint(chars, len, kFormat, function_name, reason);
57 const Error& error = Error::Handle( 63 const Error& error = Error::Handle(
58 LanguageError::New(String::Handle(String::New(chars)))); 64 LanguageError::New(String::Handle(String::New(chars))));
59 Isolate::Current()->long_jump_base()->Jump(1, error); 65 Isolate::Current()->long_jump_base()->Jump(1, error);
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 } 656 }
651 657
652 658
653 void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) { 659 void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) {
654 LoadValue(RAX, instr->value()); 660 LoadValue(RAX, instr->value());
655 661
656 #ifdef DEBUG 662 #ifdef DEBUG
657 // Check that the entry stack size matches the exit stack size. 663 // Check that the entry stack size matches the exit stack size.
658 __ movq(R10, RBP); 664 __ movq(R10, RBP);
659 __ subq(R10, RSP); 665 __ subq(R10, RSP);
660 __ cmpq(R10, Immediate(parsed_function_.stack_local_count() * kWordSize)); 666 __ cmpq(R10, Immediate(StackSize() * kWordSize));
661 Label stack_ok; 667 Label stack_ok;
662 __ j(EQUAL, &stack_ok, Assembler::kNearJump); 668 __ j(EQUAL, &stack_ok, Assembler::kNearJump);
663 __ Stop("Exit stack size does not match the entry stack size."); 669 __ Stop("Exit stack size does not match the entry stack size.");
664 __ Bind(&stack_ok); 670 __ Bind(&stack_ok);
665 #endif // DEBUG. 671 #endif // DEBUG.
666 672
667 if (FLAG_trace_functions) { 673 if (FLAG_trace_functions) {
668 __ pushq(RAX); // Preserve result. 674 __ pushq(RAX); // Preserve result.
669 const Function& function = 675 const Function& function =
670 Function::ZoneHandle(parsed_function_.function().raw()); 676 Function::ZoneHandle(parsed_function_.function().raw());
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
709 __ cmpq(RAX, RDX); 715 __ cmpq(RAX, RDX);
710 if (negated) { 716 if (negated) {
711 __ j(EQUAL, &block_info_[instr->true_successor()->block_number()]->label); 717 __ j(EQUAL, &block_info_[instr->true_successor()->block_number()]->label);
712 } else { 718 } else {
713 __ j(NOT_EQUAL, 719 __ j(NOT_EQUAL,
714 &block_info_[instr->false_successor()->block_number()]->label); 720 &block_info_[instr->false_successor()->block_number()]->label);
715 } 721 }
716 } 722 }
717 723
718 724
725 // Coped from CodeGenerator::CopyParameters (CodeGenerator will be deprecated).
726 void FlowGraphCompiler::CopyParameters() {
727 const Function& function = parsed_function_.function();
728 LocalScope* scope = parsed_function_.node_sequence()->scope();
729 const int num_fixed_params = function.num_fixed_parameters();
730 const int num_opt_params = function.num_optional_parameters();
731 ASSERT(parsed_function_.first_parameter_index() == -1);
732 // Copy positional arguments.
733 // Check that no fewer than num_fixed_params positional arguments are passed
734 // in and that no more than num_params arguments are passed in.
735 // Passed argument i at fp[1 + argc - i] copied to fp[-1 - i].
736 const int num_params = num_fixed_params + num_opt_params;
737
738 // Total number of args is the first Smi in args descriptor array (R10).
739 __ movq(RBX, FieldAddress(R10, Array::data_offset()));
740 // Check that num_args <= num_params.
741 Label wrong_num_arguments;
742 __ cmpq(RBX, Immediate(Smi::RawValue(num_params)));
743 __ j(GREATER, &wrong_num_arguments);
744 // Number of positional args is the second Smi in descriptor array (R10).
745 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize)));
746 // Check that num_pos_args >= num_fixed_params.
747 __ cmpq(RCX, Immediate(Smi::RawValue(num_fixed_params)));
748 __ j(LESS, &wrong_num_arguments);
749 // Since RBX and RCX are Smi, use TIMES_4 instead of TIMES_8.
750 // Let RBX point to the last passed positional argument, i.e. to
751 // fp[1 + num_args - (num_pos_args - 1)].
752 __ subq(RBX, RCX);
753 __ leaq(RBX, Address(RBP, RBX, TIMES_4, 2 * kWordSize));
754 // Let RDI point to the last copied positional argument, i.e. to
755 // fp[-1 - (num_pos_args - 1)].
756 __ SmiUntag(RCX);
757 __ movq(RAX, RCX);
758 __ negq(RAX);
759 __ leaq(RDI, Address(RBP, RAX, TIMES_8, 0));
760 Label loop, loop_condition;
761 __ jmp(&loop_condition, Assembler::kNearJump);
762 // We do not use the final allocation index of the variable here, i.e.
763 // scope->VariableAt(i)->index(), because captured variables still need
764 // to be copied to the context that is not yet allocated.
765 const Address argument_addr(RBX, RCX, TIMES_8, 0);
766 const Address copy_addr(RDI, RCX, TIMES_8, 0);
767 __ Bind(&loop);
768 __ movq(RAX, argument_addr);
769 __ movq(copy_addr, RAX);
770 __ Bind(&loop_condition);
771 __ decq(RCX);
772 __ j(POSITIVE, &loop, Assembler::kNearJump);
773
774 // Copy or initialize optional named arguments.
775 ASSERT(num_opt_params > 0); // Or we would not have to copy arguments.
776 // Start by alphabetically sorting the names of the optional parameters.
777 LocalVariable** opt_param = new LocalVariable*[num_opt_params];
778 int* opt_param_position = new int[num_opt_params];
779 for (int pos = num_fixed_params; pos < num_params; pos++) {
780 LocalVariable* parameter = scope->VariableAt(pos);
781 const String& opt_param_name = parameter->name();
782 int i = pos - num_fixed_params;
783 while (--i >= 0) {
784 LocalVariable* param_i = opt_param[i];
785 const intptr_t result = opt_param_name.CompareTo(param_i->name());
786 ASSERT(result != 0);
787 if (result > 0) break;
788 opt_param[i + 1] = opt_param[i];
789 opt_param_position[i + 1] = opt_param_position[i];
790 }
791 opt_param[i + 1] = parameter;
792 opt_param_position[i + 1] = pos;
793 }
794 // Generate code handling each optional parameter in alphabetical order.
795 // Total number of args is the first Smi in args descriptor array (R10).
796 __ movq(RBX, FieldAddress(R10, Array::data_offset()));
797 // Number of positional args is the second Smi in descriptor array (R10).
798 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize)));
799 __ SmiUntag(RCX);
800 // Let RBX point to the first passed argument, i.e. to fp[1 + argc - 0].
801 __ leaq(RBX, Address(RBP, RBX, TIMES_4, kWordSize)); // RBX is Smi.
802 // Let EDI point to the name/pos pair of the first named argument.
803 __ leaq(RDI, FieldAddress(R10, Array::data_offset() + (2 * kWordSize)));
804 for (int i = 0; i < num_opt_params; i++) {
805 // Handle this optional parameter only if k or fewer positional arguments
806 // have been passed, where k is the position of this optional parameter in
807 // the formal parameter list.
808 Label load_default_value, assign_optional_parameter, next_parameter;
809 const int param_pos = opt_param_position[i];
810 __ cmpq(RCX, Immediate(param_pos));
811 __ j(GREATER, &next_parameter, Assembler::kNearJump);
812 // Check if this named parameter was passed in.
813 __ movq(RAX, Address(RDI, 0)); // Load RAX with the name of the argument.
814 __ CompareObject(RAX, opt_param[i]->name());
815 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
816 // Load RAX with passed-in argument at provided arg_pos, i.e. at
817 // fp[1 + argc - arg_pos].
818 __ movq(RAX, Address(RDI, kWordSize)); // RAX is arg_pos as Smi.
819 __ addq(RDI, Immediate(2 * kWordSize)); // Point to next name/pos pair.
820 __ negq(RAX);
821 Address argument_addr(RBX, RAX, TIMES_4, 0); // RAX is a negative Smi.
822 __ movq(RAX, argument_addr);
823 __ jmp(&assign_optional_parameter, Assembler::kNearJump);
824 __ Bind(&load_default_value);
825 // Load RAX with default argument at pos.
826 const Object& value = Object::ZoneHandle(
827 parsed_function_.default_parameter_values().At(
828 param_pos - num_fixed_params));
829 __ LoadObject(RAX, value);
830 __ Bind(&assign_optional_parameter);
831 // Assign RAX to fp[-1 - param_pos].
832 // We do not use the final allocation index of the variable here, i.e.
833 // scope->VariableAt(i)->index(), because captured variables still need
834 // to be copied to the context that is not yet allocated.
835 const Address param_addr(RBP, (-1 - param_pos) * kWordSize);
836 __ movq(param_addr, RAX);
837 __ Bind(&next_parameter);
838 }
839 delete[] opt_param;
840 delete[] opt_param_position;
841 // Check that RDI now points to the null terminator in the array descriptor.
842 const Immediate raw_null =
843 Immediate(reinterpret_cast<intptr_t>(Object::null()));
844 Label all_arguments_processed;
845 __ cmpq(Address(RDI, 0), raw_null);
846 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
847
848 __ Bind(&wrong_num_arguments);
849 if (function.IsClosureFunction()) {
850 GenerateCallRuntime(AstNode::kNoId,
851 0,
852 kClosureArgumentMismatchRuntimeEntry);
853 } else {
854 // Invoke noSuchMethod function.
855 const int kNumArgsChecked = 1;
856 ICData& ic_data = ICData::ZoneHandle();
857 ic_data = ICData::New(parsed_function_.function(),
858 String::Handle(function.name()),
859 AstNode::kNoId,
860 kNumArgsChecked);
861 __ LoadObject(RBX, ic_data);
862 // RBP : points to previous frame pointer.
863 // RBP + 8 : points to return address.
864 // RBP + 16 : address of last argument (arg n-1).
865 // RSP + 16 + 8*(n-1) : address of first argument (arg 0).
866 // RBX : ic-data.
867 // R10 : arguments descriptor array.
868 __ call(&StubCode::CallNoSuchMethodFunctionLabel());
869 }
870
871 if (FLAG_trace_functions) {
872 __ pushq(RAX); // Preserve result.
873 __ PushObject(Function::ZoneHandle(function.raw()));
874 GenerateCallRuntime(AstNode::kNoId,
875 0,
876 kTraceFunctionExitRuntimeEntry);
877 __ popq(RAX); // Remove argument.
878 __ popq(RAX); // Restore result.
879 }
880 __ LeaveFrame();
881 __ ret();
882
883 __ Bind(&all_arguments_processed);
884 // Nullify originally passed arguments only after they have been copied and
885 // checked, otherwise noSuchMethod would not see their original values.
886 // This step can be skipped in case we decide that formal parameters are
887 // implicitly final, since garbage collecting the unmodified value is not
888 // an issue anymore.
889
890 // R10 : arguments descriptor array.
891 // Total number of args is the first Smi in args descriptor array (R10).
892 __ movq(RCX, FieldAddress(R10, Array::data_offset()));
893 __ SmiUntag(RCX);
894 Label null_args_loop, null_args_loop_condition;
895 __ jmp(&null_args_loop_condition, Assembler::kNearJump);
896 const Address original_argument_addr(RBP, RCX, TIMES_8, 2 * kWordSize);
897 __ Bind(&null_args_loop);
898 __ movq(original_argument_addr, raw_null);
899 __ Bind(&null_args_loop_condition);
900 __ decq(RCX);
901 __ j(POSITIVE, &null_args_loop, Assembler::kNearJump);
902 }
903
904
905 // TODO(srdjan): Investigate where to put the argument type checks for
906 // checked mode.
719 void FlowGraphCompiler::CompileGraph() { 907 void FlowGraphCompiler::CompileGraph() {
720 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. 908 // Specialized version of entry code from CodeGenerator::GenerateEntryCode.
721 const Function& function = parsed_function_.function(); 909 const Function& function = parsed_function_.function();
722 910
723 // We don't implement copied parameters yet and should have bailed out
724 // from the graph builder.
725 ASSERT(function.num_optional_parameters() == 0);
726 const int parameter_count = function.num_fixed_parameters(); 911 const int parameter_count = function.num_fixed_parameters();
912 const int num_opt_params = function.num_optional_parameters();
913 const int num_copied_params = parsed_function_.copied_parameter_count();
727 const int local_count = parsed_function_.stack_local_count(); 914 const int local_count = parsed_function_.stack_local_count();
728 __ EnterFrame(local_count * kWordSize); 915 __ EnterFrame(StackSize() * kWordSize);
916
917 // We check the number of passed arguments when we have to copy them due to
918 // the presence of optional named parameters.
919 // No such checking code is generated if only fixed parameters are declared,
920 // unless we are debug mode or unless we are compiling a closure.
921 if (num_copied_params == 0) {
729 #ifdef DEBUG 922 #ifdef DEBUG
730 const bool check_arguments = true; 923 const bool check_arguments = true;
731 #else 924 #else
732 const bool check_arguments = function.IsClosureFunction(); 925 const bool check_arguments = function.IsClosureFunction();
733 #endif 926 #endif
734 if (check_arguments) { 927 if (check_arguments) {
735 // Check that num_fixed <= argc <= num_params. 928 // Check that num_fixed <= argc <= num_params.
736 Label argc_in_range; 929 Label argc_in_range;
737 // Total number of args is the first Smi in args descriptor array (R10). 930 // Total number of args is the first Smi in args descriptor array (R10).
738 __ movq(RAX, FieldAddress(R10, Array::data_offset())); 931 __ movq(RAX, FieldAddress(R10, Array::data_offset()));
739 __ cmpq(RAX, Immediate(Smi::RawValue(parameter_count))); 932 __ cmpq(RAX, Immediate(Smi::RawValue(parameter_count)));
740 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); 933 __ j(EQUAL, &argc_in_range, Assembler::kNearJump);
741 if (function.IsClosureFunction()) { 934 if (function.IsClosureFunction()) {
742 GenerateCallRuntime(AstNode::kNoId, 935 GenerateCallRuntime(AstNode::kNoId,
743 function.token_index(), 936 function.token_index(),
744 kClosureArgumentMismatchRuntimeEntry); 937 kClosureArgumentMismatchRuntimeEntry);
745 } else { 938 } else {
746 __ Stop("Wrong number of arguments"); 939 __ Stop("Wrong number of arguments");
940 }
941 __ Bind(&argc_in_range);
747 } 942 }
748 __ Bind(&argc_in_range); 943 } else {
944 CopyParameters();
749 } 945 }
750 946
751 // Initialize locals to null. 947 // Initialize locals to null.
752 if (local_count > 0) { 948 if (local_count > 0) {
753 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(Object::null()))); 949 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(Object::null())));
754 const int base = parsed_function_.first_stack_local_index(); 950 const int base = parsed_function_.first_stack_local_index();
755 for (int i = 0; i < local_count; ++i) { 951 for (int i = 0; i < local_count; ++i) {
756 // Subtract index i (locals lie at lower addresses than RBP). 952 // Subtract index i (locals lie at lower addresses than RBP).
757 __ movq(Address(RBP, (base - i) * kWordSize), RAX); 953 __ movq(Address(RBP, (base - i) * kWordSize), RAX);
758 } 954 }
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { 1036 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) {
841 // We don't compile exception handlers yet. 1037 // We don't compile exception handlers yet.
842 code.set_exception_handlers( 1038 code.set_exception_handlers(
843 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); 1039 ExceptionHandlers::Handle(ExceptionHandlers::New(0)));
844 } 1040 }
845 1041
846 1042
847 } // namespace dart 1043 } // namespace dart
848 1044
849 #endif // defined TARGET_ARCH_X64 1045 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698