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