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 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 } | 383 } |
384 | 384 |
385 | 385 |
386 // Return false if bailed out. | 386 // Return false if bailed out. |
387 // If optimized_result_code is not NULL then it is caller's responsibility | 387 // If optimized_result_code is not NULL then it is caller's responsibility |
388 // to install code. | 388 // to install code. |
389 static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, | 389 static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
390 ParsedFunction* parsed_function, | 390 ParsedFunction* parsed_function, |
391 bool optimized, | 391 bool optimized, |
392 intptr_t osr_id, | 392 intptr_t osr_id, |
393 Code* optimized_result_code) { | 393 BackgroundCompilationResult* result) { |
394 const Function& function = parsed_function->function(); | 394 const Function& function = parsed_function->function(); |
395 if (optimized && !function.IsOptimizable()) { | 395 if (optimized && !function.IsOptimizable()) { |
396 return false; | 396 return false; |
397 } | 397 } |
398 bool is_compiled = false; | 398 bool is_compiled = false; |
399 Thread* const thread = Thread::Current(); | 399 Thread* const thread = Thread::Current(); |
400 Zone* const zone = thread->zone(); | 400 Zone* const zone = thread->zone(); |
401 Isolate* const isolate = thread->isolate(); | 401 Isolate* const isolate = thread->isolate(); |
402 CSTAT_TIMER_SCOPE(thread, codegen_timer); | 402 CSTAT_TIMER_SCOPE(thread, codegen_timer); |
403 HANDLESCOPE(thread); | 403 HANDLESCOPE(thread); |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 | 765 |
766 graph_compiler.FinalizePcDescriptors(code); | 766 graph_compiler.FinalizePcDescriptors(code); |
767 code.set_deopt_info_array(deopt_info_array); | 767 code.set_deopt_info_array(deopt_info_array); |
768 | 768 |
769 graph_compiler.FinalizeStackmaps(code); | 769 graph_compiler.FinalizeStackmaps(code); |
770 graph_compiler.FinalizeVarDescriptors(code); | 770 graph_compiler.FinalizeVarDescriptors(code); |
771 graph_compiler.FinalizeExceptionHandlers(code); | 771 graph_compiler.FinalizeExceptionHandlers(code); |
772 graph_compiler.FinalizeStaticCallTargetsTable(code); | 772 graph_compiler.FinalizeStaticCallTargetsTable(code); |
773 | 773 |
774 if (optimized) { | 774 if (optimized) { |
775 if (optimized_result_code != NULL) { | 775 if (result != NULL) { |
| 776 ASSERT(!Thread::Current()->IsMutatorThread()); |
776 // Do not install code, but return it instead. | 777 // Do not install code, but return it instead. |
777 // Since code dependencies (CHA, fields) are defined eagerly, | 778 // Since code dependencies (CHA, fields) are defined eagerly, |
778 // the code may be disabled before installing it. | 779 // the code may be disabled before installing it. |
779 code.set_owner(function); | 780 code.set_owner(function); |
780 *optimized_result_code = code.raw(); | 781 result->set_result_code(code); |
| 782 // Disable invalidation counters that are not relevant. |
| 783 if (thread->cha()->leaf_classes().is_empty()) { |
| 784 result->ClearCHAInvalidationGen(); |
| 785 } |
| 786 if (flow_graph->guarded_fields()->is_empty()) { |
| 787 result->ClearFieldInnvalidationGen(); |
| 788 } |
| 789 if (!parsed_function->HasDeferredPrefixes()) { |
| 790 result->ClearPrefixInnvalidationGen(); |
| 791 } |
781 } else { | 792 } else { |
782 const bool is_osr = osr_id != Compiler::kNoOSRDeoptId; | 793 const bool is_osr = osr_id != Compiler::kNoOSRDeoptId; |
783 function.InstallOptimizedCode(code, is_osr); | 794 function.InstallOptimizedCode(code, is_osr); |
784 } | 795 } |
785 | 796 |
786 // TODO(srdjan): In background compilation, verify that CHA has not | 797 // TODO(srdjan): In background compilation, verify that CHA has not |
787 // been invalidated in the meantime. | 798 // been invalidated in the meantime. |
788 // Register code with the classes it depends on because of CHA. | 799 // Register code with the classes it depends on because of CHA. |
789 for (intptr_t i = 0; | 800 for (intptr_t i = 0; |
790 i < thread->cha()->leaf_classes().length(); | 801 i < thread->cha()->leaf_classes().length(); |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1016 function.raw()); | 1027 function.raw()); |
1017 } | 1028 } |
1018 } | 1029 } |
1019 #endif | 1030 #endif |
1020 | 1031 |
1021 | 1032 |
1022 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline, | 1033 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline, |
1023 const Function& function, | 1034 const Function& function, |
1024 bool optimized, | 1035 bool optimized, |
1025 intptr_t osr_id, | 1036 intptr_t osr_id, |
1026 Code* result_code) { | 1037 BackgroundCompilationResult* result) { |
1027 // Check that we optimize if 'Compiler::always_optimize()' is set to true, | 1038 // Check that we optimize if 'Compiler::always_optimize()' is set to true, |
1028 // except if the function is marked as not optimizable. | 1039 // except if the function is marked as not optimizable. |
1029 ASSERT(!function.IsOptimizable() || | 1040 ASSERT(!function.IsOptimizable() || |
1030 !Compiler::always_optimize() || optimized); | 1041 !Compiler::always_optimize() || optimized); |
1031 ASSERT(Compiler::allow_recompilation() || !function.HasCode()); | 1042 ASSERT(Compiler::allow_recompilation() || !function.HasCode()); |
1032 LongJumpScope jump; | 1043 LongJumpScope jump; |
1033 if (setjmp(*jump.Set()) == 0) { | 1044 if (setjmp(*jump.Set()) == 0) { |
1034 Thread* const thread = Thread::Current(); | 1045 Thread* const thread = Thread::Current(); |
1035 Isolate* const isolate = thread->isolate(); | 1046 Isolate* const isolate = thread->isolate(); |
1036 StackZone stack_zone(thread); | 1047 StackZone stack_zone(thread); |
(...skipping 22 matching lines...) Expand all Loading... |
1059 const int64_t num_tokens_after = STAT_VALUE(thread, num_tokens_consumed); | 1070 const int64_t num_tokens_after = STAT_VALUE(thread, num_tokens_consumed); |
1060 INC_STAT(thread, | 1071 INC_STAT(thread, |
1061 num_func_tokens_compiled, | 1072 num_func_tokens_compiled, |
1062 num_tokens_after - num_tokens_before); | 1073 num_tokens_after - num_tokens_before); |
1063 } | 1074 } |
1064 | 1075 |
1065 const bool success = CompileParsedFunctionHelper(pipeline, | 1076 const bool success = CompileParsedFunctionHelper(pipeline, |
1066 parsed_function, | 1077 parsed_function, |
1067 optimized, | 1078 optimized, |
1068 osr_id, | 1079 osr_id, |
1069 result_code); | 1080 result); |
1070 if (!success) { | 1081 if (!success) { |
1071 if (optimized) { | 1082 if (optimized) { |
1072 ASSERT(!Compiler::always_optimize()); // Optimized is the only code. | 1083 ASSERT(!Compiler::always_optimize()); // Optimized is the only code. |
1073 // Optimizer bailed out. Disable optimizations and never try again. | 1084 // Optimizer bailed out. Disable optimizations and never try again. |
1074 if (FLAG_trace_compiler) { | 1085 if (FLAG_trace_compiler) { |
1075 THR_Print("--> disabling optimizations for '%s'\n", | 1086 THR_Print("--> disabling optimizations for '%s'\n", |
1076 function.ToFullyQualifiedCString()); | 1087 function.ToFullyQualifiedCString()); |
1077 } else if (FLAG_trace_failed_optimization_attempts) { | 1088 } else if (FLAG_trace_failed_optimization_attempts) { |
1078 THR_Print("Cannot optimize: %s\n", | 1089 THR_Print("Cannot optimize: %s\n", |
1079 function.ToFullyQualifiedCString()); | 1090 function.ToFullyQualifiedCString()); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1182 if (FLAG_trace_compiler) { | 1193 if (FLAG_trace_compiler) { |
1183 THR_Print("Ensure unoptimized code for %s\n", function.ToCString()); | 1194 THR_Print("Ensure unoptimized code for %s\n", function.ToCString()); |
1184 } | 1195 } |
1185 return Error::null(); | 1196 return Error::null(); |
1186 } | 1197 } |
1187 | 1198 |
1188 | 1199 |
1189 RawError* Compiler::CompileOptimizedFunction(Thread* thread, | 1200 RawError* Compiler::CompileOptimizedFunction(Thread* thread, |
1190 const Function& function, | 1201 const Function& function, |
1191 intptr_t osr_id, | 1202 intptr_t osr_id, |
1192 Code* result_code) { | 1203 BackgroundCompilationResult* res) { |
1193 VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId); | 1204 VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId); |
1194 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, | 1205 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, |
1195 "OptimizedFunction", function); | 1206 "OptimizedFunction", function); |
1196 | 1207 |
1197 // Optimization must happen in non-mutator/Dart thread if background | 1208 // Optimization must happen in non-mutator/Dart thread if background |
1198 // compilation is on. OSR compilation still occurs in the main thread. | 1209 // compilation is on. OSR compilation still occurs in the main thread. |
1199 ASSERT((osr_id != kNoOSRDeoptId) || !FLAG_background_compilation || | 1210 ASSERT((osr_id != kNoOSRDeoptId) || !FLAG_background_compilation || |
1200 !thread->IsMutatorThread()); | 1211 !thread->IsMutatorThread()); |
1201 CompilationPipeline* pipeline = | 1212 CompilationPipeline* pipeline = |
1202 CompilationPipeline::New(thread->zone(), function); | 1213 CompilationPipeline::New(thread->zone(), function); |
1203 return CompileFunctionHelper(pipeline, | 1214 return CompileFunctionHelper(pipeline, |
1204 function, | 1215 function, |
1205 true, /* optimized */ | 1216 true, /* optimized */ |
1206 osr_id, | 1217 osr_id, |
1207 result_code); | 1218 res); |
1208 } | 1219 } |
1209 | 1220 |
1210 | 1221 |
1211 // This is only used from unit tests. | 1222 // This is only used from unit tests. |
1212 RawError* Compiler::CompileParsedFunction( | 1223 RawError* Compiler::CompileParsedFunction( |
1213 ParsedFunction* parsed_function) { | 1224 ParsedFunction* parsed_function) { |
1214 LongJumpScope jump; | 1225 LongJumpScope jump; |
1215 if (setjmp(*jump.Set()) == 0) { | 1226 if (setjmp(*jump.Set()) == 0) { |
1216 // Non-optimized code generator. | 1227 // Non-optimized code generator. |
1217 DartCompilationPipeline pipeline; | 1228 DartCompilationPipeline pipeline; |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1458 explicit CompilationWorkQueue(GrowableObjectArray* data) : data_(data) {} | 1469 explicit CompilationWorkQueue(GrowableObjectArray* data) : data_(data) {} |
1459 | 1470 |
1460 intptr_t IsEmpty() const { return data_->Length() == 0; } | 1471 intptr_t IsEmpty() const { return data_->Length() == 0; } |
1461 intptr_t Length() const { return data_->Length(); } | 1472 intptr_t Length() const { return data_->Length(); } |
1462 | 1473 |
1463 void PushFrontFunction(const Function& function) { PushFront(function); } | 1474 void PushFrontFunction(const Function& function) { PushFront(function); } |
1464 RawFunction* PopBackFunction() { return Function::RawCast(PopBack()); } | 1475 RawFunction* PopBackFunction() { return Function::RawCast(PopBack()); } |
1465 RawFunction* LastFunction() { return Function::RawCast(Last()); } | 1476 RawFunction* LastFunction() { return Function::RawCast(Last()); } |
1466 | 1477 |
1467 void PushBackCode(const Code& code) { PushBack(code); } | 1478 void PushBackCode(const Code& code) { PushBack(code); } |
| 1479 void PushBackInteger(const Integer& value) { PushBack(value); } |
1468 RawCode* PopBackCode() { return Code::RawCast(PopBack()); } | 1480 RawCode* PopBackCode() { return Code::RawCast(PopBack()); } |
1469 RawCode* LastCode() { return Code::RawCast(Last()); } | 1481 RawInteger* PopBackInteger() { |
| 1482 Object& o = Object::Handle(PopBack()); |
| 1483 if (o.IsNull()) { |
| 1484 return Integer::null(); |
| 1485 } else { |
| 1486 return Integer::Cast(o).raw(); |
| 1487 } |
| 1488 } |
1470 | 1489 |
1471 private: | 1490 private: |
1472 // Adds to the queue only if 'function' is not already in there. | 1491 // Adds to the queue only if 'function' is not already in there. |
1473 void PushFront(const Object& value) { | 1492 void PushFront(const Object& value) { |
1474 for (intptr_t i = 0; i < data_->Length(); i++) { | 1493 for (intptr_t i = 0; i < data_->Length(); i++) { |
1475 if (data_->At(i) == value.raw()) { | 1494 if (data_->At(i) == value.raw()) { |
1476 return; | 1495 return; |
1477 } | 1496 } |
1478 } | 1497 } |
1479 // Insert new element in front. | 1498 // Insert new element in front. |
(...skipping 24 matching lines...) Expand all Loading... |
1504 ASSERT(!IsEmpty()); | 1523 ASSERT(!IsEmpty()); |
1505 return data_->At(data_->Length() - 1); | 1524 return data_->At(data_->Length() - 1); |
1506 } | 1525 } |
1507 | 1526 |
1508 GrowableObjectArray* data_; | 1527 GrowableObjectArray* data_; |
1509 | 1528 |
1510 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationWorkQueue); | 1529 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationWorkQueue); |
1511 }; | 1530 }; |
1512 | 1531 |
1513 | 1532 |
| 1533 |
| 1534 BackgroundCompilationResult::BackgroundCompilationResult() |
| 1535 : result_code_(Code::Handle()), |
| 1536 cha_invalidation_gen_(Integer::Handle()), |
| 1537 field_invalidation_gen_(Integer::Handle()), |
| 1538 prefix_invalidation_gen_(Integer::Handle()) { |
| 1539 } |
| 1540 |
| 1541 |
| 1542 void BackgroundCompilationResult::Init() { |
| 1543 Isolate* i = Isolate::Current(); |
| 1544 result_code_ = Code::null(); |
| 1545 cha_invalidation_gen_ = Integer::New(i->cha_invalidation_gen(), Heap::kOld); |
| 1546 field_invalidation_gen_ = |
| 1547 Integer::New(i->field_invalidation_gen(), Heap::kOld); |
| 1548 prefix_invalidation_gen_ = |
| 1549 Integer::New(i->prefix_invalidation_gen(), Heap::kOld); |
| 1550 } |
| 1551 |
| 1552 |
| 1553 bool BackgroundCompilationResult::IsValid() const { |
| 1554 if (result_code().IsNull() || result_code().IsDisabled()) { |
| 1555 return false; |
| 1556 } |
| 1557 Isolate* i = Isolate::Current(); |
| 1558 if (!cha_invalidation_gen_.IsNull() && |
| 1559 (cha_invalidation_gen_.AsInt64Value() != i->cha_invalidation_gen())) { |
| 1560 return false; |
| 1561 } |
| 1562 if (!field_invalidation_gen_.IsNull() && |
| 1563 (field_invalidation_gen_.AsInt64Value() != i->field_invalidation_gen())) { |
| 1564 return false; |
| 1565 } |
| 1566 if (!prefix_invalidation_gen_.IsNull() && |
| 1567 (prefix_invalidation_gen_.AsInt64Value() != |
| 1568 i->prefix_invalidation_gen())) { |
| 1569 return false; |
| 1570 } |
| 1571 return true; |
| 1572 } |
| 1573 |
| 1574 |
| 1575 void BackgroundCompilationResult::PrintValidity() const { |
| 1576 Object& o = Object::Handle(result_code().owner()); |
| 1577 THR_Print("BackgroundCompilationResult: %s\n", |
| 1578 Function::Cast(o).ToQualifiedCString()); |
| 1579 if (result_code().IsNull()) { |
| 1580 THR_Print(" result_code is NULL\n"); |
| 1581 return; |
| 1582 } |
| 1583 if (result_code().IsDisabled()) { |
| 1584 THR_Print(" result_code is disabled\n"); |
| 1585 return; |
| 1586 } |
| 1587 Isolate* i = Isolate::Current(); |
| 1588 THR_Print(" cha_invalidation_gen: %s (current: %u)\n", |
| 1589 cha_invalidation_gen_.ToCString(), i->cha_invalidation_gen()); |
| 1590 THR_Print(" field_invalidation_gen: %s (current: %u)\n", |
| 1591 field_invalidation_gen_.ToCString(), i->field_invalidation_gen()); |
| 1592 THR_Print(" prefix_invalidation_gen: %s (current: %u)\n", |
| 1593 prefix_invalidation_gen_.ToCString(), i->prefix_invalidation_gen()); |
| 1594 } |
| 1595 |
| 1596 |
| 1597 void BackgroundCompilationResult::PushOnQueue( |
| 1598 CompilationWorkQueue* queue) const { |
| 1599 queue->PushBackCode(result_code()); |
| 1600 queue->PushBackInteger(cha_invalidation_gen_); |
| 1601 queue->PushBackInteger(field_invalidation_gen_); |
| 1602 queue->PushBackInteger(prefix_invalidation_gen_); |
| 1603 } |
| 1604 |
| 1605 |
| 1606 void BackgroundCompilationResult::PopFromQueue(CompilationWorkQueue* queue) { |
| 1607 prefix_invalidation_gen_ = queue->PopBackInteger(); |
| 1608 field_invalidation_gen_ = queue->PopBackInteger(); |
| 1609 cha_invalidation_gen_ = queue->PopBackInteger(); |
| 1610 result_code_ = queue->PopBackCode(); |
| 1611 } |
| 1612 |
| 1613 |
1514 BackgroundCompiler::BackgroundCompiler(Isolate* isolate) | 1614 BackgroundCompiler::BackgroundCompiler(Isolate* isolate) |
1515 : isolate_(isolate), running_(true), done_(new bool()), | 1615 : isolate_(isolate), running_(true), done_(new bool()), |
1516 queue_monitor_(new Monitor()), done_monitor_(new Monitor()), | 1616 queue_monitor_(new Monitor()), done_monitor_(new Monitor()), |
1517 function_queue_length_(0) { | 1617 function_queue_length_(0) { |
1518 *done_ = false; | 1618 *done_ = false; |
1519 } | 1619 } |
1520 | 1620 |
1521 | 1621 |
1522 void BackgroundCompiler::Run() { | 1622 void BackgroundCompiler::Run() { |
1523 while (running_) { | 1623 while (running_) { |
1524 // Maybe something is already in the queue, check first before waiting | 1624 // Maybe something is already in the queue, check first before waiting |
1525 // to be notified. | 1625 // to be notified. |
1526 Thread::EnterIsolateAsHelper(isolate_); | 1626 Thread::EnterIsolateAsHelper(isolate_); |
1527 { | 1627 { |
1528 Thread* thread = Thread::Current(); | 1628 Thread* thread = Thread::Current(); |
1529 StackZone stack_zone(thread); | 1629 StackZone stack_zone(thread); |
1530 HANDLESCOPE(thread); | 1630 HANDLESCOPE(thread); |
1531 Zone* zone = stack_zone.GetZone(); | 1631 Zone* zone = stack_zone.GetZone(); |
1532 Function& function = Function::Handle(zone); | 1632 Function& function = Function::Handle(zone); |
1533 Function& temp_function = Function::Handle(zone); | 1633 Function& temp_function = Function::Handle(zone); |
1534 Code& code = Code::Handle(zone); | |
1535 function = LastFunctionOrNull(); | 1634 function = LastFunctionOrNull(); |
| 1635 BackgroundCompilationResult result; |
1536 // Finish all compilation before exiting (even if running_ is changed to | 1636 // Finish all compilation before exiting (even if running_ is changed to |
1537 // false). | 1637 // false). |
1538 while (!function.IsNull()) { | 1638 while (!function.IsNull()) { |
| 1639 result.Init(); |
1539 const Error& error = Error::Handle(zone, | 1640 const Error& error = Error::Handle(zone, |
1540 Compiler::CompileOptimizedFunction(thread, | 1641 Compiler::CompileOptimizedFunction(thread, |
1541 function, | 1642 function, |
1542 Compiler::kNoOSRDeoptId, | 1643 Compiler::kNoOSRDeoptId, |
1543 &code)); | 1644 &result)); |
1544 // TODO(srdjan): We do not expect errors while compiling optimized | 1645 // TODO(srdjan): We do not expect errors while compiling optimized |
1545 // code, any errors should have been caught when compiling | 1646 // code, any errors should have been caught when compiling |
1546 // unoptimized code. | 1647 // unoptimized code. |
1547 // If it still happens mark function as not optimizable. | 1648 // If it still happens mark function as not optimizable. |
1548 ASSERT(error.IsNull()); | 1649 ASSERT(error.IsNull()); |
1549 temp_function = RemoveFunctionOrNull(); | 1650 temp_function = RemoveFunctionOrNull(); |
1550 ASSERT(temp_function.raw() == function.raw()); | 1651 ASSERT(temp_function.raw() == function.raw()); |
1551 function = LastFunctionOrNull(); | 1652 function = LastFunctionOrNull(); |
1552 ASSERT(!code.IsNull()); | 1653 ASSERT(!result.result_code().IsNull()); |
1553 AddCode(code); | 1654 AddResult(result); |
1554 } | 1655 } |
1555 } | 1656 } |
1556 Thread::ExitIsolateAsHelper(); | 1657 Thread::ExitIsolateAsHelper(); |
1557 { | 1658 { |
1558 // Wait to be notified when the work queue is not empty. | 1659 // Wait to be notified when the work queue is not empty. |
1559 MonitorLocker ml(queue_monitor_); | 1660 MonitorLocker ml(queue_monitor_); |
1560 while ((function_queue_length() == 0) && running_) { | 1661 while ((function_queue_length() == 0) && running_) { |
1561 ml.Wait(); | 1662 ml.Wait(); |
1562 } | 1663 } |
1563 } | 1664 } |
1564 } | 1665 } |
1565 { | 1666 { |
1566 // Notify that the thread is done. | 1667 // Notify that the thread is done. |
1567 MonitorLocker ml_done(done_monitor_); | 1668 MonitorLocker ml_done(done_monitor_); |
1568 *done_ = true; | 1669 *done_ = true; |
1569 ml_done.Notify(); | 1670 ml_done.Notify(); |
1570 } | 1671 } |
1571 } | 1672 } |
1572 | 1673 |
1573 | 1674 |
1574 void BackgroundCompiler::CompileOptimized(const Function& function) { | 1675 void BackgroundCompiler::CompileOptimized(const Function& function) { |
1575 AddFunction(function); | 1676 AddFunction(function); |
1576 } | 1677 } |
1577 | 1678 |
1578 | 1679 |
1579 void BackgroundCompiler::InstallGeneratedCode() { | 1680 void BackgroundCompiler::InstallGeneratedCode() { |
| 1681 ASSERT(Thread::Current()->IsMutatorThread()); |
1580 MonitorLocker ml(queue_monitor_); | 1682 MonitorLocker ml(queue_monitor_); |
1581 CompilationWorkQueue queue(CodesQueue()); | 1683 CompilationWorkQueue queue(ResultQueue()); |
1582 Code& code = Code::Handle(); | |
1583 Object& owner = Object::Handle(); | 1684 Object& owner = Object::Handle(); |
1584 for (intptr_t i = 0; i < queue.Length(); i++) { | 1685 for (intptr_t i = 0; i < queue.Length(); i++) { |
1585 code = queue.PopBackCode(); | 1686 BackgroundCompilationResult result; |
1586 if (code.IsDisabled()) continue; | 1687 result.PopFromQueue(&queue); |
1587 owner = code.owner(); | 1688 owner = result.result_code().owner(); |
1588 const Function& function = Function::Cast(owner); | 1689 const Function& function = Function::Cast(owner); |
1589 function.InstallOptimizedCode(code, false /* not OSR */); | 1690 if (result.IsValid()) { |
| 1691 function.InstallOptimizedCode(result.result_code(), false /* not OSR */); |
| 1692 } else if (FLAG_trace_compiler) { |
| 1693 THR_Print("Drop code generated in the background compiler:\n"); |
| 1694 result.PrintValidity(); |
| 1695 } |
1590 if (function.usage_counter() < 0) { | 1696 if (function.usage_counter() < 0) { |
1591 // Reset to 0 so that it can be recompiled if needed. | 1697 // Reset to 0 so that it can be recompiled if needed. |
1592 function.set_usage_counter(0); | 1698 function.set_usage_counter(0); |
1593 } | 1699 } |
1594 } | 1700 } |
1595 } | 1701 } |
1596 | 1702 |
1597 | 1703 |
1598 GrowableObjectArray* BackgroundCompiler::FunctionsQueue() const { | 1704 GrowableObjectArray* BackgroundCompiler::FunctionsQueue() const { |
1599 return | 1705 return |
1600 &GrowableObjectArray::ZoneHandle(isolate_->compilation_function_queue()); | 1706 &GrowableObjectArray::ZoneHandle(isolate_->compilation_function_queue()); |
1601 } | 1707 } |
1602 | 1708 |
1603 | 1709 |
1604 GrowableObjectArray* BackgroundCompiler::CodesQueue() const { | 1710 GrowableObjectArray* BackgroundCompiler::ResultQueue() const { |
1605 // Use code queue | 1711 return &GrowableObjectArray::ZoneHandle(isolate_->compilation_result_queue()); |
1606 return &GrowableObjectArray::ZoneHandle(isolate_->compilation_code_queue()); | |
1607 } | 1712 } |
1608 | 1713 |
1609 | 1714 |
1610 void BackgroundCompiler::AddFunction(const Function& f) { | 1715 void BackgroundCompiler::AddFunction(const Function& f) { |
1611 MonitorLocker ml(queue_monitor_); | 1716 MonitorLocker ml(queue_monitor_); |
1612 CompilationWorkQueue queue(FunctionsQueue()); | 1717 CompilationWorkQueue queue(FunctionsQueue()); |
1613 queue.PushFrontFunction(f); | 1718 queue.PushFrontFunction(f); |
1614 set_function_queue_length(queue.Length()); | 1719 set_function_queue_length(queue.Length()); |
1615 // Notify waiting background compiler task. | 1720 // Notify waiting background compiler task. |
1616 ml.Notify(); | 1721 ml.Notify(); |
1617 } | 1722 } |
1618 | 1723 |
1619 | 1724 |
1620 RawFunction* BackgroundCompiler::RemoveFunctionOrNull() { | 1725 RawFunction* BackgroundCompiler::RemoveFunctionOrNull() { |
1621 MonitorLocker ml(queue_monitor_); | 1726 MonitorLocker ml(queue_monitor_); |
1622 CompilationWorkQueue queue(FunctionsQueue()); | 1727 CompilationWorkQueue queue(FunctionsQueue()); |
1623 if (queue.IsEmpty()) return Function::null(); | 1728 if (queue.IsEmpty()) return Function::null(); |
1624 set_function_queue_length(queue.Length() - 1); | 1729 set_function_queue_length(queue.Length() - 1); |
1625 return queue.PopBackFunction(); | 1730 return queue.PopBackFunction(); |
1626 } | 1731 } |
1627 | 1732 |
1628 | 1733 |
1629 RawFunction* BackgroundCompiler::LastFunctionOrNull() const { | 1734 RawFunction* BackgroundCompiler::LastFunctionOrNull() const { |
1630 MonitorLocker ml(queue_monitor_); | 1735 MonitorLocker ml(queue_monitor_); |
1631 CompilationWorkQueue queue(FunctionsQueue()); | 1736 CompilationWorkQueue queue(FunctionsQueue()); |
1632 return queue.IsEmpty() ? Function::null() : queue.LastFunction(); | 1737 return queue.IsEmpty() ? Function::null() : queue.LastFunction(); |
1633 } | 1738 } |
1634 | 1739 |
1635 | 1740 |
1636 void BackgroundCompiler::AddCode(const Code& c) { | 1741 void BackgroundCompiler::AddResult(const BackgroundCompilationResult& value) { |
1637 MonitorLocker ml(queue_monitor_); | 1742 MonitorLocker ml(queue_monitor_); |
1638 CompilationWorkQueue queue(CodesQueue()); | 1743 CompilationWorkQueue queue(ResultQueue()); |
1639 queue.PushBackCode(c); | 1744 value.PushOnQueue(&queue); |
1640 } | 1745 } |
1641 | 1746 |
1642 | 1747 |
1643 void BackgroundCompiler::Stop(BackgroundCompiler* task) { | 1748 void BackgroundCompiler::Stop(BackgroundCompiler* task) { |
1644 ASSERT(Isolate::Current()->background_compiler() == task); | 1749 ASSERT(Isolate::Current()->background_compiler() == task); |
1645 if (task == NULL) { | 1750 if (task == NULL) { |
1646 return; | 1751 return; |
1647 } | 1752 } |
1648 Monitor* monitor = task->queue_monitor_; | 1753 Monitor* monitor = task->queue_monitor_; |
1649 Monitor* done_monitor = task->done_monitor_; | 1754 Monitor* done_monitor = task->done_monitor_; |
(...skipping 23 matching lines...) Expand all Loading... |
1673 void BackgroundCompiler::EnsureInit(Thread* thread) { | 1778 void BackgroundCompiler::EnsureInit(Thread* thread) { |
1674 bool start_task = false; | 1779 bool start_task = false; |
1675 Isolate* isolate = thread->isolate(); | 1780 Isolate* isolate = thread->isolate(); |
1676 { | 1781 { |
1677 MutexLocker ml(isolate->mutex()); | 1782 MutexLocker ml(isolate->mutex()); |
1678 if (isolate->background_compiler() == NULL) { | 1783 if (isolate->background_compiler() == NULL) { |
1679 BackgroundCompiler* task = new BackgroundCompiler(isolate); | 1784 BackgroundCompiler* task = new BackgroundCompiler(isolate); |
1680 isolate->set_background_compiler(task); | 1785 isolate->set_background_compiler(task); |
1681 isolate->set_compilation_function_queue(GrowableObjectArray::Handle( | 1786 isolate->set_compilation_function_queue(GrowableObjectArray::Handle( |
1682 thread->zone(), GrowableObjectArray::New())); | 1787 thread->zone(), GrowableObjectArray::New())); |
1683 isolate->set_compilation_code_queue(GrowableObjectArray::Handle( | 1788 isolate->set_compilation_result_queue(GrowableObjectArray::Handle( |
1684 thread->zone(), GrowableObjectArray::New())); | 1789 thread->zone(), GrowableObjectArray::New())); |
1685 start_task = true; | 1790 start_task = true; |
1686 } | 1791 } |
1687 } | 1792 } |
1688 if (start_task) { | 1793 if (start_task) { |
1689 Dart::thread_pool()->Run(isolate->background_compiler()); | 1794 Dart::thread_pool()->Run(isolate->background_compiler()); |
1690 } | 1795 } |
1691 } | 1796 } |
1692 | 1797 |
1693 } // namespace dart | 1798 } // namespace dart |
OLD | NEW |