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

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

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

Powered by Google App Engine
This is Rietveld 408576698