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/code_generator.h" | 5 #include "vm/code_generator.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
8 #include "vm/ast.h" | 8 #include "vm/ast.h" |
9 #include "vm/code_patcher.h" | 9 #include "vm/code_patcher.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 #include "vm/symbols.h" | 24 #include "vm/symbols.h" |
25 #include "vm/thread_registry.h" | 25 #include "vm/thread_registry.h" |
26 #include "vm/verifier.h" | 26 #include "vm/verifier.h" |
27 | 27 |
28 namespace dart { | 28 namespace dart { |
29 | 29 |
30 DEFINE_FLAG(int, max_subtype_cache_entries, 100, | 30 DEFINE_FLAG(int, max_subtype_cache_entries, 100, |
31 "Maximum number of subtype cache entries (number of checks cached)."); | 31 "Maximum number of subtype cache entries (number of checks cached)."); |
32 DEFINE_FLAG(int, regexp_optimization_counter_threshold, 1000, | 32 DEFINE_FLAG(int, regexp_optimization_counter_threshold, 1000, |
33 "RegExp's usage-counter value before it is optimized, -1 means never"); | 33 "RegExp's usage-counter value before it is optimized, -1 means never"); |
34 DEFINE_FLAG(charp, optimization_filter, NULL, "Optimize only named function"); | |
35 DEFINE_FLAG(int, reoptimization_counter_threshold, 4000, | 34 DEFINE_FLAG(int, reoptimization_counter_threshold, 4000, |
36 "Counter threshold before a function gets reoptimized."); | 35 "Counter threshold before a function gets reoptimized."); |
37 DEFINE_FLAG(bool, stop_on_excessive_deoptimization, false, | |
38 "Debugging: stops program if deoptimizing same function too often"); | |
39 DEFINE_FLAG(bool, trace_deoptimization, false, "Trace deoptimization"); | 36 DEFINE_FLAG(bool, trace_deoptimization, false, "Trace deoptimization"); |
40 DEFINE_FLAG(bool, trace_deoptimization_verbose, false, | 37 DEFINE_FLAG(bool, trace_deoptimization_verbose, false, |
41 "Trace deoptimization verbose"); | 38 "Trace deoptimization verbose"); |
42 DEFINE_FLAG(bool, trace_failed_optimization_attempts, false, | |
43 "Traces all failed optimization attempts"); | |
44 DEFINE_FLAG(bool, trace_ic, false, "Trace IC handling"); | 39 DEFINE_FLAG(bool, trace_ic, false, "Trace IC handling"); |
45 DEFINE_FLAG(bool, trace_ic_miss_in_optimized, false, | 40 DEFINE_FLAG(bool, trace_ic_miss_in_optimized, false, |
46 "Trace IC miss in optimized code"); | 41 "Trace IC miss in optimized code"); |
47 DEFINE_FLAG(bool, trace_optimized_ic_calls, false, | 42 DEFINE_FLAG(bool, trace_optimized_ic_calls, false, |
48 "Trace IC calls in optimized code."); | 43 "Trace IC calls in optimized code."); |
49 DEFINE_FLAG(bool, trace_patching, false, "Trace patching of code."); | 44 DEFINE_FLAG(bool, trace_patching, false, "Trace patching of code."); |
50 DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls"); | 45 DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls"); |
51 DEFINE_FLAG(bool, trace_type_checks, false, "Trace runtime type checks."); | 46 DEFINE_FLAG(bool, trace_type_checks, false, "Trace runtime type checks."); |
52 | 47 |
53 DECLARE_FLAG(int, max_deoptimization_counter_threshold); | 48 DECLARE_FLAG(int, max_deoptimization_counter_threshold); |
(...skipping 1134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1188 const Object& result = Object::Handle( | 1183 const Object& result = Object::Handle( |
1189 DartEntry::InvokeNoSuchMethod(receiver, | 1184 DartEntry::InvokeNoSuchMethod(receiver, |
1190 original_function_name, | 1185 original_function_name, |
1191 orig_arguments, | 1186 orig_arguments, |
1192 orig_arguments_desc)); | 1187 orig_arguments_desc)); |
1193 CheckResultError(result); | 1188 CheckResultError(result); |
1194 arguments.SetReturn(result); | 1189 arguments.SetReturn(result); |
1195 } | 1190 } |
1196 | 1191 |
1197 | 1192 |
1198 static bool CanOptimizeFunction(const Function& function, Thread* thread) { | |
1199 if (FLAG_support_debugger) { | |
1200 Isolate* isolate = thread->isolate(); | |
1201 if (isolate->debugger()->IsStepping() || | |
1202 isolate->debugger()->HasBreakpoint(function, thread->zone())) { | |
1203 // We cannot set breakpoints and single step in optimized code, | |
1204 // so do not optimize the function. | |
1205 function.set_usage_counter(0); | |
1206 return false; | |
1207 } | |
1208 } | |
1209 if (function.deoptimization_counter() >= | |
1210 FLAG_max_deoptimization_counter_threshold) { | |
1211 if (FLAG_trace_failed_optimization_attempts || | |
1212 FLAG_stop_on_excessive_deoptimization) { | |
1213 THR_Print("Too many deoptimizations: %s\n", | |
1214 function.ToFullyQualifiedCString()); | |
1215 if (FLAG_stop_on_excessive_deoptimization) { | |
1216 FATAL("Stop on excessive deoptimization"); | |
1217 } | |
1218 } | |
1219 // The function will not be optimized any longer. This situation can occur | |
1220 // mostly with small optimization counter thresholds. | |
1221 function.SetIsOptimizable(false); | |
1222 function.set_usage_counter(INT_MIN); | |
1223 return false; | |
1224 } | |
1225 if (FLAG_optimization_filter != NULL) { | |
1226 // FLAG_optimization_filter is a comma-separated list of strings that are | |
1227 // matched against the fully-qualified function name. | |
1228 char* save_ptr; // Needed for strtok_r. | |
1229 const char* function_name = function.ToFullyQualifiedCString(); | |
1230 intptr_t len = strlen(FLAG_optimization_filter) + 1; // Length with \0. | |
1231 char* filter = new char[len]; | |
1232 strncpy(filter, FLAG_optimization_filter, len); // strtok modifies arg 1. | |
1233 char* token = strtok_r(filter, ",", &save_ptr); | |
1234 bool found = false; | |
1235 while (token != NULL) { | |
1236 if (strstr(function_name, token) != NULL) { | |
1237 found = true; | |
1238 break; | |
1239 } | |
1240 token = strtok_r(NULL, ",", &save_ptr); | |
1241 } | |
1242 delete[] filter; | |
1243 if (!found) { | |
1244 function.set_usage_counter(INT_MIN); | |
1245 return false; | |
1246 } | |
1247 } | |
1248 if (!function.IsOptimizable()) { | |
1249 // Huge methods (code size above --huge_method_cutoff_in_code_size) become | |
1250 // non-optimizable only after the code has been generated. | |
1251 if (FLAG_trace_failed_optimization_attempts) { | |
1252 THR_Print("Not optimizable: %s\n", function.ToFullyQualifiedCString()); | |
1253 } | |
1254 function.set_usage_counter(INT_MIN); | |
1255 return false; | |
1256 } | |
1257 return true; | |
1258 } | |
1259 | |
1260 | |
1261 DEFINE_RUNTIME_ENTRY(StackOverflow, 0) { | 1193 DEFINE_RUNTIME_ENTRY(StackOverflow, 0) { |
1262 #if defined(USING_SIMULATOR) | 1194 #if defined(USING_SIMULATOR) |
1263 uword stack_pos = Simulator::Current()->get_register(SPREG); | 1195 uword stack_pos = Simulator::Current()->get_register(SPREG); |
1264 #else | 1196 #else |
1265 uword stack_pos = Thread::GetCurrentStackPointer(); | 1197 uword stack_pos = Thread::GetCurrentStackPointer(); |
1266 #endif | 1198 #endif |
1267 // Always clear the stack overflow flags. They are meant for this | 1199 // Always clear the stack overflow flags. They are meant for this |
1268 // particular stack overflow runtime call and are not meant to | 1200 // particular stack overflow runtime call and are not meant to |
1269 // persist. | 1201 // persist. |
1270 uword stack_overflow_flags = thread->GetAndClearStackOverflowFlags(); | 1202 uword stack_overflow_flags = thread->GetAndClearStackOverflowFlags(); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1357 ASSERT(frame != NULL); | 1289 ASSERT(frame != NULL); |
1358 const Code& code = Code::ZoneHandle(frame->LookupDartCode()); | 1290 const Code& code = Code::ZoneHandle(frame->LookupDartCode()); |
1359 ASSERT(!code.IsNull()); | 1291 ASSERT(!code.IsNull()); |
1360 const Function& function = Function::Handle(code.function()); | 1292 const Function& function = Function::Handle(code.function()); |
1361 ASSERT(!function.IsNull()); | 1293 ASSERT(!function.IsNull()); |
1362 // Since the code is referenced from the frame and the ZoneHandle, | 1294 // Since the code is referenced from the frame and the ZoneHandle, |
1363 // it cannot have been removed from the function. | 1295 // it cannot have been removed from the function. |
1364 ASSERT(function.HasCode()); | 1296 ASSERT(function.HasCode()); |
1365 // Don't do OSR on intrinsified functions: The intrinsic code expects to be | 1297 // Don't do OSR on intrinsified functions: The intrinsic code expects to be |
1366 // called like a regular function and can't be entered via OSR. | 1298 // called like a regular function and can't be entered via OSR. |
1367 if (!CanOptimizeFunction(function, thread) || function.is_intrinsic()) { | 1299 if (!Compiler::CanOptimizeFunction(thread, function) || |
| 1300 function.is_intrinsic()) { |
1368 return; | 1301 return; |
1369 } | 1302 } |
1370 | 1303 |
1371 // The unoptimized code is on the stack and should never be detached from | 1304 // The unoptimized code is on the stack and should never be detached from |
1372 // the function at this point. | 1305 // the function at this point. |
1373 ASSERT(function.unoptimized_code() != Object::null()); | 1306 ASSERT(function.unoptimized_code() != Object::null()); |
1374 intptr_t osr_id = | 1307 intptr_t osr_id = |
1375 Code::Handle(function.unoptimized_code()).GetDeoptIdForOsr(frame->pc()); | 1308 Code::Handle(function.unoptimized_code()).GetDeoptIdForOsr(frame->pc()); |
1376 ASSERT(osr_id != Compiler::kNoOSRDeoptId); | 1309 ASSERT(osr_id != Compiler::kNoOSRDeoptId); |
1377 if (FLAG_trace_osr) { | 1310 if (FLAG_trace_osr) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1427 // This is called from function that needs to be optimized. | 1360 // This is called from function that needs to be optimized. |
1428 // The requesting function can be already optimized (reoptimization). | 1361 // The requesting function can be already optimized (reoptimization). |
1429 // Returns the Code object where to continue execution. | 1362 // Returns the Code object where to continue execution. |
1430 DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) { | 1363 DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) { |
1431 #if !defined(DART_PRECOMPILED_RUNTIME) | 1364 #if !defined(DART_PRECOMPILED_RUNTIME) |
1432 const Function& function = Function::CheckedHandle(zone, | 1365 const Function& function = Function::CheckedHandle(zone, |
1433 arguments.ArgAt(0)); | 1366 arguments.ArgAt(0)); |
1434 ASSERT(!function.IsNull()); | 1367 ASSERT(!function.IsNull()); |
1435 ASSERT(function.HasCode()); | 1368 ASSERT(function.HasCode()); |
1436 | 1369 |
1437 if (CanOptimizeFunction(function, thread)) { | 1370 if (Compiler::CanOptimizeFunction(thread, function)) { |
1438 if (FLAG_background_compilation) { | 1371 if (FLAG_background_compilation) { |
1439 Field& field = Field::Handle(zone, isolate->GetDeoptimizingBoxedField()); | 1372 Field& field = Field::Handle(zone, isolate->GetDeoptimizingBoxedField()); |
1440 while (!field.IsNull()) { | 1373 while (!field.IsNull()) { |
1441 if (FLAG_trace_optimization || FLAG_trace_field_guards) { | 1374 if (FLAG_trace_optimization || FLAG_trace_field_guards) { |
1442 THR_Print("Lazy disabling unboxing of %s\n", field.ToCString()); | 1375 THR_Print("Lazy disabling unboxing of %s\n", field.ToCString()); |
1443 } | 1376 } |
1444 field.set_is_unboxing_candidate(false); | 1377 field.set_is_unboxing_candidate(false); |
1445 field.DeoptimizeDependentCode(); | 1378 field.DeoptimizeDependentCode(); |
1446 // Get next field. | 1379 // Get next field. |
1447 field = isolate->GetDeoptimizingBoxedField(); | 1380 field = isolate->GetDeoptimizingBoxedField(); |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1885 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 1818 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
1886 const TypedData& new_data = | 1819 const TypedData& new_data = |
1887 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 1820 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
1888 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 1821 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
1889 typed_data_cell.SetAt(0, new_data); | 1822 typed_data_cell.SetAt(0, new_data); |
1890 arguments.SetReturn(new_data); | 1823 arguments.SetReturn(new_data); |
1891 } | 1824 } |
1892 | 1825 |
1893 | 1826 |
1894 } // namespace dart | 1827 } // namespace dart |
OLD | NEW |