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/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" |
11 #include "vm/class_finalizer.h" | 11 #include "vm/class_finalizer.h" |
12 #include "vm/code_observers.h" | 12 #include "vm/code_observers.h" |
13 #include "vm/compiler.h" | 13 #include "vm/compiler.h" |
14 #include "vm/compiler_stats.h" | 14 #include "vm/compiler_stats.h" |
15 #include "vm/dart_api_message.h" | 15 #include "vm/dart_api_message.h" |
16 #include "vm/dart_api_state.h" | 16 #include "vm/dart_api_state.h" |
17 #include "vm/dart_entry.h" | 17 #include "vm/dart_entry.h" |
18 #include "vm/debugger.h" | 18 #include "vm/debugger.h" |
19 #include "vm/deopt_instructions.h" | 19 #include "vm/deopt_instructions.h" |
20 #include "vm/flags.h" | 20 #include "vm/flags.h" |
21 #include "vm/heap.h" | 21 #include "vm/heap.h" |
22 #include "vm/isolate_reload.h" | |
22 #include "vm/lockers.h" | 23 #include "vm/lockers.h" |
23 #include "vm/log.h" | 24 #include "vm/log.h" |
24 #include "vm/message_handler.h" | 25 #include "vm/message_handler.h" |
25 #include "vm/object_id_ring.h" | 26 #include "vm/object_id_ring.h" |
26 #include "vm/object_store.h" | 27 #include "vm/object_store.h" |
27 #include "vm/object.h" | 28 #include "vm/object.h" |
28 #include "vm/os_thread.h" | 29 #include "vm/os_thread.h" |
29 #include "vm/port.h" | 30 #include "vm/port.h" |
30 #include "vm/profiler.h" | 31 #include "vm/profiler.h" |
31 #include "vm/reusable_handles.h" | 32 #include "vm/reusable_handles.h" |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
127 thread->DeferOOBMessageInterrupts(); | 128 thread->DeferOOBMessageInterrupts(); |
128 } | 129 } |
129 | 130 |
130 | 131 |
131 NoOOBMessageScope::~NoOOBMessageScope() { | 132 NoOOBMessageScope::~NoOOBMessageScope() { |
132 thread()->RestoreOOBMessageInterrupts(); | 133 thread()->RestoreOOBMessageInterrupts(); |
133 } | 134 } |
134 | 135 |
135 | 136 |
136 | 137 |
138 NoReloadScope::NoReloadScope(Isolate* isolate, Thread* thread) | |
139 : StackResource(thread), | |
140 isolate_(isolate) { | |
141 ASSERT(isolate_ != NULL); | |
142 isolate_->no_reload_scope_depth_++; | |
143 ASSERT(isolate_->no_reload_scope_depth_ >= 0); | |
144 } | |
145 | |
146 | |
147 NoReloadScope::~NoReloadScope() { | |
148 isolate_->no_reload_scope_depth_--; | |
149 ASSERT(isolate_->no_reload_scope_depth_ >= 0); | |
150 } | |
151 | |
152 | |
137 void Isolate::RegisterClass(const Class& cls) { | 153 void Isolate::RegisterClass(const Class& cls) { |
154 NOT_IN_PRODUCT( | |
155 if (IsReloading()) { | |
156 reload_context()->RegisterClass(cls); | |
157 return; | |
158 } | |
159 ) | |
138 class_table()->Register(cls); | 160 class_table()->Register(cls); |
139 } | 161 } |
140 | 162 |
141 | 163 |
142 void Isolate::RegisterClassAt(intptr_t index, const Class& cls) { | 164 void Isolate::RegisterClassAt(intptr_t index, const Class& cls) { |
143 class_table()->RegisterAt(index, cls); | 165 class_table()->RegisterAt(index, cls); |
144 } | 166 } |
145 | 167 |
146 | 168 |
147 void Isolate::ValidateClassTable() { | 169 void Isolate::ValidateClassTable() { |
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
617 return MessageHandler::kShutdown; | 639 return MessageHandler::kShutdown; |
618 } | 640 } |
619 } | 641 } |
620 } | 642 } |
621 return MessageHandler::kError; | 643 return MessageHandler::kError; |
622 } | 644 } |
623 | 645 |
624 | 646 |
625 MessageHandler::MessageStatus IsolateMessageHandler::ProcessUnhandledException( | 647 MessageHandler::MessageStatus IsolateMessageHandler::ProcessUnhandledException( |
626 const Error& result) { | 648 const Error& result) { |
649 NOT_IN_PRODUCT( | |
650 if (I->IsReloading()) { | |
651 I->ReportReloadError(result); | |
652 return kOK; | |
653 } | |
654 ) | |
627 // Generate the error and stacktrace strings for the error message. | 655 // Generate the error and stacktrace strings for the error message. |
628 String& exc_str = String::Handle(T->zone()); | 656 String& exc_str = String::Handle(T->zone()); |
629 String& stacktrace_str = String::Handle(T->zone()); | 657 String& stacktrace_str = String::Handle(T->zone()); |
630 if (result.IsUnhandledException()) { | 658 if (result.IsUnhandledException()) { |
631 Zone* zone = T->zone(); | 659 Zone* zone = T->zone(); |
632 const UnhandledException& uhe = UnhandledException::Cast(result); | 660 const UnhandledException& uhe = UnhandledException::Cast(result); |
633 const Instance& exception = Instance::Handle(zone, uhe.exception()); | 661 const Instance& exception = Instance::Handle(zone, uhe.exception()); |
634 Object& tmp = Object::Handle(zone); | 662 Object& tmp = Object::Handle(zone); |
635 tmp = DartLibraryCalls::ToString(exception); | 663 tmp = DartLibraryCalls::ToString(exception); |
636 if (!tmp.IsString()) { | 664 if (!tmp.IsString()) { |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
778 is_service_isolate_(false), | 806 is_service_isolate_(false), |
779 stacktrace_(NULL), | 807 stacktrace_(NULL), |
780 stack_frame_index_(-1), | 808 stack_frame_index_(-1), |
781 last_allocationprofile_accumulator_reset_timestamp_(0), | 809 last_allocationprofile_accumulator_reset_timestamp_(0), |
782 last_allocationprofile_gc_timestamp_(0), | 810 last_allocationprofile_gc_timestamp_(0), |
783 object_id_ring_(NULL), | 811 object_id_ring_(NULL), |
784 tag_table_(GrowableObjectArray::null()), | 812 tag_table_(GrowableObjectArray::null()), |
785 deoptimized_code_array_(GrowableObjectArray::null()), | 813 deoptimized_code_array_(GrowableObjectArray::null()), |
786 sticky_error_(Error::null()), | 814 sticky_error_(Error::null()), |
787 background_compiler_(NULL), | 815 background_compiler_(NULL), |
816 background_compiler_disabled_count_(0), | |
rmacnak
2016/05/13 17:59:34
depth
Cutch
2016/05/17 18:03:51
Done.
| |
788 pending_service_extension_calls_(GrowableObjectArray::null()), | 817 pending_service_extension_calls_(GrowableObjectArray::null()), |
789 registered_service_extension_handlers_(GrowableObjectArray::null()), | 818 registered_service_extension_handlers_(GrowableObjectArray::null()), |
790 metrics_list_head_(NULL), | 819 metrics_list_head_(NULL), |
791 compilation_allowed_(true), | 820 compilation_allowed_(true), |
792 all_classes_finalized_(false), | 821 all_classes_finalized_(false), |
793 next_(NULL), | 822 next_(NULL), |
794 pause_loop_monitor_(NULL), | 823 pause_loop_monitor_(NULL), |
795 field_invalidation_gen_(kInvalidGen), | 824 field_invalidation_gen_(kInvalidGen), |
796 loading_invalidation_gen_(kInvalidGen), | 825 loading_invalidation_gen_(kInvalidGen), |
797 top_level_parsing_count_(0), | 826 top_level_parsing_count_(0), |
798 field_list_mutex_(new Mutex()), | 827 field_list_mutex_(new Mutex()), |
799 boxed_field_list_(GrowableObjectArray::null()), | 828 boxed_field_list_(GrowableObjectArray::null()), |
800 disabling_field_list_(GrowableObjectArray::null()), | 829 disabling_field_list_(GrowableObjectArray::null()), |
801 spawn_count_monitor_(new Monitor()), | 830 spawn_count_monitor_(new Monitor()), |
802 spawn_count_(0) { | 831 spawn_count_(0), |
832 has_attempted_reload_(false), | |
833 no_reload_scope_depth_(0), | |
834 reload_context_(NULL) { | |
803 NOT_IN_PRODUCT(FlagsCopyFrom(api_flags)); | 835 NOT_IN_PRODUCT(FlagsCopyFrom(api_flags)); |
804 // TODO(asiva): A Thread is not available here, need to figure out | 836 // TODO(asiva): A Thread is not available here, need to figure out |
805 // how the vm_tag (kEmbedderTagId) can be set, these tags need to | 837 // how the vm_tag (kEmbedderTagId) can be set, these tags need to |
806 // move to the OSThread structure. | 838 // move to the OSThread structure. |
807 set_user_tag(UserTags::kDefaultUserTag); | 839 set_user_tag(UserTags::kDefaultUserTag); |
808 } | 840 } |
809 | 841 |
810 #undef REUSABLE_HANDLE_SCOPE_INIT | 842 #undef REUSABLE_HANDLE_SCOPE_INIT |
811 #undef REUSABLE_HANDLE_INITIALIZERS | 843 #undef REUSABLE_HANDLE_INITIALIZERS |
812 | 844 |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1009 // as 'load in progres'. Set the status to 'loaded'. | 1041 // as 'load in progres'. Set the status to 'loaded'. |
1010 if (lib.LoadInProgress()) { | 1042 if (lib.LoadInProgress()) { |
1011 lib.SetLoaded(); | 1043 lib.SetLoaded(); |
1012 } | 1044 } |
1013 lib.InitExportedNamesCache(); | 1045 lib.InitExportedNamesCache(); |
1014 } | 1046 } |
1015 TokenStream::CloseSharedTokenList(this); | 1047 TokenStream::CloseSharedTokenList(this); |
1016 } | 1048 } |
1017 | 1049 |
1018 | 1050 |
1051 bool Isolate::CanReload() const { | |
1052 #ifndef PRODUCT | |
1053 return (!ServiceIsolate::IsServiceIsolateDescendant(this) && | |
1054 is_runnable() && !IsReloading() && no_reload_scope_depth_ == 0); | |
1055 #else | |
1056 return false; | |
1057 #endif | |
1058 } | |
1059 | |
1060 | |
1061 #ifndef PRODUCT | |
1062 void Isolate::ReportReloadError(const Error& error) { | |
1063 ASSERT(IsReloading()); | |
1064 reload_context_->AbortReload(error); | |
1065 delete reload_context_; | |
1066 reload_context_ = NULL; | |
1067 } | |
1068 | |
1069 | |
1070 void Isolate::OnStackReload() { | |
1071 UNREACHABLE(); | |
1072 } | |
1073 | |
1074 | |
1075 void Isolate::ReloadSources(bool test_mode) { | |
1076 ASSERT(!IsReloading()); | |
1077 has_attempted_reload_ = true; | |
1078 reload_context_ = new IsolateReloadContext(this, test_mode); | |
1079 reload_context_->StartReload(); | |
1080 } | |
1081 | |
1082 #endif | |
1083 | |
1084 | |
1085 void Isolate::DoneFinalizing() { | |
1086 NOT_IN_PRODUCT( | |
1087 if (IsReloading()) { | |
1088 reload_context_->FinishReload(); | |
1089 if (reload_context_->has_error() && reload_context_->test_mode()) { | |
1090 // If the reload has an error and we are in test mode keep the reload | |
1091 // context on the isolate so that it can be used by unit tests. | |
1092 return; | |
1093 } | |
1094 if (!reload_context_->has_error()) { | |
1095 reload_context_->ReportSuccess(); | |
1096 } | |
1097 delete reload_context_; | |
1098 reload_context_ = NULL; | |
1099 } | |
1100 ) | |
1101 } | |
1102 | |
1103 | |
1104 | |
1019 bool Isolate::MakeRunnable() { | 1105 bool Isolate::MakeRunnable() { |
1020 ASSERT(Isolate::Current() == NULL); | 1106 ASSERT(Isolate::Current() == NULL); |
1021 | 1107 |
1022 MutexLocker ml(mutex_); | 1108 MutexLocker ml(mutex_); |
1023 // Check if we are in a valid state to make the isolate runnable. | 1109 // Check if we are in a valid state to make the isolate runnable. |
1024 if (is_runnable() == true) { | 1110 if (is_runnable() == true) { |
1025 return false; // Already runnable. | 1111 return false; // Already runnable. |
1026 } | 1112 } |
1027 // Set the isolate as runnable and if we are being spawned schedule | 1113 // Set the isolate as runnable and if we are being spawned schedule |
1028 // isolate on thread pool for execution. | 1114 // isolate on thread pool for execution. |
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1683 // 'disabling_field_list_' access via mutator and background compilation | 1769 // 'disabling_field_list_' access via mutator and background compilation |
1684 // threads is guarded with a monitor. This means that we can visit it only | 1770 // threads is guarded with a monitor. This means that we can visit it only |
1685 // when at safepoint or the field_list_mutex_ lock has been taken. | 1771 // when at safepoint or the field_list_mutex_ lock has been taken. |
1686 visitor->VisitPointer(reinterpret_cast<RawObject**>(&disabling_field_list_)); | 1772 visitor->VisitPointer(reinterpret_cast<RawObject**>(&disabling_field_list_)); |
1687 | 1773 |
1688 // Visit objects in the debugger. | 1774 // Visit objects in the debugger. |
1689 if (FLAG_support_debugger) { | 1775 if (FLAG_support_debugger) { |
1690 debugger()->VisitObjectPointers(visitor); | 1776 debugger()->VisitObjectPointers(visitor); |
1691 } | 1777 } |
1692 | 1778 |
1779 NOT_IN_PRODUCT( | |
1780 // Visit objects that are being used for isolate reload. | |
1781 if (reload_context() != NULL) { | |
1782 reload_context()->VisitObjectPointers(visitor); | |
1783 } | |
1784 ) | |
1785 | |
1693 // Visit objects that are being used for deoptimization. | 1786 // Visit objects that are being used for deoptimization. |
1694 if (deopt_context() != NULL) { | 1787 if (deopt_context() != NULL) { |
1695 deopt_context()->VisitObjectPointers(visitor); | 1788 deopt_context()->VisitObjectPointers(visitor); |
1696 } | 1789 } |
1697 | 1790 |
1698 // Visit objects in all threads (e.g., Dart stack, handles in zones). | 1791 // Visit objects in all threads (e.g., Dart stack, handles in zones). |
1699 thread_registry()->VisitObjectPointers(visitor, validate_frames); | 1792 thread_registry()->VisitObjectPointers(visitor, validate_frames); |
1700 } | 1793 } |
1701 | 1794 |
1702 | 1795 |
1703 void Isolate::VisitWeakPersistentHandles(HandleVisitor* visitor) { | 1796 void Isolate::VisitWeakPersistentHandles(HandleVisitor* visitor) { |
1704 if (api_state() != NULL) { | 1797 if (api_state() != NULL) { |
1705 api_state()->VisitWeakHandles(visitor); | 1798 api_state()->VisitWeakHandles(visitor); |
1706 } | 1799 } |
1707 } | 1800 } |
1708 | 1801 |
1709 | 1802 |
1710 void Isolate::PrepareForGC() { | 1803 void Isolate::PrepareForGC() { |
1711 thread_registry()->PrepareForGC(); | 1804 thread_registry()->PrepareForGC(); |
1712 } | 1805 } |
1713 | 1806 |
1714 | 1807 |
1808 RawClass* Isolate::GetClassForHeapWalkAt(intptr_t cid) { | |
1809 RawClass* raw_class = NULL; | |
1810 #ifndef PRODUCT | |
1811 if (IsReloading()) { | |
1812 raw_class = reload_context()->GetClassForHeapWalkAt(cid); | |
1813 } else { | |
1814 raw_class = class_table()->At(cid); | |
1815 } | |
1816 #else | |
1817 raw_class = class_table()->At(cid); | |
1818 #endif // !PRODUCT | |
1819 ASSERT(raw_class != NULL); | |
1820 ASSERT(raw_class->ptr()->id_ == cid); | |
1821 return raw_class; | |
1822 } | |
1823 | |
1824 | |
1715 static const char* ExceptionPauseInfoToServiceEnum(Dart_ExceptionPauseInfo pi) { | 1825 static const char* ExceptionPauseInfoToServiceEnum(Dart_ExceptionPauseInfo pi) { |
1716 switch (pi) { | 1826 switch (pi) { |
1717 case kPauseOnAllExceptions: | 1827 case kPauseOnAllExceptions: |
1718 return "All"; | 1828 return "All"; |
1719 case kNoPauseOnExceptions: | 1829 case kNoPauseOnExceptions: |
1720 return "None"; | 1830 return "None"; |
1721 case kPauseOnUnhandledExceptions: | 1831 case kPauseOnUnhandledExceptions: |
1722 return "Unhandled"; | 1832 return "Unhandled"; |
1723 default: | 1833 default: |
1724 UNIMPLEMENTED(); | 1834 UNIMPLEMENTED(); |
(...skipping 23 matching lines...) Expand all Loading... | |
1748 jsobj.AddPropertyTimeMillis("startTime", start_time_millis); | 1858 jsobj.AddPropertyTimeMillis("startTime", start_time_millis); |
1749 { | 1859 { |
1750 JSONObject jsheap(&jsobj, "_heaps"); | 1860 JSONObject jsheap(&jsobj, "_heaps"); |
1751 heap()->PrintToJSONObject(Heap::kNew, &jsheap); | 1861 heap()->PrintToJSONObject(Heap::kNew, &jsheap); |
1752 heap()->PrintToJSONObject(Heap::kOld, &jsheap); | 1862 heap()->PrintToJSONObject(Heap::kOld, &jsheap); |
1753 } | 1863 } |
1754 | 1864 |
1755 jsobj.AddProperty("runnable", is_runnable()); | 1865 jsobj.AddProperty("runnable", is_runnable()); |
1756 jsobj.AddProperty("livePorts", message_handler()->live_ports()); | 1866 jsobj.AddProperty("livePorts", message_handler()->live_ports()); |
1757 jsobj.AddProperty("pauseOnExit", message_handler()->should_pause_on_exit()); | 1867 jsobj.AddProperty("pauseOnExit", message_handler()->should_pause_on_exit()); |
1868 jsobj.AddProperty("_isReloading", IsReloading()); | |
1758 | 1869 |
1759 if (debugger() != NULL) { | 1870 if (debugger() != NULL) { |
1760 if (!is_runnable()) { | 1871 if (!is_runnable()) { |
1761 // Isolate is not yet runnable. | 1872 // Isolate is not yet runnable. |
1762 ASSERT(debugger()->PauseEvent() == NULL); | 1873 ASSERT(debugger()->PauseEvent() == NULL); |
1763 ServiceEvent pause_event(this, ServiceEvent::kNone); | 1874 ServiceEvent pause_event(this, ServiceEvent::kNone); |
1764 jsobj.AddProperty("pauseEvent", &pause_event); | 1875 jsobj.AddProperty("pauseEvent", &pause_event); |
1765 } else if (message_handler()->is_paused_on_start() || | 1876 } else if (message_handler()->is_paused_on_start() || |
1766 message_handler()->should_pause_on_start()) { | 1877 message_handler()->should_pause_on_start()) { |
1767 ASSERT(debugger()->PauseEvent() == NULL); | 1878 ASSERT(debugger()->PauseEvent() == NULL); |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2181 if (pause_loop_monitor_ == NULL) { | 2292 if (pause_loop_monitor_ == NULL) { |
2182 pause_loop_monitor_ = new Monitor(); | 2293 pause_loop_monitor_ = new Monitor(); |
2183 } | 2294 } |
2184 Dart_EnterScope(); | 2295 Dart_EnterScope(); |
2185 MonitorLocker ml(pause_loop_monitor_); | 2296 MonitorLocker ml(pause_loop_monitor_); |
2186 | 2297 |
2187 Dart_MessageNotifyCallback saved_notify_callback = | 2298 Dart_MessageNotifyCallback saved_notify_callback = |
2188 message_notify_callback(); | 2299 message_notify_callback(); |
2189 set_message_notify_callback(Isolate::WakePauseEventHandler); | 2300 set_message_notify_callback(Isolate::WakePauseEventHandler); |
2190 | 2301 |
2302 const bool had_isolate_reload_context = reload_context() != NULL; | |
2303 const int64_t start_time_micros = | |
2304 !had_isolate_reload_context ? 0 : reload_context()->start_time_micros(); | |
2191 bool resume = false; | 2305 bool resume = false; |
2192 while (true) { | 2306 while (true) { |
2193 // Handle all available vm service messages, up to a resume | 2307 // Handle all available vm service messages, up to a resume |
2194 // request. | 2308 // request. |
2195 while (!resume && Dart_HasServiceMessages()) { | 2309 while (!resume && Dart_HasServiceMessages()) { |
2196 ml.Exit(); | 2310 ml.Exit(); |
2197 resume = Dart_HandleServiceMessages(); | 2311 resume = Dart_HandleServiceMessages(); |
2198 ml.Enter(); | 2312 ml.Enter(); |
2199 } | 2313 } |
2200 if (resume) { | 2314 if (resume) { |
2201 break; | 2315 break; |
2202 } | 2316 } |
2203 | 2317 |
2318 if (had_isolate_reload_context && (reload_context() == NULL)) { | |
2319 const int64_t reload_time_micros = | |
2320 OS::GetCurrentMonotonicMicros() - start_time_micros; | |
2321 double reload_millis = | |
2322 MicrosecondsToMilliseconds(reload_time_micros); | |
2323 OS::Print("Reloading has finished! (%.2f ms)\n", reload_millis); | |
rmacnak
2016/05/13 17:59:34
if FLAG_trace_reload
Cutch
2016/05/17 18:03:52
Done.
| |
2324 break; | |
2325 } | |
2326 | |
2204 // Wait for more service messages. | 2327 // Wait for more service messages. |
2205 Monitor::WaitResult res = ml.Wait(); | 2328 Monitor::WaitResult res = ml.Wait(); |
2206 ASSERT(res == Monitor::kNotified); | 2329 ASSERT(res == Monitor::kNotified); |
2207 } | 2330 } |
2208 set_message_notify_callback(saved_notify_callback); | 2331 set_message_notify_callback(saved_notify_callback); |
2209 Dart_ExitScope(); | 2332 Dart_ExitScope(); |
2210 } | 2333 } |
2211 | 2334 |
2212 | 2335 |
2213 void Isolate::VisitIsolates(IsolateVisitor* visitor) { | 2336 void Isolate::VisitIsolates(IsolateVisitor* visitor) { |
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2717 void IsolateSpawnState::DecrementSpawnCount() { | 2840 void IsolateSpawnState::DecrementSpawnCount() { |
2718 ASSERT(spawn_count_monitor_ != NULL); | 2841 ASSERT(spawn_count_monitor_ != NULL); |
2719 ASSERT(spawn_count_ != NULL); | 2842 ASSERT(spawn_count_ != NULL); |
2720 MonitorLocker ml(spawn_count_monitor_); | 2843 MonitorLocker ml(spawn_count_monitor_); |
2721 ASSERT(*spawn_count_ > 0); | 2844 ASSERT(*spawn_count_ > 0); |
2722 *spawn_count_ = *spawn_count_ - 1; | 2845 *spawn_count_ = *spawn_count_ - 1; |
2723 ml.Notify(); | 2846 ml.Notify(); |
2724 } | 2847 } |
2725 | 2848 |
2726 } // namespace dart | 2849 } // namespace dart |
OLD | NEW |