| 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/compiler.h" | 5 #include "vm/compiler.h" |
| 6 | 6 |
| 7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
| 8 | 8 |
| 9 #include "vm/ast_printer.h" | 9 #include "vm/ast_printer.h" |
| 10 #include "vm/block_scheduler.h" | 10 #include "vm/block_scheduler.h" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 DEFINE_FLAG(bool, loop_invariant_code_motion, true, | 53 DEFINE_FLAG(bool, loop_invariant_code_motion, true, |
| 54 "Do loop invariant code motion."); | 54 "Do loop invariant code motion."); |
| 55 DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph."); | 55 DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph."); |
| 56 DEFINE_FLAG(bool, print_flow_graph_optimized, false, | 56 DEFINE_FLAG(bool, print_flow_graph_optimized, false, |
| 57 "Print the IR flow graph when optimizing."); | 57 "Print the IR flow graph when optimizing."); |
| 58 DEFINE_FLAG(bool, print_ic_data_map, false, | 58 DEFINE_FLAG(bool, print_ic_data_map, false, |
| 59 "Print the deopt-id to ICData map in optimizing compiler."); | 59 "Print the deopt-id to ICData map in optimizing compiler."); |
| 60 DEFINE_FLAG(bool, range_analysis, true, "Enable range analysis"); | 60 DEFINE_FLAG(bool, range_analysis, true, "Enable range analysis"); |
| 61 DEFINE_FLAG(bool, reorder_basic_blocks, true, "Enable basic-block reordering."); | 61 DEFINE_FLAG(bool, reorder_basic_blocks, true, "Enable basic-block reordering."); |
| 62 DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations."); | 62 DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations."); |
| 63 DEFINE_FLAG(bool, trace_optimizing_compiler, false, |
| 64 "Trace only optimizing compiler operations."); |
| 63 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler."); | 65 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler."); |
| 64 DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining"); | 66 DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining"); |
| 65 DEFINE_FLAG(bool, verify_compiler, false, | 67 DEFINE_FLAG(bool, verify_compiler, false, |
| 66 "Enable compiler verification assertions"); | 68 "Enable compiler verification assertions"); |
| 67 DEFINE_FLAG(int, max_speculative_inlining_attempts, 1, | 69 DEFINE_FLAG(int, max_speculative_inlining_attempts, 1, |
| 68 "Max number of attempts with speculative inlining (precompilation only)"); | 70 "Max number of attempts with speculative inlining (precompilation only)"); |
| 69 | 71 |
| 70 DECLARE_FLAG(bool, background_compilation); | 72 DECLARE_FLAG(bool, background_compilation); |
| 71 DECLARE_FLAG(bool, load_deferred_eagerly); | 73 DECLARE_FLAG(bool, load_deferred_eagerly); |
| 72 DECLARE_FLAG(bool, trace_failed_optimization_attempts); | 74 DECLARE_FLAG(bool, trace_failed_optimization_attempts); |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 | 494 |
| 493 if (optimized()) { | 495 if (optimized()) { |
| 494 // Installs code while at safepoint. | 496 // Installs code while at safepoint. |
| 495 if (thread()->IsMutatorThread()) { | 497 if (thread()->IsMutatorThread()) { |
| 496 const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId; | 498 const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId; |
| 497 function.InstallOptimizedCode(code, is_osr); | 499 function.InstallOptimizedCode(code, is_osr); |
| 498 } else { | 500 } else { |
| 499 // Background compilation. | 501 // Background compilation. |
| 500 // Before installing code check generation counts if the code may | 502 // Before installing code check generation counts if the code may |
| 501 // have become invalid. | 503 // have become invalid. |
| 504 const bool trace_compiler = |
| 505 FLAG_trace_compiler || FLAG_trace_optimizing_compiler; |
| 502 bool code_is_valid = true; | 506 bool code_is_valid = true; |
| 503 if (!thread()->cha()->leaf_classes().is_empty()) { | 507 if (!thread()->cha()->leaf_classes().is_empty()) { |
| 504 if (cha_invalidation_gen_at_start() != | 508 if (cha_invalidation_gen_at_start() != |
| 505 isolate()->cha_invalidation_gen()) { | 509 isolate()->cha_invalidation_gen()) { |
| 506 code_is_valid = false; | 510 code_is_valid = false; |
| 511 if (trace_compiler) { |
| 512 THR_Print("--> FAIL: CHA invalidation."); |
| 513 } |
| 507 } | 514 } |
| 508 } | 515 } |
| 509 if (!flow_graph->guarded_fields()->is_empty()) { | 516 if (!flow_graph->guarded_fields()->is_empty()) { |
| 510 if (field_invalidation_gen_at_start() != | 517 if (field_invalidation_gen_at_start() != |
| 511 isolate()->field_invalidation_gen()) { | 518 isolate()->field_invalidation_gen()) { |
| 512 code_is_valid = false; | 519 code_is_valid = false; |
| 520 if (trace_compiler) { |
| 521 THR_Print("--> FAIL: Field invalidation."); |
| 522 } |
| 513 } | 523 } |
| 514 } | 524 } |
| 515 if (parsed_function()->HasDeferredPrefixes()) { | 525 if (parsed_function()->HasDeferredPrefixes()) { |
| 516 if (prefix_invalidation_gen_at_start() != | 526 if (prefix_invalidation_gen_at_start() != |
| 517 isolate()->prefix_invalidation_gen()) { | 527 isolate()->prefix_invalidation_gen()) { |
| 518 code_is_valid = false; | 528 code_is_valid = false; |
| 529 if (trace_compiler) { |
| 530 THR_Print("--> FAIL: Prefix invalidation."); |
| 531 } |
| 519 } | 532 } |
| 520 } | 533 } |
| 521 if (code_is_valid) { | 534 if (code_is_valid) { |
| 522 const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId; | 535 const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId; |
| 523 ASSERT(!is_osr); // OSR is compiled in background. | 536 ASSERT(!is_osr); // OSR is compiled in background. |
| 524 function.InstallOptimizedCode(code, is_osr); | 537 function.InstallOptimizedCode(code, is_osr); |
| 525 } | 538 } |
| 526 if (function.usage_counter() < 0) { | 539 if (function.usage_counter() < 0) { |
| 527 // Reset to 0 so that it can be recompiled if needed. | 540 // Reset to 0 so that it can be recompiled if needed. |
| 528 function.set_usage_counter(0); | 541 function.set_usage_counter(0); |
| (...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1072 ASSERT(Compiler::always_optimize()); | 1085 ASSERT(Compiler::always_optimize()); |
| 1073 ASSERT(use_speculative_inlining); | 1086 ASSERT(use_speculative_inlining); |
| 1074 for (intptr_t i = 0; i < inlining_black_list.length(); ++i) { | 1087 for (intptr_t i = 0; i < inlining_black_list.length(); ++i) { |
| 1075 ASSERT(inlining_black_list[i] != val); | 1088 ASSERT(inlining_black_list[i] != val); |
| 1076 } | 1089 } |
| 1077 #endif | 1090 #endif |
| 1078 inlining_black_list.Add(val); | 1091 inlining_black_list.Add(val); |
| 1079 const intptr_t max_attempts = FLAG_max_speculative_inlining_attempts; | 1092 const intptr_t max_attempts = FLAG_max_speculative_inlining_attempts; |
| 1080 if (inlining_black_list.length() >= max_attempts) { | 1093 if (inlining_black_list.length() >= max_attempts) { |
| 1081 use_speculative_inlining = false; | 1094 use_speculative_inlining = false; |
| 1082 if (FLAG_trace_compiler) { | 1095 if (FLAG_trace_compiler || FLAG_trace_optimizing_compiler) { |
| 1083 THR_Print("Disabled speculative inlining after %" Pd " attempts.\n", | 1096 THR_Print("Disabled speculative inlining after %" Pd " attempts.\n", |
| 1084 inlining_black_list.length()); | 1097 inlining_black_list.length()); |
| 1085 } | 1098 } |
| 1086 } | 1099 } |
| 1087 } else { | 1100 } else { |
| 1088 // If the error isn't due to an out of range branch offset, we don't | 1101 // If the error isn't due to an out of range branch offset, we don't |
| 1089 // try again (done = true), and indicate that we did not finish | 1102 // try again (done = true), and indicate that we did not finish |
| 1090 // compiling (is_compiled = false). | 1103 // compiling (is_compiled = false). |
| 1091 if (FLAG_trace_bailout) { | 1104 if (FLAG_trace_bailout) { |
| 1092 THR_Print("%s\n", error.ToErrorCString()); | 1105 THR_Print("%s\n", error.ToErrorCString()); |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1277 // except if the function is marked as not optimizable. | 1290 // except if the function is marked as not optimizable. |
| 1278 ASSERT(!function.IsOptimizable() || | 1291 ASSERT(!function.IsOptimizable() || |
| 1279 !Compiler::always_optimize() || optimized); | 1292 !Compiler::always_optimize() || optimized); |
| 1280 ASSERT(Compiler::allow_recompilation() || !function.HasCode()); | 1293 ASSERT(Compiler::allow_recompilation() || !function.HasCode()); |
| 1281 LongJumpScope jump; | 1294 LongJumpScope jump; |
| 1282 if (setjmp(*jump.Set()) == 0) { | 1295 if (setjmp(*jump.Set()) == 0) { |
| 1283 Thread* const thread = Thread::Current(); | 1296 Thread* const thread = Thread::Current(); |
| 1284 Isolate* const isolate = thread->isolate(); | 1297 Isolate* const isolate = thread->isolate(); |
| 1285 StackZone stack_zone(thread); | 1298 StackZone stack_zone(thread); |
| 1286 Zone* const zone = stack_zone.GetZone(); | 1299 Zone* const zone = stack_zone.GetZone(); |
| 1287 Timer per_compile_timer(FLAG_trace_compiler, "Compilation time"); | 1300 const bool trace_compiler = |
| 1301 FLAG_trace_compiler || |
| 1302 (FLAG_trace_optimizing_compiler && optimized); |
| 1303 Timer per_compile_timer(trace_compiler, "Compilation time"); |
| 1288 per_compile_timer.Start(); | 1304 per_compile_timer.Start(); |
| 1289 | 1305 |
| 1290 ParsedFunction* parsed_function = new(zone) ParsedFunction( | 1306 ParsedFunction* parsed_function = new(zone) ParsedFunction( |
| 1291 thread, Function::ZoneHandle(zone, function.raw())); | 1307 thread, Function::ZoneHandle(zone, function.raw())); |
| 1292 if (FLAG_trace_compiler) { | 1308 if (trace_compiler) { |
| 1293 THR_Print("Compiling %s%sfunction: '%s' @ token %" Pd ", size %" Pd "\n", | 1309 THR_Print("Compiling %s%sfunction: '%s' @ token %" Pd ", size %" Pd "\n", |
| 1294 (osr_id == Compiler::kNoOSRDeoptId ? "" : "osr "), | 1310 (osr_id == Compiler::kNoOSRDeoptId ? "" : "osr "), |
| 1295 (optimized ? "optimized " : ""), | 1311 (optimized ? "optimized " : ""), |
| 1296 function.ToFullyQualifiedCString(), | 1312 function.ToFullyQualifiedCString(), |
| 1297 function.token_pos(), | 1313 function.token_pos(), |
| 1298 (function.end_token_pos() - function.token_pos())); | 1314 (function.end_token_pos() - function.token_pos())); |
| 1299 } | 1315 } |
| 1300 INC_STAT(thread, num_functions_compiled, 1); | 1316 INC_STAT(thread, num_functions_compiled, 1); |
| 1301 if (optimized) { | 1317 if (optimized) { |
| 1302 INC_STAT(thread, num_functions_optimized, 1); | 1318 INC_STAT(thread, num_functions_optimized, 1); |
| 1303 } | 1319 } |
| 1304 { | 1320 { |
| 1305 HANDLESCOPE(thread); | 1321 HANDLESCOPE(thread); |
| 1306 const int64_t num_tokens_before = STAT_VALUE(thread, num_tokens_consumed); | 1322 const int64_t num_tokens_before = STAT_VALUE(thread, num_tokens_consumed); |
| 1307 pipeline->ParseFunction(parsed_function); | 1323 pipeline->ParseFunction(parsed_function); |
| 1308 const int64_t num_tokens_after = STAT_VALUE(thread, num_tokens_consumed); | 1324 const int64_t num_tokens_after = STAT_VALUE(thread, num_tokens_consumed); |
| 1309 INC_STAT(thread, | 1325 INC_STAT(thread, |
| 1310 num_func_tokens_compiled, | 1326 num_func_tokens_compiled, |
| 1311 num_tokens_after - num_tokens_before); | 1327 num_tokens_after - num_tokens_before); |
| 1312 } | 1328 } |
| 1313 | 1329 |
| 1314 CompileParsedFunctionHelper helper(parsed_function, optimized, osr_id); | 1330 CompileParsedFunctionHelper helper(parsed_function, optimized, osr_id); |
| 1315 const bool success = helper.Compile(pipeline); | 1331 const bool success = helper.Compile(pipeline); |
| 1316 if (!success) { | 1332 if (!success) { |
| 1317 if (optimized) { | 1333 if (optimized) { |
| 1318 ASSERT(!Compiler::always_optimize()); // Optimized is the only code. | 1334 ASSERT(!Compiler::always_optimize()); // Optimized is the only code. |
| 1319 // Optimizer bailed out. Disable optimizations and never try again. | 1335 // Optimizer bailed out. Disable optimizations and never try again. |
| 1320 if (FLAG_trace_compiler) { | 1336 if (trace_compiler) { |
| 1321 THR_Print("--> disabling optimizations for '%s'\n", | 1337 THR_Print("--> disabling optimizations for '%s'\n", |
| 1322 function.ToFullyQualifiedCString()); | 1338 function.ToFullyQualifiedCString()); |
| 1323 } else if (FLAG_trace_failed_optimization_attempts) { | 1339 } else if (FLAG_trace_failed_optimization_attempts) { |
| 1324 THR_Print("Cannot optimize: %s\n", | 1340 THR_Print("Cannot optimize: %s\n", |
| 1325 function.ToFullyQualifiedCString()); | 1341 function.ToFullyQualifiedCString()); |
| 1326 } | 1342 } |
| 1327 function.SetIsOptimizable(false); | 1343 function.SetIsOptimizable(false); |
| 1328 return Error::null(); | 1344 return Error::null(); |
| 1329 } else { | 1345 } else { |
| 1330 // Encountered error. | 1346 // Encountered error. |
| 1331 Error& error = Error::Handle(); | 1347 Error& error = Error::Handle(); |
| 1332 // We got an error during compilation. | 1348 // We got an error during compilation. |
| 1333 error = isolate->object_store()->sticky_error(); | 1349 error = isolate->object_store()->sticky_error(); |
| 1334 isolate->object_store()->clear_sticky_error(); | 1350 isolate->object_store()->clear_sticky_error(); |
| 1335 return error.raw(); | 1351 return error.raw(); |
| 1336 } | 1352 } |
| 1337 } | 1353 } |
| 1338 | 1354 |
| 1339 per_compile_timer.Stop(); | 1355 per_compile_timer.Stop(); |
| 1340 | 1356 |
| 1341 if (FLAG_trace_compiler) { | 1357 if (trace_compiler && success) { |
| 1342 THR_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n", | 1358 THR_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n", |
| 1343 function.ToFullyQualifiedCString(), | 1359 function.ToFullyQualifiedCString(), |
| 1344 Code::Handle(function.CurrentCode()).EntryPoint(), | 1360 Code::Handle(function.CurrentCode()).EntryPoint(), |
| 1345 Code::Handle(function.CurrentCode()).Size(), | 1361 Code::Handle(function.CurrentCode()).Size(), |
| 1346 per_compile_timer.TotalElapsedTime()); | 1362 per_compile_timer.TotalElapsedTime()); |
| 1347 } | 1363 } |
| 1348 | 1364 |
| 1349 isolate->debugger()->NotifyCompilation(function); | 1365 isolate->debugger()->NotifyCompilation(function); |
| 1350 | 1366 |
| 1351 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) { | 1367 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) { |
| (...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2015 } | 2031 } |
| 2016 | 2032 |
| 2017 | 2033 |
| 2018 void BackgroundCompiler::EnsureInit(Thread* thread) { | 2034 void BackgroundCompiler::EnsureInit(Thread* thread) { |
| 2019 UNREACHABLE(); | 2035 UNREACHABLE(); |
| 2020 } | 2036 } |
| 2021 | 2037 |
| 2022 #endif // DART_PRECOMPILED | 2038 #endif // DART_PRECOMPILED |
| 2023 | 2039 |
| 2024 } // namespace dart | 2040 } // namespace dart |
| OLD | NEW |