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

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

Issue 1343373003: Revert "VM: New calling convention for generated code." (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 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
« no previous file with comments | « runtime/vm/flow_graph_compiler.cc ('k') | runtime/vm/flow_graph_compiler_arm64.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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 93
94 // Emit all kMaterializeObject instructions describing objects to be 94 // Emit all kMaterializeObject instructions describing objects to be
95 // materialized on the deoptimization as a prefix to the deoptimization info. 95 // materialized on the deoptimization as a prefix to the deoptimization info.
96 EmitMaterializations(deopt_env_, builder); 96 EmitMaterializations(deopt_env_, builder);
97 97
98 // The real frame starts here. 98 // The real frame starts here.
99 builder->MarkFrameStart(); 99 builder->MarkFrameStart();
100 100
101 Zone* zone = compiler->zone(); 101 Zone* zone = compiler->zone();
102 102
103 // Current PP, FP, and PC.
103 builder->AddPp(current->function(), slot_ix++); 104 builder->AddPp(current->function(), slot_ix++);
104 builder->AddPcMarker(Function::Handle(zone), slot_ix++);
105 builder->AddCallerFp(slot_ix++); 105 builder->AddCallerFp(slot_ix++);
106 builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++); 106 builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++);
107 107
108 // Callee's PC marker is not used anymore. Pass Function::null() to set to 0.
109 builder->AddPcMarker(Function::Handle(zone), slot_ix++);
110
108 // Emit all values that are needed for materialization as a part of the 111 // Emit all values that are needed for materialization as a part of the
109 // expression stack for the bottom-most frame. This guarantees that GC 112 // expression stack for the bottom-most frame. This guarantees that GC
110 // will be able to find them during materialization. 113 // will be able to find them during materialization.
111 slot_ix = builder->EmitMaterializationArguments(slot_ix); 114 slot_ix = builder->EmitMaterializationArguments(slot_ix);
112 115
113 // For the innermost environment, set outgoing arguments and the locals. 116 // For the innermost environment, set outgoing arguments and the locals.
114 for (intptr_t i = current->Length() - 1; 117 for (intptr_t i = current->Length() - 1;
115 i >= current->fixed_parameter_count(); 118 i >= current->fixed_parameter_count();
116 i--) { 119 i--) {
117 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++); 120 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++);
118 } 121 }
119 122
120 Environment* previous = current; 123 Environment* previous = current;
121 current = current->outer(); 124 current = current->outer();
122 while (current != NULL) { 125 while (current != NULL) {
126 // PP, FP, and PC.
123 builder->AddPp(current->function(), slot_ix++); 127 builder->AddPp(current->function(), slot_ix++);
124 builder->AddPcMarker(previous->function(), slot_ix++);
125 builder->AddCallerFp(slot_ix++); 128 builder->AddCallerFp(slot_ix++);
126 129
127 // For any outer environment the deopt id is that of the call instruction 130 // For any outer environment the deopt id is that of the call instruction
128 // which is recorded in the outer environment. 131 // which is recorded in the outer environment.
129 builder->AddReturnAddress( 132 builder->AddReturnAddress(
130 current->function(), 133 current->function(),
131 Isolate::ToDeoptAfter(current->deopt_id()), 134 Isolate::ToDeoptAfter(current->deopt_id()),
132 slot_ix++); 135 slot_ix++);
133 136
137 // PC marker.
138 builder->AddPcMarker(previous->function(), slot_ix++);
139
134 // The values of outgoing arguments can be changed from the inlined call so 140 // The values of outgoing arguments can be changed from the inlined call so
135 // we must read them from the previous environment. 141 // we must read them from the previous environment.
136 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { 142 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
137 builder->AddCopy(previous->ValueAt(i), 143 builder->AddCopy(previous->ValueAt(i),
138 previous->LocationAt(i), 144 previous->LocationAt(i),
139 slot_ix++); 145 slot_ix++);
140 } 146 }
141 147
142 // Set the locals, note that outgoing arguments are not in the environment. 148 // Set the locals, note that outgoing arguments are not in the environment.
143 for (intptr_t i = current->Length() - 1; 149 for (intptr_t i = current->Length() - 1;
144 i >= current->fixed_parameter_count(); 150 i >= current->fixed_parameter_count();
145 i--) { 151 i--) {
146 builder->AddCopy(current->ValueAt(i), 152 builder->AddCopy(current->ValueAt(i),
147 current->LocationAt(i), 153 current->LocationAt(i),
148 slot_ix++); 154 slot_ix++);
149 } 155 }
150 156
151 // Iterate on the outer environment. 157 // Iterate on the outer environment.
152 previous = current; 158 previous = current;
153 current = current->outer(); 159 current = current->outer();
154 } 160 }
155 // The previous pointer is now the outermost environment. 161 // The previous pointer is now the outermost environment.
156 ASSERT(previous != NULL); 162 ASSERT(previous != NULL);
157 163
158 // Set slots for the outermost environment. 164 // For the outermost environment, set caller PC, caller PP, and caller FP.
159 builder->AddCallerPp(slot_ix++); 165 builder->AddCallerPp(slot_ix++);
160 builder->AddPcMarker(previous->function(), slot_ix++);
161 builder->AddCallerFp(slot_ix++); 166 builder->AddCallerFp(slot_ix++);
162 builder->AddCallerPc(slot_ix++); 167 builder->AddCallerPc(slot_ix++);
163 168
169 // PC marker.
170 builder->AddPcMarker(previous->function(), slot_ix++);
171
164 // For the outermost environment, set the incoming arguments. 172 // For the outermost environment, set the incoming arguments.
165 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { 173 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
166 builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++); 174 builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
167 } 175 }
168 176
169 return builder->CreateDeoptInfo(deopt_table); 177 return builder->CreateDeoptInfo(deopt_table);
170 } 178 }
171 179
172 180
173 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, 181 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
174 intptr_t stub_ix) { 182 intptr_t stub_ix) {
175 // Calls do not need stubs, they share a deoptimization trampoline. 183 // Calls do not need stubs, they share a deoptimization trampoline.
176 ASSERT(reason() != ICData::kDeoptAtCall); 184 ASSERT(reason() != ICData::kDeoptAtCall);
177 Assembler* assem = compiler->assembler(); 185 Assembler* assem = compiler->assembler();
178 #define __ assem-> 186 #define __ assem->
179 __ Comment("%s", Name()); 187 __ Comment("%s", Name());
180 __ Bind(entry_label()); 188 __ Bind(entry_label());
181 if (FLAG_trap_on_deoptimization) { 189 if (FLAG_trap_on_deoptimization) {
182 __ bkpt(0); 190 __ bkpt(0);
183 } 191 }
184 192
185 ASSERT(deopt_env() != NULL); 193 ASSERT(deopt_env() != NULL);
186 194
187 // LR may be live. It will be clobbered by BranchLink, so cache it in IP. 195 // LR may be live. It will be clobbered by BranchLink, so cache it in IP.
188 // It will be restored at the top of the deoptimization stub, specifically in 196 // It will be restored at the top of the deoptimization stub, specifically in
189 // GenerateDeoptimizationSequence in stub_code_arm.cc. 197 // GenerateDeoptimizationSequence in stub_code_arm.cc.
190 __ Push(CODE_REG);
191 __ mov(IP, Operand(LR)); 198 __ mov(IP, Operand(LR));
192 __ BranchLink(*StubCode::Deoptimize_entry()); 199 __ BranchLink(*StubCode::Deoptimize_entry());
193 set_pc_offset(assem->CodeSize()); 200 set_pc_offset(assem->CodeSize());
194 #undef __ 201 #undef __
195 } 202 }
196 203
197 204
198 #define __ assembler()-> 205 #define __ assembler()->
199 206
200 207
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 const int num_params = 752 const int num_params =
746 num_fixed_params + num_opt_pos_params + num_opt_named_params; 753 num_fixed_params + num_opt_pos_params + num_opt_named_params;
747 ASSERT(function.NumParameters() == num_params); 754 ASSERT(function.NumParameters() == num_params);
748 ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotFromFp); 755 ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotFromFp);
749 756
750 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args, 757 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args,
751 // where num_pos_args is the number of positional arguments passed in. 758 // where num_pos_args is the number of positional arguments passed in.
752 const int min_num_pos_args = num_fixed_params; 759 const int min_num_pos_args = num_fixed_params;
753 const int max_num_pos_args = num_fixed_params + num_opt_pos_params; 760 const int max_num_pos_args = num_fixed_params + num_opt_pos_params;
754 761
755 __ ldr(R10, FieldAddress(R4, ArgumentsDescriptor::positional_count_offset())); 762 __ ldr(R9, FieldAddress(R4, ArgumentsDescriptor::positional_count_offset()));
756 // Check that min_num_pos_args <= num_pos_args. 763 // Check that min_num_pos_args <= num_pos_args.
757 Label wrong_num_arguments; 764 Label wrong_num_arguments;
758 __ CompareImmediate(R10, Smi::RawValue(min_num_pos_args)); 765 __ CompareImmediate(R9, Smi::RawValue(min_num_pos_args));
759 __ b(&wrong_num_arguments, LT); 766 __ b(&wrong_num_arguments, LT);
760 // Check that num_pos_args <= max_num_pos_args. 767 // Check that num_pos_args <= max_num_pos_args.
761 __ CompareImmediate(R10, Smi::RawValue(max_num_pos_args)); 768 __ CompareImmediate(R9, Smi::RawValue(max_num_pos_args));
762 __ b(&wrong_num_arguments, GT); 769 __ b(&wrong_num_arguments, GT);
763 770
764 // Copy positional arguments. 771 // Copy positional arguments.
765 // Argument i passed at fp[kParamEndSlotFromFp + num_args - i] is copied 772 // Argument i passed at fp[kParamEndSlotFromFp + num_args - i] is copied
766 // to fp[kFirstLocalSlotFromFp - i]. 773 // to fp[kFirstLocalSlotFromFp - i].
767 774
768 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset())); 775 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
769 // Since R7 and R10 are Smi, use LSL 1 instead of LSL 2. 776 // Since R7 and R9 are Smi, use LSL 1 instead of LSL 2.
770 // Let R7 point to the last passed positional argument, i.e. to 777 // Let R7 point to the last passed positional argument, i.e. to
771 // fp[kParamEndSlotFromFp + num_args - (num_pos_args - 1)]. 778 // fp[kParamEndSlotFromFp + num_args - (num_pos_args - 1)].
772 __ sub(R7, R7, Operand(R10)); 779 __ sub(R7, R7, Operand(R9));
773 __ add(R7, FP, Operand(R7, LSL, 1)); 780 __ add(R7, FP, Operand(R7, LSL, 1));
774 __ add(R7, R7, Operand((kParamEndSlotFromFp + 1) * kWordSize)); 781 __ add(R7, R7, Operand((kParamEndSlotFromFp + 1) * kWordSize));
775 782
776 // Let R6 point to the last copied positional argument, i.e. to 783 // Let R6 point to the last copied positional argument, i.e. to
777 // fp[kFirstLocalSlotFromFp - (num_pos_args - 1)]. 784 // fp[kFirstLocalSlotFromFp - (num_pos_args - 1)].
778 __ AddImmediate(R6, FP, (kFirstLocalSlotFromFp + 1) * kWordSize); 785 __ AddImmediate(R6, FP, (kFirstLocalSlotFromFp + 1) * kWordSize);
779 __ sub(R6, R6, Operand(R10, LSL, 1)); // R10 is a Smi. 786 __ sub(R6, R6, Operand(R9, LSL, 1)); // R9 is a Smi.
780 __ SmiUntag(R10); 787 __ SmiUntag(R9);
781 Label loop, loop_condition; 788 Label loop, loop_condition;
782 __ b(&loop_condition); 789 __ b(&loop_condition);
783 // We do not use the final allocation index of the variable here, i.e. 790 // We do not use the final allocation index of the variable here, i.e.
784 // scope->VariableAt(i)->index(), because captured variables still need 791 // scope->VariableAt(i)->index(), because captured variables still need
785 // to be copied to the context that is not yet allocated. 792 // to be copied to the context that is not yet allocated.
786 const Address argument_addr(R7, R10, LSL, 2); 793 const Address argument_addr(R7, R9, LSL, 2);
787 const Address copy_addr(R6, R10, LSL, 2); 794 const Address copy_addr(R6, R9, LSL, 2);
788 __ Bind(&loop); 795 __ Bind(&loop);
789 __ ldr(IP, argument_addr); 796 __ ldr(IP, argument_addr);
790 __ str(IP, copy_addr); 797 __ str(IP, copy_addr);
791 __ Bind(&loop_condition); 798 __ Bind(&loop_condition);
792 __ subs(R10, R10, Operand(1)); 799 __ subs(R9, R9, Operand(1));
793 __ b(&loop, PL); 800 __ b(&loop, PL);
794 801
795 // Copy or initialize optional named arguments. 802 // Copy or initialize optional named arguments.
796 Label all_arguments_processed; 803 Label all_arguments_processed;
797 #ifdef DEBUG 804 #ifdef DEBUG
798 const bool check_correct_named_args = true; 805 const bool check_correct_named_args = true;
799 #else 806 #else
800 const bool check_correct_named_args = function.IsClosureFunction(); 807 const bool check_correct_named_args = function.IsClosureFunction();
801 #endif 808 #endif
802 if (num_opt_named_params > 0) { 809 if (num_opt_named_params > 0) {
(...skipping 10 matching lines...) Expand all
813 ASSERT(result != 0); 820 ASSERT(result != 0);
814 if (result > 0) break; 821 if (result > 0) break;
815 opt_param[i + 1] = opt_param[i]; 822 opt_param[i + 1] = opt_param[i];
816 opt_param_position[i + 1] = opt_param_position[i]; 823 opt_param_position[i + 1] = opt_param_position[i];
817 } 824 }
818 opt_param[i + 1] = parameter; 825 opt_param[i + 1] = parameter;
819 opt_param_position[i + 1] = pos; 826 opt_param_position[i + 1] = pos;
820 } 827 }
821 // Generate code handling each optional parameter in alphabetical order. 828 // Generate code handling each optional parameter in alphabetical order.
822 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset())); 829 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
823 __ ldr(R10, 830 __ ldr(R9,
824 FieldAddress(R4, ArgumentsDescriptor::positional_count_offset())); 831 FieldAddress(R4, ArgumentsDescriptor::positional_count_offset()));
825 __ SmiUntag(R10); 832 __ SmiUntag(R9);
826 // Let R7 point to the first passed argument, i.e. to 833 // Let R7 point to the first passed argument, i.e. to
827 // fp[kParamEndSlotFromFp + num_args - 0]; num_args (R7) is Smi. 834 // fp[kParamEndSlotFromFp + num_args - 0]; num_args (R7) is Smi.
828 __ add(R7, FP, Operand(R7, LSL, 1)); 835 __ add(R7, FP, Operand(R7, LSL, 1));
829 __ AddImmediate(R7, R7, kParamEndSlotFromFp * kWordSize); 836 __ AddImmediate(R7, R7, kParamEndSlotFromFp * kWordSize);
830 // Let R6 point to the entry of the first named argument. 837 // Let R6 point to the entry of the first named argument.
831 __ add(R6, R4, Operand( 838 __ add(R6, R4, Operand(
832 ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag)); 839 ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag));
833 for (int i = 0; i < num_opt_named_params; i++) { 840 for (int i = 0; i < num_opt_named_params; i++) {
834 Label load_default_value, assign_optional_parameter; 841 Label load_default_value, assign_optional_parameter;
835 const int param_pos = opt_param_position[i]; 842 const int param_pos = opt_param_position[i];
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
867 delete[] opt_param_position; 874 delete[] opt_param_position;
868 if (check_correct_named_args) { 875 if (check_correct_named_args) {
869 // Check that R6 now points to the null terminator in the arguments 876 // Check that R6 now points to the null terminator in the arguments
870 // descriptor. 877 // descriptor.
871 __ ldr(R5, Address(R6, 0)); 878 __ ldr(R5, Address(R6, 0));
872 __ CompareObject(R5, Object::null_object()); 879 __ CompareObject(R5, Object::null_object());
873 __ b(&all_arguments_processed, EQ); 880 __ b(&all_arguments_processed, EQ);
874 } 881 }
875 } else { 882 } else {
876 ASSERT(num_opt_pos_params > 0); 883 ASSERT(num_opt_pos_params > 0);
877 __ ldr(R10, 884 __ ldr(R9,
878 FieldAddress(R4, ArgumentsDescriptor::positional_count_offset())); 885 FieldAddress(R4, ArgumentsDescriptor::positional_count_offset()));
879 __ SmiUntag(R10); 886 __ SmiUntag(R9);
880 for (int i = 0; i < num_opt_pos_params; i++) { 887 for (int i = 0; i < num_opt_pos_params; i++) {
881 Label next_parameter; 888 Label next_parameter;
882 // Handle this optional positional parameter only if k or fewer positional 889 // Handle this optional positional parameter only if k or fewer positional
883 // arguments have been passed, where k is param_pos, the position of this 890 // arguments have been passed, where k is param_pos, the position of this
884 // optional parameter in the formal parameter list. 891 // optional parameter in the formal parameter list.
885 const int param_pos = num_fixed_params + i; 892 const int param_pos = num_fixed_params + i;
886 __ CompareImmediate(R10, param_pos); 893 __ CompareImmediate(R9, param_pos);
887 __ b(&next_parameter, GT); 894 __ b(&next_parameter, GT);
888 // Load R5 with default argument. 895 // Load R5 with default argument.
889 const Object& value = parsed_function().DefaultParameterValueAt(i); 896 const Object& value = parsed_function().DefaultParameterValueAt(i);
890 __ LoadObject(R5, value); 897 __ LoadObject(R5, value);
891 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos]. 898 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos].
892 // We do not use the final allocation index of the variable here, i.e. 899 // We do not use the final allocation index of the variable here, i.e.
893 // scope->VariableAt(i)->index(), because captured variables still need 900 // scope->VariableAt(i)->index(), because captured variables still need
894 // to be copied to the context that is not yet allocated. 901 // to be copied to the context that is not yet allocated.
895 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; 902 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos;
896 const Address param_addr(FP, computed_param_pos * kWordSize); 903 const Address param_addr(FP, computed_param_pos * kWordSize);
897 __ str(R5, param_addr); 904 __ str(R5, param_addr);
898 __ Bind(&next_parameter); 905 __ Bind(&next_parameter);
899 } 906 }
900 if (check_correct_named_args) { 907 if (check_correct_named_args) {
901 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset())); 908 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
902 __ SmiUntag(R7); 909 __ SmiUntag(R7);
903 // Check that R10 equals R7, i.e. no named arguments passed. 910 // Check that R9 equals R7, i.e. no named arguments passed.
904 __ cmp(R10, Operand(R7)); 911 __ cmp(R9, Operand(R7));
905 __ b(&all_arguments_processed, EQ); 912 __ b(&all_arguments_processed, EQ);
906 } 913 }
907 } 914 }
908 915
909 __ Bind(&wrong_num_arguments); 916 __ Bind(&wrong_num_arguments);
910 if (function.IsClosureFunction()) { 917 if (function.IsClosureFunction()) {
911 __ LeaveDartFrame(kKeepCalleePP); // The arguments are still on the stack. 918 ASSERT(assembler()->constant_pool_allowed());
919 __ LeaveDartFrame(); // The arguments are still on the stack.
920 // Do not use caller's pool ptr in branch.
921 ASSERT(!assembler()->constant_pool_allowed());
912 __ Branch(*StubCode::CallClosureNoSuchMethod_entry()); 922 __ Branch(*StubCode::CallClosureNoSuchMethod_entry());
923 __ set_constant_pool_allowed(true);
913 // The noSuchMethod call may return to the caller, but not here. 924 // The noSuchMethod call may return to the caller, but not here.
914 } else if (check_correct_named_args) { 925 } else if (check_correct_named_args) {
915 __ Stop("Wrong arguments"); 926 __ Stop("Wrong arguments");
916 } 927 }
917 928
918 __ Bind(&all_arguments_processed); 929 __ Bind(&all_arguments_processed);
919 // Nullify originally passed arguments only after they have been copied and 930 // Nullify originally passed arguments only after they have been copied and
920 // checked, otherwise noSuchMethod would not see their original values. 931 // checked, otherwise noSuchMethod would not see their original values.
921 // This step can be skipped in case we decide that formal parameters are 932 // This step can be skipped in case we decide that formal parameters are
922 // implicitly final, since garbage collecting the unmodified value is not 933 // implicitly final, since garbage collecting the unmodified value is not
923 // an issue anymore. 934 // an issue anymore.
924 935
925 // R4 : arguments descriptor array. 936 // R4 : arguments descriptor array.
926 __ ldr(R10, FieldAddress(R4, ArgumentsDescriptor::count_offset())); 937 __ ldr(R9, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
927 __ SmiUntag(R10); 938 __ SmiUntag(R9);
928 __ add(R7, FP, Operand((kParamEndSlotFromFp + 1) * kWordSize)); 939 __ add(R7, FP, Operand((kParamEndSlotFromFp + 1) * kWordSize));
929 const Address original_argument_addr(R7, R10, LSL, 2); 940 const Address original_argument_addr(R7, R9, LSL, 2);
930 __ LoadObject(IP, Object::null_object()); 941 __ LoadObject(IP, Object::null_object());
931 Label null_args_loop, null_args_loop_condition; 942 Label null_args_loop, null_args_loop_condition;
932 __ b(&null_args_loop_condition); 943 __ b(&null_args_loop_condition);
933 __ Bind(&null_args_loop); 944 __ Bind(&null_args_loop);
934 __ str(IP, original_argument_addr); 945 __ str(IP, original_argument_addr);
935 __ Bind(&null_args_loop_condition); 946 __ Bind(&null_args_loop_condition);
936 __ subs(R10, R10, Operand(1)); 947 __ subs(R9, R9, Operand(1));
937 __ b(&null_args_loop, PL); 948 __ b(&null_args_loop, PL);
938 } 949 }
939 950
940 951
941 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { 952 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) {
942 // LR: return address. 953 // LR: return address.
943 // SP: receiver. 954 // SP: receiver.
944 // Sequence node has one return node, its input is load field node. 955 // Sequence node has one return node, its input is load field node.
945 __ Comment("Inlined Getter"); 956 __ Comment("Inlined Getter");
946 __ ldr(R0, Address(SP, 0 * kWordSize)); 957 __ ldr(R0, Address(SP, 0 * kWordSize));
947 __ LoadFromOffset(kWord, R0, R0, offset - kHeapObjectTag); 958 __ LoadFromOffset(kWord, R0, R0, offset - kHeapObjectTag);
948 __ Ret(); 959 __ Ret();
949 } 960 }
950 961
951 962
952 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) { 963 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) {
953 // LR: return address. 964 // LR: return address.
954 // SP+1: receiver. 965 // SP+1: receiver.
955 // SP+0: value. 966 // SP+0: value.
956 // Sequence node has one store node and one return NULL node. 967 // Sequence node has one store node and one return NULL node.
957 __ Comment("Inlined Setter"); 968 __ Comment("Inlined Setter");
958 __ ldr(R0, Address(SP, 1 * kWordSize)); // Receiver. 969 __ ldr(R0, Address(SP, 1 * kWordSize)); // Receiver.
959 __ ldr(R1, Address(SP, 0 * kWordSize)); // Value. 970 __ ldr(R1, Address(SP, 0 * kWordSize)); // Value.
960 __ StoreIntoObjectOffset(R0, offset, R1); 971 __ StoreIntoObjectOffset(R0, offset, R1);
961 __ LoadObject(R0, Object::null_object()); 972 __ LoadObject(R0, Object::null_object());
962 __ Ret(); 973 __ Ret();
963 } 974 }
964 975
965 976
966 static const Register new_pp = R7;
967
968
969 void FlowGraphCompiler::EmitFrameEntry() { 977 void FlowGraphCompiler::EmitFrameEntry() {
970 const Function& function = parsed_function().function(); 978 const Function& function = parsed_function().function();
971 if (CanOptimizeFunction() && 979 if (CanOptimizeFunction() &&
972 function.IsOptimizable() && 980 function.IsOptimizable() &&
973 (!is_optimizing() || may_reoptimize())) { 981 (!is_optimizing() || may_reoptimize())) {
974 const Register function_reg = R6; 982 const Register function_reg = R6;
975 983
976 // The pool pointer is not setup before entering the Dart frame. 984 // The pool pointer is not setup before entering the Dart frame.
985 // Preserve PP of caller.
986 __ mov(R7, Operand(PP));
977 // Temporarily setup pool pointer for this dart function. 987 // Temporarily setup pool pointer for this dart function.
978 __ LoadPoolPointer(new_pp); 988 __ LoadPoolPointer();
979 // Load function object from object pool. 989 // Load function object from object pool.
980 __ LoadFunctionFromCalleePool(function_reg, function, new_pp); 990 __ LoadObject(function_reg, function); // Uses PP.
991 // Restore PP of caller.
992 __ mov(PP, Operand(R7));
993 __ set_constant_pool_allowed(false);
981 994
982 __ ldr(R3, FieldAddress(function_reg, 995 // Patch point is after the eventually inlined function object.
996 entry_patch_pc_offset_ = assembler()->CodeSize();
997
998 __ ldr(R7, FieldAddress(function_reg,
983 Function::usage_counter_offset())); 999 Function::usage_counter_offset()));
984 // Reoptimization of an optimized function is triggered by counting in 1000 // Reoptimization of an optimized function is triggered by counting in
985 // IC stubs, but not at the entry of the function. 1001 // IC stubs, but not at the entry of the function.
986 if (!is_optimizing()) { 1002 if (!is_optimizing()) {
987 __ add(R3, R3, Operand(1)); 1003 __ add(R7, R7, Operand(1));
988 __ str(R3, FieldAddress(function_reg, 1004 __ str(R7, FieldAddress(function_reg,
989 Function::usage_counter_offset())); 1005 Function::usage_counter_offset()));
990 } 1006 }
991 __ CompareImmediate(R3, GetOptimizationThreshold()); 1007 __ CompareImmediate(R7, GetOptimizationThreshold());
992 ASSERT(function_reg == R6); 1008 ASSERT(function_reg == R6);
993 __ Branch(*StubCode::OptimizeFunction_entry(), kNotPatchable, new_pp, GE); 1009 __ Branch(*StubCode::OptimizeFunction_entry(), GE);
1010 } else if (!flow_graph().IsCompiledForOsr()) {
1011 entry_patch_pc_offset_ = assembler()->CodeSize();
994 } 1012 }
995 __ Comment("Enter frame"); 1013 __ Comment("Enter frame");
996 if (flow_graph().IsCompiledForOsr()) { 1014 if (flow_graph().IsCompiledForOsr()) {
997 intptr_t extra_slots = StackSize() 1015 intptr_t extra_slots = StackSize()
998 - flow_graph().num_stack_locals() 1016 - flow_graph().num_stack_locals()
999 - flow_graph().num_copied_params(); 1017 - flow_graph().num_copied_params();
1000 ASSERT(extra_slots >= 0); 1018 ASSERT(extra_slots >= 0);
1001 __ EnterOsrFrame(extra_slots * kWordSize); 1019 __ EnterOsrFrame(extra_slots * kWordSize);
1002 } else { 1020 } else {
1003 ASSERT(StackSize() >= 0); 1021 ASSERT(StackSize() >= 0);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1046 __ ldr(R0, FieldAddress(R4, ArgumentsDescriptor::count_offset())); 1064 __ ldr(R0, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
1047 __ CompareImmediate(R0, Smi::RawValue(num_fixed_params)); 1065 __ CompareImmediate(R0, Smi::RawValue(num_fixed_params));
1048 __ b(&wrong_num_arguments, NE); 1066 __ b(&wrong_num_arguments, NE);
1049 __ ldr(R1, FieldAddress(R4, 1067 __ ldr(R1, FieldAddress(R4,
1050 ArgumentsDescriptor::positional_count_offset())); 1068 ArgumentsDescriptor::positional_count_offset()));
1051 __ cmp(R0, Operand(R1)); 1069 __ cmp(R0, Operand(R1));
1052 __ b(&correct_num_arguments, EQ); 1070 __ b(&correct_num_arguments, EQ);
1053 __ Bind(&wrong_num_arguments); 1071 __ Bind(&wrong_num_arguments);
1054 if (function.IsClosureFunction()) { 1072 if (function.IsClosureFunction()) {
1055 ASSERT(assembler()->constant_pool_allowed()); 1073 ASSERT(assembler()->constant_pool_allowed());
1056 __ LeaveDartFrame(kKeepCalleePP); // Arguments are still on the stack. 1074 __ LeaveDartFrame(); // The arguments are still on the stack.
1075 // Do not use caller's pool ptr in branch.
1076 ASSERT(!assembler()->constant_pool_allowed());
1057 __ Branch(*StubCode::CallClosureNoSuchMethod_entry()); 1077 __ Branch(*StubCode::CallClosureNoSuchMethod_entry());
1078 __ set_constant_pool_allowed(true);
1058 // The noSuchMethod call may return to the caller, but not here. 1079 // The noSuchMethod call may return to the caller, but not here.
1059 } else { 1080 } else {
1060 __ Stop("Wrong number of arguments"); 1081 __ Stop("Wrong number of arguments");
1061 } 1082 }
1062 __ Bind(&correct_num_arguments); 1083 __ Bind(&correct_num_arguments);
1063 } 1084 }
1064 } else if (!flow_graph().IsCompiledForOsr()) { 1085 } else if (!flow_graph().IsCompiledForOsr()) {
1065 CopyParameters(); 1086 CopyParameters();
1066 } 1087 }
1067 1088
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1100 __ StoreToOffset(kWord, R0, FP, (slot_base - i) * kWordSize); 1121 __ StoreToOffset(kWord, R0, FP, (slot_base - i) * kWordSize);
1101 } 1122 }
1102 } 1123 }
1103 } 1124 }
1104 1125
1105 VisitBlocks(); 1126 VisitBlocks();
1106 1127
1107 __ bkpt(0); 1128 __ bkpt(0);
1108 ASSERT(assembler()->constant_pool_allowed()); 1129 ASSERT(assembler()->constant_pool_allowed());
1109 GenerateDeferredCode(); 1130 GenerateDeferredCode();
1131 // Emit function patching code. This will be swapped with the first 3
1132 // instructions at entry point.
1133 patch_code_pc_offset_ = assembler()->CodeSize();
1134 __ BranchPatchable(*StubCode::FixCallersTarget_entry());
1110 1135
1111 if (is_optimizing()) { 1136 if (is_optimizing()) {
1112 lazy_deopt_pc_offset_ = assembler()->CodeSize(); 1137 lazy_deopt_pc_offset_ = assembler()->CodeSize();
1113 __ Branch(*StubCode::DeoptimizeLazy_entry()); 1138 __ Branch(*StubCode::DeoptimizeLazy_entry());
1114 } 1139 }
1115 } 1140 }
1116 1141
1117 1142
1118 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, 1143 void FlowGraphCompiler::GenerateCall(intptr_t token_pos,
1119 const StubEntry& stub_entry, 1144 const StubEntry& stub_entry,
(...skipping 750 matching lines...) Expand 10 before | Expand all | Expand 10 after
1870 DRegister dreg = EvenDRegisterOf(reg); 1895 DRegister dreg = EvenDRegisterOf(reg);
1871 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); 1896 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex));
1872 } 1897 }
1873 1898
1874 1899
1875 #undef __ 1900 #undef __
1876 1901
1877 } // namespace dart 1902 } // namespace dart
1878 1903
1879 #endif // defined TARGET_ARCH_ARM 1904 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler.cc ('k') | runtime/vm/flow_graph_compiler_arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698