OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |