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

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

Issue 9693020: Optional arguments in new compiler. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 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/code_generator_x64.h ('k') | runtime/vm/flow_graph_builder.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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/code_generator.h" 8 #include "vm/code_generator.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 ExternalLabel target_label("InlineCache", label_address); 331 ExternalLabel target_label("InlineCache", label_address);
332 332
333 __ call(&target_label); 333 __ call(&target_label);
334 AddCurrentDescriptor(PcDescriptors::kIcCall, 334 AddCurrentDescriptor(PcDescriptors::kIcCall,
335 node_id, 335 node_id,
336 token_index); 336 token_index);
337 __ addq(RSP, Immediate(num_arguments * kWordSize)); 337 __ addq(RSP, Immediate(num_arguments * kWordSize));
338 } 338 }
339 339
340 340
341 // Check that no fewer than num_fixed_params positional arguments are passed
342 // in and that no more than num_params arguments are passed in.
343 // Passed argument i at fp[1 + argc - i] copied to fp[-1 - i].
344 void CodeGenerator::CopyParameters() {
345 const Function& function = parsed_function_.function();
346 LocalScope* scope = parsed_function_.node_sequence()->scope();
347 const int num_fixed_params = function.num_fixed_parameters();
348 const int num_opt_params = function.num_optional_parameters();
349
350 ASSERT(parsed_function_.first_parameter_index() == -1);
351 // Copy positional arguments.
352 // Check that no fewer than num_fixed_params positional arguments are passed
353 // in and that no more than num_params arguments are passed in.
354 // Passed argument i at fp[1 + argc - i] copied to fp[-1 - i].
355 const int num_params = num_fixed_params + num_opt_params;
356
357 // Total number of args is the first Smi in args descriptor array (R10).
358 __ movq(RBX, FieldAddress(R10, Array::data_offset()));
359 // Check that num_args <= num_params.
360 Label wrong_num_arguments;
361 __ cmpq(RBX, Immediate(Smi::RawValue(num_params)));
362 __ j(GREATER, &wrong_num_arguments);
363 // Number of positional args is the second Smi in descriptor array (R10).
364 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize)));
365 // Check that num_pos_args >= num_fixed_params.
366 __ cmpq(RCX, Immediate(Smi::RawValue(num_fixed_params)));
367 __ j(LESS, &wrong_num_arguments);
368 // Since RBX and RCX are Smi, use TIMES_4 instead of TIMES_8.
369 // Let RBX point to the last passed positional argument, i.e. to
370 // fp[1 + num_args - (num_pos_args - 1)].
371 __ subq(RBX, RCX);
372 __ leaq(RBX, Address(RBP, RBX, TIMES_4, 2 * kWordSize));
373 // Let RDI point to the last copied positional argument, i.e. to
374 // fp[-1 - (num_pos_args - 1)].
375 __ SmiUntag(RCX);
376 __ movq(RAX, RCX);
377 __ negq(RAX);
378 __ leaq(RDI, Address(RBP, RAX, TIMES_8, 0));
379 Label loop, loop_condition;
380 __ jmp(&loop_condition, Assembler::kNearJump);
381 // We do not use the final allocation index of the variable here, i.e.
382 // scope->VariableAt(i)->index(), because captured variables still need
383 // to be copied to the context that is not yet allocated.
384 const Address argument_addr(RBX, RCX, TIMES_8, 0);
385 const Address copy_addr(RDI, RCX, TIMES_8, 0);
386 __ Bind(&loop);
387 __ movq(RAX, argument_addr);
388 __ movq(copy_addr, RAX);
389 __ Bind(&loop_condition);
390 __ decq(RCX);
391 __ j(POSITIVE, &loop, Assembler::kNearJump);
392
393 // Copy or initialize optional named arguments.
394 ASSERT(num_opt_params > 0); // Or we would not have to copy arguments.
395 // Start by alphabetically sorting the names of the optional parameters.
396 LocalVariable** opt_param = new LocalVariable*[num_opt_params];
397 int* opt_param_position = new int[num_opt_params];
398 for (int pos = num_fixed_params; pos < num_params; pos++) {
399 LocalVariable* parameter = scope->VariableAt(pos);
400 const String& opt_param_name = parameter->name();
401 int i = pos - num_fixed_params;
402 while (--i >= 0) {
403 LocalVariable* param_i = opt_param[i];
404 const intptr_t result = opt_param_name.CompareTo(param_i->name());
405 ASSERT(result != 0);
406 if (result > 0) break;
407 opt_param[i + 1] = opt_param[i];
408 opt_param_position[i + 1] = opt_param_position[i];
409 }
410 opt_param[i + 1] = parameter;
411 opt_param_position[i + 1] = pos;
412 }
413 // Generate code handling each optional parameter in alphabetical order.
414 // Total number of args is the first Smi in args descriptor array (R10).
415 __ movq(RBX, FieldAddress(R10, Array::data_offset()));
416 // Number of positional args is the second Smi in descriptor array (R10).
417 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize)));
418 __ SmiUntag(RCX);
419 // Let RBX point to the first passed argument, i.e. to fp[1 + argc - 0].
420 __ leaq(RBX, Address(RBP, RBX, TIMES_4, kWordSize)); // RBX is Smi.
421 // Let EDI point to the name/pos pair of the first named argument.
422 __ leaq(RDI, FieldAddress(R10, Array::data_offset() + (2 * kWordSize)));
423 for (int i = 0; i < num_opt_params; i++) {
424 // Handle this optional parameter only if k or fewer positional arguments
425 // have been passed, where k is the position of this optional parameter in
426 // the formal parameter list.
427 Label load_default_value, assign_optional_parameter, next_parameter;
428 const int param_pos = opt_param_position[i];
429 __ cmpq(RCX, Immediate(param_pos));
430 __ j(GREATER, &next_parameter, Assembler::kNearJump);
431 // Check if this named parameter was passed in.
432 __ movq(RAX, Address(RDI, 0)); // Load RAX with the name of the argument.
433 __ CompareObject(RAX, opt_param[i]->name());
434 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
435 // Load RAX with passed-in argument at provided arg_pos, i.e. at
436 // fp[1 + argc - arg_pos].
437 __ movq(RAX, Address(RDI, kWordSize)); // RAX is arg_pos as Smi.
438 __ addq(RDI, Immediate(2 * kWordSize)); // Point to next name/pos pair.
439 __ negq(RAX);
440 Address argument_addr(RBX, RAX, TIMES_4, 0); // RAX is a negative Smi.
441 __ movq(RAX, argument_addr);
442 __ jmp(&assign_optional_parameter, Assembler::kNearJump);
443 __ Bind(&load_default_value);
444 // Load RAX with default argument at pos.
445 const Object& value = Object::ZoneHandle(
446 parsed_function_.default_parameter_values().At(
447 param_pos - num_fixed_params));
448 __ LoadObject(RAX, value);
449 __ Bind(&assign_optional_parameter);
450 // Assign RAX to fp[-1 - param_pos].
451 // We do not use the final allocation index of the variable here, i.e.
452 // scope->VariableAt(i)->index(), because captured variables still need
453 // to be copied to the context that is not yet allocated.
454 const Address param_addr(RBP, (-1 - param_pos) * kWordSize);
455 __ movq(param_addr, RAX);
456 __ Bind(&next_parameter);
457 }
458 delete[] opt_param;
459 delete[] opt_param_position;
460 // Check that RDI now points to the null terminator in the array descriptor.
461 const Immediate raw_null =
462 Immediate(reinterpret_cast<intptr_t>(Object::null()));
463 Label all_arguments_processed;
464 __ cmpq(Address(RDI, 0), raw_null);
465 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
466
467 __ Bind(&wrong_num_arguments);
468 if (function.IsClosureFunction()) {
469 GenerateCallRuntime(AstNode::kNoId,
470 0,
471 kClosureArgumentMismatchRuntimeEntry);
472 } else {
473 // Invoke noSuchMethod function.
474 const int kNumArgsChecked = 1;
475 ICData& ic_data = ICData::ZoneHandle();
476 ic_data = ICData::New(parsed_function().function(),
477 String::Handle(function.name()),
478 AstNode::kNoId,
479 kNumArgsChecked);
480 __ LoadObject(RBX, ic_data);
481 // RBP : points to previous frame pointer.
482 // RBP + 8 : points to return address.
483 // RBP + 16 : address of last argument (arg n-1).
484 // RSP + 16 + 8*(n-1) : address of first argument (arg 0).
485 // RBX : ic-data.
486 // R10 : arguments descriptor array.
487 __ call(&StubCode::CallNoSuchMethodFunctionLabel());
488 }
489
490 if (FLAG_trace_functions) {
491 __ pushq(RAX); // Preserve result.
492 __ PushObject(Function::ZoneHandle(function.raw()));
493 GenerateCallRuntime(AstNode::kNoId,
494 0,
495 kTraceFunctionExitRuntimeEntry);
496 __ popq(RAX); // Remove argument.
497 __ popq(RAX); // Restore result.
498 }
499 __ LeaveFrame();
500 __ ret();
501
502 __ Bind(&all_arguments_processed);
503 // Nullify originally passed arguments only after they have been copied and
504 // checked, otherwise noSuchMethod would not see their original values.
505 // This step can be skipped in case we decide that formal parameters are
506 // implicitly final, since garbage collecting the unmodified value is not
507 // an issue anymore.
508
509 // R10 : arguments descriptor array.
510 // Total number of args is the first Smi in args descriptor array (R10).
511 __ movq(RCX, FieldAddress(R10, Array::data_offset()));
512 __ SmiUntag(RCX);
513 Label null_args_loop, null_args_loop_condition;
514 __ jmp(&null_args_loop_condition, Assembler::kNearJump);
515 const Address original_argument_addr(RBP, RCX, TIMES_8, 2 * kWordSize);
516 __ Bind(&null_args_loop);
517 __ movq(original_argument_addr, raw_null);
518 __ Bind(&null_args_loop_condition);
519 __ decq(RCX);
520 __ j(POSITIVE, &null_args_loop, Assembler::kNearJump);
521 }
522
523
524 // Call to generate entry code:
525 // - compute frame size and setup frame.
526 // - allocate local variables on stack.
527 // - optionally check if number of arguments match.
528 // - initialize all non-argument locals to null.
529 //
341 // Input parameters: 530 // Input parameters:
342 // RSP : points to return address. 531 // RSP : points to return address.
343 // RSP + 8 : address of last argument (arg n-1). 532 // RSP + 8 : address of last argument (arg n-1).
344 // RSP + 8*n : address of first argument (arg 0). 533 // RSP + 8*n : address of first argument (arg 0).
345 // R10 : arguments descriptor array. 534 // R10 : arguments descriptor array.
346 void CodeGenerator::GenerateEntryCode() { 535 void CodeGenerator::GenerateEntryCode() {
347 const Immediate raw_null = 536 const Immediate raw_null =
348 Immediate(reinterpret_cast<intptr_t>(Object::null())); 537 Immediate(reinterpret_cast<intptr_t>(Object::null()));
349 const Function& function = parsed_function_.function(); 538 const Function& function = parsed_function_.function();
350 539
(...skipping 11 matching lines...) Expand all
362 num_copied_params + parsed_function_.stack_local_count(); 551 num_copied_params + parsed_function_.stack_local_count();
363 set_locals_space_size(stack_slot_count * kWordSize); 552 set_locals_space_size(stack_slot_count * kWordSize);
364 __ EnterFrame(locals_space_size()); 553 __ EnterFrame(locals_space_size());
365 554
366 // 2. Optionally check if the number of arguments matches. We check the 555 // 2. Optionally check if the number of arguments matches. We check the
367 // number of passed arguments when we have to copy them due to the 556 // number of passed arguments when we have to copy them due to the
368 // presence of optional named parameters. No such checking code is 557 // presence of optional named parameters. No such checking code is
369 // generated if only fixed parameters are declared, unless we are in debug 558 // generated if only fixed parameters are declared, unless we are in debug
370 // mode or unless we are compiling a closure. 559 // mode or unless we are compiling a closure.
371 if (num_copied_params == 0) { 560 if (num_copied_params == 0) {
561 ASSERT(num_opt_params == 0);
372 #if defined(DEBUG) 562 #if defined(DEBUG)
373 const bool check_arguments = true; // Always check arguments in debug mode. 563 const bool check_arguments = true; // Always check arguments in debug mode.
374 #else 564 #else
375 // The number of arguments passed to closure functions must always be 565 // The number of arguments passed to closure functions must always be
376 // checked here, because no resolving stub (normally responsible for the 566 // checked here, because no resolving stub (normally responsible for the
377 // check) is involved in closure calls. 567 // check) is involved in closure calls.
378 const bool check_arguments = function.IsClosureFunction(); 568 const bool check_arguments = function.IsClosureFunction();
379 #endif 569 #endif
380 if (check_arguments) { 570 if (check_arguments) {
381 // Check that num_fixed <= argc <= num_params. 571 // Check that num_fixed <= argc <= num_params.
382 Label argc_in_range; 572 Label argc_in_range;
383 // Total number of args is the first Smi in args descriptor array (R10). 573 // Total number of args is the first Smi in args descriptor array (R10).
384 __ movq(RAX, FieldAddress(R10, Array::data_offset())); 574 __ movq(RAX, FieldAddress(R10, Array::data_offset()));
385 if (num_opt_params == 0) { 575 __ cmpq(RAX, Immediate(Smi::RawValue(num_fixed_params)));
386 __ cmpq(RAX, Immediate(Smi::RawValue(num_fixed_params))); 576 __ j(EQUAL, &argc_in_range, Assembler::kNearJump);
387 __ j(EQUAL, &argc_in_range, Assembler::kNearJump);
388 } else {
389 __ subq(RAX, Immediate(Smi::RawValue(num_fixed_params)));
390 __ cmpq(RAX, Immediate(Smi::RawValue(num_opt_params)));
391 __ j(BELOW_EQUAL, &argc_in_range, Assembler::kNearJump);
392 }
393 if (function.IsClosureFunction()) { 577 if (function.IsClosureFunction()) {
394 GenerateCallRuntime(AstNode::kNoId, 578 GenerateCallRuntime(AstNode::kNoId,
395 0, 579 0,
396 kClosureArgumentMismatchRuntimeEntry); 580 kClosureArgumentMismatchRuntimeEntry);
397 } else { 581 } else {
398 __ Stop("Wrong number of arguments"); 582 __ Stop("Wrong number of arguments");
399 } 583 }
400 __ Bind(&argc_in_range); 584 __ Bind(&argc_in_range);
401 } 585 }
402 } else { 586 } else {
403 ASSERT(parsed_function_.first_parameter_index() == -1); 587 CopyParameters();
404 // Copy positional arguments.
405 // Check that no fewer than num_fixed_params positional arguments are passed
406 // in and that no more than num_params arguments are passed in.
407 // Passed argument i at fp[1 + argc - i] copied to fp[-1 - i].
408 const int num_params = num_fixed_params + num_opt_params;
409
410 // Total number of args is the first Smi in args descriptor array (R10).
411 __ movq(RBX, FieldAddress(R10, Array::data_offset()));
412 // Check that num_args <= num_params.
413 Label wrong_num_arguments;
414 __ cmpq(RBX, Immediate(Smi::RawValue(num_params)));
415 __ j(GREATER, &wrong_num_arguments);
416 // Number of positional args is the second Smi in descriptor array (R10).
417 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize)));
418 // Check that num_pos_args >= num_fixed_params.
419 __ cmpq(RCX, Immediate(Smi::RawValue(num_fixed_params)));
420 __ j(LESS, &wrong_num_arguments);
421 // Since RBX and RCX are Smi, use TIMES_4 instead of TIMES_8.
422 // Let RBX point to the last passed positional argument, i.e. to
423 // fp[1 + num_args - (num_pos_args - 1)].
424 __ subq(RBX, RCX);
425 __ leaq(RBX, Address(RBP, RBX, TIMES_4, 2 * kWordSize));
426 // Let RDI point to the last copied positional argument, i.e. to
427 // fp[-1 - (num_pos_args - 1)].
428 __ SmiUntag(RCX);
429 __ movq(RAX, RCX);
430 __ negq(RAX);
431 __ leaq(RDI, Address(RBP, RAX, TIMES_8, 0));
432 Label loop, loop_condition;
433 __ jmp(&loop_condition, Assembler::kNearJump);
434 // We do not use the final allocation index of the variable here, i.e.
435 // scope->VariableAt(i)->index(), because captured variables still need
436 // to be copied to the context that is not yet allocated.
437 const Address argument_addr(RBX, RCX, TIMES_8, 0);
438 const Address copy_addr(RDI, RCX, TIMES_8, 0);
439 __ Bind(&loop);
440 __ movq(RAX, argument_addr);
441 __ movq(copy_addr, RAX);
442 __ Bind(&loop_condition);
443 __ decq(RCX);
444 __ j(POSITIVE, &loop, Assembler::kNearJump);
445
446 // Copy or initialize optional named arguments.
447 ASSERT(num_opt_params > 0); // Or we would not have to copy arguments.
448 // Start by alphabetically sorting the names of the optional parameters.
449 LocalVariable** opt_param = new LocalVariable*[num_opt_params];
450 int* opt_param_position = new int[num_opt_params];
451 for (int pos = num_fixed_params; pos < num_params; pos++) {
452 LocalVariable* parameter = scope->VariableAt(pos);
453 const String& opt_param_name = parameter->name();
454 int i = pos - num_fixed_params;
455 while (--i >= 0) {
456 LocalVariable* param_i = opt_param[i];
457 const intptr_t result = opt_param_name.CompareTo(param_i->name());
458 ASSERT(result != 0);
459 if (result > 0) break;
460 opt_param[i + 1] = opt_param[i];
461 opt_param_position[i + 1] = opt_param_position[i];
462 }
463 opt_param[i + 1] = parameter;
464 opt_param_position[i + 1] = pos;
465 }
466 // Generate code handling each optional parameter in alphabetical order.
467 // Total number of args is the first Smi in args descriptor array (R10).
468 __ movq(RBX, FieldAddress(R10, Array::data_offset()));
469 // Number of positional args is the second Smi in descriptor array (R10).
470 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize)));
471 __ SmiUntag(RCX);
472 // Let RBX point to the first passed argument, i.e. to fp[1 + argc - 0].
473 __ leaq(RBX, Address(RBP, RBX, TIMES_4, kWordSize)); // RBX is Smi.
474 // Let EDI point to the name/pos pair of the first named argument.
475 __ leaq(RDI, FieldAddress(R10, Array::data_offset() + (2 * kWordSize)));
476 for (int i = 0; i < num_opt_params; i++) {
477 // Handle this optional parameter only if k or fewer positional arguments
478 // have been passed, where k is the position of this optional parameter in
479 // the formal parameter list.
480 Label load_default_value, assign_optional_parameter, next_parameter;
481 const int param_pos = opt_param_position[i];
482 __ cmpq(RCX, Immediate(param_pos));
483 __ j(GREATER, &next_parameter, Assembler::kNearJump);
484 // Check if this named parameter was passed in.
485 __ movq(RAX, Address(RDI, 0)); // Load RAX with the name of the argument.
486 __ CompareObject(RAX, opt_param[i]->name());
487 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
488 // Load RAX with passed-in argument at provided arg_pos, i.e. at
489 // fp[1 + argc - arg_pos].
490 __ movq(RAX, Address(RDI, kWordSize)); // RAX is arg_pos as Smi.
491 __ addq(RDI, Immediate(2 * kWordSize)); // Point to next name/pos pair.
492 __ negq(RAX);
493 Address argument_addr(RBX, RAX, TIMES_4, 0); // RAX is a negative Smi.
494 __ movq(RAX, argument_addr);
495 __ jmp(&assign_optional_parameter, Assembler::kNearJump);
496 __ Bind(&load_default_value);
497 // Load RAX with default argument at pos.
498 const Object& value = Object::ZoneHandle(
499 parsed_function_.default_parameter_values().At(
500 param_pos - num_fixed_params));
501 __ LoadObject(RAX, value);
502 __ Bind(&assign_optional_parameter);
503 // Assign RAX to fp[-1 - param_pos].
504 // We do not use the final allocation index of the variable here, i.e.
505 // scope->VariableAt(i)->index(), because captured variables still need
506 // to be copied to the context that is not yet allocated.
507 const Address param_addr(RBP, (-1 - param_pos) * kWordSize);
508 __ movq(param_addr, RAX);
509 __ Bind(&next_parameter);
510 }
511 delete[] opt_param;
512 delete[] opt_param_position;
513 // Check that RDI now points to the null terminator in the array descriptor.
514 Label all_arguments_processed;
515 __ cmpq(Address(RDI, 0), raw_null);
516 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
517
518 __ Bind(&wrong_num_arguments);
519 if (function.IsClosureFunction()) {
520 GenerateCallRuntime(AstNode::kNoId,
521 0,
522 kClosureArgumentMismatchRuntimeEntry);
523 } else {
524 // Invoke noSuchMethod function.
525 const int kNumArgsChecked = 1;
526 ICData& ic_data = ICData::ZoneHandle();
527 ic_data = ICData::New(parsed_function().function(),
528 String::Handle(function.name()),
529 AstNode::kNoId,
530 kNumArgsChecked);
531 __ LoadObject(RBX, ic_data);
532 // RBP : points to previous frame pointer.
533 // RBP + 8 : points to return address.
534 // RBP + 16 : address of last argument (arg n-1).
535 // RSP + 16 + 8*(n-1) : address of first argument (arg 0).
536 // RBX : ic-data.
537 // R10 : arguments descriptor array.
538 __ call(&StubCode::CallNoSuchMethodFunctionLabel());
539 }
540
541 if (FLAG_trace_functions) {
542 __ pushq(RAX); // Preserve result.
543 __ PushObject(Function::ZoneHandle(function.raw()));
544 GenerateCallRuntime(AstNode::kNoId,
545 0,
546 kTraceFunctionExitRuntimeEntry);
547 __ popq(RAX); // Remove argument.
548 __ popq(RAX); // Restore result.
549 }
550 __ LeaveFrame();
551 __ ret();
552
553 __ Bind(&all_arguments_processed);
554 // Nullify originally passed arguments only after they have been copied and
555 // checked, otherwise noSuchMethod would not see their original values.
556 // This step can be skipped in case we decide that formal parameters are
557 // implicitly final, since garbage collecting the unmodified value is not
558 // an issue anymore.
559
560 // R10 : arguments descriptor array.
561 // Total number of args is the first Smi in args descriptor array (R10).
562 __ movq(RCX, FieldAddress(R10, Array::data_offset()));
563 __ SmiUntag(RCX);
564 Label null_args_loop, null_args_loop_condition;
565 __ jmp(&null_args_loop_condition, Assembler::kNearJump);
566 const Address original_argument_addr(RBP, RCX, TIMES_8, 2 * kWordSize);
567 __ Bind(&null_args_loop);
568 __ movq(original_argument_addr, raw_null);
569 __ Bind(&null_args_loop_condition);
570 __ decq(RCX);
571 __ j(POSITIVE, &null_args_loop, Assembler::kNearJump);
572 } 588 }
573 589
574 // 3. Initialize (non-argument) stack-allocated locals to null. 590 // 3. Initialize (non-argument) stack-allocated locals to null.
575 // 591 //
576 // TODO(regis): For now, always unroll the init loop. Decide later above 592 // TODO(regis): For now, always unroll the init loop. Decide later above
577 // which threshold to implement a loop. Consider emitting pushes instead 593 // which threshold to implement a loop. Consider emitting pushes instead
578 // of moves. 594 // of moves.
579 const int base = parsed_function_.first_stack_local_index(); 595 const int base = parsed_function_.first_stack_local_index();
580 for (int index = 0; index < parsed_function_.stack_local_count(); ++index) { 596 for (int index = 0; index < parsed_function_.stack_local_count(); ++index) {
581 if (index == 0) { 597 if (index == 0) {
(...skipping 2064 matching lines...) Expand 10 before | Expand all | Expand 10 after
2646 const Error& error = Error::Handle( 2662 const Error& error = Error::Handle(
2647 Parser::FormatError(script, token_index, "Error", format, args)); 2663 Parser::FormatError(script, token_index, "Error", format, args));
2648 va_end(args); 2664 va_end(args);
2649 Isolate::Current()->long_jump_base()->Jump(1, error); 2665 Isolate::Current()->long_jump_base()->Jump(1, error);
2650 UNREACHABLE(); 2666 UNREACHABLE();
2651 } 2667 }
2652 2668
2653 } // namespace dart 2669 } // namespace dart
2654 2670
2655 #endif // defined TARGET_ARCH_X64 2671 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/code_generator_x64.h ('k') | runtime/vm/flow_graph_builder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698