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

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

Issue 1419223003: Re-assign registers on ARM so PP and CODE_REG are below R7 (FP on iOS). (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 1 month 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
« no previous file with comments | « runtime/vm/disassembler_arm.cc ('k') | runtime/vm/instructions_arm.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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
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 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl); 400 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl);
401 return false; 401 return false;
402 } 402 }
403 // Otherwise fallthrough. 403 // Otherwise fallthrough.
404 return true; 404 return true;
405 } 405 }
406 406
407 407
408 // Uses SubtypeTestCache to store instance class and result. 408 // Uses SubtypeTestCache to store instance class and result.
409 // R0: instance to test. 409 // R0: instance to test.
410 // Clobbers R1-R5. 410 // Clobbers R1-R4,R9.
411 // Immediate class test already done. 411 // Immediate class test already done.
412 // TODO(srdjan): Implement a quicker subtype check, as type test 412 // TODO(srdjan): Implement a quicker subtype check, as type test
413 // arrays can grow too high, but they may be useful when optimizing 413 // arrays can grow too high, but they may be useful when optimizing
414 // code (type-feedback). 414 // code (type-feedback).
415 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( 415 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup(
416 intptr_t token_pos, 416 intptr_t token_pos,
417 const Class& type_class, 417 const Class& type_class,
418 Label* is_instance_lbl, 418 Label* is_instance_lbl,
419 Label* is_not_instance_lbl) { 419 Label* is_not_instance_lbl) {
420 __ Comment("Subtype1TestCacheLookup"); 420 __ Comment("Subtype1TestCacheLookup");
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 const int num_params = 749 const int num_params =
750 num_fixed_params + num_opt_pos_params + num_opt_named_params; 750 num_fixed_params + num_opt_pos_params + num_opt_named_params;
751 ASSERT(function.NumParameters() == num_params); 751 ASSERT(function.NumParameters() == num_params);
752 ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotFromFp); 752 ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotFromFp);
753 753
754 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args, 754 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args,
755 // where num_pos_args is the number of positional arguments passed in. 755 // where num_pos_args is the number of positional arguments passed in.
756 const int min_num_pos_args = num_fixed_params; 756 const int min_num_pos_args = num_fixed_params;
757 const int max_num_pos_args = num_fixed_params + num_opt_pos_params; 757 const int max_num_pos_args = num_fixed_params + num_opt_pos_params;
758 758
759 __ ldr(R10, FieldAddress(R4, ArgumentsDescriptor::positional_count_offset())); 759 __ ldr(R6, FieldAddress(R4, ArgumentsDescriptor::positional_count_offset()));
760 // Check that min_num_pos_args <= num_pos_args. 760 // Check that min_num_pos_args <= num_pos_args.
761 Label wrong_num_arguments; 761 Label wrong_num_arguments;
762 __ CompareImmediate(R10, Smi::RawValue(min_num_pos_args)); 762 __ CompareImmediate(R6, Smi::RawValue(min_num_pos_args));
763 __ b(&wrong_num_arguments, LT); 763 __ b(&wrong_num_arguments, LT);
764 // Check that num_pos_args <= max_num_pos_args. 764 // Check that num_pos_args <= max_num_pos_args.
765 __ CompareImmediate(R10, Smi::RawValue(max_num_pos_args)); 765 __ CompareImmediate(R6, Smi::RawValue(max_num_pos_args));
766 __ b(&wrong_num_arguments, GT); 766 __ b(&wrong_num_arguments, GT);
767 767
768 // Copy positional arguments. 768 // Copy positional arguments.
769 // Argument i passed at fp[kParamEndSlotFromFp + num_args - i] is copied 769 // Argument i passed at fp[kParamEndSlotFromFp + num_args - i] is copied
770 // to fp[kFirstLocalSlotFromFp - i]. 770 // to fp[kFirstLocalSlotFromFp - i].
771 771
772 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset())); 772 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
773 // Since R7 and R10 are Smi, use LSL 1 instead of LSL 2. 773 // Since R7 and R6 are Smi, use LSL 1 instead of LSL 2.
774 // Let R7 point to the last passed positional argument, i.e. to 774 // Let R7 point to the last passed positional argument, i.e. to
775 // fp[kParamEndSlotFromFp + num_args - (num_pos_args - 1)]. 775 // fp[kParamEndSlotFromFp + num_args - (num_pos_args - 1)].
776 __ sub(R7, R7, Operand(R10)); 776 __ sub(R7, R7, Operand(R6));
777 __ add(R7, FP, Operand(R7, LSL, 1)); 777 __ add(R7, FP, Operand(R7, LSL, 1));
778 __ add(R7, R7, Operand((kParamEndSlotFromFp + 1) * kWordSize)); 778 __ add(R7, R7, Operand((kParamEndSlotFromFp + 1) * kWordSize));
779 779
780 // Let R6 point to the last copied positional argument, i.e. to 780 // Let R8 point to the last copied positional argument, i.e. to
781 // fp[kFirstLocalSlotFromFp - (num_pos_args - 1)]. 781 // fp[kFirstLocalSlotFromFp - (num_pos_args - 1)].
782 __ AddImmediate(R6, FP, (kFirstLocalSlotFromFp + 1) * kWordSize); 782 __ AddImmediate(R8, FP, (kFirstLocalSlotFromFp + 1) * kWordSize);
783 __ sub(R6, R6, Operand(R10, LSL, 1)); // R10 is a Smi. 783 __ sub(R8, R8, Operand(R6, LSL, 1)); // R6 is a Smi.
784 __ SmiUntag(R10); 784 __ SmiUntag(R6);
785 Label loop, loop_condition; 785 Label loop, loop_condition;
786 __ b(&loop_condition); 786 __ b(&loop_condition);
787 // We do not use the final allocation index of the variable here, i.e. 787 // We do not use the final allocation index of the variable here, i.e.
788 // scope->VariableAt(i)->index(), because captured variables still need 788 // scope->VariableAt(i)->index(), because captured variables still need
789 // to be copied to the context that is not yet allocated. 789 // to be copied to the context that is not yet allocated.
790 const Address argument_addr(R7, R10, LSL, 2); 790 const Address argument_addr(R7, R6, LSL, 2);
791 const Address copy_addr(R6, R10, LSL, 2); 791 const Address copy_addr(R8, R6, LSL, 2);
792 __ Bind(&loop); 792 __ Bind(&loop);
793 __ ldr(IP, argument_addr); 793 __ ldr(IP, argument_addr);
794 __ str(IP, copy_addr); 794 __ str(IP, copy_addr);
795 __ Bind(&loop_condition); 795 __ Bind(&loop_condition);
796 __ subs(R10, R10, Operand(1)); 796 __ subs(R6, R6, Operand(1));
797 __ b(&loop, PL); 797 __ b(&loop, PL);
798 798
799 // Copy or initialize optional named arguments. 799 // Copy or initialize optional named arguments.
800 Label all_arguments_processed; 800 Label all_arguments_processed;
801 #ifdef DEBUG 801 #ifdef DEBUG
802 const bool check_correct_named_args = true; 802 const bool check_correct_named_args = true;
803 #else 803 #else
804 const bool check_correct_named_args = function.IsClosureFunction(); 804 const bool check_correct_named_args = function.IsClosureFunction();
805 #endif 805 #endif
806 if (num_opt_named_params > 0) { 806 if (num_opt_named_params > 0) {
(...skipping 10 matching lines...) Expand all
817 ASSERT(result != 0); 817 ASSERT(result != 0);
818 if (result > 0) break; 818 if (result > 0) break;
819 opt_param[i + 1] = opt_param[i]; 819 opt_param[i + 1] = opt_param[i];
820 opt_param_position[i + 1] = opt_param_position[i]; 820 opt_param_position[i + 1] = opt_param_position[i];
821 } 821 }
822 opt_param[i + 1] = parameter; 822 opt_param[i + 1] = parameter;
823 opt_param_position[i + 1] = pos; 823 opt_param_position[i + 1] = pos;
824 } 824 }
825 // Generate code handling each optional parameter in alphabetical order. 825 // Generate code handling each optional parameter in alphabetical order.
826 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset())); 826 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
827 __ ldr(R10, 827 __ ldr(R6,
828 FieldAddress(R4, ArgumentsDescriptor::positional_count_offset())); 828 FieldAddress(R4, ArgumentsDescriptor::positional_count_offset()));
829 __ SmiUntag(R10); 829 __ SmiUntag(R6);
830 // Let R7 point to the first passed argument, i.e. to 830 // Let R7 point to the first passed argument, i.e. to
831 // fp[kParamEndSlotFromFp + num_args - 0]; num_args (R7) is Smi. 831 // fp[kParamEndSlotFromFp + num_args - 0]; num_args (R7) is Smi.
832 __ add(R7, FP, Operand(R7, LSL, 1)); 832 __ add(R7, FP, Operand(R7, LSL, 1));
833 __ AddImmediate(R7, R7, kParamEndSlotFromFp * kWordSize); 833 __ AddImmediate(R7, R7, kParamEndSlotFromFp * kWordSize);
834 // Let R6 point to the entry of the first named argument. 834 // Let R8 point to the entry of the first named argument.
835 __ add(R6, R4, Operand( 835 __ add(R8, R4, Operand(
836 ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag)); 836 ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag));
837 for (int i = 0; i < num_opt_named_params; i++) { 837 for (int i = 0; i < num_opt_named_params; i++) {
838 Label load_default_value, assign_optional_parameter; 838 Label load_default_value, assign_optional_parameter;
839 const int param_pos = opt_param_position[i]; 839 const int param_pos = opt_param_position[i];
840 // Check if this named parameter was passed in. 840 // Check if this named parameter was passed in.
841 // Load R5 with the name of the argument. 841 // Load R9 with the name of the argument.
842 __ ldr(R5, Address(R6, ArgumentsDescriptor::name_offset())); 842 __ ldr(R9, Address(R8, ArgumentsDescriptor::name_offset()));
843 ASSERT(opt_param[i]->name().IsSymbol()); 843 ASSERT(opt_param[i]->name().IsSymbol());
844 __ CompareObject(R5, opt_param[i]->name()); 844 __ CompareObject(R9, opt_param[i]->name());
845 __ b(&load_default_value, NE); 845 __ b(&load_default_value, NE);
846 // Load R5 with passed-in argument at provided arg_pos, i.e. at 846 // Load R9 with passed-in argument at provided arg_pos, i.e. at
847 // fp[kParamEndSlotFromFp + num_args - arg_pos]. 847 // fp[kParamEndSlotFromFp + num_args - arg_pos].
848 __ ldr(R5, Address(R6, ArgumentsDescriptor::position_offset())); 848 __ ldr(R9, Address(R8, ArgumentsDescriptor::position_offset()));
849 // R5 is arg_pos as Smi. 849 // R9 is arg_pos as Smi.
850 // Point to next named entry. 850 // Point to next named entry.
851 __ add(R6, R6, Operand(ArgumentsDescriptor::named_entry_size())); 851 __ add(R8, R8, Operand(ArgumentsDescriptor::named_entry_size()));
852 __ rsb(R5, R5, Operand(0)); 852 __ rsb(R9, R9, Operand(0));
853 Address argument_addr(R7, R5, LSL, 1); // R5 is a negative Smi. 853 Address argument_addr(R7, R9, LSL, 1); // R9 is a negative Smi.
854 __ ldr(R5, argument_addr); 854 __ ldr(R9, argument_addr);
855 __ b(&assign_optional_parameter); 855 __ b(&assign_optional_parameter);
856 __ Bind(&load_default_value); 856 __ Bind(&load_default_value);
857 // Load R5 with default argument. 857 // Load R9 with default argument.
858 const Instance& value = parsed_function().DefaultParameterValueAt( 858 const Instance& value = parsed_function().DefaultParameterValueAt(
859 param_pos - num_fixed_params); 859 param_pos - num_fixed_params);
860 __ LoadObject(R5, value); 860 __ LoadObject(R9, value);
861 __ Bind(&assign_optional_parameter); 861 __ Bind(&assign_optional_parameter);
862 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos]. 862 // Assign R9 to fp[kFirstLocalSlotFromFp - param_pos].
863 // We do not use the final allocation index of the variable here, i.e. 863 // We do not use the final allocation index of the variable here, i.e.
864 // scope->VariableAt(i)->index(), because captured variables still need 864 // scope->VariableAt(i)->index(), because captured variables still need
865 // to be copied to the context that is not yet allocated. 865 // to be copied to the context that is not yet allocated.
866 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; 866 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos;
867 const Address param_addr(FP, computed_param_pos * kWordSize); 867 const Address param_addr(FP, computed_param_pos * kWordSize);
868 __ str(R5, param_addr); 868 __ str(R9, param_addr);
869 } 869 }
870 delete[] opt_param; 870 delete[] opt_param;
871 delete[] opt_param_position; 871 delete[] opt_param_position;
872 if (check_correct_named_args) { 872 if (check_correct_named_args) {
873 // Check that R6 now points to the null terminator in the arguments 873 // Check that R8 now points to the null terminator in the arguments
874 // descriptor. 874 // descriptor.
875 __ ldr(R5, Address(R6, 0)); 875 __ ldr(R9, Address(R8, 0));
876 __ CompareObject(R5, Object::null_object()); 876 __ CompareObject(R9, Object::null_object());
877 __ b(&all_arguments_processed, EQ); 877 __ b(&all_arguments_processed, EQ);
878 } 878 }
879 } else { 879 } else {
880 ASSERT(num_opt_pos_params > 0); 880 ASSERT(num_opt_pos_params > 0);
881 __ ldr(R10, 881 __ ldr(R6,
882 FieldAddress(R4, ArgumentsDescriptor::positional_count_offset())); 882 FieldAddress(R4, ArgumentsDescriptor::positional_count_offset()));
883 __ SmiUntag(R10); 883 __ SmiUntag(R6);
884 for (int i = 0; i < num_opt_pos_params; i++) { 884 for (int i = 0; i < num_opt_pos_params; i++) {
885 Label next_parameter; 885 Label next_parameter;
886 // Handle this optional positional parameter only if k or fewer positional 886 // Handle this optional positional parameter only if k or fewer positional
887 // arguments have been passed, where k is param_pos, the position of this 887 // arguments have been passed, where k is param_pos, the position of this
888 // optional parameter in the formal parameter list. 888 // optional parameter in the formal parameter list.
889 const int param_pos = num_fixed_params + i; 889 const int param_pos = num_fixed_params + i;
890 __ CompareImmediate(R10, param_pos); 890 __ CompareImmediate(R6, param_pos);
891 __ b(&next_parameter, GT); 891 __ b(&next_parameter, GT);
892 // Load R5 with default argument. 892 // Load R9 with default argument.
893 const Object& value = parsed_function().DefaultParameterValueAt(i); 893 const Object& value = parsed_function().DefaultParameterValueAt(i);
894 __ LoadObject(R5, value); 894 __ LoadObject(R9, value);
895 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos]. 895 // Assign R9 to fp[kFirstLocalSlotFromFp - param_pos].
896 // We do not use the final allocation index of the variable here, i.e. 896 // We do not use the final allocation index of the variable here, i.e.
897 // scope->VariableAt(i)->index(), because captured variables still need 897 // scope->VariableAt(i)->index(), because captured variables still need
898 // to be copied to the context that is not yet allocated. 898 // to be copied to the context that is not yet allocated.
899 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; 899 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos;
900 const Address param_addr(FP, computed_param_pos * kWordSize); 900 const Address param_addr(FP, computed_param_pos * kWordSize);
901 __ str(R5, param_addr); 901 __ str(R9, param_addr);
902 __ Bind(&next_parameter); 902 __ Bind(&next_parameter);
903 } 903 }
904 if (check_correct_named_args) { 904 if (check_correct_named_args) {
905 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset())); 905 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
906 __ SmiUntag(R7); 906 __ SmiUntag(R7);
907 // Check that R10 equals R7, i.e. no named arguments passed. 907 // Check that R6 equals R7, i.e. no named arguments passed.
908 __ cmp(R10, Operand(R7)); 908 __ cmp(R6, Operand(R7));
909 __ b(&all_arguments_processed, EQ); 909 __ b(&all_arguments_processed, EQ);
910 } 910 }
911 } 911 }
912 912
913 __ Bind(&wrong_num_arguments); 913 __ Bind(&wrong_num_arguments);
914 if (function.IsClosureFunction()) { 914 if (function.IsClosureFunction()) {
915 __ LeaveDartFrame(kKeepCalleePP); // The arguments are still on the stack. 915 __ LeaveDartFrame(kKeepCalleePP); // The arguments are still on the stack.
916 __ Branch(*StubCode::CallClosureNoSuchMethod_entry()); 916 __ Branch(*StubCode::CallClosureNoSuchMethod_entry());
917 // The noSuchMethod call may return to the caller, but not here. 917 // The noSuchMethod call may return to the caller, but not here.
918 } else if (check_correct_named_args) { 918 } else if (check_correct_named_args) {
919 __ Stop("Wrong arguments"); 919 __ Stop("Wrong arguments");
920 } 920 }
921 921
922 __ Bind(&all_arguments_processed); 922 __ Bind(&all_arguments_processed);
923 // Nullify originally passed arguments only after they have been copied and 923 // Nullify originally passed arguments only after they have been copied and
924 // checked, otherwise noSuchMethod would not see their original values. 924 // checked, otherwise noSuchMethod would not see their original values.
925 // This step can be skipped in case we decide that formal parameters are 925 // This step can be skipped in case we decide that formal parameters are
926 // implicitly final, since garbage collecting the unmodified value is not 926 // implicitly final, since garbage collecting the unmodified value is not
927 // an issue anymore. 927 // an issue anymore.
928 928
929 // R4 : arguments descriptor array. 929 // R4 : arguments descriptor array.
930 __ ldr(R10, FieldAddress(R4, ArgumentsDescriptor::count_offset())); 930 __ ldr(R6, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
931 __ SmiUntag(R10); 931 __ SmiUntag(R6);
932 __ add(R7, FP, Operand((kParamEndSlotFromFp + 1) * kWordSize)); 932 __ add(R7, FP, Operand((kParamEndSlotFromFp + 1) * kWordSize));
933 const Address original_argument_addr(R7, R10, LSL, 2); 933 const Address original_argument_addr(R7, R6, LSL, 2);
934 __ LoadObject(IP, Object::null_object()); 934 __ LoadObject(IP, Object::null_object());
935 Label null_args_loop, null_args_loop_condition; 935 Label null_args_loop, null_args_loop_condition;
936 __ b(&null_args_loop_condition); 936 __ b(&null_args_loop_condition);
937 __ Bind(&null_args_loop); 937 __ Bind(&null_args_loop);
938 __ str(IP, original_argument_addr); 938 __ str(IP, original_argument_addr);
939 __ Bind(&null_args_loop_condition); 939 __ Bind(&null_args_loop_condition);
940 __ subs(R10, R10, Operand(1)); 940 __ subs(R6, R6, Operand(1));
941 __ b(&null_args_loop, PL); 941 __ b(&null_args_loop, PL);
942 } 942 }
943 943
944 944
945 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { 945 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) {
946 // LR: return address. 946 // LR: return address.
947 // SP: receiver. 947 // SP: receiver.
948 // Sequence node has one return node, its input is load field node. 948 // Sequence node has one return node, its input is load field node.
949 __ Comment("Inlined Getter"); 949 __ Comment("Inlined Getter");
950 __ ldr(R0, Address(SP, 0 * kWordSize)); 950 __ ldr(R0, Address(SP, 0 * kWordSize));
(...skipping 17 matching lines...) Expand all
968 968
969 969
970 static const Register new_pp = R7; 970 static const Register new_pp = R7;
971 971
972 972
973 void FlowGraphCompiler::EmitFrameEntry() { 973 void FlowGraphCompiler::EmitFrameEntry() {
974 const Function& function = parsed_function().function(); 974 const Function& function = parsed_function().function();
975 if (CanOptimizeFunction() && 975 if (CanOptimizeFunction() &&
976 function.IsOptimizable() && 976 function.IsOptimizable() &&
977 (!is_optimizing() || may_reoptimize())) { 977 (!is_optimizing() || may_reoptimize())) {
978 const Register function_reg = R6; 978 const Register function_reg = R8;
979 979
980 // The pool pointer is not setup before entering the Dart frame. 980 // The pool pointer is not setup before entering the Dart frame.
981 // Temporarily setup pool pointer for this dart function. 981 // Temporarily setup pool pointer for this dart function.
982 __ LoadPoolPointer(new_pp); 982 __ LoadPoolPointer(new_pp);
983 // Load function object from object pool. 983 // Load function object from object pool.
984 __ LoadFunctionFromCalleePool(function_reg, function, new_pp); 984 __ LoadFunctionFromCalleePool(function_reg, function, new_pp);
985 985
986 __ ldr(R3, FieldAddress(function_reg, 986 __ ldr(R3, FieldAddress(function_reg,
987 Function::usage_counter_offset())); 987 Function::usage_counter_offset()));
988 // Reoptimization of an optimized function is triggered by counting in 988 // Reoptimization of an optimized function is triggered by counting in
989 // IC stubs, but not at the entry of the function. 989 // IC stubs, but not at the entry of the function.
990 if (!is_optimizing()) { 990 if (!is_optimizing()) {
991 __ add(R3, R3, Operand(1)); 991 __ add(R3, R3, Operand(1));
992 __ str(R3, FieldAddress(function_reg, 992 __ str(R3, FieldAddress(function_reg,
993 Function::usage_counter_offset())); 993 Function::usage_counter_offset()));
994 } 994 }
995 __ CompareImmediate(R3, GetOptimizationThreshold()); 995 __ CompareImmediate(R3, GetOptimizationThreshold());
996 ASSERT(function_reg == R6); 996 ASSERT(function_reg == R8);
997 __ Branch(*StubCode::OptimizeFunction_entry(), kNotPatchable, new_pp, GE); 997 __ Branch(*StubCode::OptimizeFunction_entry(), kNotPatchable, new_pp, GE);
998 } 998 }
999 __ Comment("Enter frame"); 999 __ Comment("Enter frame");
1000 if (flow_graph().IsCompiledForOsr()) { 1000 if (flow_graph().IsCompiledForOsr()) {
1001 intptr_t extra_slots = StackSize() 1001 intptr_t extra_slots = StackSize()
1002 - flow_graph().num_stack_locals() 1002 - flow_graph().num_stack_locals()
1003 - flow_graph().num_copied_params(); 1003 - flow_graph().num_copied_params();
1004 ASSERT(extra_slots >= 0); 1004 ASSERT(extra_slots >= 0);
1005 __ EnterOsrFrame(extra_slots * kWordSize); 1005 __ EnterOsrFrame(extra_slots * kWordSize);
1006 } else { 1006 } else {
1007 ASSERT(StackSize() >= 0); 1007 ASSERT(StackSize() >= 0);
1008 __ EnterDartFrame(StackSize() * kWordSize); 1008 __ EnterDartFrame(StackSize() * kWordSize);
1009 } 1009 }
1010 } 1010 }
1011 1011
1012 1012
1013 // Input parameters: 1013 // Input parameters:
1014 // LR: return address. 1014 // LR: return address.
1015 // SP: address of last argument. 1015 // SP: address of last argument.
1016 // FP: caller's frame pointer. 1016 // FP: caller's frame pointer.
1017 // PP: caller's pool pointer. 1017 // PP: caller's pool pointer.
1018 // R5: ic-data. 1018 // R9: ic-data.
1019 // R4: arguments descriptor array. 1019 // R4: arguments descriptor array.
1020 void FlowGraphCompiler::CompileGraph() { 1020 void FlowGraphCompiler::CompileGraph() {
1021 InitCompiler(); 1021 InitCompiler();
1022 1022
1023 if (TryIntrinsify()) { 1023 if (TryIntrinsify()) {
1024 // Skip regular code generation. 1024 // Skip regular code generation.
1025 return; 1025 return;
1026 } 1026 }
1027 1027
1028 EmitFrameEntry(); 1028 EmitFrameEntry();
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
1218 intptr_t token_pos, 1218 intptr_t token_pos,
1219 LocationSummary* locs) { 1219 LocationSummary* locs) {
1220 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0); 1220 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
1221 // Each ICData propagated from unoptimized to optimized code contains the 1221 // Each ICData propagated from unoptimized to optimized code contains the
1222 // function that corresponds to the Dart function of that IC call. Due 1222 // function that corresponds to the Dart function of that IC call. Due
1223 // to inlining in optimized code, that function may not correspond to the 1223 // to inlining in optimized code, that function may not correspond to the
1224 // top-level function (parsed_function().function()) which could be 1224 // top-level function (parsed_function().function()) which could be
1225 // reoptimized and which counter needs to be incremented. 1225 // reoptimized and which counter needs to be incremented.
1226 // Pass the function explicitly, it is used in IC stub. 1226 // Pass the function explicitly, it is used in IC stub.
1227 1227
1228 __ LoadObject(R6, parsed_function().function()); 1228 __ LoadObject(R8, parsed_function().function());
1229 __ LoadUniqueObject(R5, ic_data); 1229 __ LoadUniqueObject(R9, ic_data);
1230 GenerateDartCall(deopt_id, 1230 GenerateDartCall(deopt_id,
1231 token_pos, 1231 token_pos,
1232 stub_entry, 1232 stub_entry,
1233 RawPcDescriptors::kIcCall, 1233 RawPcDescriptors::kIcCall,
1234 locs); 1234 locs);
1235 __ Drop(argument_count); 1235 __ Drop(argument_count);
1236 } 1236 }
1237 1237
1238 1238
1239 void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry, 1239 void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry,
1240 const ICData& ic_data, 1240 const ICData& ic_data,
1241 intptr_t argument_count, 1241 intptr_t argument_count,
1242 intptr_t deopt_id, 1242 intptr_t deopt_id,
1243 intptr_t token_pos, 1243 intptr_t token_pos,
1244 LocationSummary* locs) { 1244 LocationSummary* locs) {
1245 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0); 1245 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
1246 __ LoadUniqueObject(R5, ic_data); 1246 __ LoadUniqueObject(R9, ic_data);
1247 GenerateDartCall(deopt_id, 1247 GenerateDartCall(deopt_id,
1248 token_pos, 1248 token_pos,
1249 stub_entry, 1249 stub_entry,
1250 RawPcDescriptors::kIcCall, 1250 RawPcDescriptors::kIcCall,
1251 locs); 1251 locs);
1252 __ Drop(argument_count); 1252 __ Drop(argument_count);
1253 } 1253 }
1254 1254
1255 1255
1256 void FlowGraphCompiler::EmitMegamorphicInstanceCall( 1256 void FlowGraphCompiler::EmitMegamorphicInstanceCall(
(...skipping 12 matching lines...) Expand all
1269 const Register cacheR = R1; 1269 const Register cacheR = R1;
1270 const Register targetR = R1; 1270 const Register targetR = R1;
1271 __ LoadFromOffset(kWord, receiverR, SP, (argument_count - 1) * kWordSize); 1271 __ LoadFromOffset(kWord, receiverR, SP, (argument_count - 1) * kWordSize);
1272 __ LoadObject(cacheR, cache); 1272 __ LoadObject(cacheR, cache);
1273 1273
1274 if (FLAG_use_megamorphic_stub) { 1274 if (FLAG_use_megamorphic_stub) {
1275 __ BranchLink(*StubCode::MegamorphicLookup_entry()); 1275 __ BranchLink(*StubCode::MegamorphicLookup_entry());
1276 } else { 1276 } else {
1277 StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR); 1277 StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR);
1278 } 1278 }
1279 __ LoadObject(R5, ic_data); 1279 __ LoadObject(R9, ic_data);
1280 __ LoadObject(R4, arguments_descriptor); 1280 __ LoadObject(R4, arguments_descriptor);
1281 __ blx(targetR); 1281 __ blx(targetR);
1282 AddCurrentDescriptor(RawPcDescriptors::kOther, Thread::kNoDeoptId, token_pos); 1282 AddCurrentDescriptor(RawPcDescriptors::kOther, Thread::kNoDeoptId, token_pos);
1283 RecordSafepoint(locs); 1283 RecordSafepoint(locs);
1284 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id); 1284 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
1285 if (is_optimizing()) { 1285 if (is_optimizing()) {
1286 AddDeoptIndexAtCall(deopt_id_after, token_pos); 1286 AddDeoptIndexAtCall(deopt_id_after, token_pos);
1287 } else { 1287 } else {
1288 // Add deoptimization continuation point after the call and before the 1288 // Add deoptimization continuation point after the call and before the
1289 // arguments are removed. 1289 // arguments are removed.
1290 AddCurrentDescriptor(RawPcDescriptors::kDeopt, 1290 AddCurrentDescriptor(RawPcDescriptors::kDeopt,
1291 deopt_id_after, token_pos); 1291 deopt_id_after, token_pos);
1292 } 1292 }
1293 __ Drop(argument_count); 1293 __ Drop(argument_count);
1294 } 1294 }
1295 1295
1296 1296
1297 void FlowGraphCompiler::EmitUnoptimizedStaticCall( 1297 void FlowGraphCompiler::EmitUnoptimizedStaticCall(
1298 intptr_t argument_count, 1298 intptr_t argument_count,
1299 intptr_t deopt_id, 1299 intptr_t deopt_id,
1300 intptr_t token_pos, 1300 intptr_t token_pos,
1301 LocationSummary* locs, 1301 LocationSummary* locs,
1302 const ICData& ic_data) { 1302 const ICData& ic_data) {
1303 const StubEntry* stub_entry = 1303 const StubEntry* stub_entry =
1304 StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested()); 1304 StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
1305 __ LoadObject(R5, ic_data); 1305 __ LoadObject(R9, ic_data);
1306 GenerateDartCall(deopt_id, 1306 GenerateDartCall(deopt_id,
1307 token_pos, 1307 token_pos,
1308 *stub_entry, 1308 *stub_entry,
1309 RawPcDescriptors::kUnoptStaticCall, 1309 RawPcDescriptors::kUnoptStaticCall,
1310 locs); 1310 locs);
1311 __ Drop(argument_count); 1311 __ Drop(argument_count);
1312 } 1312 }
1313 1313
1314 1314
1315 void FlowGraphCompiler::EmitOptimizedStaticCall( 1315 void FlowGraphCompiler::EmitOptimizedStaticCall(
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after
1873 DRegister dreg = EvenDRegisterOf(reg); 1873 DRegister dreg = EvenDRegisterOf(reg);
1874 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); 1874 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex));
1875 } 1875 }
1876 1876
1877 1877
1878 #undef __ 1878 #undef __
1879 1879
1880 } // namespace dart 1880 } // namespace dart
1881 1881
1882 #endif // defined TARGET_ARCH_ARM 1882 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/disassembler_arm.cc ('k') | runtime/vm/instructions_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698