| 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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 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 1028 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1064 __ lw(T1, Address(SP, 0 * kWordSize)); // Value. | 1065 __ lw(T1, Address(SP, 0 * kWordSize)); // Value. |
| 1065 __ StoreIntoObject(T0, FieldAddress(T0, offset), T1); | 1066 __ StoreIntoObject(T0, FieldAddress(T0, offset), T1); |
| 1066 __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null())); | 1067 __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null())); |
| 1067 __ Ret(); | 1068 __ Ret(); |
| 1068 __ delay_slot()->mov(V0, TMP); | 1069 __ delay_slot()->mov(V0, TMP); |
| 1069 } | 1070 } |
| 1070 | 1071 |
| 1071 | 1072 |
| 1072 void FlowGraphCompiler::EmitFrameEntry() { | 1073 void FlowGraphCompiler::EmitFrameEntry() { |
| 1073 const Function& function = parsed_function().function(); | 1074 const Function& function = parsed_function().function(); |
| 1074 if (CanOptimizeFunction() && function.is_optimizable()) { | 1075 if (CanOptimizeFunction() && |
| 1075 const bool can_optimize = !is_optimizing() || may_reoptimize(); | 1076 function.is_optimizable() && |
| 1077 (!is_optimizing() || may_reoptimize())) { |
| 1076 const Register function_reg = T0; | 1078 const Register function_reg = T0; |
| 1077 if (can_optimize) { | |
| 1078 Label next; | |
| 1079 // The pool pointer is not setup before entering the Dart frame. | |
| 1080 | 1079 |
| 1081 __ mov(TMP1, RA); // Save RA. | 1080 Label next; |
| 1082 __ bal(&next); // Branch and link to next instruction to get PC in RA. | 1081 // The pool pointer is not setup before entering the Dart frame. |
| 1083 __ delay_slot()->mov(T2, RA); // Save PC of the following mov. | 1082 __ mov(TMP1, RA); // Save RA. |
| 1083 __ bal(&next); // Branch and link to next instruction to get PC in RA. |
| 1084 __ delay_slot()->mov(T2, RA); // Save PC of the following mov. |
| 1085 // Calculate offset of pool pointer from the PC. |
| 1086 const intptr_t object_pool_pc_dist = |
| 1087 Instructions::HeaderSize() - Instructions::object_pool_offset() + |
| 1088 assembler()->CodeSize(); |
| 1089 __ Bind(&next); |
| 1090 __ mov(RA, TMP1); // Restore RA. |
| 1091 // Preserve PP of caller. |
| 1092 __ mov(T1, PP); |
| 1093 // Temporarily setup pool pointer for this dart function. |
| 1094 __ lw(PP, Address(T2, -object_pool_pc_dist)); |
| 1095 // Load function object from object pool. |
| 1096 __ LoadObject(function_reg, function); // Uses PP. |
| 1097 // Restore PP of caller. |
| 1098 __ mov(PP, T1); |
| 1084 | 1099 |
| 1085 // Calculate offset of pool pointer from the PC. | |
| 1086 const intptr_t object_pool_pc_dist = | |
| 1087 Instructions::HeaderSize() - Instructions::object_pool_offset() + | |
| 1088 assembler()->CodeSize(); | |
| 1089 | |
| 1090 __ Bind(&next); | |
| 1091 __ mov(RA, TMP1); // Restore RA. | |
| 1092 | |
| 1093 // Preserve PP of caller. | |
| 1094 __ mov(T1, PP); | |
| 1095 | |
| 1096 // Temporarily setup pool pointer for this dart function. | |
| 1097 __ lw(PP, Address(T2, -object_pool_pc_dist)); | |
| 1098 | |
| 1099 // Load function object from object pool. | |
| 1100 __ LoadObject(function_reg, function); // Uses PP. | |
| 1101 | |
| 1102 // Restore PP of caller. | |
| 1103 __ mov(PP, T1); | |
| 1104 } | |
| 1105 // Patch point is after the eventually inlined function object. | 1100 // Patch point is after the eventually inlined function object. |
| 1106 AddCurrentDescriptor(PcDescriptors::kEntryPatch, | 1101 AddCurrentDescriptor(PcDescriptors::kEntryPatch, |
| 1107 Isolate::kNoDeoptId, | 1102 Isolate::kNoDeoptId, |
| 1108 0); // No token position. | 1103 0); // No token position. |
| 1109 if (can_optimize) { | 1104 intptr_t threshold = FLAG_optimization_counter_threshold; |
| 1110 // Reoptimization of optimized function is triggered by counting in | 1105 __ lw(T1, FieldAddress(function_reg, Function::usage_counter_offset())); |
| 1106 if (is_optimizing()) { |
| 1107 // Reoptimization of an optimized function is triggered by counting in |
| 1111 // IC stubs, but not at the entry of the function. | 1108 // IC stubs, but not at the entry of the function. |
| 1112 if (!is_optimizing()) { | 1109 threshold = FLAG_reoptimization_counter_threshold; |
| 1113 __ lw(T1, FieldAddress(function_reg, | 1110 } else { |
| 1114 Function::usage_counter_offset())); | 1111 __ addiu(T1, T1, Immediate(1)); |
| 1115 __ addiu(T1, T1, Immediate(1)); | 1112 __ sw(T1, FieldAddress(function_reg, Function::usage_counter_offset())); |
| 1116 __ sw(T1, FieldAddress(function_reg, | 1113 } |
| 1117 Function::usage_counter_offset())); | |
| 1118 } else { | |
| 1119 __ lw(T1, FieldAddress(function_reg, | |
| 1120 Function::usage_counter_offset())); | |
| 1121 } | |
| 1122 | 1114 |
| 1123 // Skip Branch if T1 is less than the threshold. | 1115 // Skip Branch if T1 is less than the threshold. |
| 1124 Label dont_branch; | 1116 Label dont_branch; |
| 1125 __ BranchSignedLess(T1, FLAG_optimization_counter_threshold, | 1117 __ BranchSignedLess(T1, threshold, &dont_branch); |
| 1126 &dont_branch); | |
| 1127 | 1118 |
| 1128 ASSERT(function_reg == T0); | 1119 ASSERT(function_reg == T0); |
| 1129 __ Branch(&StubCode::OptimizeFunctionLabel()); | 1120 __ Branch(&StubCode::OptimizeFunctionLabel()); |
| 1130 | 1121 |
| 1131 __ Bind(&dont_branch); | 1122 __ Bind(&dont_branch); |
| 1132 } | 1123 |
| 1133 } else { | 1124 } else if (!flow_graph().IsCompiledForOsr()) { |
| 1134 AddCurrentDescriptor(PcDescriptors::kEntryPatch, | 1125 AddCurrentDescriptor(PcDescriptors::kEntryPatch, |
| 1135 Isolate::kNoDeoptId, | 1126 Isolate::kNoDeoptId, |
| 1136 0); // No token position. | 1127 0); // No token position. |
| 1137 } | 1128 } |
| 1138 __ Comment("Enter frame"); | 1129 __ Comment("Enter frame"); |
| 1139 __ EnterDartFrame(StackSize() * kWordSize); | 1130 if (flow_graph().IsCompiledForOsr()) { |
| 1131 intptr_t extra_slots = StackSize() |
| 1132 - flow_graph().num_stack_locals() |
| 1133 - flow_graph().num_copied_params(); |
| 1134 ASSERT(extra_slots >= 0); |
| 1135 __ EnterOsrFrame(extra_slots * kWordSize); |
| 1136 } else { |
| 1137 ASSERT(StackSize() >= 0); |
| 1138 __ EnterDartFrame(StackSize() * kWordSize); |
| 1139 } |
| 1140 } | 1140 } |
| 1141 | 1141 |
| 1142 | 1142 |
| 1143 // Input parameters: | 1143 // Input parameters: |
| 1144 // RA: return address. | 1144 // RA: return address. |
| 1145 // SP: address of last argument. | 1145 // SP: address of last argument. |
| 1146 // FP: caller's frame pointer. | 1146 // FP: caller's frame pointer. |
| 1147 // PP: caller's pool pointer. | 1147 // PP: caller's pool pointer. |
| 1148 // S5: ic-data. | 1148 // S5: ic-data. |
| 1149 // S4: arguments descriptor array. | 1149 // S4: arguments descriptor array. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1166 const int num_copied_params = parsed_function().num_copied_params(); | 1166 const int num_copied_params = parsed_function().num_copied_params(); |
| 1167 const int num_locals = parsed_function().num_stack_locals(); | 1167 const int num_locals = parsed_function().num_stack_locals(); |
| 1168 | 1168 |
| 1169 // We check the number of passed arguments when we have to copy them due to | 1169 // We check the number of passed arguments when we have to copy them due to |
| 1170 // the presence of optional parameters. | 1170 // the presence of optional parameters. |
| 1171 // No such checking code is generated if only fixed parameters are declared, | 1171 // No such checking code is generated if only fixed parameters are declared, |
| 1172 // unless we are in debug mode or unless we are compiling a closure. | 1172 // unless we are in debug mode or unless we are compiling a closure. |
| 1173 if (num_copied_params == 0) { | 1173 if (num_copied_params == 0) { |
| 1174 #ifdef DEBUG | 1174 #ifdef DEBUG |
| 1175 ASSERT(!parsed_function().function().HasOptionalParameters()); | 1175 ASSERT(!parsed_function().function().HasOptionalParameters()); |
| 1176 const bool check_arguments = true; | 1176 const bool check_arguments = !flow_graph().IsCompiledForOsr(); |
| 1177 #else | 1177 #else |
| 1178 const bool check_arguments = | 1178 const bool check_arguments = |
| 1179 function.IsClosureFunction() || function.IsNoSuchMethodDispatcher(); | 1179 (function.IsClosureFunction() || function.IsNoSuchMethodDispatcher()) && |
| 1180 !flow_graph().IsCompiledForOsr(); |
| 1180 #endif | 1181 #endif |
| 1181 if (check_arguments) { | 1182 if (check_arguments) { |
| 1182 __ TraceSimMsg("Check argument count"); | 1183 __ TraceSimMsg("Check argument count"); |
| 1183 __ Comment("Check argument count"); | 1184 __ Comment("Check argument count"); |
| 1184 // Check that exactly num_fixed arguments are passed in. | 1185 // Check that exactly num_fixed arguments are passed in. |
| 1185 Label correct_num_arguments, wrong_num_arguments; | 1186 Label correct_num_arguments, wrong_num_arguments; |
| 1186 __ lw(T0, FieldAddress(S4, ArgumentsDescriptor::count_offset())); | 1187 __ lw(T0, FieldAddress(S4, ArgumentsDescriptor::count_offset())); |
| 1187 __ BranchNotEqual(T0, Smi::RawValue(num_fixed_params), | 1188 __ BranchNotEqual(T0, Smi::RawValue(num_fixed_params), |
| 1188 &wrong_num_arguments); | 1189 &wrong_num_arguments); |
| 1189 | 1190 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1205 __ LoadObject(S5, ic_data); | 1206 __ LoadObject(S5, ic_data); |
| 1206 __ LeaveDartFrame(); // The arguments are still on the stack. | 1207 __ LeaveDartFrame(); // The arguments are still on the stack. |
| 1207 __ Branch(&StubCode::CallNoSuchMethodFunctionLabel()); | 1208 __ Branch(&StubCode::CallNoSuchMethodFunctionLabel()); |
| 1208 // The noSuchMethod call may return to the caller, but not here. | 1209 // The noSuchMethod call may return to the caller, but not here. |
| 1209 __ break_(0); | 1210 __ break_(0); |
| 1210 } else { | 1211 } else { |
| 1211 __ Stop("Wrong number of arguments"); | 1212 __ Stop("Wrong number of arguments"); |
| 1212 } | 1213 } |
| 1213 __ Bind(&correct_num_arguments); | 1214 __ Bind(&correct_num_arguments); |
| 1214 } | 1215 } |
| 1215 } else { | 1216 } else if (!flow_graph().IsCompiledForOsr()) { |
| 1216 CopyParameters(); | 1217 CopyParameters(); |
| 1217 } | 1218 } |
| 1218 | 1219 |
| 1219 // In unoptimized code, initialize (non-argument) stack allocated slots to | 1220 // In unoptimized code, initialize (non-argument) stack allocated slots to |
| 1220 // null. | 1221 // null. |
| 1221 if (!is_optimizing() && (num_locals > 0)) { | 1222 if (!is_optimizing() && (num_locals > 0)) { |
| 1222 __ TraceSimMsg("Initialize spill slots"); | 1223 __ TraceSimMsg("Initialize spill slots"); |
| 1223 __ Comment("Initialize spill slots"); | 1224 __ Comment("Initialize spill slots"); |
| 1224 const intptr_t slot_base = parsed_function().first_stack_local_index(); | 1225 const intptr_t slot_base = parsed_function().first_stack_local_index(); |
| 1225 for (intptr_t i = 0; i < num_locals; ++i) { | 1226 for (intptr_t i = 0; i < num_locals; ++i) { |
| (...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1997 __ AddImmediate(SP, kDoubleSize); | 1998 __ AddImmediate(SP, kDoubleSize); |
| 1998 } | 1999 } |
| 1999 | 2000 |
| 2000 | 2001 |
| 2001 #undef __ | 2002 #undef __ |
| 2002 | 2003 |
| 2003 | 2004 |
| 2004 } // namespace dart | 2005 } // namespace dart |
| 2005 | 2006 |
| 2006 #endif // defined TARGET_ARCH_MIPS | 2007 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |