Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 757 __ jmp(&all_arguments_processed, Assembler::kNearJump); | 757 __ jmp(&all_arguments_processed, Assembler::kNearJump); |
| 758 } | 758 } |
| 759 | 759 |
| 760 __ Bind(&wrong_num_arguments); | 760 __ Bind(&wrong_num_arguments); |
| 761 if (StackSize() != 0) { | 761 if (StackSize() != 0) { |
| 762 // We need to unwind the space we reserved for locals and copied parameters. | 762 // We need to unwind the space we reserved for locals and copied parameters. |
| 763 // The NoSuchMethodFunction stub does not expect to see that area on the | 763 // The NoSuchMethodFunction stub does not expect to see that area on the |
| 764 // stack. | 764 // stack. |
| 765 __ addl(ESP, Immediate(StackSize() * kWordSize)); | 765 __ addl(ESP, Immediate(StackSize() * kWordSize)); |
| 766 } | 766 } |
| 767 // The calls below have empty stackmaps because we have just dropped the | |
| 768 // spill slots. | |
| 769 BitmapBuilder* empty_stack_bitmap = new BitmapBuilder(); | |
| 767 if (function.IsClosureFunction()) { | 770 if (function.IsClosureFunction()) { |
| 768 GenerateCallRuntime(Isolate::kNoDeoptId, | 771 GenerateCallRuntime(Isolate::kNoDeoptId, |
| 769 0, | 772 0, |
| 770 CatchClauseNode::kInvalidTryIndex, | 773 CatchClauseNode::kInvalidTryIndex, |
| 771 kClosureArgumentMismatchRuntimeEntry, | 774 kClosureArgumentMismatchRuntimeEntry, |
| 772 NULL); | 775 empty_stack_bitmap); |
| 773 } else { | 776 } else { |
| 774 ASSERT(!IsLeaf()); | 777 ASSERT(!IsLeaf()); |
| 775 // Invoke noSuchMethod function. | 778 // Invoke noSuchMethod function. |
| 776 const int kNumArgsChecked = 1; | 779 const int kNumArgsChecked = 1; |
| 777 ICData& ic_data = ICData::ZoneHandle(); | 780 ICData& ic_data = ICData::ZoneHandle(); |
| 778 ic_data = ICData::New(function, | 781 ic_data = ICData::New(function, |
| 779 String::Handle(function.name()), | 782 String::Handle(function.name()), |
| 780 Isolate::kNoDeoptId, | 783 Isolate::kNoDeoptId, |
| 781 kNumArgsChecked); | 784 kNumArgsChecked); |
| 782 __ LoadObject(ECX, ic_data); | 785 __ LoadObject(ECX, ic_data); |
| 783 // EBP - 4 : PC marker, allows easy identification of RawInstruction obj. | 786 // EBP - 4 : PC marker, allows easy identification of RawInstruction obj. |
| 784 // EBP : points to previous frame pointer. | 787 // EBP : points to previous frame pointer. |
| 785 // EBP + 4 : points to return address. | 788 // EBP + 4 : points to return address. |
| 786 // EBP + 8 : address of last argument (arg n-1). | 789 // EBP + 8 : address of last argument (arg n-1). |
| 787 // ESP + 8 + 4*(n-1) : address of first argument (arg 0). | 790 // ESP + 8 + 4*(n-1) : address of first argument (arg 0). |
| 788 // ECX : ic-data. | 791 // ECX : ic-data. |
| 789 // EDX : arguments descriptor array. | 792 // EDX : arguments descriptor array. |
| 790 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); | 793 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); |
| 794 if (is_optimizing()) { | |
| 795 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), | |
| 796 empty_stack_bitmap); | |
| 797 } | |
| 791 } | 798 } |
| 792 | 799 |
| 793 if (FLAG_trace_functions) { | 800 if (FLAG_trace_functions) { |
| 794 __ pushl(EAX); // Preserve result. | 801 __ pushl(EAX); // Preserve result. |
| 795 __ PushObject(Function::ZoneHandle(function.raw())); | 802 __ PushObject(Function::ZoneHandle(function.raw())); |
| 796 GenerateCallRuntime(Isolate::kNoDeoptId, | 803 GenerateCallRuntime(Isolate::kNoDeoptId, |
| 797 0, | 804 0, |
| 798 CatchClauseNode::kInvalidTryIndex, | 805 CatchClauseNode::kInvalidTryIndex, |
| 799 kTraceFunctionExitRuntimeEntry, | 806 kTraceFunctionExitRuntimeEntry, |
| 800 NULL); | 807 empty_stack_bitmap); |
| 801 __ popl(EAX); // Remove argument. | 808 __ popl(EAX); // Remove argument. |
| 802 __ popl(EAX); // Restore result. | 809 __ popl(EAX); // Restore result. |
| 803 } | 810 } |
| 804 __ LeaveFrame(); | 811 __ LeaveFrame(); |
| 805 __ ret(); | 812 __ ret(); |
| 806 | 813 |
| 807 __ Bind(&all_arguments_processed); | 814 __ Bind(&all_arguments_processed); |
| 808 // Nullify originally passed arguments only after they have been copied and | 815 // Nullify originally passed arguments only after they have been copied and |
| 809 // checked, otherwise noSuchMethod would not see their original values. | 816 // checked, otherwise noSuchMethod would not see their original values. |
| 810 // This step can be skipped in case we decide that formal parameters are | 817 // This step can be skipped in case we decide that formal parameters are |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 891 | 898 |
| 892 const int parameter_count = function.num_fixed_parameters(); | 899 const int parameter_count = function.num_fixed_parameters(); |
| 893 const int copied_parameter_count = parsed_function().copied_parameter_count(); | 900 const int copied_parameter_count = parsed_function().copied_parameter_count(); |
| 894 const int local_count = parsed_function().stack_local_count(); | 901 const int local_count = parsed_function().stack_local_count(); |
| 895 __ Comment("Enter frame"); | 902 __ Comment("Enter frame"); |
| 896 if (IsLeaf()) { | 903 if (IsLeaf()) { |
| 897 AssemblerMacros::EnterDartLeafFrame(assembler(), (StackSize() * kWordSize)); | 904 AssemblerMacros::EnterDartLeafFrame(assembler(), (StackSize() * kWordSize)); |
| 898 } else { | 905 } else { |
| 899 AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize)); | 906 AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize)); |
| 900 } | 907 } |
| 908 | |
| 909 // For optimized code, keep a bitmap of the frame in order to build | |
| 910 // stackmaps for GC safepoints in the prologue. | |
| 911 BitmapBuilder* stack_bitmap = NULL; | |
| 912 if (is_optimizing()) { | |
| 913 // Spill slots are allocated but not initialized. | |
| 914 stack_bitmap = new BitmapBuilder(); | |
| 915 stack_bitmap->SetLength(StackSize()); | |
| 916 } | |
| 917 | |
| 901 // We check the number of passed arguments when we have to copy them due to | 918 // We check the number of passed arguments when we have to copy them due to |
| 902 // the presence of optional named parameters. | 919 // the presence of optional named parameters. |
| 903 // No such checking code is generated if only fixed parameters are declared, | 920 // No such checking code is generated if only fixed parameters are declared, |
| 904 // unless we are debug mode or unless we are compiling a closure. | 921 // unless we are debug mode or unless we are compiling a closure. |
| 905 if (copied_parameter_count == 0) { | 922 if (copied_parameter_count == 0) { |
| 906 #ifdef DEBUG | 923 #ifdef DEBUG |
| 907 const bool check_arguments = true; | 924 const bool check_arguments = true; |
| 908 #else | 925 #else |
| 909 const bool check_arguments = function.IsClosureFunction(); | 926 const bool check_arguments = function.IsClosureFunction(); |
| 910 #endif | 927 #endif |
| 911 if (check_arguments) { | 928 if (check_arguments) { |
| 912 __ Comment("Check argument count"); | 929 __ Comment("Check argument count"); |
| 913 // Check that num_fixed <= argc <= num_params. | 930 // Check that num_fixed <= argc <= num_params. |
| 914 Label argc_in_range; | 931 Label argc_in_range; |
| 915 // Total number of args is the first Smi in args descriptor array (EDX). | 932 // Total number of args is the first Smi in args descriptor array (EDX). |
| 916 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 933 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 917 __ cmpl(EAX, Immediate(Smi::RawValue(parameter_count))); | 934 __ cmpl(EAX, Immediate(Smi::RawValue(parameter_count))); |
| 918 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); | 935 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); |
| 919 if (function.IsClosureFunction()) { | 936 if (function.IsClosureFunction()) { |
| 920 GenerateCallRuntime(Isolate::kNoDeoptId, | 937 GenerateCallRuntime(Isolate::kNoDeoptId, |
| 921 function.token_pos(), | 938 function.token_pos(), |
| 922 CatchClauseNode::kInvalidTryIndex, | 939 CatchClauseNode::kInvalidTryIndex, |
| 923 kClosureArgumentMismatchRuntimeEntry, | 940 kClosureArgumentMismatchRuntimeEntry, |
| 924 NULL); | 941 stack_bitmap); |
| 925 } else { | 942 } else { |
| 926 __ Stop("Wrong number of arguments"); | 943 __ Stop("Wrong number of arguments"); |
| 927 } | 944 } |
| 928 __ Bind(&argc_in_range); | 945 __ Bind(&argc_in_range); |
| 929 } | 946 } |
| 930 } else { | 947 } else { |
| 931 CopyParameters(); | 948 CopyParameters(); |
| 932 } | 949 } |
| 933 | 950 |
| 934 // Initialize (non-argument) stack allocated slots to null. | 951 // In unoptimized code, initialize (non-argument) stack allocated slots to |
| 935 // | 952 // null. |
| 936 // TODO(vegorov): introduce stack maps and stop initializing all spill slots | 953 if (!is_optimizing() && (local_count > 0)) { |
| 937 // with null. | |
| 938 intptr_t uninitialized_slot_count; | |
| 939 if (is_optimizing()) { | |
| 940 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); | |
| 941 uninitialized_slot_count = | |
| 942 entry->spill_slot_count() - copied_parameter_count; | |
| 943 } else { | |
| 944 uninitialized_slot_count = local_count; | |
| 945 } | |
| 946 const intptr_t slot_base = parsed_function().first_stack_local_index(); | |
| 947 | |
| 948 if (uninitialized_slot_count > 0) { | |
| 949 __ Comment("Initialize spill slots"); | 954 __ Comment("Initialize spill slots"); |
|
Vyacheslav Egorov (Google)
2012/08/22 13:22:08
"Initialize locals"
| |
| 955 const intptr_t slot_base = parsed_function().first_stack_local_index(); | |
| 950 const Immediate raw_null = | 956 const Immediate raw_null = |
| 951 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 957 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 952 __ movl(EAX, raw_null); | 958 __ movl(EAX, raw_null); |
| 953 for (intptr_t i = 0; i < uninitialized_slot_count; ++i) { | 959 for (intptr_t i = 0; i < local_count; ++i) { |
| 954 // Subtract index i (locals lie at lower addresses than EBP). | 960 // Subtract index i (locals lie at lower addresses than EBP). |
| 955 __ movl(Address(EBP, (slot_base - i) * kWordSize), EAX); | 961 __ movl(Address(EBP, (slot_base - i) * kWordSize), EAX); |
| 956 } | 962 } |
| 957 } | 963 } |
| 958 | 964 |
| 959 if (FLAG_print_scopes) { | 965 if (FLAG_print_scopes) { |
| 960 // Print the function scope (again) after generating the prologue in order | 966 // Print the function scope (again) after generating the prologue in order |
| 961 // to see annotations such as allocation indices of locals. | 967 // to see annotations such as allocation indices of locals. |
| 962 if (FLAG_print_ast) { | 968 if (FLAG_print_ast) { |
| 963 // Second printing. | 969 // Second printing. |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 994 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos, try_index); | 1000 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos, try_index); |
| 995 } | 1001 } |
| 996 | 1002 |
| 997 | 1003 |
| 998 void FlowGraphCompiler::GenerateCallRuntime(intptr_t deopt_id, | 1004 void FlowGraphCompiler::GenerateCallRuntime(intptr_t deopt_id, |
| 999 intptr_t token_pos, | 1005 intptr_t token_pos, |
| 1000 intptr_t try_index, | 1006 intptr_t try_index, |
| 1001 const RuntimeEntry& entry, | 1007 const RuntimeEntry& entry, |
| 1002 BitmapBuilder* stack_bitmap) { | 1008 BitmapBuilder* stack_bitmap) { |
| 1003 ASSERT(!IsLeaf()); | 1009 ASSERT(!IsLeaf()); |
| 1010 ASSERT(!is_optimizing() || (stack_bitmap != NULL)); | |
| 1004 __ CallRuntime(entry); | 1011 __ CallRuntime(entry); |
| 1005 if (is_optimizing() && (stack_bitmap != NULL)) { | 1012 if (is_optimizing()) { |
| 1006 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), stack_bitmap); | 1013 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), stack_bitmap); |
| 1007 } | 1014 } |
| 1008 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos, try_index); | 1015 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos, try_index); |
| 1009 } | 1016 } |
| 1010 | 1017 |
| 1011 | 1018 |
| 1012 intptr_t FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, | 1019 intptr_t FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, |
| 1013 const ICData& ic_data, | 1020 const ICData& ic_data, |
| 1014 const Array& arguments_descriptor, | 1021 const Array& arguments_descriptor, |
| 1015 intptr_t argument_count) { | 1022 intptr_t argument_count) { |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1214 __ popl(ECX); | 1221 __ popl(ECX); |
| 1215 __ popl(EAX); | 1222 __ popl(EAX); |
| 1216 } | 1223 } |
| 1217 | 1224 |
| 1218 | 1225 |
| 1219 #undef __ | 1226 #undef __ |
| 1220 | 1227 |
| 1221 } // namespace dart | 1228 } // namespace dart |
| 1222 | 1229 |
| 1223 #endif // defined TARGET_ARCH_IA32 | 1230 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |