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