Chromium Code Reviews| 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 1384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1395 Isolate* const isolate = thread->isolate(); | 1395 Isolate* const isolate = thread->isolate(); |
| 1396 const Object& result = | 1396 const Object& result = |
| 1397 PassiveObject::Handle(isolate->object_store()->sticky_error()); | 1397 PassiveObject::Handle(isolate->object_store()->sticky_error()); |
| 1398 isolate->object_store()->clear_sticky_error(); | 1398 isolate->object_store()->clear_sticky_error(); |
| 1399 return result.raw(); | 1399 return result.raw(); |
| 1400 } | 1400 } |
| 1401 UNREACHABLE(); | 1401 UNREACHABLE(); |
| 1402 return Object::null(); | 1402 return Object::null(); |
| 1403 } | 1403 } |
| 1404 | 1404 |
| 1405 | |
| 1406 // A simple workqueue containing functions to be optimized. | |
| 1407 // TODO(srdjan): Write a more efficient implementation. | |
| 1408 class CompilationWorkQueue : public ValueObject { | |
|
koda
2015/10/05 18:13:00
Be consistent w.r.t. "work queue" vs "workqueue".
srdjan
2015/10/05 19:16:47
Done; Two words.
| |
| 1409 public: | |
| 1410 explicit CompilationWorkQueue(Isolate* isolate) : | |
| 1411 data_(GrowableObjectArray::Handle()) { | |
| 1412 data_ = isolate->background_compilation_queue(); | |
| 1413 } | |
| 1414 | |
| 1415 intptr_t IsEmpty() const { return data_.Length() == 0; } | |
| 1416 | |
| 1417 // Adds to the queue only if not already in there. | |
| 1418 void AddUnique(const Function& function) { | |
| 1419 for (intptr_t i = 0; i < data_.Length(); i++) { | |
| 1420 if (data_.At(i) == function.raw()) { | |
| 1421 return; | |
| 1422 } | |
| 1423 } | |
| 1424 // Insert new element in front. | |
| 1425 Object& f = Object::Handle(); | |
| 1426 data_.Add(f); | |
| 1427 for (intptr_t i = data_.Length() - 1; i > 0; i--) { | |
| 1428 f = data_.At(i - 1); | |
| 1429 data_.SetAt(i, f); | |
| 1430 } | |
| 1431 data_.SetAt(0, function); | |
| 1432 } | |
| 1433 | |
| 1434 | |
| 1435 RawFunction* Remove() { | |
|
koda
2015/10/05 18:13:00
Clarify/emphasize that AddUnique/Remove together m
srdjan
2015/10/05 19:16:47
Renamed to PushFront/PopBack.
| |
| 1436 ASSERT(!IsEmpty()); | |
| 1437 Object& result = Object::Handle(); | |
| 1438 result = data_.At(data_.Length() - 1); | |
| 1439 data_.SetLength(data_.Length() - 1); | |
| 1440 return Function::Cast(result).raw(); | |
| 1441 } | |
| 1442 | |
| 1443 private: | |
| 1444 GrowableObjectArray& data_; | |
| 1445 | |
| 1446 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationWorkQueue); | |
| 1447 }; | |
| 1448 | |
| 1449 | |
| 1450 BackgroundCompiler::BackgroundCompiler(Isolate* isolate) | |
| 1451 : isolate_(isolate), running_(true), done_(new bool()), | |
| 1452 monitor_(new Monitor()), done_monitor_(new Monitor()) { | |
| 1453 *done_ = false; | |
| 1454 } | |
| 1455 | |
| 1456 | |
| 1457 void BackgroundCompiler::Run() { | |
| 1458 while (running_) { | |
| 1459 { | |
| 1460 // Wait to be notified when the workqueue is not empty. | |
| 1461 MonitorLocker ml(monitor_); | |
| 1462 ml.Wait(); | |
| 1463 } | |
| 1464 | |
| 1465 Thread::EnterIsolateAsHelper(isolate_); | |
| 1466 { | |
| 1467 Thread* thread = Thread::Current(); | |
| 1468 StackZone stack_zone(thread); | |
| 1469 HANDLESCOPE(thread); | |
| 1470 Function& function = Function::Handle(); | |
| 1471 function = RemoveOrNull(); | |
| 1472 while (!function.IsNull()) { | |
| 1473 if (true) { | |
| 1474 // Debugging printing | |
| 1475 THR_Print("Background compilation: %s\n", | |
| 1476 function.ToQualifiedCString()); | |
| 1477 } else { | |
| 1478 const Error& error = Error::Handle( | |
| 1479 Compiler::CompileOptimizedFunction(thread, function)); | |
| 1480 // TODO(srdjan): We do not expect errors in optimized code. If it | |
|
koda
2015/10/05 18:13:00
Clarify that you mean errors *while compiling* opt
srdjan
2015/10/05 19:16:47
Done.
| |
| 1481 // still happens mark function as not optimizable. | |
| 1482 ASSERT(error.IsNull()); | |
| 1483 } | |
| 1484 function = RemoveOrNull(); | |
| 1485 } | |
| 1486 } | |
| 1487 Thread::ExitIsolateAsHelper(); | |
| 1488 } | |
| 1489 { | |
| 1490 // Notify that the thread is done. | |
| 1491 MonitorLocker ml_done(done_monitor_); | |
| 1492 *done_ = true; | |
| 1493 ml_done.Notify(); | |
| 1494 } | |
| 1495 } | |
| 1496 | |
| 1497 | |
| 1498 void BackgroundCompiler::CompileOptimized(const Function& function) { | |
| 1499 Add(function); | |
| 1500 } | |
| 1501 | |
| 1502 | |
| 1503 void BackgroundCompiler::Add(const Function& f) const { | |
| 1504 MonitorLocker ml(monitor_); | |
| 1505 CompilationWorkQueue queue(isolate_); | |
| 1506 queue.AddUnique(f); | |
| 1507 ml.Notify(); | |
| 1508 } | |
| 1509 | |
| 1510 | |
| 1511 RawFunction* BackgroundCompiler::RemoveOrNull() const { | |
| 1512 MonitorLocker ml(monitor_); | |
| 1513 CompilationWorkQueue queue(isolate_); | |
| 1514 return queue.IsEmpty() ? Function::null() : queue.Remove(); | |
| 1515 } | |
| 1516 | |
| 1517 | |
| 1518 void BackgroundCompiler::Stop(BackgroundCompiler* task) { | |
| 1519 if (task == NULL) { | |
| 1520 return; | |
| 1521 } | |
| 1522 Monitor* monitor = task->monitor_; | |
| 1523 Monitor* done_monitor = task->done_monitor_; | |
| 1524 bool* task_done = task->done_; | |
| 1525 // Wake up compiler task and stop it. | |
| 1526 { | |
| 1527 MonitorLocker ml(task->monitor_); | |
| 1528 task->running_ = false; | |
| 1529 task = NULL; | |
| 1530 // 'task' will be deleted by thread pool. | |
|
koda
2015/10/05 18:13:00
This comment should go before NULL'ing task, to be
srdjan
2015/10/05 19:16:47
Done.
| |
| 1531 ml.Notify(); | |
| 1532 } | |
| 1533 | |
| 1534 { | |
| 1535 MonitorLocker ml_done(done_monitor); | |
| 1536 while (!(*task_done)) { | |
| 1537 ml_done.Wait(); | |
| 1538 } | |
| 1539 } | |
| 1540 delete task_done; | |
| 1541 delete done_monitor; | |
| 1542 delete monitor; | |
| 1543 } | |
| 1544 | |
| 1545 | |
| 1546 void BackgroundCompiler::EnsureInit(Isolate* isolate) { | |
| 1547 MutexLocker ml(isolate->mutex()); | |
| 1548 if (isolate->background_compiler() == NULL) { | |
| 1549 BackgroundCompiler* task = new BackgroundCompiler(isolate); | |
| 1550 isolate->set_background_compiler(task); | |
| 1551 isolate->set_background_compilation_queue( | |
| 1552 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New())); | |
| 1553 Dart::thread_pool()->Run(task); | |
|
koda
2015/10/05 18:13:00
This does not need to be under the lock and is a n
srdjan
2015/10/05 19:16:47
Done.
| |
| 1554 } | |
| 1555 } | |
| 1556 | |
| 1405 } // namespace dart | 1557 } // namespace dart |
| OLD | NEW |