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

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

Issue 11360116: Pass closure object as first implicit argument to closure functions. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 1 month 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/dart_entry.cc ('k') | runtime/vm/flow_graph_compiler_x64.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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 609 matching lines...) Expand 10 before | Expand all | Expand 10 after
620 Definition* defn = instr->AsDefinition(); 620 Definition* defn = instr->AsDefinition();
621 if ((defn != NULL) && defn->is_used()) { 621 if ((defn != NULL) && defn->is_used()) {
622 __ pushl(defn->locs()->out().reg()); 622 __ pushl(defn->locs()->out().reg());
623 } 623 }
624 } 624 }
625 625
626 626
627 void FlowGraphCompiler::CopyParameters() { 627 void FlowGraphCompiler::CopyParameters() {
628 __ Comment("Copy parameters"); 628 __ Comment("Copy parameters");
629 const Function& function = parsed_function().function(); 629 const Function& function = parsed_function().function();
630 const bool is_native_instance_closure =
631 function.is_native() && function.IsImplicitInstanceClosureFunction();
632 LocalScope* scope = parsed_function().node_sequence()->scope(); 630 LocalScope* scope = parsed_function().node_sequence()->scope();
633 const int num_fixed_params = function.num_fixed_parameters(); 631 const int num_fixed_params = function.num_fixed_parameters();
634 const int num_opt_pos_params = function.NumOptionalPositionalParameters(); 632 const int num_opt_pos_params = function.NumOptionalPositionalParameters();
635 int num_opt_named_params = function.NumOptionalNamedParameters(); 633 const int num_opt_named_params = function.NumOptionalNamedParameters();
636 const int num_params = 634 const int num_params =
637 num_fixed_params + num_opt_pos_params + num_opt_named_params; 635 num_fixed_params + num_opt_pos_params + num_opt_named_params;
638 int implicit_this_param_pos = is_native_instance_closure ? -1 : 0; 636 ASSERT(function.NumParameters() == num_params);
639 ASSERT(parsed_function().first_parameter_index() == 637 ASSERT(parsed_function().first_parameter_index() ==
640 ParsedFunction::kFirstLocalSlotIndex + implicit_this_param_pos); 638 ParsedFunction::kFirstLocalSlotIndex);
641 639
642 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args, 640 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args,
643 // where num_pos_args is the number of positional arguments passed in. 641 // where num_pos_args is the number of positional arguments passed in.
644 const int min_num_pos_args = num_fixed_params; 642 const int min_num_pos_args = num_fixed_params;
645 const int max_num_pos_args = num_fixed_params + num_opt_pos_params; 643 const int max_num_pos_args = num_fixed_params + num_opt_pos_params;
646 644
647 // Number of positional args is the second Smi in descriptor array (EDX). 645 // Number of positional args is the second Smi in descriptor array (EDX).
648 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); 646 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize)));
649 // Check that min_num_pos_args <= num_pos_args. 647 // Check that min_num_pos_args <= num_pos_args.
650 Label wrong_num_arguments; 648 Label wrong_num_arguments;
(...skipping 10 matching lines...) Expand all
661 // Total number of args is the first Smi in args descriptor array (EDX). 659 // Total number of args is the first Smi in args descriptor array (EDX).
662 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); 660 __ movl(EBX, FieldAddress(EDX, Array::data_offset()));
663 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4. 661 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4.
664 // Let EBX point to the last passed positional argument, i.e. to 662 // Let EBX point to the last passed positional argument, i.e. to
665 // fp[1 + num_args - (num_pos_args - 1)]. 663 // fp[1 + num_args - (num_pos_args - 1)].
666 __ subl(EBX, ECX); 664 __ subl(EBX, ECX);
667 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize)); 665 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize));
668 666
669 // Let EDI point to the last copied positional argument, i.e. to 667 // Let EDI point to the last copied positional argument, i.e. to
670 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)]. 668 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)].
671 const int index = 669 const int index = ParsedFunction::kFirstLocalSlotIndex + 1;
672 ParsedFunction::kFirstLocalSlotIndex + 1 + implicit_this_param_pos;
673 // First copy captured receiver if function is an implicit native closure.
674 if (is_native_instance_closure) {
675 __ movl(EAX, FieldAddress(CTX, Context::variable_offset(0)));
676 __ movl(Address(EBP, (index * kWordSize)), EAX);
677 }
678 __ leal(EDI, Address(EBP, (index * kWordSize))); 670 __ leal(EDI, Address(EBP, (index * kWordSize)));
679 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling. 671 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling.
680 __ subl(EDI, ECX); 672 __ subl(EDI, ECX);
681 __ SmiUntag(ECX); 673 __ SmiUntag(ECX);
682 Label loop, loop_condition; 674 Label loop, loop_condition;
683 __ jmp(&loop_condition, Assembler::kNearJump); 675 __ jmp(&loop_condition, Assembler::kNearJump);
684 // We do not use the final allocation index of the variable here, i.e. 676 // We do not use the final allocation index of the variable here, i.e.
685 // scope->VariableAt(i)->index(), because captured variables still need 677 // scope->VariableAt(i)->index(), because captured variables still need
686 // to be copied to the context that is not yet allocated. 678 // to be copied to the context that is not yet allocated.
687 const Address argument_addr(EBX, ECX, TIMES_4, 0); 679 const Address argument_addr(EBX, ECX, TIMES_4, 0);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 // Load EAX with default argument. 738 // Load EAX with default argument.
747 const Object& value = Object::ZoneHandle( 739 const Object& value = Object::ZoneHandle(
748 parsed_function().default_parameter_values().At( 740 parsed_function().default_parameter_values().At(
749 param_pos - num_fixed_params)); 741 param_pos - num_fixed_params));
750 __ LoadObject(EAX, value); 742 __ LoadObject(EAX, value);
751 __ Bind(&assign_optional_parameter); 743 __ Bind(&assign_optional_parameter);
752 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. 744 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos].
753 // We do not use the final allocation index of the variable here, i.e. 745 // We do not use the final allocation index of the variable here, i.e.
754 // scope->VariableAt(i)->index(), because captured variables still need 746 // scope->VariableAt(i)->index(), because captured variables still need
755 // to be copied to the context that is not yet allocated. 747 // to be copied to the context that is not yet allocated.
756 intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex - 748 const intptr_t computed_param_pos =
757 param_pos + implicit_this_param_pos); 749 ParsedFunction::kFirstLocalSlotIndex - param_pos;
758 const Address param_addr(EBP, (computed_param_pos * kWordSize)); 750 const Address param_addr(EBP, (computed_param_pos * kWordSize));
759 __ movl(param_addr, EAX); 751 __ movl(param_addr, EAX);
760 __ Bind(&next_parameter); 752 __ Bind(&next_parameter);
761 } 753 }
762 delete[] opt_param; 754 delete[] opt_param;
763 delete[] opt_param_position; 755 delete[] opt_param_position;
764 // Check that EDI now points to the null terminator in the array descriptor. 756 // Check that EDI now points to the null terminator in the array descriptor.
765 __ cmpl(Address(EDI, 0), raw_null); 757 __ cmpl(Address(EDI, 0), raw_null);
766 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); 758 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
767 } else if (num_opt_pos_params > 0) { 759 } else {
760 ASSERT(num_opt_pos_params > 0);
768 // Number of positional args is the second Smi in descriptor array (EDX). 761 // Number of positional args is the second Smi in descriptor array (EDX).
769 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); 762 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize)));
770 __ SmiUntag(ECX); 763 __ SmiUntag(ECX);
771 for (int i = 0; i < num_opt_pos_params; i++) { 764 for (int i = 0; i < num_opt_pos_params; i++) {
772 Label next_parameter; 765 Label next_parameter;
773 // Handle this optional positonal parameter only if k or fewer positional 766 // Handle this optional positonal parameter only if k or fewer positional
774 // arguments have been passed, where k is param_pos, the position of this 767 // arguments have been passed, where k is param_pos, the position of this
775 // optional parameter in the formal parameter list. 768 // optional parameter in the formal parameter list.
776 const int param_pos = num_fixed_params + i; 769 const int param_pos = num_fixed_params + i;
777 __ cmpl(ECX, Immediate(param_pos)); 770 __ cmpl(ECX, Immediate(param_pos));
778 __ j(GREATER, &next_parameter, Assembler::kNearJump); 771 __ j(GREATER, &next_parameter, Assembler::kNearJump);
779 // Load RAX with default argument. 772 // Load RAX with default argument.
780 const Object& value = Object::ZoneHandle( 773 const Object& value = Object::ZoneHandle(
781 parsed_function().default_parameter_values().At(i)); 774 parsed_function().default_parameter_values().At(i));
782 __ LoadObject(EAX, value); 775 __ LoadObject(EAX, value);
783 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. 776 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos].
784 // We do not use the final allocation index of the variable here, i.e. 777 // We do not use the final allocation index of the variable here, i.e.
785 // scope->VariableAt(i)->index(), because captured variables still need 778 // scope->VariableAt(i)->index(), because captured variables still need
786 // to be copied to the context that is not yet allocated. 779 // to be copied to the context that is not yet allocated.
787 intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex - 780 const intptr_t computed_param_pos =
788 param_pos + implicit_this_param_pos); 781 ParsedFunction::kFirstLocalSlotIndex - param_pos;
789 const Address param_addr(EBP, (computed_param_pos * kWordSize)); 782 const Address param_addr(EBP, (computed_param_pos * kWordSize));
790 __ movl(param_addr, EAX); 783 __ movl(param_addr, EAX);
791 __ Bind(&next_parameter); 784 __ Bind(&next_parameter);
792 } 785 }
793 // Total number of args is the first Smi in args descriptor array (EDX). 786 // Total number of args is the first Smi in args descriptor array (EDX).
794 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); 787 __ movl(EBX, FieldAddress(EDX, Array::data_offset()));
795 __ SmiUntag(EBX); 788 __ SmiUntag(EBX);
796 // Check that ECX equals EBX, i.e. no named arguments passed. 789 // Check that ECX equals EBX, i.e. no named arguments passed.
797 __ cmpl(ECX, EBX); 790 __ cmpl(ECX, EBX);
798 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); 791 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
799 } else {
800 ASSERT(is_native_instance_closure);
801 __ jmp(&all_arguments_processed, Assembler::kNearJump);
802 } 792 }
803 793
804 __ Bind(&wrong_num_arguments); 794 __ Bind(&wrong_num_arguments);
805 if (StackSize() != 0) { 795 if (StackSize() != 0) {
806 // We need to unwind the space we reserved for locals and copied parameters. 796 // We need to unwind the space we reserved for locals and copied parameters.
807 // The NoSuchMethodFunction stub does not expect to see that area on the 797 // The NoSuchMethodFunction stub does not expect to see that area on the
808 // stack. 798 // stack.
809 __ addl(ESP, Immediate(StackSize() * kWordSize)); 799 __ addl(ESP, Immediate(StackSize() * kWordSize));
810 } 800 }
811 // The calls immediately below have empty stackmaps because we have just 801 // The calls immediately below have empty stackmaps because we have just
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after
1387 __ popl(ECX); 1377 __ popl(ECX);
1388 __ popl(EAX); 1378 __ popl(EAX);
1389 } 1379 }
1390 1380
1391 1381
1392 #undef __ 1382 #undef __
1393 1383
1394 } // namespace dart 1384 } // namespace dart
1395 1385
1396 #endif // defined TARGET_ARCH_IA32 1386 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/dart_entry.cc ('k') | runtime/vm/flow_graph_compiler_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698