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), |
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); |
| 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 |