| 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" |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 NoOOBMessageScope::NoOOBMessageScope(Thread* thread) : StackResource(thread) { | 137 NoOOBMessageScope::NoOOBMessageScope(Thread* thread) : StackResource(thread) { |
| 138 thread->DeferOOBMessageInterrupts(); | 138 thread->DeferOOBMessageInterrupts(); |
| 139 } | 139 } |
| 140 | 140 |
| 141 NoOOBMessageScope::~NoOOBMessageScope() { | 141 NoOOBMessageScope::~NoOOBMessageScope() { |
| 142 thread()->RestoreOOBMessageInterrupts(); | 142 thread()->RestoreOOBMessageInterrupts(); |
| 143 } | 143 } |
| 144 | 144 |
| 145 NoReloadScope::NoReloadScope(Isolate* isolate, Thread* thread) | 145 NoReloadScope::NoReloadScope(Isolate* isolate, Thread* thread) |
| 146 : StackResource(thread), isolate_(isolate) { | 146 : StackResource(thread), isolate_(isolate) { |
| 147 #if !defined(PRODUCT) |
| 147 ASSERT(isolate_ != NULL); | 148 ASSERT(isolate_ != NULL); |
| 148 AtomicOperations::FetchAndIncrement(&(isolate_->no_reload_scope_depth_)); | 149 AtomicOperations::FetchAndIncrement(&(isolate_->no_reload_scope_depth_)); |
| 149 ASSERT(AtomicOperations::LoadRelaxed(&(isolate_->no_reload_scope_depth_)) >= | 150 ASSERT(AtomicOperations::LoadRelaxed(&(isolate_->no_reload_scope_depth_)) >= |
| 150 0); | 151 0); |
| 152 #endif // !defined(PRODUCT) |
| 151 } | 153 } |
| 152 | 154 |
| 153 NoReloadScope::~NoReloadScope() { | 155 NoReloadScope::~NoReloadScope() { |
| 156 #if !defined(PRODUCT) |
| 154 AtomicOperations::FetchAndDecrement(&(isolate_->no_reload_scope_depth_)); | 157 AtomicOperations::FetchAndDecrement(&(isolate_->no_reload_scope_depth_)); |
| 155 ASSERT(AtomicOperations::LoadRelaxed(&(isolate_->no_reload_scope_depth_)) >= | 158 ASSERT(AtomicOperations::LoadRelaxed(&(isolate_->no_reload_scope_depth_)) >= |
| 156 0); | 159 0); |
| 160 #endif // !defined(PRODUCT) |
| 157 } | 161 } |
| 158 | 162 |
| 159 void Isolate::RegisterClass(const Class& cls) { | 163 void Isolate::RegisterClass(const Class& cls) { |
| 160 #if !defined(PRODUCT) | 164 #if !defined(PRODUCT) |
| 161 if (IsReloading()) { | 165 if (IsReloading()) { |
| 162 reload_context()->RegisterClass(cls); | 166 reload_context()->RegisterClass(cls); |
| 163 return; | 167 return; |
| 164 } | 168 } |
| 165 #endif // !defined(PRODUCT) | 169 #endif // !defined(PRODUCT) |
| 166 class_table()->Register(cls); | 170 class_table()->Register(cls); |
| (...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 reusable_##object##_handle_scope_active_(false), | 731 reusable_##object##_handle_scope_active_(false), |
| 728 #else | 732 #else |
| 729 #define REUSABLE_HANDLE_SCOPE_INIT(object) | 733 #define REUSABLE_HANDLE_SCOPE_INIT(object) |
| 730 #endif // defined(DEBUG) | 734 #endif // defined(DEBUG) |
| 731 | 735 |
| 732 #define REUSABLE_HANDLE_INITIALIZERS(object) object##_handle_(NULL), | 736 #define REUSABLE_HANDLE_INITIALIZERS(object) object##_handle_(NULL), |
| 733 | 737 |
| 734 // TODO(srdjan): Some Isolate monitors can be shared. Replace their usage with | 738 // TODO(srdjan): Some Isolate monitors can be shared. Replace their usage with |
| 735 // that shared monitor. | 739 // that shared monitor. |
| 736 Isolate::Isolate(const Dart_IsolateFlags& api_flags) | 740 Isolate::Isolate(const Dart_IsolateFlags& api_flags) |
| 737 : store_buffer_(new StoreBuffer()), | 741 : BaseIsolate(), |
| 742 store_buffer_(new StoreBuffer()), |
| 738 heap_(NULL), | 743 heap_(NULL), |
| 739 user_tag_(0), | 744 user_tag_(0), |
| 740 current_tag_(UserTag::null()), | 745 current_tag_(UserTag::null()), |
| 741 default_tag_(UserTag::null()), | 746 default_tag_(UserTag::null()), |
| 747 ic_miss_code_(Code::null()), |
| 742 object_store_(NULL), | 748 object_store_(NULL), |
| 743 class_table_(), | 749 class_table_(), |
| 744 single_step_(false), | 750 single_step_(false), |
| 751 errors_fatal_(true), |
| 752 is_runnable_(false), |
| 753 is_service_isolate_(false), |
| 754 compilation_allowed_(true), |
| 755 all_classes_finalized_(false), |
| 756 remapping_cids_(false), |
| 757 #if !defined(PRODUCT) |
| 758 resume_request_(false), |
| 759 has_attempted_reload_(false), |
| 760 should_pause_post_service_request_(false), |
| 761 debugger_name_(NULL), |
| 762 start_time_micros_(OS::GetCurrentMonotonicMicros()), |
| 763 debugger_(NULL), |
| 764 last_resume_timestamp_(OS::GetCurrentTimeMillis()), |
| 765 last_allocationprofile_accumulator_reset_timestamp_(0), |
| 766 last_allocationprofile_gc_timestamp_(0), |
| 767 vm_tag_counters_(), |
| 768 pending_service_extension_calls_(GrowableObjectArray::null()), |
| 769 registered_service_extension_handlers_(GrowableObjectArray::null()), |
| 770 metrics_list_head_(NULL), |
| 771 pause_loop_monitor_(NULL), |
| 772 #define ISOLATE_METRIC_CONSTRUCTORS(type, variable, name, unit) \ |
| 773 metric_##variable##_(), |
| 774 ISOLATE_METRIC_LIST(ISOLATE_METRIC_CONSTRUCTORS) |
| 775 #undef ISOLATE_METRIC_CONSTRUCTORS |
| 776 no_reload_scope_depth_(0), |
| 777 reload_every_n_stack_overflow_checks_(FLAG_reload_every), |
| 778 reload_context_(NULL), |
| 779 last_reload_timestamp_(OS::GetCurrentTimeMillis()), |
| 780 object_id_ring_(NULL), |
| 781 #endif // !defined(PRODUCT) |
| 745 thread_registry_(new ThreadRegistry()), | 782 thread_registry_(new ThreadRegistry()), |
| 746 safepoint_handler_(new SafepointHandler(this)), | 783 safepoint_handler_(new SafepointHandler(this)), |
| 747 message_notify_callback_(NULL), | 784 message_notify_callback_(NULL), |
| 748 name_(NULL), | 785 name_(NULL), |
| 749 debugger_name_(NULL), | |
| 750 start_time_micros_(OS::GetCurrentMonotonicMicros()), | |
| 751 main_port_(0), | 786 main_port_(0), |
| 752 origin_id_(0), | 787 origin_id_(0), |
| 753 pause_capability_(0), | 788 pause_capability_(0), |
| 754 terminate_capability_(0), | 789 terminate_capability_(0), |
| 755 errors_fatal_(true), | |
| 756 init_callback_data_(NULL), | 790 init_callback_data_(NULL), |
| 757 environment_callback_(NULL), | 791 environment_callback_(NULL), |
| 758 library_tag_handler_(NULL), | 792 library_tag_handler_(NULL), |
| 759 api_state_(NULL), | 793 api_state_(NULL), |
| 760 #if !defined(PRODUCT) | |
| 761 debugger_(NULL), | |
| 762 resume_request_(false), | |
| 763 last_resume_timestamp_(OS::GetCurrentTimeMillis()), | |
| 764 #endif | |
| 765 random_(), | 794 random_(), |
| 766 simulator_(NULL), | 795 simulator_(NULL), |
| 767 mutex_(new Mutex()), | 796 mutex_(new Mutex()), |
| 768 symbols_mutex_(new Mutex()), | 797 symbols_mutex_(new Mutex()), |
| 769 type_canonicalization_mutex_(new Mutex()), | 798 type_canonicalization_mutex_(new Mutex()), |
| 770 constant_canonicalization_mutex_(new Mutex()), | 799 constant_canonicalization_mutex_(new Mutex()), |
| 771 megamorphic_lookup_mutex_(new Mutex()), | 800 megamorphic_lookup_mutex_(new Mutex()), |
| 772 message_handler_(NULL), | 801 message_handler_(NULL), |
| 773 spawn_state_(NULL), | 802 spawn_state_(NULL), |
| 774 is_runnable_(false), | |
| 775 gc_prologue_callback_(NULL), | 803 gc_prologue_callback_(NULL), |
| 776 gc_epilogue_callback_(NULL), | 804 gc_epilogue_callback_(NULL), |
| 777 defer_finalization_count_(0), | 805 defer_finalization_count_(0), |
| 778 pending_deopts_(new MallocGrowableArray<PendingLazyDeopt>), | 806 pending_deopts_(new MallocGrowableArray<PendingLazyDeopt>), |
| 779 deopt_context_(NULL), | 807 deopt_context_(NULL), |
| 780 is_service_isolate_(false), | |
| 781 last_allocationprofile_accumulator_reset_timestamp_(0), | |
| 782 last_allocationprofile_gc_timestamp_(0), | |
| 783 object_id_ring_(NULL), | |
| 784 tag_table_(GrowableObjectArray::null()), | 808 tag_table_(GrowableObjectArray::null()), |
| 785 deoptimized_code_array_(GrowableObjectArray::null()), | 809 deoptimized_code_array_(GrowableObjectArray::null()), |
| 786 sticky_error_(Error::null()), | 810 sticky_error_(Error::null()), |
| 787 background_compiler_(NULL), | 811 background_compiler_(NULL), |
| 788 background_compiler_disabled_depth_(0), | 812 background_compiler_disabled_depth_(0), |
| 789 pending_service_extension_calls_(GrowableObjectArray::null()), | |
| 790 registered_service_extension_handlers_(GrowableObjectArray::null()), | |
| 791 metrics_list_head_(NULL), | |
| 792 compilation_allowed_(true), | |
| 793 all_classes_finalized_(false), | |
| 794 remapping_cids_(false), | |
| 795 next_(NULL), | 813 next_(NULL), |
| 796 pause_loop_monitor_(NULL), | |
| 797 loading_invalidation_gen_(kInvalidGen), | 814 loading_invalidation_gen_(kInvalidGen), |
| 798 top_level_parsing_count_(0), | 815 top_level_parsing_count_(0), |
| 799 field_list_mutex_(new Mutex()), | 816 field_list_mutex_(new Mutex()), |
| 800 boxed_field_list_(GrowableObjectArray::null()), | 817 boxed_field_list_(GrowableObjectArray::null()), |
| 801 spawn_count_monitor_(new Monitor()), | 818 spawn_count_monitor_(new Monitor()), |
| 802 spawn_count_(0), | 819 spawn_count_(0), |
| 803 #define ISOLATE_METRIC_CONSTRUCTORS(type, variable, name, unit) \ | 820 handler_info_cache_(), |
| 804 metric_##variable##_(), | 821 catch_entry_state_cache_() { |
| 805 ISOLATE_METRIC_LIST(ISOLATE_METRIC_CONSTRUCTORS) | |
| 806 #undef ISOLATE_METRIC_CONSTRUCTORS | |
| 807 has_attempted_reload_(false), | |
| 808 no_reload_scope_depth_(0), | |
| 809 reload_every_n_stack_overflow_checks_(FLAG_reload_every), | |
| 810 reload_context_(NULL), | |
| 811 last_reload_timestamp_(OS::GetCurrentTimeMillis()), | |
| 812 should_pause_post_service_request_(false), | |
| 813 handler_info_cache_() { | |
| 814 NOT_IN_PRODUCT(FlagsCopyFrom(api_flags)); | 822 NOT_IN_PRODUCT(FlagsCopyFrom(api_flags)); |
| 815 // TODO(asiva): A Thread is not available here, need to figure out | 823 // TODO(asiva): A Thread is not available here, need to figure out |
| 816 // how the vm_tag (kEmbedderTagId) can be set, these tags need to | 824 // how the vm_tag (kEmbedderTagId) can be set, these tags need to |
| 817 // move to the OSThread structure. | 825 // move to the OSThread structure. |
| 818 set_user_tag(UserTags::kDefaultUserTag); | 826 set_user_tag(UserTags::kDefaultUserTag); |
| 819 } | 827 } |
| 820 | 828 |
| 821 #undef REUSABLE_HANDLE_SCOPE_INIT | 829 #undef REUSABLE_HANDLE_SCOPE_INIT |
| 822 #undef REUSABLE_HANDLE_INITIALIZERS | 830 #undef REUSABLE_HANDLE_INITIALIZERS |
| 823 | 831 |
| 824 Isolate::~Isolate() { | 832 Isolate::~Isolate() { |
| 833 #if !defined(PRODUCT) |
| 834 free(debugger_name_); |
| 835 delete debugger_; |
| 836 if (FLAG_support_service) { |
| 837 delete object_id_ring_; |
| 838 } |
| 839 object_id_ring_ = NULL; |
| 840 delete pause_loop_monitor_; |
| 841 pause_loop_monitor_ = NULL; |
| 842 #endif // !defined(PRODUCT) |
| 843 |
| 825 free(name_); | 844 free(name_); |
| 826 free(debugger_name_); | |
| 827 delete store_buffer_; | 845 delete store_buffer_; |
| 828 delete heap_; | 846 delete heap_; |
| 829 delete object_store_; | 847 delete object_store_; |
| 830 delete api_state_; | 848 delete api_state_; |
| 831 #ifndef PRODUCT | |
| 832 delete debugger_; | |
| 833 #endif // !PRODUCT | |
| 834 #if defined(USING_SIMULATOR) | 849 #if defined(USING_SIMULATOR) |
| 835 delete simulator_; | 850 delete simulator_; |
| 836 #endif | 851 #endif |
| 837 delete mutex_; | 852 delete mutex_; |
| 838 mutex_ = NULL; // Fail fast if interrupts are scheduled on a dead isolate. | 853 mutex_ = NULL; // Fail fast if interrupts are scheduled on a dead isolate. |
| 839 delete symbols_mutex_; | 854 delete symbols_mutex_; |
| 840 symbols_mutex_ = NULL; | 855 symbols_mutex_ = NULL; |
| 841 delete type_canonicalization_mutex_; | 856 delete type_canonicalization_mutex_; |
| 842 type_canonicalization_mutex_ = NULL; | 857 type_canonicalization_mutex_ = NULL; |
| 843 delete constant_canonicalization_mutex_; | 858 delete constant_canonicalization_mutex_; |
| 844 constant_canonicalization_mutex_ = NULL; | 859 constant_canonicalization_mutex_ = NULL; |
| 845 delete megamorphic_lookup_mutex_; | 860 delete megamorphic_lookup_mutex_; |
| 846 megamorphic_lookup_mutex_ = NULL; | 861 megamorphic_lookup_mutex_ = NULL; |
| 847 delete pending_deopts_; | 862 delete pending_deopts_; |
| 848 pending_deopts_ = NULL; | 863 pending_deopts_ = NULL; |
| 849 delete message_handler_; | 864 delete message_handler_; |
| 850 message_handler_ = NULL; // Fail fast if we send messages to a dead isolate. | 865 message_handler_ = NULL; // Fail fast if we send messages to a dead isolate. |
| 851 ASSERT(deopt_context_ == NULL); // No deopt in progress when isolate deleted. | 866 ASSERT(deopt_context_ == NULL); // No deopt in progress when isolate deleted. |
| 852 delete spawn_state_; | 867 delete spawn_state_; |
| 853 #ifndef PRODUCT | |
| 854 if (FLAG_support_service) { | |
| 855 delete object_id_ring_; | |
| 856 } | |
| 857 #endif // !PRODUCT | |
| 858 object_id_ring_ = NULL; | |
| 859 delete pause_loop_monitor_; | |
| 860 pause_loop_monitor_ = NULL; | |
| 861 delete field_list_mutex_; | 868 delete field_list_mutex_; |
| 862 field_list_mutex_ = NULL; | 869 field_list_mutex_ = NULL; |
| 863 ASSERT(spawn_count_ == 0); | 870 ASSERT(spawn_count_ == 0); |
| 864 delete spawn_count_monitor_; | 871 delete spawn_count_monitor_; |
| 865 delete safepoint_handler_; | 872 delete safepoint_handler_; |
| 866 delete thread_registry_; | 873 delete thread_registry_; |
| 867 } | 874 } |
| 868 | 875 |
| 869 void Isolate::InitOnce() { | 876 void Isolate::InitOnce() { |
| 870 create_callback_ = NULL; | 877 create_callback_ = NULL; |
| 871 isolates_list_monitor_ = new Monitor(); | 878 isolates_list_monitor_ = new Monitor(); |
| 872 ASSERT(isolates_list_monitor_ != NULL); | 879 ASSERT(isolates_list_monitor_ != NULL); |
| 873 EnableIsolateCreation(); | 880 EnableIsolateCreation(); |
| 874 } | 881 } |
| 875 | 882 |
| 876 Isolate* Isolate::Init(const char* name_prefix, | 883 Isolate* Isolate::Init(const char* name_prefix, |
| 877 const Dart_IsolateFlags& api_flags, | 884 const Dart_IsolateFlags& api_flags, |
| 878 bool is_vm_isolate) { | 885 bool is_vm_isolate) { |
| 879 Isolate* result = new Isolate(api_flags); | 886 Isolate* result = new Isolate(api_flags); |
| 880 ASSERT(result != NULL); | 887 ASSERT(result != NULL); |
| 881 | 888 |
| 889 #if !defined(PRODUCT) |
| 882 // Initialize metrics. | 890 // Initialize metrics. |
| 883 #define ISOLATE_METRIC_INIT(type, variable, name, unit) \ | 891 #define ISOLATE_METRIC_INIT(type, variable, name, unit) \ |
| 884 result->metric_##variable##_.Init(result, name, NULL, Metric::unit); | 892 result->metric_##variable##_.Init(result, name, NULL, Metric::unit); |
| 885 ISOLATE_METRIC_LIST(ISOLATE_METRIC_INIT); | 893 ISOLATE_METRIC_LIST(ISOLATE_METRIC_INIT); |
| 886 #undef ISOLATE_METRIC_INIT | 894 #undef ISOLATE_METRIC_INIT |
| 895 #endif // !defined(PRODUCT) |
| 887 | 896 |
| 888 Heap::Init(result, | 897 Heap::Init(result, |
| 889 is_vm_isolate | 898 is_vm_isolate |
| 890 ? 0 // New gen size 0; VM isolate should only allocate in old. | 899 ? 0 // New gen size 0; VM isolate should only allocate in old. |
| 891 : FLAG_new_gen_semi_max_size * MBInWords, | 900 : FLAG_new_gen_semi_max_size * MBInWords, |
| 892 FLAG_old_gen_heap_size * MBInWords, | 901 FLAG_old_gen_heap_size * MBInWords, |
| 893 FLAG_external_max_size * MBInWords); | 902 FLAG_external_max_size * MBInWords); |
| 894 | 903 |
| 895 // TODO(5411455): For now just set the recently created isolate as | 904 // TODO(5411455): For now just set the recently created isolate as |
| 896 // the current isolate. | 905 // the current isolate. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 966 void Isolate::ScheduleMessageInterrupts() { | 975 void Isolate::ScheduleMessageInterrupts() { |
| 967 // We take the threads lock here to ensure that the mutator thread does not | 976 // We take the threads lock here to ensure that the mutator thread does not |
| 968 // exit the isolate while we are trying to schedule interrupts on it. | 977 // exit the isolate while we are trying to schedule interrupts on it. |
| 969 MonitorLocker ml(threads_lock()); | 978 MonitorLocker ml(threads_lock()); |
| 970 Thread* mthread = mutator_thread(); | 979 Thread* mthread = mutator_thread(); |
| 971 if (mthread != NULL) { | 980 if (mthread != NULL) { |
| 972 mthread->ScheduleInterrupts(Thread::kMessageInterrupt); | 981 mthread->ScheduleInterrupts(Thread::kMessageInterrupt); |
| 973 } | 982 } |
| 974 } | 983 } |
| 975 | 984 |
| 985 #if !defined(PRODUCT) |
| 976 void Isolate::set_debugger_name(const char* name) { | 986 void Isolate::set_debugger_name(const char* name) { |
| 977 free(debugger_name_); | 987 free(debugger_name_); |
| 978 debugger_name_ = strdup(name); | 988 debugger_name_ = strdup(name); |
| 979 } | 989 } |
| 980 | 990 |
| 981 int64_t Isolate::UptimeMicros() const { | 991 int64_t Isolate::UptimeMicros() const { |
| 982 return OS::GetCurrentMonotonicMicros() - start_time_micros_; | 992 return OS::GetCurrentMonotonicMicros() - start_time_micros_; |
| 983 } | 993 } |
| 994 #endif // !defined(PRODUCT) |
| 984 | 995 |
| 985 bool Isolate::IsPaused() const { | 996 bool Isolate::IsPaused() const { |
| 986 #if defined(PRODUCT) | 997 #if defined(PRODUCT) |
| 987 return false; | 998 return false; |
| 988 #else | 999 #else |
| 989 return (debugger_ != NULL) && (debugger_->PauseEvent() != NULL); | 1000 return (debugger_ != NULL) && (debugger_->PauseEvent() != NULL); |
| 990 #endif | 1001 #endif // !defined(PRODUCT) |
| 991 } | 1002 } |
| 992 | 1003 |
| 993 RawError* Isolate::PausePostRequest() { | 1004 RawError* Isolate::PausePostRequest() { |
| 994 #if !defined(PRODUCT) | 1005 #if !defined(PRODUCT) |
| 995 if (debugger_ == NULL) { | 1006 if (debugger_ == NULL) { |
| 996 return Error::null(); | 1007 return Error::null(); |
| 997 } | 1008 } |
| 998 ASSERT(!IsPaused()); | 1009 ASSERT(!IsPaused()); |
| 999 const Error& error = Error::Handle(debugger_->PausePostRequest()); | 1010 const Error& error = Error::Handle(debugger_->PausePostRequest()); |
| 1000 if (!error.IsNull()) { | 1011 if (!error.IsNull()) { |
| 1001 if (Thread::Current()->top_exit_frame_info() == 0) { | 1012 if (Thread::Current()->top_exit_frame_info() == 0) { |
| 1002 return error.raw(); | 1013 return error.raw(); |
| 1003 } else { | 1014 } else { |
| 1004 Exceptions::PropagateError(error); | 1015 Exceptions::PropagateError(error); |
| 1005 UNREACHABLE(); | 1016 UNREACHABLE(); |
| 1006 } | 1017 } |
| 1007 } | 1018 } |
| 1008 #endif | 1019 #endif |
| 1009 return Error::null(); | 1020 return Error::null(); |
| 1010 } | 1021 } |
| 1011 | 1022 |
| 1012 void Isolate::BuildName(const char* name_prefix) { | 1023 void Isolate::BuildName(const char* name_prefix) { |
| 1013 ASSERT(name_ == NULL); | 1024 ASSERT(name_ == NULL); |
| 1014 if (name_prefix == NULL) { | 1025 if (name_prefix == NULL) { |
| 1015 name_prefix = "isolate"; | 1026 name_prefix = "isolate"; |
| 1016 } | 1027 } |
| 1017 set_debugger_name(name_prefix); | 1028 NOT_IN_PRODUCT(set_debugger_name(name_prefix)); |
| 1018 if (ServiceIsolate::NameEquals(name_prefix)) { | 1029 if (ServiceIsolate::NameEquals(name_prefix)) { |
| 1019 name_ = strdup(name_prefix); | 1030 name_ = strdup(name_prefix); |
| 1020 return; | 1031 return; |
| 1021 } | 1032 } |
| 1022 name_ = OS::SCreate(NULL, "%s-%" Pd64 "", name_prefix, main_port()); | 1033 name_ = OS::SCreate(NULL, "%s-%" Pd64 "", name_prefix, main_port()); |
| 1023 } | 1034 } |
| 1024 | 1035 |
| 1025 void Isolate::DoneLoading() { | 1036 void Isolate::DoneLoading() { |
| 1026 GrowableObjectArray& libs = | 1037 GrowableObjectArray& libs = |
| 1027 GrowableObjectArray::Handle(current_zone(), object_store()->libraries()); | 1038 GrowableObjectArray::Handle(current_zone(), object_store()->libraries()); |
| 1028 Library& lib = Library::Handle(current_zone()); | 1039 Library& lib = Library::Handle(current_zone()); |
| 1029 intptr_t num_libs = libs.Length(); | 1040 intptr_t num_libs = libs.Length(); |
| 1030 for (intptr_t i = 0; i < num_libs; i++) { | 1041 for (intptr_t i = 0; i < num_libs; i++) { |
| 1031 lib ^= libs.At(i); | 1042 lib ^= libs.At(i); |
| 1032 // If this library was loaded with Dart_LoadLibrary, it was marked | 1043 // If this library was loaded with Dart_LoadLibrary, it was marked |
| 1033 // as 'load in progres'. Set the status to 'loaded'. | 1044 // as 'load in progres'. Set the status to 'loaded'. |
| 1034 if (lib.LoadInProgress()) { | 1045 if (lib.LoadInProgress()) { |
| 1035 lib.SetLoaded(); | 1046 lib.SetLoaded(); |
| 1036 } | 1047 } |
| 1037 } | 1048 } |
| 1038 TokenStream::CloseSharedTokenList(this); | 1049 TokenStream::CloseSharedTokenList(this); |
| 1039 } | 1050 } |
| 1040 | 1051 |
| 1052 #if !defined(PRODUCT) |
| 1041 bool Isolate::CanReload() const { | 1053 bool Isolate::CanReload() const { |
| 1042 #ifndef PRODUCT | |
| 1043 return !ServiceIsolate::IsServiceIsolateDescendant(this) && is_runnable() && | 1054 return !ServiceIsolate::IsServiceIsolateDescendant(this) && is_runnable() && |
| 1044 !IsReloading() && | 1055 !IsReloading() && |
| 1045 (AtomicOperations::LoadRelaxed(&no_reload_scope_depth_) == 0) && | 1056 (AtomicOperations::LoadRelaxed(&no_reload_scope_depth_) == 0) && |
| 1046 IsolateCreationEnabled(); | 1057 IsolateCreationEnabled(); |
| 1047 #else | |
| 1048 return false; | |
| 1049 #endif | |
| 1050 } | 1058 } |
| 1051 | 1059 |
| 1052 #ifndef PRODUCT | |
| 1053 bool Isolate::ReloadSources(JSONStream* js, | 1060 bool Isolate::ReloadSources(JSONStream* js, |
| 1054 bool force_reload, | 1061 bool force_reload, |
| 1055 const char* root_script_url, | 1062 const char* root_script_url, |
| 1056 const char* packages_url, | 1063 const char* packages_url, |
| 1057 bool dont_delete_reload_context) { | 1064 bool dont_delete_reload_context) { |
| 1058 ASSERT(!IsReloading()); | 1065 ASSERT(!IsReloading()); |
| 1059 has_attempted_reload_ = true; | 1066 has_attempted_reload_ = true; |
| 1060 reload_context_ = new IsolateReloadContext(this, js); | 1067 reload_context_ = new IsolateReloadContext(this, js); |
| 1061 reload_context_->Reload(force_reload, root_script_url, packages_url); | 1068 reload_context_->Reload(force_reload, root_script_url, packages_url); |
| 1062 bool success = !reload_context_->reload_aborted(); | 1069 bool success = !reload_context_->reload_aborted(); |
| 1063 if (!dont_delete_reload_context) { | 1070 if (!dont_delete_reload_context) { |
| 1064 DeleteReloadContext(); | 1071 DeleteReloadContext(); |
| 1065 } | 1072 } |
| 1066 return success; | 1073 return success; |
| 1067 } | 1074 } |
| 1068 | 1075 |
| 1069 void Isolate::DeleteReloadContext() { | 1076 void Isolate::DeleteReloadContext() { |
| 1070 // Another thread may be in the middle of GetClassForHeapWalkAt. | 1077 // Another thread may be in the middle of GetClassForHeapWalkAt. |
| 1071 Thread* thread = Thread::Current(); | 1078 Thread* thread = Thread::Current(); |
| 1072 SafepointOperationScope safepoint_scope(thread); | 1079 SafepointOperationScope safepoint_scope(thread); |
| 1073 | 1080 |
| 1074 delete reload_context_; | 1081 delete reload_context_; |
| 1075 reload_context_ = NULL; | 1082 reload_context_ = NULL; |
| 1076 } | 1083 } |
| 1077 #endif // !PRODUCT | 1084 #endif // !defined(PRODUCT) |
| 1078 | 1085 |
| 1079 void Isolate::DoneFinalizing() { | 1086 void Isolate::DoneFinalizing() { |
| 1080 #if !defined(PRODUCT) | 1087 #if !defined(PRODUCT) |
| 1081 if (IsReloading()) { | 1088 if (IsReloading()) { |
| 1082 reload_context_->FinalizeLoading(); | 1089 reload_context_->FinalizeLoading(); |
| 1083 } | 1090 } |
| 1084 #endif // !defined(PRODUCT) | 1091 #endif // !defined(PRODUCT) |
| 1085 } | 1092 } |
| 1086 | 1093 |
| 1087 bool Isolate::MakeRunnable() { | 1094 bool Isolate::MakeRunnable() { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1116 TimelineEvent* event = stream->StartEvent(); | 1123 TimelineEvent* event = stream->StartEvent(); |
| 1117 if (event != NULL) { | 1124 if (event != NULL) { |
| 1118 event->Instant("Runnable"); | 1125 event->Instant("Runnable"); |
| 1119 event->Complete(); | 1126 event->Complete(); |
| 1120 } | 1127 } |
| 1121 } | 1128 } |
| 1122 if (FLAG_support_service && Service::isolate_stream.enabled()) { | 1129 if (FLAG_support_service && Service::isolate_stream.enabled()) { |
| 1123 ServiceEvent runnableEvent(this, ServiceEvent::kIsolateRunnable); | 1130 ServiceEvent runnableEvent(this, ServiceEvent::kIsolateRunnable); |
| 1124 Service::HandleEvent(&runnableEvent); | 1131 Service::HandleEvent(&runnableEvent); |
| 1125 } | 1132 } |
| 1126 #endif // !PRODUCT | |
| 1127 GetRunnableLatencyMetric()->set_value(UptimeMicros()); | 1133 GetRunnableLatencyMetric()->set_value(UptimeMicros()); |
| 1128 if (FLAG_print_benchmarking_metrics) { | 1134 if (FLAG_print_benchmarking_metrics) { |
| 1129 { | 1135 { |
| 1130 StartIsolateScope scope(this); | 1136 StartIsolateScope scope(this); |
| 1131 heap()->CollectAllGarbage(); | 1137 heap()->CollectAllGarbage(); |
| 1132 } | 1138 } |
| 1133 int64_t heap_size = (heap()->UsedInWords(Heap::kNew) * kWordSize) + | 1139 int64_t heap_size = (heap()->UsedInWords(Heap::kNew) * kWordSize) + |
| 1134 (heap()->UsedInWords(Heap::kOld) * kWordSize); | 1140 (heap()->UsedInWords(Heap::kOld) * kWordSize); |
| 1135 GetRunnableHeapSizeMetric()->set_value(heap_size); | 1141 GetRunnableHeapSizeMetric()->set_value(heap_size); |
| 1136 } | 1142 } |
| 1143 #endif // !PRODUCT |
| 1137 return true; | 1144 return true; |
| 1138 } | 1145 } |
| 1139 | 1146 |
| 1140 bool Isolate::VerifyPauseCapability(const Object& capability) const { | 1147 bool Isolate::VerifyPauseCapability(const Object& capability) const { |
| 1141 return !capability.IsNull() && capability.IsCapability() && | 1148 return !capability.IsNull() && capability.IsCapability() && |
| 1142 (pause_capability() == Capability::Cast(capability).Id()); | 1149 (pause_capability() == Capability::Cast(capability).Id()); |
| 1143 } | 1150 } |
| 1144 | 1151 |
| 1145 bool Isolate::VerifyTerminateCapability(const Object& capability) const { | 1152 bool Isolate::VerifyTerminateCapability(const Object& capability) const { |
| 1146 return !capability.IsNull() && capability.IsCapability() && | 1153 return !capability.IsNull() && capability.IsCapability() && |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1590 if (FLAG_support_timeline && FLAG_timing) { | 1597 if (FLAG_support_timeline && FLAG_timing) { |
| 1591 TimelinePauseTrace tpt; | 1598 TimelinePauseTrace tpt; |
| 1592 tpt.Print(); | 1599 tpt.Print(); |
| 1593 } | 1600 } |
| 1594 #endif // !PRODUCT | 1601 #endif // !PRODUCT |
| 1595 | 1602 |
| 1596 // Finalize any weak persistent handles with a non-null referent. | 1603 // Finalize any weak persistent handles with a non-null referent. |
| 1597 FinalizeWeakPersistentHandlesVisitor visitor; | 1604 FinalizeWeakPersistentHandlesVisitor visitor; |
| 1598 api_state()->weak_persistent_handles().VisitHandles(&visitor); | 1605 api_state()->weak_persistent_handles().VisitHandles(&visitor); |
| 1599 | 1606 |
| 1607 #if !defined(PRODUCT) |
| 1600 if (FLAG_dump_megamorphic_stats) { | 1608 if (FLAG_dump_megamorphic_stats) { |
| 1601 MegamorphicCacheTable::PrintSizes(this); | 1609 MegamorphicCacheTable::PrintSizes(this); |
| 1602 } | 1610 } |
| 1603 if (FLAG_dump_symbol_stats) { | 1611 if (FLAG_dump_symbol_stats) { |
| 1604 Symbols::DumpStats(this); | 1612 Symbols::DumpStats(this); |
| 1605 } | 1613 } |
| 1606 if (FLAG_trace_isolates) { | 1614 if (FLAG_trace_isolates) { |
| 1607 heap()->PrintSizes(); | 1615 heap()->PrintSizes(); |
| 1608 OS::Print( | 1616 OS::Print( |
| 1609 "[-] Stopping isolate:\n" | 1617 "[-] Stopping isolate:\n" |
| 1610 "\tisolate: %s\n", | 1618 "\tisolate: %s\n", |
| 1611 name()); | 1619 name()); |
| 1612 } | 1620 } |
| 1613 if (FLAG_print_metrics || FLAG_print_benchmarking_metrics) { | 1621 if (FLAG_print_metrics || FLAG_print_benchmarking_metrics) { |
| 1614 LogBlock lb; | 1622 LogBlock lb; |
| 1615 OS::PrintErr("Printing metrics for %s\n", name()); | 1623 OS::PrintErr("Printing metrics for %s\n", name()); |
| 1616 #define ISOLATE_METRIC_PRINT(type, variable, name, unit) \ | 1624 #define ISOLATE_METRIC_PRINT(type, variable, name, unit) \ |
| 1617 OS::PrintErr("%s\n", metric_##variable##_.ToString()); | 1625 OS::PrintErr("%s\n", metric_##variable##_.ToString()); |
| 1618 ISOLATE_METRIC_LIST(ISOLATE_METRIC_PRINT) | 1626 ISOLATE_METRIC_LIST(ISOLATE_METRIC_PRINT) |
| 1619 #undef ISOLATE_METRIC_PRINT | 1627 #undef ISOLATE_METRIC_PRINT |
| 1620 OS::PrintErr("\n"); | 1628 OS::PrintErr("\n"); |
| 1621 } | 1629 } |
| 1630 #endif // !defined(PRODUCT) |
| 1622 } | 1631 } |
| 1623 | 1632 |
| 1624 void Isolate::StopBackgroundCompiler() { | 1633 void Isolate::StopBackgroundCompiler() { |
| 1625 // Wait until all background compilation has finished. | 1634 // Wait until all background compilation has finished. |
| 1626 if (background_compiler_ != NULL) { | 1635 if (background_compiler_ != NULL) { |
| 1627 BackgroundCompiler::Stop(this); | 1636 BackgroundCompiler::Stop(this); |
| 1628 } | 1637 } |
| 1629 } | 1638 } |
| 1630 | 1639 |
| 1640 #if !defined(PRODUCT) |
| 1631 void Isolate::MaybeIncreaseReloadEveryNStackOverflowChecks() { | 1641 void Isolate::MaybeIncreaseReloadEveryNStackOverflowChecks() { |
| 1632 if (FLAG_reload_every_back_off) { | 1642 if (FLAG_reload_every_back_off) { |
| 1633 if (reload_every_n_stack_overflow_checks_ < 5000) { | 1643 if (reload_every_n_stack_overflow_checks_ < 5000) { |
| 1634 reload_every_n_stack_overflow_checks_ += 99; | 1644 reload_every_n_stack_overflow_checks_ += 99; |
| 1635 } else { | 1645 } else { |
| 1636 reload_every_n_stack_overflow_checks_ *= 2; | 1646 reload_every_n_stack_overflow_checks_ *= 2; |
| 1637 } | 1647 } |
| 1638 // Cap the value. | 1648 // Cap the value. |
| 1639 if (reload_every_n_stack_overflow_checks_ > 1000000) { | 1649 if (reload_every_n_stack_overflow_checks_ > 1000000) { |
| 1640 reload_every_n_stack_overflow_checks_ = 1000000; | 1650 reload_every_n_stack_overflow_checks_ = 1000000; |
| 1641 } | 1651 } |
| 1642 } | 1652 } |
| 1643 } | 1653 } |
| 1654 #endif // !defined(PRODUCT) |
| 1644 | 1655 |
| 1645 void Isolate::Shutdown() { | 1656 void Isolate::Shutdown() { |
| 1646 ASSERT(this == Isolate::Current()); | 1657 ASSERT(this == Isolate::Current()); |
| 1647 StopBackgroundCompiler(); | 1658 StopBackgroundCompiler(); |
| 1648 | 1659 |
| 1649 #if defined(DEBUG) | 1660 #if defined(DEBUG) |
| 1650 if (heap_ != NULL && FLAG_verify_on_transition) { | 1661 if (heap_ != NULL && FLAG_verify_on_transition) { |
| 1651 // The VM isolate keeps all objects marked. | 1662 // The VM isolate keeps all objects marked. |
| 1652 heap_->Verify(this == Dart::vm_isolate() ? kRequireMarked : kForbidMarked); | 1663 heap_->Verify(this == Dart::vm_isolate() ? kRequireMarked : kForbidMarked); |
| 1653 } | 1664 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1679 if (heap_ != NULL) { | 1690 if (heap_ != NULL) { |
| 1680 // Wait for any concurrent GC tasks to finish before shutting down. | 1691 // Wait for any concurrent GC tasks to finish before shutting down. |
| 1681 // TODO(koda): Support faster sweeper shutdown (e.g., after current page). | 1692 // TODO(koda): Support faster sweeper shutdown (e.g., after current page). |
| 1682 PageSpace* old_space = heap_->old_space(); | 1693 PageSpace* old_space = heap_->old_space(); |
| 1683 MonitorLocker ml(old_space->tasks_lock()); | 1694 MonitorLocker ml(old_space->tasks_lock()); |
| 1684 while (old_space->tasks() > 0) { | 1695 while (old_space->tasks() > 0) { |
| 1685 ml.Wait(); | 1696 ml.Wait(); |
| 1686 } | 1697 } |
| 1687 } | 1698 } |
| 1688 | 1699 |
| 1700 #if !defined(PRODUCT) |
| 1689 if (FLAG_check_reloaded && is_runnable() && (this != Dart::vm_isolate()) && | 1701 if (FLAG_check_reloaded && is_runnable() && (this != Dart::vm_isolate()) && |
| 1690 !ServiceIsolate::IsServiceIsolateDescendant(this)) { | 1702 !ServiceIsolate::IsServiceIsolateDescendant(this)) { |
| 1691 if (!HasAttemptedReload()) { | 1703 if (!HasAttemptedReload()) { |
| 1692 FATAL( | 1704 FATAL( |
| 1693 "Isolate did not reload before exiting and " | 1705 "Isolate did not reload before exiting and " |
| 1694 "--check-reloaded is enabled.\n"); | 1706 "--check-reloaded is enabled.\n"); |
| 1695 } | 1707 } |
| 1696 } | 1708 } |
| 1709 #endif // !defined(PRODUCT) |
| 1697 | 1710 |
| 1698 // Then, proceed with low-level teardown. | 1711 // Then, proceed with low-level teardown. |
| 1699 LowLevelShutdown(); | 1712 LowLevelShutdown(); |
| 1700 | 1713 |
| 1701 #if defined(DEBUG) | 1714 #if defined(DEBUG) |
| 1702 // No concurrent sweeper tasks should be running at this point. | 1715 // No concurrent sweeper tasks should be running at this point. |
| 1703 if (heap_ != NULL) { | 1716 if (heap_ != NULL) { |
| 1704 PageSpace* old_space = heap_->old_space(); | 1717 PageSpace* old_space = heap_->old_space(); |
| 1705 MonitorLocker ml(old_space->tasks_lock()); | 1718 MonitorLocker ml(old_space->tasks_lock()); |
| 1706 ASSERT(old_space->tasks() == 0); | 1719 ASSERT(old_space->tasks() == 0); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1767 if (background_compiler() != NULL) { | 1780 if (background_compiler() != NULL) { |
| 1768 background_compiler()->VisitPointers(visitor); | 1781 background_compiler()->VisitPointers(visitor); |
| 1769 } | 1782 } |
| 1770 | 1783 |
| 1771 // Visit the deoptimized code array which is stored in the isolate. | 1784 // Visit the deoptimized code array which is stored in the isolate. |
| 1772 visitor->VisitPointer( | 1785 visitor->VisitPointer( |
| 1773 reinterpret_cast<RawObject**>(&deoptimized_code_array_)); | 1786 reinterpret_cast<RawObject**>(&deoptimized_code_array_)); |
| 1774 | 1787 |
| 1775 visitor->VisitPointer(reinterpret_cast<RawObject**>(&sticky_error_)); | 1788 visitor->VisitPointer(reinterpret_cast<RawObject**>(&sticky_error_)); |
| 1776 | 1789 |
| 1790 #if !defined(PRODUCT) |
| 1777 // Visit the pending service extension calls. | 1791 // Visit the pending service extension calls. |
| 1778 visitor->VisitPointer( | 1792 visitor->VisitPointer( |
| 1779 reinterpret_cast<RawObject**>(&pending_service_extension_calls_)); | 1793 reinterpret_cast<RawObject**>(&pending_service_extension_calls_)); |
| 1780 | 1794 |
| 1781 // Visit the registered service extension handlers. | 1795 // Visit the registered service extension handlers. |
| 1782 visitor->VisitPointer( | 1796 visitor->VisitPointer( |
| 1783 reinterpret_cast<RawObject**>(®istered_service_extension_handlers_)); | 1797 reinterpret_cast<RawObject**>(®istered_service_extension_handlers_)); |
| 1798 #endif // !defined(PRODUCT) |
| 1784 | 1799 |
| 1785 // Visit the boxed_field_list_. | 1800 // Visit the boxed_field_list_. |
| 1786 // 'boxed_field_list_' access via mutator and background compilation threads | 1801 // 'boxed_field_list_' access via mutator and background compilation threads |
| 1787 // is guarded with a monitor. This means that we can visit it only | 1802 // is guarded with a monitor. This means that we can visit it only |
| 1788 // when at safepoint or the field_list_mutex_ lock has been taken. | 1803 // when at safepoint or the field_list_mutex_ lock has been taken. |
| 1789 visitor->VisitPointer(reinterpret_cast<RawObject**>(&boxed_field_list_)); | 1804 visitor->VisitPointer(reinterpret_cast<RawObject**>(&boxed_field_list_)); |
| 1790 | 1805 |
| 1791 #if !defined(PRODUCT) | 1806 #if !defined(PRODUCT) |
| 1792 // Visit objects in the debugger. | 1807 // Visit objects in the debugger. |
| 1793 debugger()->VisitObjectPointers(visitor); | 1808 debugger()->VisitObjectPointers(visitor); |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2062 } | 2077 } |
| 2063 // TODO(johnmccutchan): Scan this array and the isolate's profile before | 2078 // TODO(johnmccutchan): Scan this array and the isolate's profile before |
| 2064 // old space GC and remove the keep_code flag. | 2079 // old space GC and remove the keep_code flag. |
| 2065 deoptimized_code.Add(code); | 2080 deoptimized_code.Add(code); |
| 2066 } | 2081 } |
| 2067 | 2082 |
| 2068 void Isolate::clear_sticky_error() { | 2083 void Isolate::clear_sticky_error() { |
| 2069 sticky_error_ = Error::null(); | 2084 sticky_error_ = Error::null(); |
| 2070 } | 2085 } |
| 2071 | 2086 |
| 2087 #if !defined(PRODUCT) |
| 2072 void Isolate::set_pending_service_extension_calls( | 2088 void Isolate::set_pending_service_extension_calls( |
| 2073 const GrowableObjectArray& value) { | 2089 const GrowableObjectArray& value) { |
| 2074 pending_service_extension_calls_ = value.raw(); | 2090 pending_service_extension_calls_ = value.raw(); |
| 2075 } | 2091 } |
| 2076 | 2092 |
| 2077 void Isolate::set_registered_service_extension_handlers( | 2093 void Isolate::set_registered_service_extension_handlers( |
| 2078 const GrowableObjectArray& value) { | 2094 const GrowableObjectArray& value) { |
| 2079 registered_service_extension_handlers_ = value.raw(); | 2095 registered_service_extension_handlers_ = value.raw(); |
| 2080 } | 2096 } |
| 2097 #endif // !defined(PRODUCT) |
| 2081 | 2098 |
| 2082 void Isolate::AddDeoptimizingBoxedField(const Field& field) { | 2099 void Isolate::AddDeoptimizingBoxedField(const Field& field) { |
| 2083 ASSERT(Compiler::IsBackgroundCompilation()); | 2100 ASSERT(Compiler::IsBackgroundCompilation()); |
| 2084 ASSERT(!field.IsOriginal()); | 2101 ASSERT(!field.IsOriginal()); |
| 2085 // The enclosed code allocates objects and can potentially trigger a GC, | 2102 // The enclosed code allocates objects and can potentially trigger a GC, |
| 2086 // ensure that we account for safepoints when grabbing the lock. | 2103 // ensure that we account for safepoints when grabbing the lock. |
| 2087 SafepointMutexLocker ml(field_list_mutex_); | 2104 SafepointMutexLocker ml(field_list_mutex_); |
| 2088 if (boxed_field_list_ == GrowableObjectArray::null()) { | 2105 if (boxed_field_list_ == GrowableObjectArray::null()) { |
| 2089 boxed_field_list_ = GrowableObjectArray::New(Heap::kOld); | 2106 boxed_field_list_ = GrowableObjectArray::New(Heap::kOld); |
| 2090 } | 2107 } |
| (...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2836 void IsolateSpawnState::DecrementSpawnCount() { | 2853 void IsolateSpawnState::DecrementSpawnCount() { |
| 2837 ASSERT(spawn_count_monitor_ != NULL); | 2854 ASSERT(spawn_count_monitor_ != NULL); |
| 2838 ASSERT(spawn_count_ != NULL); | 2855 ASSERT(spawn_count_ != NULL); |
| 2839 MonitorLocker ml(spawn_count_monitor_); | 2856 MonitorLocker ml(spawn_count_monitor_); |
| 2840 ASSERT(*spawn_count_ > 0); | 2857 ASSERT(*spawn_count_ > 0); |
| 2841 *spawn_count_ = *spawn_count_ - 1; | 2858 *spawn_count_ = *spawn_count_ - 1; |
| 2842 ml.Notify(); | 2859 ml.Notify(); |
| 2843 } | 2860 } |
| 2844 | 2861 |
| 2845 } // namespace dart | 2862 } // namespace dart |
| OLD | NEW |