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

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
« no previous file with comments | « runtime/vm/find_code_object_test.cc ('k') | runtime/vm/flow_graph_compiler_ia32.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 "lib/error.h" 10 #include "lib/error.h"
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 159
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 // Input parameters:
170 // R4: arguments descriptor array.
169 void FlowGraphCompiler::CopyParameters() { 171 void FlowGraphCompiler::CopyParameters() {
170 UNIMPLEMENTED(); 172 __ Comment("Copy parameters");
173 const Function& function = parsed_function().function();
174 LocalScope* scope = parsed_function().node_sequence()->scope();
175 const int num_fixed_params = function.num_fixed_parameters();
176 const int num_opt_pos_params = function.NumOptionalPositionalParameters();
177 const int num_opt_named_params = function.NumOptionalNamedParameters();
178 const int num_params =
179 num_fixed_params + num_opt_pos_params + num_opt_named_params;
180 ASSERT(function.NumParameters() == num_params);
181 ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotIndex);
182
183 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args,
184 // where num_pos_args is the number of positional arguments passed in.
185 const int min_num_pos_args = num_fixed_params;
186 const int max_num_pos_args = num_fixed_params + num_opt_pos_params;
187
188 __ ldr(R8, FieldAddress(R4, ArgumentsDescriptor::positional_count_offset()));
189 // Check that min_num_pos_args <= num_pos_args.
190 Label wrong_num_arguments;
191 __ CompareImmediate(R8, Smi::RawValue(min_num_pos_args));
192 __ b(&wrong_num_arguments, LT);
193 // Check that num_pos_args <= max_num_pos_args.
194 __ CompareImmediate(R8, Smi::RawValue(max_num_pos_args));
195 __ b(&wrong_num_arguments, GT);
196
197 // Copy positional arguments.
198 // Argument i passed at fp[kLastParamSlotIndex + num_args - 1 - i] is copied
199 // to fp[kFirstLocalSlotIndex - i].
200
201 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
202 // Since R7 and R8 are Smi, use LSL 1 instead of LSL 2.
203 // Let R7 point to the last passed positional argument, i.e. to
204 // fp[kLastParamSlotIndex + num_args - 1 - (num_pos_args - 1)].
205 __ sub(R7, R7, ShifterOperand(R8));
206 __ add(R7, FP, ShifterOperand(R7, LSL, 1));
207 __ add(R7, R7, ShifterOperand(kLastParamSlotIndex * kWordSize));
208
209 // Let R6 point to the last copied positional argument, i.e. to
210 // fp[kFirstLocalSlotIndex - (num_pos_args - 1)].
211 __ AddImmediate(R6, FP, (kFirstLocalSlotIndex + 1) * kWordSize);
212 __ sub(R6, R6, ShifterOperand(R8, LSL, 1)); // R8 is a Smi.
213 __ SmiUntag(R8);
214 Label loop, loop_condition;
215 __ b(&loop_condition);
216 // We do not use the final allocation index of the variable here, i.e.
217 // scope->VariableAt(i)->index(), because captured variables still need
218 // to be copied to the context that is not yet allocated.
219 const Address argument_addr(R7, R8, LSL, 2);
220 const Address copy_addr(R6, R8, LSL, 2);
221 __ Bind(&loop);
222 __ ldr(IP, argument_addr);
223 __ str(IP, copy_addr);
224 __ Bind(&loop_condition);
225 __ subs(R8, R8, ShifterOperand(1));
226 __ b(&loop, PL);
227
228 // Copy or initialize optional named arguments.
229 Label all_arguments_processed;
230 if (num_opt_named_params > 0) {
231 // Start by alphabetically sorting the names of the optional parameters.
232 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params];
233 int* opt_param_position = new int[num_opt_named_params];
234 for (int pos = num_fixed_params; pos < num_params; pos++) {
235 LocalVariable* parameter = scope->VariableAt(pos);
236 const String& opt_param_name = parameter->name();
237 int i = pos - num_fixed_params;
238 while (--i >= 0) {
239 LocalVariable* param_i = opt_param[i];
240 const intptr_t result = opt_param_name.CompareTo(param_i->name());
241 ASSERT(result != 0);
242 if (result > 0) break;
243 opt_param[i + 1] = opt_param[i];
244 opt_param_position[i + 1] = opt_param_position[i];
245 }
246 opt_param[i + 1] = parameter;
247 opt_param_position[i + 1] = pos;
248 }
249 // Generate code handling each optional parameter in alphabetical order.
250 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
251 __ ldr(R8,
252 FieldAddress(R4, ArgumentsDescriptor::positional_count_offset()));
253 __ SmiUntag(R8);
254 // Let R7 point to the first passed argument, i.e. to
255 // fp[kLastParamSlotIndex + num_args - 1 - 0]; num_args (R7) is Smi.
256 __ add(R7, FP, ShifterOperand(R7, LSL, 1));
257 __ AddImmediate(R7, R7, (kLastParamSlotIndex - 1) * kWordSize);
258 // Let R6 point to the entry of the first named argument.
259 __ add(R6, R4, ShifterOperand(
260 ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag));
261 for (int i = 0; i < num_opt_named_params; i++) {
262 Label load_default_value, assign_optional_parameter;
263 const int param_pos = opt_param_position[i];
264 // Check if this named parameter was passed in.
265 // Load R5 with the name of the argument.
266 __ ldr(R5, Address(R6, ArgumentsDescriptor::name_offset()));
267 ASSERT(opt_param[i]->name().IsSymbol());
268 __ CompareObject(R5, opt_param[i]->name());
269 __ b(&load_default_value, NE);
270 // Load R5 with passed-in argument at provided arg_pos, i.e. at
271 // fp[kLastParamSlotIndex + num_args - 1 - arg_pos].
272 __ ldr(R5, Address(R6, ArgumentsDescriptor::position_offset()));
273 // R5 is arg_pos as Smi.
274 // Point to next named entry.
275 __ add(R6, R6, ShifterOperand(ArgumentsDescriptor::named_entry_size()));
276 __ rsb(R5, R5, ShifterOperand(0));
277 Address argument_addr(R7, R5, LSL, 1); // R5 is a negative Smi.
278 __ ldr(R5, argument_addr);
279 __ b(&assign_optional_parameter);
280 __ Bind(&load_default_value);
281 // Load R5 with default argument.
282 const Object& value = Object::ZoneHandle(
283 parsed_function().default_parameter_values().At(
284 param_pos - num_fixed_params));
285 __ LoadObject(R5, value);
286 __ Bind(&assign_optional_parameter);
287 // Assign R5 to fp[kFirstLocalSlotIndex - param_pos].
288 // We do not use the final allocation index of the variable here, i.e.
289 // scope->VariableAt(i)->index(), because captured variables still need
290 // to be copied to the context that is not yet allocated.
291 const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos;
292 const Address param_addr(FP, computed_param_pos * kWordSize);
293 __ str(R5, param_addr);
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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 } else { 449 } else {
229 AddCurrentDescriptor(PcDescriptors::kEntryPatch, 450 AddCurrentDescriptor(PcDescriptors::kEntryPatch,
230 Isolate::kNoDeoptId, 451 Isolate::kNoDeoptId,
231 0); // No token position. 452 0); // No token position.
232 } 453 }
233 __ Comment("Enter frame"); 454 __ Comment("Enter frame");
234 __ EnterDartFrame((StackSize() * kWordSize)); 455 __ EnterDartFrame((StackSize() * kWordSize));
235 } 456 }
236 457
237 458
459 // Input parameters:
460 // LR: return address.
461 // SP: address of last argument.
462 // FP: caller's frame pointer.
463 // PP: caller's pool pointer.
464 // R5: ic-data.
465 // R4: arguments descriptor array.
238 void FlowGraphCompiler::CompileGraph() { 466 void FlowGraphCompiler::CompileGraph() {
239 InitCompiler(); 467 InitCompiler();
240 if (TryIntrinsify()) { 468 if (TryIntrinsify()) {
241 // Although this intrinsified code will never be patched, it must satisfy 469 // Although this intrinsified code will never be patched, it must satisfy
242 // CodePatcher::CodeIsPatchable, which verifies that this code has a minimum 470 // CodePatcher::CodeIsPatchable, which verifies that this code has a minimum
243 // code size. 471 // code size.
244 __ bkpt(0); 472 __ bkpt(0);
245 __ Branch(&StubCode::FixCallersTargetLabel()); 473 __ Branch(&StubCode::FixCallersTargetLabel());
246 return; 474 return;
247 } 475 }
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 } 656 }
429 657
430 658
431 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, 659 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
432 const ICData& ic_data, 660 const ICData& ic_data,
433 const Array& arguments_descriptor, 661 const Array& arguments_descriptor,
434 intptr_t argument_count, 662 intptr_t argument_count,
435 intptr_t deopt_id, 663 intptr_t deopt_id,
436 intptr_t token_pos, 664 intptr_t token_pos,
437 LocationSummary* locs) { 665 LocationSummary* locs) {
438 UNIMPLEMENTED(); 666 __ LoadObject(R5, ic_data);
667 __ LoadObject(R4, arguments_descriptor);
668 GenerateDartCall(deopt_id,
669 token_pos,
670 target_label,
671 PcDescriptors::kIcCall,
672 locs);
673 __ Drop(argument_count);
439 } 674 }
440 675
441 676
442 void FlowGraphCompiler::EmitMegamorphicInstanceCall( 677 void FlowGraphCompiler::EmitMegamorphicInstanceCall(
443 const ICData& ic_data, 678 const ICData& ic_data,
444 const Array& arguments_descriptor, 679 const Array& arguments_descriptor,
445 intptr_t argument_count, 680 intptr_t argument_count,
446 intptr_t deopt_id, 681 intptr_t deopt_id,
447 intptr_t token_pos, 682 intptr_t token_pos,
448 LocationSummary* locs) { 683 LocationSummary* locs) {
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 858
624 859
625 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { 860 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) {
626 UNIMPLEMENTED(); 861 UNIMPLEMENTED();
627 } 862 }
628 863
629 864
630 } // namespace dart 865 } // namespace dart
631 866
632 #endif // defined TARGET_ARCH_ARM 867 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/find_code_object_test.cc ('k') | runtime/vm/flow_graph_compiler_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698