Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: runtime/vm/isolate.cc

Issue 1812753002: - Move (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/isolate.h" 5 #include "vm/isolate.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "include/dart_native_api.h" 8 #include "include/dart_native_api.h"
9 #include "platform/assert.h" 9 #include "platform/assert.h"
10 #include "platform/text_buffer.h" 10 #include "platform/text_buffer.h"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 #include "vm/timeline_analysis.h" 46 #include "vm/timeline_analysis.h"
47 #include "vm/timer.h" 47 #include "vm/timer.h"
48 #include "vm/visitor.h" 48 #include "vm/visitor.h"
49 49
50 50
51 namespace dart { 51 namespace dart {
52 52
53 DECLARE_FLAG(bool, print_metrics); 53 DECLARE_FLAG(bool, print_metrics);
54 DECLARE_FLAG(bool, timing); 54 DECLARE_FLAG(bool, timing);
55 DECLARE_FLAG(bool, trace_service); 55 DECLARE_FLAG(bool, trace_service);
56 DECLARE_FLAG(bool, trace_service_verbose);
57 56
58 DEFINE_FLAG(bool, trace_isolates, false, 57 DEFINE_FLAG(bool, trace_isolates, false,
59 "Trace isolate creation and shut down."); 58 "Trace isolate creation and shut down.");
60 DEFINE_FLAG(bool, pause_isolates_on_start, false, 59 DEFINE_FLAG(bool, pause_isolates_on_start, false,
61 "Pause isolates before starting."); 60 "Pause isolates before starting.");
62 DEFINE_FLAG(bool, pause_isolates_on_exit, false, 61 DEFINE_FLAG(bool, pause_isolates_on_exit, false,
63 "Pause isolates exiting."); 62 "Pause isolates exiting.");
64 DEFINE_FLAG(bool, pause_isolates_on_unhandled_exceptions, false, 63 DEFINE_FLAG(bool, pause_isolates_on_unhandled_exceptions, false,
65 "Pause isolates on unhandled exceptions."); 64 "Pause isolates on unhandled exceptions.");
66 65
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 } else { 141 } else {
143 uint8_t* obj_data; 142 uint8_t* obj_data;
144 intptr_t obj_len; 143 intptr_t obj_len;
145 SerializeObject(obj, &obj_data, &obj_len, false); 144 SerializeObject(obj, &obj_data, &obj_len, false);
146 return new Message(dest_port, obj_data, obj_len, Message::kNormalPriority); 145 return new Message(dest_port, obj_data, obj_len, Message::kNormalPriority);
147 } 146 }
148 } 147 }
149 148
150 149
151 NoOOBMessageScope::NoOOBMessageScope(Thread* thread) : StackResource(thread) { 150 NoOOBMessageScope::NoOOBMessageScope(Thread* thread) : StackResource(thread) {
152 isolate()->DeferOOBMessageInterrupts(); 151 thread->DeferOOBMessageInterrupts();
153 } 152 }
154 153
155 154
156 NoOOBMessageScope::~NoOOBMessageScope() { 155 NoOOBMessageScope::~NoOOBMessageScope() {
157 isolate()->RestoreOOBMessageInterrupts(); 156 thread()->RestoreOOBMessageInterrupts();
158 } 157 }
159 158
160 159
161 160
162 void Isolate::RegisterClass(const Class& cls) { 161 void Isolate::RegisterClass(const Class& cls) {
163 class_table()->Register(cls); 162 class_table()->Register(cls);
164 } 163 }
165 164
166 165
167 void Isolate::RegisterClassAt(intptr_t index, const Class& cls) { 166 void Isolate::RegisterClassAt(intptr_t index, const Class& cls) {
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 UNREACHABLE(); 424 UNREACHABLE();
426 break; 425 break;
427 #endif // defined(DEBUG) 426 #endif // defined(DEBUG)
428 } 427 }
429 return Error::null(); 428 return Error::null();
430 } 429 }
431 430
432 431
433 void IsolateMessageHandler::MessageNotify(Message::Priority priority) { 432 void IsolateMessageHandler::MessageNotify(Message::Priority priority) {
434 if (priority >= Message::kOOBPriority) { 433 if (priority >= Message::kOOBPriority) {
435 // Handle out of band messages even if the isolate is busy. 434 // Handle out of band messages even if the mutator thread is busy.
436 I->ScheduleInterrupts(Isolate::kMessageInterrupt); 435 I->ScheduleMessageInterrupts();
437 } 436 }
438 Dart_MessageNotifyCallback callback = I->message_notify_callback(); 437 Dart_MessageNotifyCallback callback = I->message_notify_callback();
439 if (callback) { 438 if (callback) {
440 // Allow the embedder to handle message notification. 439 // Allow the embedder to handle message notification.
441 (*callback)(Api::CastIsolate(I)); 440 (*callback)(Api::CastIsolate(I));
442 } 441 }
443 } 442 }
444 443
445 444
446 MessageHandler::MessageStatus IsolateMessageHandler::HandleMessage( 445 MessageHandler::MessageStatus IsolateMessageHandler::HandleMessage(
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 #else 749 #else
751 #define REUSABLE_HANDLE_SCOPE_INIT(object) 750 #define REUSABLE_HANDLE_SCOPE_INIT(object)
752 #endif // defined(DEBUG) 751 #endif // defined(DEBUG)
753 752
754 #define REUSABLE_HANDLE_INITIALIZERS(object) \ 753 #define REUSABLE_HANDLE_INITIALIZERS(object) \
755 object##_handle_(NULL), 754 object##_handle_(NULL),
756 755
757 // TODO(srdjan): Some Isolate monitors can be shared. Replace their usage with 756 // TODO(srdjan): Some Isolate monitors can be shared. Replace their usage with
758 // that shared monitor. 757 // that shared monitor.
759 Isolate::Isolate(const Dart_IsolateFlags& api_flags) 758 Isolate::Isolate(const Dart_IsolateFlags& api_flags)
760 : stack_limit_(0), 759 : store_buffer_(new StoreBuffer()),
761 store_buffer_(new StoreBuffer()),
762 heap_(NULL), 760 heap_(NULL),
763 user_tag_(0), 761 user_tag_(0),
764 current_tag_(UserTag::null()), 762 current_tag_(UserTag::null()),
765 default_tag_(UserTag::null()), 763 default_tag_(UserTag::null()),
766 class_table_(), 764 class_table_(),
767 single_step_(false), 765 single_step_(false),
768 thread_registry_(new ThreadRegistry()), 766 thread_registry_(new ThreadRegistry()),
769 safepoint_handler_(new SafepointHandler(this)), 767 safepoint_handler_(new SafepointHandler(this)),
770 message_notify_callback_(NULL), 768 message_notify_callback_(NULL),
771 name_(NULL), 769 name_(NULL),
(...skipping 13 matching lines...) Expand all
785 debugger_(NULL), 783 debugger_(NULL),
786 resume_request_(false), 784 resume_request_(false),
787 last_resume_timestamp_(OS::GetCurrentTimeMillis()), 785 last_resume_timestamp_(OS::GetCurrentTimeMillis()),
788 has_compiled_code_(false), 786 has_compiled_code_(false),
789 random_(), 787 random_(),
790 simulator_(NULL), 788 simulator_(NULL),
791 mutex_(new Mutex()), 789 mutex_(new Mutex()),
792 symbols_mutex_(new Mutex()), 790 symbols_mutex_(new Mutex()),
793 type_canonicalization_mutex_(new Mutex()), 791 type_canonicalization_mutex_(new Mutex()),
794 constant_canonicalization_mutex_(new Mutex()), 792 constant_canonicalization_mutex_(new Mutex()),
795 saved_stack_limit_(0),
796 deferred_interrupts_mask_(0),
797 deferred_interrupts_(0),
798 stack_overflow_flags_(0),
799 stack_overflow_count_(0),
800 message_handler_(NULL), 793 message_handler_(NULL),
801 spawn_state_(NULL), 794 spawn_state_(NULL),
802 is_runnable_(false), 795 is_runnable_(false),
803 gc_prologue_callback_(NULL), 796 gc_prologue_callback_(NULL),
804 gc_epilogue_callback_(NULL), 797 gc_epilogue_callback_(NULL),
805 defer_finalization_count_(0), 798 defer_finalization_count_(0),
806 deopt_context_(NULL), 799 deopt_context_(NULL),
807 compiler_stats_(NULL), 800 compiler_stats_(NULL),
808 is_service_isolate_(false), 801 is_service_isolate_(false),
809 stacktrace_(NULL), 802 stacktrace_(NULL),
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
972 result->LowLevelShutdown(); 965 result->LowLevelShutdown();
973 Thread::ExitIsolate(); 966 Thread::ExitIsolate();
974 delete result; 967 delete result;
975 return NULL; 968 return NULL;
976 } 969 }
977 970
978 return result; 971 return result;
979 } 972 }
980 973
981 974
982 /* static */
983 uword Isolate::GetCurrentStackPointer() {
984 // Since AddressSanitizer's detect_stack_use_after_return instruments the
985 // C++ code to give out fake stack addresses, we call a stub in that case.
986 uword (*func)() = reinterpret_cast<uword (*)()>(
987 StubCode::GetStackPointer_entry()->EntryPoint());
988 // But for performance (and to support simulators), we normally use a local.
989 #if defined(__has_feature)
990 #if __has_feature(address_sanitizer)
991 uword current_sp = func();
992 return current_sp;
993 #else
994 uword stack_allocated_local_address = reinterpret_cast<uword>(&func);
995 return stack_allocated_local_address;
996 #endif
997 #else
998 uword stack_allocated_local_address = reinterpret_cast<uword>(&func);
999 return stack_allocated_local_address;
1000 #endif
1001 }
1002
1003
1004 void Isolate::SetupInstructionsSnapshotPage( 975 void Isolate::SetupInstructionsSnapshotPage(
1005 const uint8_t* instructions_snapshot_buffer) { 976 const uint8_t* instructions_snapshot_buffer) {
1006 InstructionsSnapshot snapshot(instructions_snapshot_buffer); 977 InstructionsSnapshot snapshot(instructions_snapshot_buffer);
1007 #if defined(DEBUG) 978 #if defined(DEBUG)
1008 if (FLAG_trace_isolates) { 979 if (FLAG_trace_isolates) {
1009 OS::Print("Precompiled instructions are at [0x%" Px ", 0x%" Px ")\n", 980 OS::Print("Precompiled instructions are at [0x%" Px ", 0x%" Px ")\n",
1010 reinterpret_cast<uword>(snapshot.instructions_start()), 981 reinterpret_cast<uword>(snapshot.instructions_start()),
1011 reinterpret_cast<uword>(snapshot.instructions_start()) + 982 reinterpret_cast<uword>(snapshot.instructions_start()) +
1012 snapshot.instructions_size()); 983 snapshot.instructions_size());
1013 } 984 }
(...skipping 13 matching lines...) Expand all
1027 reinterpret_cast<uword>(snapshot.data_start()) + 998 reinterpret_cast<uword>(snapshot.data_start()) +
1028 snapshot.data_size()); 999 snapshot.data_size());
1029 } 1000 }
1030 #endif 1001 #endif
1031 heap_->SetupExternalPage(snapshot.data_start(), 1002 heap_->SetupExternalPage(snapshot.data_start(),
1032 snapshot.data_size(), 1003 snapshot.data_size(),
1033 /* is_executable = */ false); 1004 /* is_executable = */ false);
1034 } 1005 }
1035 1006
1036 1007
1008 void Isolate::ScheduleMessageInterrupts() {
1009 // We take the threads lock here to ensure that the mutator thread does not
1010 // exit the isolate while we are trying to schedule interrupts on it.
1011 MonitorLocker ml(threads_lock());
1012 Thread* mthread = mutator_thread();
1013 if (mthread != NULL) {
1014 mthread->ScheduleInterrupts(Thread::kMessageInterrupt);
1015 }
1016 }
1017
1037 1018
1038 void Isolate::set_debugger_name(const char* name) { 1019 void Isolate::set_debugger_name(const char* name) {
1039 free(debugger_name_); 1020 free(debugger_name_);
1040 debugger_name_ = strdup(name); 1021 debugger_name_ = strdup(name);
1041 } 1022 }
1042 1023
1043 1024
1044 void Isolate::BuildName(const char* name_prefix) { 1025 void Isolate::BuildName(const char* name_prefix) {
1045 ASSERT(name_ == NULL); 1026 ASSERT(name_ == NULL);
1046 if (name_prefix == NULL) { 1027 if (name_prefix == NULL) {
1047 name_prefix = "isolate"; 1028 name_prefix = "isolate";
1048 } 1029 }
1049 set_debugger_name(name_prefix); 1030 set_debugger_name(name_prefix);
1050 if (ServiceIsolate::NameEquals(name_prefix)) { 1031 if (ServiceIsolate::NameEquals(name_prefix)) {
1051 name_ = strdup(name_prefix); 1032 name_ = strdup(name_prefix);
1052 return; 1033 return;
1053 } 1034 }
1054 name_ = OS::SCreate(NULL, "%s-%" Pd64 "", name_prefix, main_port()); 1035 name_ = OS::SCreate(NULL, "%s-%" Pd64 "", name_prefix, main_port());
1055 } 1036 }
1056 1037
1057 1038
1058 void Isolate::SetStackLimitFromStackBase(uword stack_base) {
1059 // Set stack limit.
1060 #if defined(USING_SIMULATOR)
1061 // Ignore passed-in native stack top and use Simulator stack top.
1062 Simulator* sim = Simulator::Current(); // May allocate a simulator.
1063 ASSERT(simulator() == sim); // This isolate's simulator is the current one.
1064 stack_base = sim->StackTop();
1065 // The overflow area is accounted for by the simulator.
1066 #endif
1067 SetStackLimit(stack_base - OSThread::GetSpecifiedStackSize());
1068 }
1069
1070
1071 void Isolate::SetStackLimit(uword limit) {
1072 // The isolate setting the stack limit is not necessarily the isolate which
1073 // the stack limit is being set on.
1074 MutexLocker ml(mutex_);
1075 if (stack_limit_ == saved_stack_limit_) {
1076 // No interrupt pending, set stack_limit_ too.
1077 stack_limit_ = limit;
1078 }
1079 saved_stack_limit_ = limit;
1080 }
1081
1082
1083 void Isolate::ClearStackLimit() {
1084 SetStackLimit(~static_cast<uword>(0));
1085 }
1086
1087
1088 void Isolate::DoneLoading() { 1039 void Isolate::DoneLoading() {
1089 GrowableObjectArray& libs = GrowableObjectArray::Handle(current_zone(), 1040 GrowableObjectArray& libs = GrowableObjectArray::Handle(current_zone(),
1090 object_store()->libraries()); 1041 object_store()->libraries());
1091 Library& lib = Library::Handle(current_zone()); 1042 Library& lib = Library::Handle(current_zone());
1092 intptr_t num_libs = libs.Length(); 1043 intptr_t num_libs = libs.Length();
1093 for (intptr_t i = 0; i < num_libs; i++) { 1044 for (intptr_t i = 0; i < num_libs; i++) {
1094 lib ^= libs.At(i); 1045 lib ^= libs.At(i);
1095 // If this library was loaded with Dart_LoadLibrary, it was marked 1046 // If this library was loaded with Dart_LoadLibrary, it was marked
1096 // as 'load in progres'. Set the status to 'loaded'. 1047 // as 'load in progres'. Set the status to 'loaded'.
1097 if (lib.LoadInProgress()) { 1048 if (lib.LoadInProgress()) {
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
1481 1432
1482 1433
1483 void Isolate::Run() { 1434 void Isolate::Run() {
1484 message_handler()->Run(Dart::thread_pool(), 1435 message_handler()->Run(Dart::thread_pool(),
1485 RunIsolate, 1436 RunIsolate,
1486 ShutdownIsolate, 1437 ShutdownIsolate,
1487 reinterpret_cast<uword>(this)); 1438 reinterpret_cast<uword>(this));
1488 } 1439 }
1489 1440
1490 1441
1491 void Isolate::ScheduleInterrupts(uword interrupt_bits) {
1492 MutexLocker ml(mutex_);
1493 ASSERT((interrupt_bits & ~kInterruptsMask) == 0); // Must fit in mask.
1494
1495 // Check to see if any of the requested interrupts should be deferred.
1496 uword defer_bits = interrupt_bits & deferred_interrupts_mask_;
1497 if (defer_bits != 0) {
1498 deferred_interrupts_ |= defer_bits;
1499 interrupt_bits &= ~deferred_interrupts_mask_;
1500 if (interrupt_bits == 0) {
1501 return;
1502 }
1503 }
1504
1505 if (stack_limit_ == saved_stack_limit_) {
1506 stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask;
1507 }
1508 stack_limit_ |= interrupt_bits;
1509 }
1510
1511
1512 uword Isolate::GetAndClearInterrupts() {
1513 MutexLocker ml(mutex_);
1514 if (stack_limit_ == saved_stack_limit_) {
1515 return 0; // No interrupt was requested.
1516 }
1517 uword interrupt_bits = stack_limit_ & kInterruptsMask;
1518 stack_limit_ = saved_stack_limit_;
1519 return interrupt_bits;
1520 }
1521
1522
1523 void Isolate::DeferOOBMessageInterrupts() {
1524 MutexLocker ml(mutex_);
1525 ASSERT(deferred_interrupts_mask_ == 0);
1526 deferred_interrupts_mask_ = kMessageInterrupt;
1527
1528 if (stack_limit_ != saved_stack_limit_) {
1529 // Defer any interrupts which are currently pending.
1530 deferred_interrupts_ = stack_limit_ & deferred_interrupts_mask_;
1531
1532 // Clear deferrable interrupts, if present.
1533 stack_limit_ &= ~deferred_interrupts_mask_;
1534
1535 if ((stack_limit_ & kInterruptsMask) == 0) {
1536 // No other pending interrupts. Restore normal stack limit.
1537 stack_limit_ = saved_stack_limit_;
1538 }
1539 }
1540 if (FLAG_trace_service && FLAG_trace_service_verbose) {
1541 OS::Print("[+%" Pd64 "ms] Isolate %s deferring OOB interrupts\n",
1542 Dart::timestamp(), name());
1543 }
1544 }
1545
1546
1547 void Isolate::RestoreOOBMessageInterrupts() {
1548 MutexLocker ml(mutex_);
1549 ASSERT(deferred_interrupts_mask_ == kMessageInterrupt);
1550 deferred_interrupts_mask_ = 0;
1551 if (deferred_interrupts_ != 0) {
1552 if (stack_limit_ == saved_stack_limit_) {
1553 stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask;
1554 }
1555 stack_limit_ |= deferred_interrupts_;
1556 deferred_interrupts_ = 0;
1557 }
1558 if (FLAG_trace_service && FLAG_trace_service_verbose) {
1559 OS::Print("[+%" Pd64 "ms] Isolate %s restoring OOB interrupts\n",
1560 Dart::timestamp(), name());
1561 }
1562 }
1563
1564
1565 RawError* Isolate::HandleInterrupts() {
1566 uword interrupt_bits = GetAndClearInterrupts();
1567 if ((interrupt_bits & kVMInterrupt) != 0) {
1568 if (store_buffer()->Overflowed()) {
1569 if (FLAG_verbose_gc) {
1570 OS::PrintErr("Scavenge scheduled by store buffer overflow.\n");
1571 }
1572 heap()->CollectGarbage(Heap::kNew);
1573 }
1574 }
1575 if ((interrupt_bits & kMessageInterrupt) != 0) {
1576 MessageHandler::MessageStatus status =
1577 message_handler()->HandleOOBMessages();
1578 if (status != MessageHandler::kOK) {
1579 // False result from HandleOOBMessages signals that the isolate should
1580 // be terminating.
1581 if (FLAG_trace_isolates) {
1582 OS::Print("[!] Terminating isolate due to OOB message:\n"
1583 "\tisolate: %s\n", name());
1584 }
1585 Thread* thread = Thread::Current();
1586 const Error& error = Error::Handle(thread->sticky_error());
1587 ASSERT(!error.IsNull() && error.IsUnwindError());
1588 thread->clear_sticky_error();
1589 return error.raw();
1590 }
1591 }
1592 return Error::null();
1593 }
1594
1595
1596 uword Isolate::GetAndClearStackOverflowFlags() {
1597 uword stack_overflow_flags = stack_overflow_flags_;
1598 stack_overflow_flags_ = 0;
1599 return stack_overflow_flags;
1600 }
1601
1602
1603 void Isolate::AddClosureFunction(const Function& function) const { 1442 void Isolate::AddClosureFunction(const Function& function) const {
1604 GrowableObjectArray& closures = 1443 GrowableObjectArray& closures =
1605 GrowableObjectArray::Handle(object_store()->closure_functions()); 1444 GrowableObjectArray::Handle(object_store()->closure_functions());
1606 ASSERT(!closures.IsNull()); 1445 ASSERT(!closures.IsNull());
1607 ASSERT(function.IsNonImplicitClosureFunction()); 1446 ASSERT(function.IsNonImplicitClosureFunction());
1608 closures.Add(function, Heap::kOld); 1447 closures.Add(function, Heap::kOld);
1609 } 1448 }
1610 1449
1611 1450
1612 // If the linear lookup turns out to be too expensive, the list 1451 // If the linear lookup turns out to be too expensive, the list
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
1750 #if defined(DEBUG) 1589 #if defined(DEBUG)
1751 if (heap_ != NULL) { 1590 if (heap_ != NULL) {
1752 // The VM isolate keeps all objects marked. 1591 // The VM isolate keeps all objects marked.
1753 heap_->Verify(this == Dart::vm_isolate() ? kRequireMarked : kForbidMarked); 1592 heap_->Verify(this == Dart::vm_isolate() ? kRequireMarked : kForbidMarked);
1754 } 1593 }
1755 #endif // DEBUG 1594 #endif // DEBUG
1756 1595
1757 Thread* thread = Thread::Current(); 1596 Thread* thread = Thread::Current();
1758 1597
1759 // Don't allow anymore dart code to execution on this isolate. 1598 // Don't allow anymore dart code to execution on this isolate.
1760 ClearStackLimit(); 1599 thread->ClearStackLimit();
1761 1600
1762 // First, perform higher-level cleanup that may need to allocate. 1601 // First, perform higher-level cleanup that may need to allocate.
1763 { 1602 {
1764 // Ensure we have a zone and handle scope so that we can call VM functions. 1603 // Ensure we have a zone and handle scope so that we can call VM functions.
1765 StackZone stack_zone(thread); 1604 StackZone stack_zone(thread);
1766 HandleScope handle_scope(thread); 1605 HandleScope handle_scope(thread);
1767 1606
1768 // Write out the coverage data if collection has been enabled. 1607 // Write out the coverage data if collection has been enabled.
1769 if ((this != Dart::vm_isolate()) && 1608 if ((this != Dart::vm_isolate()) &&
1770 !ServiceIsolate::IsServiceIsolateDescendant(this)) { 1609 !ServiceIsolate::IsServiceIsolateDescendant(this)) {
(...skipping 1084 matching lines...) Expand 10 before | Expand all | Expand 10 after
2855 void IsolateSpawnState::DecrementSpawnCount() { 2694 void IsolateSpawnState::DecrementSpawnCount() {
2856 ASSERT(spawn_count_monitor_ != NULL); 2695 ASSERT(spawn_count_monitor_ != NULL);
2857 ASSERT(spawn_count_ != NULL); 2696 ASSERT(spawn_count_ != NULL);
2858 MonitorLocker ml(spawn_count_monitor_); 2697 MonitorLocker ml(spawn_count_monitor_);
2859 ASSERT(*spawn_count_ > 0); 2698 ASSERT(*spawn_count_ > 0);
2860 *spawn_count_ = *spawn_count_ - 1; 2699 *spawn_count_ = *spawn_count_ - 1;
2861 ml.Notify(); 2700 ml.Notify();
2862 } 2701 }
2863 2702
2864 } // namespace dart 2703 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698