| 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 15 matching lines...) Expand all Loading... |
| 26 void DeoptimizationStub::GenerateCode(FlowGraphCompiler* compiler) { | 26 void DeoptimizationStub::GenerateCode(FlowGraphCompiler* compiler) { |
| 27 Assembler* assem = compiler->assembler(); | 27 Assembler* assem = compiler->assembler(); |
| 28 #define __ assem-> | 28 #define __ assem-> |
| 29 __ Comment("Deopt stub for id %d", deopt_id_); | 29 __ Comment("Deopt stub for id %d", deopt_id_); |
| 30 __ Bind(entry_label()); | 30 __ Bind(entry_label()); |
| 31 for (intptr_t i = 0; i < registers_.length(); i++) { | 31 for (intptr_t i = 0; i < registers_.length(); i++) { |
| 32 if (registers_[i] != kNoRegister) { | 32 if (registers_[i] != kNoRegister) { |
| 33 __ pushq(registers_[i]); | 33 __ pushq(registers_[i]); |
| 34 } | 34 } |
| 35 } | 35 } |
| 36 if (compiler->IsLeaf()) { |
| 37 Label L; |
| 38 __ call(&L); |
| 39 const intptr_t offset = assem->CodeSize(); |
| 40 __ Bind(&L); |
| 41 __ popq(RAX); |
| 42 __ subq(RAX, |
| 43 Immediate(offset - AssemblerMacros::kOffsetOfSavedPCfromEntrypoint)); |
| 44 __ movq(Address(RBP, -kWordSize), RAX); |
| 45 } |
| 36 __ movq(RAX, Immediate(Smi::RawValue(reason_))); | 46 __ movq(RAX, Immediate(Smi::RawValue(reason_))); |
| 37 __ call(&StubCode::DeoptimizeLabel()); | 47 __ call(&StubCode::DeoptimizeLabel()); |
| 38 compiler->AddCurrentDescriptor(PcDescriptors::kOther, | 48 compiler->AddCurrentDescriptor(PcDescriptors::kOther, |
| 39 deopt_id_, | 49 deopt_id_, |
| 40 deopt_token_pos_, | 50 deopt_token_pos_, |
| 41 try_index_); | 51 try_index_); |
| 42 #undef __ | 52 #undef __ |
| 43 } | 53 } |
| 44 | 54 |
| 45 | 55 |
| (...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 // The NoSuchMethodFunction stub does not expect to see that area on the | 768 // The NoSuchMethodFunction stub does not expect to see that area on the |
| 759 // stack. | 769 // stack. |
| 760 __ addq(RSP, Immediate(StackSize() * kWordSize)); | 770 __ addq(RSP, Immediate(StackSize() * kWordSize)); |
| 761 } | 771 } |
| 762 if (function.IsClosureFunction()) { | 772 if (function.IsClosureFunction()) { |
| 763 GenerateCallRuntime(AstNode::kNoId, | 773 GenerateCallRuntime(AstNode::kNoId, |
| 764 0, | 774 0, |
| 765 CatchClauseNode::kInvalidTryIndex, | 775 CatchClauseNode::kInvalidTryIndex, |
| 766 kClosureArgumentMismatchRuntimeEntry); | 776 kClosureArgumentMismatchRuntimeEntry); |
| 767 } else { | 777 } else { |
| 778 ASSERT(!IsLeaf()); |
| 768 // Invoke noSuchMethod function. | 779 // Invoke noSuchMethod function. |
| 769 const int kNumArgsChecked = 1; | 780 const int kNumArgsChecked = 1; |
| 770 ICData& ic_data = ICData::ZoneHandle(); | 781 ICData& ic_data = ICData::ZoneHandle(); |
| 771 ic_data = ICData::New(function, | 782 ic_data = ICData::New(function, |
| 772 String::Handle(function.name()), | 783 String::Handle(function.name()), |
| 773 AstNode::kNoId, | 784 AstNode::kNoId, |
| 774 kNumArgsChecked); | 785 kNumArgsChecked); |
| 775 __ LoadObject(RBX, ic_data); | 786 __ LoadObject(RBX, ic_data); |
| 776 // RBP - 8 : PC marker, allows easy identification of RawInstruction obj. | 787 // RBP - 8 : PC marker, allows easy identification of RawInstruction obj. |
| 777 // RBP : points to previous frame pointer. | 788 // RBP : points to previous frame pointer. |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 878 __ int3(); | 889 __ int3(); |
| 879 __ jmp(&StubCode::FixCallersTargetLabel()); | 890 __ jmp(&StubCode::FixCallersTargetLabel()); |
| 880 return; | 891 return; |
| 881 } | 892 } |
| 882 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. | 893 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. |
| 883 const Function& function = parsed_function().function(); | 894 const Function& function = parsed_function().function(); |
| 884 | 895 |
| 885 const int parameter_count = function.num_fixed_parameters(); | 896 const int parameter_count = function.num_fixed_parameters(); |
| 886 const int num_copied_params = parsed_function().copied_parameter_count(); | 897 const int num_copied_params = parsed_function().copied_parameter_count(); |
| 887 const int local_count = parsed_function().stack_local_count(); | 898 const int local_count = parsed_function().stack_local_count(); |
| 888 AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize)); | 899 if (IsLeaf()) { |
| 900 AssemblerMacros::EnterDartLeafFrame(assembler(), (StackSize() * kWordSize)); |
| 901 } else { |
| 902 AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize)); |
| 903 } |
| 889 // We check the number of passed arguments when we have to copy them due to | 904 // We check the number of passed arguments when we have to copy them due to |
| 890 // the presence of optional named parameters. | 905 // the presence of optional named parameters. |
| 891 // No such checking code is generated if only fixed parameters are declared, | 906 // No such checking code is generated if only fixed parameters are declared, |
| 892 // unless we are debug mode or unless we are compiling a closure. | 907 // unless we are debug mode or unless we are compiling a closure. |
| 893 if (num_copied_params == 0) { | 908 if (num_copied_params == 0) { |
| 894 #ifdef DEBUG | 909 #ifdef DEBUG |
| 895 const bool check_arguments = true; | 910 const bool check_arguments = true; |
| 896 #else | 911 #else |
| 897 const bool check_arguments = function.IsClosureFunction(); | 912 const bool check_arguments = function.IsClosureFunction(); |
| 898 #endif | 913 #endif |
| (...skipping 22 matching lines...) Expand all Loading... |
| 921 const Immediate raw_null = | 936 const Immediate raw_null = |
| 922 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 937 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 923 __ movq(RAX, raw_null); | 938 __ movq(RAX, raw_null); |
| 924 const int base = parsed_function().first_stack_local_index(); | 939 const int base = parsed_function().first_stack_local_index(); |
| 925 for (int i = 0; i < local_count; ++i) { | 940 for (int i = 0; i < local_count; ++i) { |
| 926 // Subtract index i (locals lie at lower addresses than RBP). | 941 // Subtract index i (locals lie at lower addresses than RBP). |
| 927 __ movq(Address(RBP, (base - i) * kWordSize), RAX); | 942 __ movq(Address(RBP, (base - i) * kWordSize), RAX); |
| 928 } | 943 } |
| 929 } | 944 } |
| 930 | 945 |
| 931 // Generate stack overflow check. | 946 if (!IsLeaf()) { |
| 932 __ movq(RDI, Immediate(Isolate::Current()->stack_limit_address())); | 947 // Generate stack overflow check. |
| 933 __ cmpq(RSP, Address(RDI, 0)); | 948 __ movq(RDI, Immediate(Isolate::Current()->stack_limit_address())); |
| 934 Label no_stack_overflow; | 949 __ cmpq(RSP, Address(RDI, 0)); |
| 935 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); | 950 Label no_stack_overflow; |
| 936 GenerateCallRuntime(AstNode::kNoId, | 951 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); |
| 937 function.token_pos(), | 952 GenerateCallRuntime(AstNode::kNoId, |
| 938 CatchClauseNode::kInvalidTryIndex, | 953 function.token_pos(), |
| 939 kStackOverflowRuntimeEntry); | 954 CatchClauseNode::kInvalidTryIndex, |
| 940 __ Bind(&no_stack_overflow); | 955 kStackOverflowRuntimeEntry); |
| 941 | 956 __ Bind(&no_stack_overflow); |
| 957 } |
| 942 if (FLAG_print_scopes) { | 958 if (FLAG_print_scopes) { |
| 943 // Print the function scope (again) after generating the prologue in order | 959 // Print the function scope (again) after generating the prologue in order |
| 944 // to see annotations such as allocation indices of locals. | 960 // to see annotations such as allocation indices of locals. |
| 945 if (FLAG_print_ast) { | 961 if (FLAG_print_ast) { |
| 946 // Second printing. | 962 // Second printing. |
| 947 OS::Print("Annotated "); | 963 OS::Print("Annotated "); |
| 948 } | 964 } |
| 949 AstPrinter::PrintFunctionScope(parsed_function()); | 965 AstPrinter::PrintFunctionScope(parsed_function()); |
| 950 } | 966 } |
| 951 | 967 |
| 952 VisitBlocks(); | 968 VisitBlocks(); |
| 953 | 969 |
| 954 __ int3(); | 970 __ int3(); |
| 955 GenerateDeferredCode(); | 971 GenerateDeferredCode(); |
| 956 // Emit function patching code. This will be swapped with the first 13 bytes | 972 // Emit function patching code. This will be swapped with the first 13 bytes |
| 957 // at entry point. | 973 // at entry point. |
| 958 pc_descriptors_list()->AddDescriptor(PcDescriptors::kPatchCode, | 974 pc_descriptors_list()->AddDescriptor(PcDescriptors::kPatchCode, |
| 959 assembler()->CodeSize(), | 975 assembler()->CodeSize(), |
| 960 AstNode::kNoId, | 976 AstNode::kNoId, |
| 961 0, | 977 0, |
| 962 -1); | 978 -1); |
| 963 __ jmp(&StubCode::FixCallersTargetLabel()); | 979 __ jmp(&StubCode::FixCallersTargetLabel()); |
| 964 } | 980 } |
| 965 | 981 |
| 966 | 982 |
| 967 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 983 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, |
| 968 intptr_t try_index, | 984 intptr_t try_index, |
| 969 const ExternalLabel* label, | 985 const ExternalLabel* label, |
| 970 PcDescriptors::Kind kind) { | 986 PcDescriptors::Kind kind) { |
| 987 ASSERT(!IsLeaf()); |
| 971 ASSERT(frame_register_allocator()->IsSpilled()); | 988 ASSERT(frame_register_allocator()->IsSpilled()); |
| 972 __ call(label); | 989 __ call(label); |
| 973 AddCurrentDescriptor(kind, AstNode::kNoId, token_pos, try_index); | 990 AddCurrentDescriptor(kind, AstNode::kNoId, token_pos, try_index); |
| 974 } | 991 } |
| 975 | 992 |
| 976 | 993 |
| 977 void FlowGraphCompiler::GenerateCallRuntime(intptr_t cid, | 994 void FlowGraphCompiler::GenerateCallRuntime(intptr_t cid, |
| 978 intptr_t token_pos, | 995 intptr_t token_pos, |
| 979 intptr_t try_index, | 996 intptr_t try_index, |
| 980 const RuntimeEntry& entry) { | 997 const RuntimeEntry& entry) { |
| 998 ASSERT(!IsLeaf()); |
| 981 ASSERT(frame_register_allocator()->IsSpilled()); | 999 ASSERT(frame_register_allocator()->IsSpilled()); |
| 982 __ CallRuntime(entry); | 1000 __ CallRuntime(entry); |
| 983 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_pos, try_index); | 1001 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_pos, try_index); |
| 984 } | 1002 } |
| 985 | 1003 |
| 986 | 1004 |
| 987 intptr_t FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, | 1005 intptr_t FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, |
| 988 const ICData& ic_data, | 1006 const ICData& ic_data, |
| 989 const Array& arguments_descriptor, | 1007 const Array& arguments_descriptor, |
| 990 intptr_t argument_count) { | 1008 intptr_t argument_count) { |
| 1009 ASSERT(!IsLeaf()); |
| 991 __ LoadObject(RBX, ic_data); | 1010 __ LoadObject(RBX, ic_data); |
| 992 __ LoadObject(R10, arguments_descriptor); | 1011 __ LoadObject(R10, arguments_descriptor); |
| 993 | 1012 |
| 994 __ call(target_label); | 1013 __ call(target_label); |
| 995 const intptr_t descr_offset = assembler()->CodeSize(); | 1014 const intptr_t descr_offset = assembler()->CodeSize(); |
| 996 __ Drop(argument_count); | 1015 __ Drop(argument_count); |
| 997 return descr_offset; | 1016 return descr_offset; |
| 998 } | 1017 } |
| 999 | 1018 |
| 1000 | 1019 |
| 1001 intptr_t FlowGraphCompiler::EmitStaticCall(const Function& function, | 1020 intptr_t FlowGraphCompiler::EmitStaticCall(const Function& function, |
| 1002 const Array& arguments_descriptor, | 1021 const Array& arguments_descriptor, |
| 1003 intptr_t argument_count) { | 1022 intptr_t argument_count) { |
| 1023 ASSERT(!IsLeaf()); |
| 1004 __ LoadObject(RBX, function); | 1024 __ LoadObject(RBX, function); |
| 1005 __ LoadObject(R10, arguments_descriptor); | 1025 __ LoadObject(R10, arguments_descriptor); |
| 1006 __ call(&StubCode::CallStaticFunctionLabel()); | 1026 __ call(&StubCode::CallStaticFunctionLabel()); |
| 1007 const intptr_t descr_offset = assembler()->CodeSize(); | 1027 const intptr_t descr_offset = assembler()->CodeSize(); |
| 1008 __ Drop(argument_count); | 1028 __ Drop(argument_count); |
| 1009 return descr_offset; | 1029 return descr_offset; |
| 1010 } | 1030 } |
| 1011 | 1031 |
| 1012 | 1032 |
| 1013 // Checks class id of instance against all 'class_ids'. Jump to 'deopt' label | 1033 // Checks class id of instance against all 'class_ids'. Jump to 'deopt' label |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1057 __ cvtsi2sd(result, temp); | 1077 __ cvtsi2sd(result, temp); |
| 1058 __ Bind(&done); | 1078 __ Bind(&done); |
| 1059 } | 1079 } |
| 1060 | 1080 |
| 1061 | 1081 |
| 1062 #undef __ | 1082 #undef __ |
| 1063 | 1083 |
| 1064 } // namespace dart | 1084 } // namespace dart |
| 1065 | 1085 |
| 1066 #endif // defined TARGET_ARCH_X64 | 1086 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |