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

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

Issue 12663024: Implement optional parameter handling in ARM vm. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
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 "lib/error.h" 10 #include "lib/error.h"
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) { 160 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
161 if (is_optimizing()) return; 161 if (is_optimizing()) return;
162 Definition* defn = instr->AsDefinition(); 162 Definition* defn = instr->AsDefinition();
163 if ((defn != NULL) && defn->is_used()) { 163 if ((defn != NULL) && defn->is_used()) {
164 __ Push(defn->locs()->out().reg()); 164 __ Push(defn->locs()->out().reg());
165 } 165 }
166 } 166 }
167 167
168 168
169 void FlowGraphCompiler::CopyParameters() { 169 void FlowGraphCompiler::CopyParameters() {
170 UNIMPLEMENTED(); 170 __ Comment("Copy parameters");
zra 2013/03/22 16:45:10 Maybe add a comment explaining register contents o
regis 2013/03/22 17:26:11 Added comment here and in FlowGraphCompiler::Compi
171 const Function& function = parsed_function().function();
172 LocalScope* scope = parsed_function().node_sequence()->scope();
173 const int num_fixed_params = function.num_fixed_parameters();
174 const int num_opt_pos_params = function.NumOptionalPositionalParameters();
175 const int num_opt_named_params = function.NumOptionalNamedParameters();
176 const int num_params =
177 num_fixed_params + num_opt_pos_params + num_opt_named_params;
178 ASSERT(function.NumParameters() == num_params);
179 ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotIndex);
180
181 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args,
182 // where num_pos_args is the number of positional arguments passed in.
183 const int min_num_pos_args = num_fixed_params;
184 const int max_num_pos_args = num_fixed_params + num_opt_pos_params;
185
186 __ ldr(R8, FieldAddress(R4, ArgumentsDescriptor::positional_count_offset()));
187 // Check that min_num_pos_args <= num_pos_args.
188 Label wrong_num_arguments;
189 __ CompareImmediate(R8, Smi::RawValue(min_num_pos_args));
190 __ b(&wrong_num_arguments, LT);
191 // Check that num_pos_args <= max_num_pos_args.
192 __ CompareImmediate(R8, Smi::RawValue(max_num_pos_args));
193 __ b(&wrong_num_arguments, GT);
194
195 // Copy positional arguments.
196 // Argument i passed at fp[kLastParamSlotIndex + num_args - 1 - i] is copied
197 // to fp[kFirstLocalSlotIndex - i].
198
199 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
200 // Since R7 and R8 are Smi, use LSL 1 instead of LSL 2.
201 // Let R7 point to the last passed positional argument, i.e. to
202 // fp[kLastParamSlotIndex + num_args - 1 - (num_pos_args - 1)].
203 __ sub(R7, R7, ShifterOperand(R8));
204 __ add(R7, FP, ShifterOperand(R7, LSL, 1));
205 __ add(R7, R7, ShifterOperand(kLastParamSlotIndex * kWordSize));
206
207 // Let R6 point to the last copied positional argument, i.e. to
208 // fp[kFirstLocalSlotIndex - (num_pos_args - 1)].
209 __ AddImmediate(R6, FP, (kFirstLocalSlotIndex + 1) * kWordSize);
210 __ sub(R6, R6, ShifterOperand(R8, LSL, 1)); // R8 is a Smi.
211 __ SmiUntag(R8);
212 Label loop, loop_condition;
213 __ b(&loop_condition);
214 // We do not use the final allocation index of the variable here, i.e.
215 // scope->VariableAt(i)->index(), because captured variables still need
216 // to be copied to the context that is not yet allocated.
217 const Address argument_addr(R7, R8, LSL, 2);
218 const Address copy_addr(R6, R8, LSL, 2);
219 __ Bind(&loop);
220 __ ldr(IP, argument_addr);
221 __ str(IP, copy_addr);
222 __ Bind(&loop_condition);
223 __ subs(R8, R8, ShifterOperand(1));
224 __ b(&loop, PL);
225
226 // Copy or initialize optional named arguments.
227 Label all_arguments_processed;
228 if (num_opt_named_params > 0) {
229 // Start by alphabetically sorting the names of the optional parameters.
230 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params];
231 int* opt_param_position = new int[num_opt_named_params];
232 for (int pos = num_fixed_params; pos < num_params; pos++) {
233 LocalVariable* parameter = scope->VariableAt(pos);
234 const String& opt_param_name = parameter->name();
235 int i = pos - num_fixed_params;
236 while (--i >= 0) {
237 LocalVariable* param_i = opt_param[i];
238 const intptr_t result = opt_param_name.CompareTo(param_i->name());
239 ASSERT(result != 0);
240 if (result > 0) break;
241 opt_param[i + 1] = opt_param[i];
242 opt_param_position[i + 1] = opt_param_position[i];
243 }
244 opt_param[i + 1] = parameter;
245 opt_param_position[i + 1] = pos;
246 }
247 // Generate code handling each optional parameter in alphabetical order.
248 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
249 __ ldr(R8,
250 FieldAddress(R4, ArgumentsDescriptor::positional_count_offset()));
251 __ SmiUntag(R8);
252 // Let R7 point to the first passed argument, i.e. to fp[1 + argc - 0].
zra 2013/03/22 16:45:10 Is this comment outdated?
regis 2013/03/22 17:26:11 Yes. I forgot to remove the old version. The newer
253 // Let R7 point to the first passed argument, i.e. to
254 // fp[kLastParamSlotIndex + num_args - 1 - 0]; num_args (R7) is Smi.
255 __ add(R7, FP, ShifterOperand(R7, LSL, 1));
256 __ AddImmediate(R7, R7, (kLastParamSlotIndex - 1) * kWordSize);
257 // Let R6 point to the entry of the first named argument.
258 __ add(R6, R4, ShifterOperand(
259 ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag));
260 for (int i = 0; i < num_opt_named_params; i++) {
261 Label load_default_value, assign_optional_parameter, next_parameter;
262 const int param_pos = opt_param_position[i];
263 // Check if this named parameter was passed in.
264 // Load R5 with the name of the argument.
265 __ ldr(R5, Address(R6, ArgumentsDescriptor::name_offset()));
266 ASSERT(opt_param[i]->name().IsSymbol());
267 __ CompareObject(R5, opt_param[i]->name());
268 __ b(&load_default_value, NE);
269 // Load R5 with passed-in argument at provided arg_pos, i.e. at
270 // fp[kLastParamSlotIndex + num_args - 1 - arg_pos].
271 __ ldr(R5, Address(R6, ArgumentsDescriptor::position_offset()));
272 // R5 is arg_pos as Smi.
273 // Point to next named entry.
274 __ add(R6, R6, ShifterOperand(ArgumentsDescriptor::named_entry_size()));
275 __ rsb(R5, R5, ShifterOperand(0));
276 Address argument_addr(R7, R5, LSL, 1); // R5 is a negative Smi.
277 __ ldr(R5, argument_addr);
278 __ b(&assign_optional_parameter);
279 __ Bind(&load_default_value);
280 // Load R5 with default argument.
281 const Object& value = Object::ZoneHandle(
282 parsed_function().default_parameter_values().At(
283 param_pos - num_fixed_params));
284 __ LoadObject(R5, value);
285 __ Bind(&assign_optional_parameter);
286 // Assign R5 to fp[kFirstLocalSlotIndex - param_pos].
287 // We do not use the final allocation index of the variable here, i.e.
288 // scope->VariableAt(i)->index(), because captured variables still need
289 // to be copied to the context that is not yet allocated.
290 const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos;
291 const Address param_addr(FP, computed_param_pos * kWordSize);
292 __ str(R5, param_addr);
293 __ Bind(&next_parameter);
zra 2013/03/22 16:45:10 Does anything branch to here?
regis 2013/03/22 17:26:11 Good catch. This is left over code from a previous
294 }
295 delete[] opt_param;
296 delete[] opt_param_position;
297 // Check that R6 now points to the null terminator in the array descriptor.
298 __ ldr(R5, Address(R6, 0));
299 __ CompareImmediate(R5, reinterpret_cast<int32_t>(Object::null()));
300 __ b(&all_arguments_processed, EQ);
301 } else {
302 ASSERT(num_opt_pos_params > 0);
303 __ ldr(R8,
304 FieldAddress(R4, ArgumentsDescriptor::positional_count_offset()));
305 __ SmiUntag(R8);
306 for (int i = 0; i < num_opt_pos_params; i++) {
307 Label next_parameter;
308 // Handle this optional positional parameter only if k or fewer positional
309 // arguments have been passed, where k is param_pos, the position of this
310 // optional parameter in the formal parameter list.
311 const int param_pos = num_fixed_params + i;
312 __ CompareImmediate(R8, param_pos);
313 __ b(&next_parameter, GT);
314 // Load R5 with default argument.
315 const Object& value = Object::ZoneHandle(
316 parsed_function().default_parameter_values().At(i));
317 __ LoadObject(R5, value);
318 // Assign R5 to fp[kFirstLocalSlotIndex - param_pos].
319 // We do not use the final allocation index of the variable here, i.e.
320 // scope->VariableAt(i)->index(), because captured variables still need
321 // to be copied to the context that is not yet allocated.
322 const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos;
323 const Address param_addr(FP, computed_param_pos * kWordSize);
324 __ str(R5, param_addr);
325 __ Bind(&next_parameter);
326 }
327 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
328 __ SmiUntag(R7);
329 // Check that R8 equals R7, i.e. no named arguments passed.
330 __ cmp(R8, ShifterOperand(R7));
331 __ b(&all_arguments_processed, EQ);
332 }
333
334 __ Bind(&wrong_num_arguments);
335 if (StackSize() != 0) {
336 // We need to unwind the space we reserved for locals and copied parameters.
337 // The NoSuchMethodFunction stub does not expect to see that area on the
338 // stack.
339 __ AddImmediate(SP, StackSize() * kWordSize);
340 }
341 // The call below has an empty stackmap because we have just
342 // dropped the spill slots.
343 BitmapBuilder* empty_stack_bitmap = new BitmapBuilder();
344
345 // Invoke noSuchMethod function passing the original name of the function.
346 // If the function is a closure function, use "call" as the original name.
347 const String& name = String::Handle(
348 function.IsClosureFunction() ? Symbols::Call().raw() : function.name());
349 const int kNumArgsChecked = 1;
350 const ICData& ic_data = ICData::ZoneHandle(
351 ICData::New(function, name, Isolate::kNoDeoptId, kNumArgsChecked));
352 __ LoadObject(R5, ic_data);
353 // FP - 4 : saved PP, object pool pointer of caller.
354 // FP + 0 : previous frame pointer.
355 // FP + 4 : return address.
356 // FP + 8 : PC marker, for easy identification of RawInstruction obj.
357 // FP + 12: last argument (arg n-1).
358 // SP + 0 : saved PP.
359 // SP + 16 + 4*(n-1) : first argument (arg 0).
360 // R5 : ic-data.
361 // R4 : arguments descriptor array.
362 __ BranchLink(&StubCode::CallNoSuchMethodFunctionLabel());
363 if (is_optimizing()) {
364 stackmap_table_builder_->AddEntry(assembler()->CodeSize(),
365 empty_stack_bitmap,
366 0); // No registers.
367 }
368 // The noSuchMethod call may return.
369 __ LeaveDartFrame();
370 __ Ret();
371
372 __ Bind(&all_arguments_processed);
373 // Nullify originally passed arguments only after they have been copied and
374 // checked, otherwise noSuchMethod would not see their original values.
375 // This step can be skipped in case we decide that formal parameters are
376 // implicitly final, since garbage collecting the unmodified value is not
377 // an issue anymore.
378
379 // R4 : arguments descriptor array.
380 __ ldr(R8, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
381 __ SmiUntag(R8);
382 __ add(R7, FP, ShifterOperand(kLastParamSlotIndex * kWordSize));
383 const Address original_argument_addr(R7, R8, LSL, 2);
384 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
385 Label null_args_loop, null_args_loop_condition;
386 __ b(&null_args_loop_condition);
387 __ Bind(&null_args_loop);
388 __ str(IP, original_argument_addr);
389 __ Bind(&null_args_loop_condition);
390 __ subs(R8, R8, ShifterOperand(1));
391 __ b(&null_args_loop, PL);
171 } 392 }
172 393
173 394
174 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { 395 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) {
175 UNIMPLEMENTED(); 396 UNIMPLEMENTED();
176 } 397 }
177 398
178 399
179 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) { 400 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) {
180 UNIMPLEMENTED(); 401 UNIMPLEMENTED();
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 } 649 }
429 650
430 651
431 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, 652 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
432 const ICData& ic_data, 653 const ICData& ic_data,
433 const Array& arguments_descriptor, 654 const Array& arguments_descriptor,
434 intptr_t argument_count, 655 intptr_t argument_count,
435 intptr_t deopt_id, 656 intptr_t deopt_id,
436 intptr_t token_pos, 657 intptr_t token_pos,
437 LocationSummary* locs) { 658 LocationSummary* locs) {
438 UNIMPLEMENTED(); 659 __ LoadObject(R5, ic_data);
660 __ LoadObject(R4, arguments_descriptor);
661 GenerateDartCall(deopt_id,
662 token_pos,
663 target_label,
664 PcDescriptors::kIcCall,
665 locs);
666 __ Drop(argument_count);
439 } 667 }
440 668
441 669
442 void FlowGraphCompiler::EmitMegamorphicInstanceCall( 670 void FlowGraphCompiler::EmitMegamorphicInstanceCall(
443 const ICData& ic_data, 671 const ICData& ic_data,
444 const Array& arguments_descriptor, 672 const Array& arguments_descriptor,
445 intptr_t argument_count, 673 intptr_t argument_count,
446 intptr_t deopt_id, 674 intptr_t deopt_id,
447 intptr_t token_pos, 675 intptr_t token_pos,
448 LocationSummary* locs) { 676 LocationSummary* locs) {
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 851
624 852
625 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { 853 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) {
626 UNIMPLEMENTED(); 854 UNIMPLEMENTED();
627 } 855 }
628 856
629 857
630 } // namespace dart 858 } // namespace dart
631 859
632 #endif // defined TARGET_ARCH_ARM 860 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698