| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 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" |
| 11 #include "vm/ast_printer.h" | 11 #include "vm/ast_printer.h" |
| 12 #include "vm/dart_entry.h" | 12 #include "vm/dart_entry.h" |
| 13 #include "vm/deopt_instructions.h" | 13 #include "vm/deopt_instructions.h" |
| 14 #include "vm/il_printer.h" | 14 #include "vm/il_printer.h" |
| 15 #include "vm/locations.h" | 15 #include "vm/locations.h" |
| 16 #include "vm/object_store.h" | 16 #include "vm/object_store.h" |
| 17 #include "vm/parser.h" | 17 #include "vm/parser.h" |
| 18 #include "vm/stack_frame.h" | 18 #include "vm/stack_frame.h" |
| 19 #include "vm/stub_code.h" | 19 #include "vm/stub_code.h" |
| 20 #include "vm/symbols.h" | 20 #include "vm/symbols.h" |
| 21 | 21 |
| 22 namespace dart { | 22 namespace dart { |
| 23 | 23 |
| 24 DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization."); | 24 DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization."); |
| 25 DECLARE_FLAG(int, optimization_counter_threshold); | 25 DECLARE_FLAG(int, optimization_counter_threshold); |
| 26 DECLARE_FLAG(int, reoptimization_counter_threshold); |
| 26 DECLARE_FLAG(bool, print_ast); | 27 DECLARE_FLAG(bool, print_ast); |
| 27 DECLARE_FLAG(bool, print_scopes); | 28 DECLARE_FLAG(bool, print_scopes); |
| 28 DECLARE_FLAG(bool, enable_type_checks); | 29 DECLARE_FLAG(bool, enable_type_checks); |
| 29 DECLARE_FLAG(bool, eliminate_type_checks); | 30 DECLARE_FLAG(bool, eliminate_type_checks); |
| 30 | 31 |
| 31 | 32 |
| 32 FlowGraphCompiler::~FlowGraphCompiler() { | 33 FlowGraphCompiler::~FlowGraphCompiler() { |
| 33 // BlockInfos are zone-allocated, so their destructors are not called. | 34 // BlockInfos are zone-allocated, so their destructors are not called. |
| 34 // Verify the labels explicitly here. | 35 // Verify the labels explicitly here. |
| 35 for (int i = 0; i < block_info_.length(); ++i) { | 36 for (int i = 0; i < block_info_.length(); ++i) { |
| (...skipping 998 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1034 __ ldr(R0, Address(SP, 1 * kWordSize)); // Receiver. | 1035 __ ldr(R0, Address(SP, 1 * kWordSize)); // Receiver. |
| 1035 __ ldr(R1, Address(SP, 0 * kWordSize)); // Value. | 1036 __ ldr(R1, Address(SP, 0 * kWordSize)); // Value. |
| 1036 __ StoreIntoObject(R0, FieldAddress(R0, offset), R1); | 1037 __ StoreIntoObject(R0, FieldAddress(R0, offset), R1); |
| 1037 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | 1038 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); |
| 1038 __ Ret(); | 1039 __ Ret(); |
| 1039 } | 1040 } |
| 1040 | 1041 |
| 1041 | 1042 |
| 1042 void FlowGraphCompiler::EmitFrameEntry() { | 1043 void FlowGraphCompiler::EmitFrameEntry() { |
| 1043 const Function& function = parsed_function().function(); | 1044 const Function& function = parsed_function().function(); |
| 1044 if (CanOptimizeFunction() && function.is_optimizable()) { | 1045 if (CanOptimizeFunction() && |
| 1045 const bool can_optimize = !is_optimizing() || may_reoptimize(); | 1046 function.is_optimizable() && |
| 1047 (!is_optimizing() || may_reoptimize())) { |
| 1046 const Register function_reg = R6; | 1048 const Register function_reg = R6; |
| 1047 if (can_optimize) { | |
| 1048 // The pool pointer is not setup before entering the Dart frame. | |
| 1049 | 1049 |
| 1050 // Preserve PP of caller. | 1050 // The pool pointer is not setup before entering the Dart frame. |
| 1051 __ mov(R7, ShifterOperand(PP)); | 1051 // Preserve PP of caller. |
| 1052 __ mov(R7, ShifterOperand(PP)); |
| 1053 // Temporarily setup pool pointer for this dart function. |
| 1054 __ LoadPoolPointer(); |
| 1055 // Load function object from object pool. |
| 1056 __ LoadObject(function_reg, function); // Uses PP. |
| 1057 // Restore PP of caller. |
| 1058 __ mov(PP, ShifterOperand(R7)); |
| 1052 | 1059 |
| 1053 // Temporarily setup pool pointer for this dart function. | |
| 1054 __ LoadPoolPointer(); | |
| 1055 | |
| 1056 // Load function object from object pool. | |
| 1057 __ LoadObject(function_reg, function); // Uses PP. | |
| 1058 | |
| 1059 // Restore PP of caller. | |
| 1060 __ mov(PP, ShifterOperand(R7)); | |
| 1061 } | |
| 1062 // Patch point is after the eventually inlined function object. | 1060 // Patch point is after the eventually inlined function object. |
| 1063 AddCurrentDescriptor(PcDescriptors::kEntryPatch, | 1061 AddCurrentDescriptor(PcDescriptors::kEntryPatch, |
| 1064 Isolate::kNoDeoptId, | 1062 Isolate::kNoDeoptId, |
| 1065 0); // No token position. | 1063 0); // No token position. |
| 1066 if (can_optimize) { | 1064 intptr_t threshold = FLAG_optimization_counter_threshold; |
| 1067 // Reoptimization of optimized function is triggered by counting in | 1065 __ ldr(R7, FieldAddress(function_reg, |
| 1066 Function::usage_counter_offset())); |
| 1067 if (is_optimizing()) { |
| 1068 // Reoptimization of an optimized function is triggered by counting in |
| 1068 // IC stubs, but not at the entry of the function. | 1069 // IC stubs, but not at the entry of the function. |
| 1069 if (!is_optimizing()) { | 1070 threshold = FLAG_reoptimization_counter_threshold; |
| 1070 __ ldr(R7, FieldAddress(function_reg, | 1071 } else { |
| 1071 Function::usage_counter_offset())); | 1072 __ add(R7, R7, ShifterOperand(1)); |
| 1072 __ add(R7, R7, ShifterOperand(1)); | 1073 __ str(R7, FieldAddress(function_reg, |
| 1073 __ str(R7, FieldAddress(function_reg, | 1074 Function::usage_counter_offset())); |
| 1074 Function::usage_counter_offset())); | |
| 1075 } else { | |
| 1076 __ ldr(R7, FieldAddress(function_reg, | |
| 1077 Function::usage_counter_offset())); | |
| 1078 } | |
| 1079 __ CompareImmediate(R7, FLAG_optimization_counter_threshold); | |
| 1080 ASSERT(function_reg == R6); | |
| 1081 __ Branch(&StubCode::OptimizeFunctionLabel(), GE); | |
| 1082 } | 1075 } |
| 1083 } else { | 1076 __ CompareImmediate(R7, threshold); |
| 1077 ASSERT(function_reg == R6); |
| 1078 __ Branch(&StubCode::OptimizeFunctionLabel(), GE); |
| 1079 } else if (!flow_graph().IsCompiledForOsr()) { |
| 1084 AddCurrentDescriptor(PcDescriptors::kEntryPatch, | 1080 AddCurrentDescriptor(PcDescriptors::kEntryPatch, |
| 1085 Isolate::kNoDeoptId, | 1081 Isolate::kNoDeoptId, |
| 1086 0); // No token position. | 1082 0); // No token position. |
| 1087 } | 1083 } |
| 1088 __ Comment("Enter frame"); | 1084 __ Comment("Enter frame"); |
| 1089 __ EnterDartFrame(StackSize() * kWordSize); | 1085 if (flow_graph().IsCompiledForOsr()) { |
| 1086 intptr_t extra_slots = StackSize() |
| 1087 - flow_graph().num_stack_locals() |
| 1088 - flow_graph().num_copied_params(); |
| 1089 ASSERT(extra_slots >= 0); |
| 1090 __ EnterOsrFrame(extra_slots * kWordSize); |
| 1091 } else { |
| 1092 ASSERT(StackSize() >= 0); |
| 1093 __ EnterDartFrame(StackSize() * kWordSize); |
| 1094 } |
| 1090 } | 1095 } |
| 1091 | 1096 |
| 1092 | 1097 |
| 1093 // Input parameters: | 1098 // Input parameters: |
| 1094 // LR: return address. | 1099 // LR: return address. |
| 1095 // SP: address of last argument. | 1100 // SP: address of last argument. |
| 1096 // FP: caller's frame pointer. | 1101 // FP: caller's frame pointer. |
| 1097 // PP: caller's pool pointer. | 1102 // PP: caller's pool pointer. |
| 1098 // R5: ic-data. | 1103 // R5: ic-data. |
| 1099 // R4: arguments descriptor array. | 1104 // R4: arguments descriptor array. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1116 const int num_copied_params = parsed_function().num_copied_params(); | 1121 const int num_copied_params = parsed_function().num_copied_params(); |
| 1117 const int num_locals = parsed_function().num_stack_locals(); | 1122 const int num_locals = parsed_function().num_stack_locals(); |
| 1118 | 1123 |
| 1119 // We check the number of passed arguments when we have to copy them due to | 1124 // We check the number of passed arguments when we have to copy them due to |
| 1120 // the presence of optional parameters. | 1125 // the presence of optional parameters. |
| 1121 // No such checking code is generated if only fixed parameters are declared, | 1126 // No such checking code is generated if only fixed parameters are declared, |
| 1122 // unless we are in debug mode or unless we are compiling a closure. | 1127 // unless we are in debug mode or unless we are compiling a closure. |
| 1123 if (num_copied_params == 0) { | 1128 if (num_copied_params == 0) { |
| 1124 #ifdef DEBUG | 1129 #ifdef DEBUG |
| 1125 ASSERT(!parsed_function().function().HasOptionalParameters()); | 1130 ASSERT(!parsed_function().function().HasOptionalParameters()); |
| 1126 const bool check_arguments = true; | 1131 const bool check_arguments = !flow_graph().IsCompiledForOsr(); |
| 1127 #else | 1132 #else |
| 1128 const bool check_arguments = | 1133 const bool check_arguments = |
| 1129 function.IsClosureFunction() || function.IsNoSuchMethodDispatcher(); | 1134 (function.IsClosureFunction() || function.IsNoSuchMethodDispatcher()) && |
| 1135 !flow_graph().IsCompiledForOsr(); |
| 1130 #endif | 1136 #endif |
| 1131 if (check_arguments) { | 1137 if (check_arguments) { |
| 1132 __ Comment("Check argument count"); | 1138 __ Comment("Check argument count"); |
| 1133 // Check that exactly num_fixed arguments are passed in. | 1139 // Check that exactly num_fixed arguments are passed in. |
| 1134 Label correct_num_arguments, wrong_num_arguments; | 1140 Label correct_num_arguments, wrong_num_arguments; |
| 1135 __ ldr(R0, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | 1141 __ ldr(R0, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
| 1136 __ CompareImmediate(R0, Smi::RawValue(num_fixed_params)); | 1142 __ CompareImmediate(R0, Smi::RawValue(num_fixed_params)); |
| 1137 __ b(&wrong_num_arguments, NE); | 1143 __ b(&wrong_num_arguments, NE); |
| 1138 __ ldr(R1, FieldAddress(R4, | 1144 __ ldr(R1, FieldAddress(R4, |
| 1139 ArgumentsDescriptor::positional_count_offset())); | 1145 ArgumentsDescriptor::positional_count_offset())); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1154 __ LoadObject(R5, ic_data); | 1160 __ LoadObject(R5, ic_data); |
| 1155 __ LeaveDartFrame(); // The arguments are still on the stack. | 1161 __ LeaveDartFrame(); // The arguments are still on the stack. |
| 1156 __ Branch(&StubCode::CallNoSuchMethodFunctionLabel()); | 1162 __ Branch(&StubCode::CallNoSuchMethodFunctionLabel()); |
| 1157 // The noSuchMethod call may return to the caller, but not here. | 1163 // The noSuchMethod call may return to the caller, but not here. |
| 1158 __ bkpt(0); | 1164 __ bkpt(0); |
| 1159 } else { | 1165 } else { |
| 1160 __ Stop("Wrong number of arguments"); | 1166 __ Stop("Wrong number of arguments"); |
| 1161 } | 1167 } |
| 1162 __ Bind(&correct_num_arguments); | 1168 __ Bind(&correct_num_arguments); |
| 1163 } | 1169 } |
| 1164 } else { | 1170 } else if (!flow_graph().IsCompiledForOsr()) { |
| 1165 CopyParameters(); | 1171 CopyParameters(); |
| 1166 } | 1172 } |
| 1167 | 1173 |
| 1168 // In unoptimized code, initialize (non-argument) stack allocated slots to | 1174 // In unoptimized code, initialize (non-argument) stack allocated slots to |
| 1169 // null. | 1175 // null. |
| 1170 if (!is_optimizing() && (num_locals > 0)) { | 1176 if (!is_optimizing() && (num_locals > 0)) { |
| 1171 __ Comment("Initialize spill slots"); | 1177 __ Comment("Initialize spill slots"); |
| 1172 const intptr_t slot_base = parsed_function().first_stack_local_index(); | 1178 const intptr_t slot_base = parsed_function().first_stack_local_index(); |
| 1173 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | 1179 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); |
| 1174 for (intptr_t i = 0; i < num_locals; ++i) { | 1180 for (intptr_t i = 0; i < num_locals; ++i) { |
| (...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1839 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { | 1845 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { |
| 1840 __ vldrd(reg, Address(SP, kDoubleSize, Address::PostIndex)); | 1846 __ vldrd(reg, Address(SP, kDoubleSize, Address::PostIndex)); |
| 1841 } | 1847 } |
| 1842 | 1848 |
| 1843 | 1849 |
| 1844 #undef __ | 1850 #undef __ |
| 1845 | 1851 |
| 1846 } // namespace dart | 1852 } // namespace dart |
| 1847 | 1853 |
| 1848 #endif // defined TARGET_ARCH_ARM | 1854 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |