@@ -103,68 +103,102 @@ class ReadOnlyHandles {
103103
104104class DartInitializationState : public AllStatic {
105105 public:
106- static bool SetInitializing () {
107- ASSERT (in_use_count_.load () == 0 );
108- uint8_t expected = kUnInitialized ;
109- return state_.compare_exchange_strong (expected, kInitializing );
106+ static bool StartInit () {
107+ uword expected = PhaseField::encode (kUnInitialized ) | CountField::encode (0 );
108+ uword desired = PhaseField::encode (kInitializing ) | CountField::encode (0 );
109+ return state_.compare_exchange_strong (expected, desired,
110+ std::memory_order_acquire);
110111 }
111112
112- static void ResetInitializing () {
113- ASSERT (in_use_count_.load () == 0 );
114- uint8_t expected = kInitializing ;
115- bool result = state_.compare_exchange_strong (expected, kUnInitialized );
113+ static void AbandonInit () {
114+ uword expected = PhaseField::encode (kInitializing ) | CountField::encode (0 );
115+ uword desired = PhaseField::encode (kUnInitialized ) | CountField::encode (0 );
116+ bool result = state_.compare_exchange_strong (expected, desired,
117+ std::memory_order_release);
116118 ASSERT (result);
117119 }
118120
119- static void SetInitialized () {
120- ASSERT (in_use_count_.load () == 0 );
121- uint8_t expected = kInitializing ;
122- bool result = state_.compare_exchange_strong (expected, kInitialized );
121+ static void FinishInit () {
122+ uword expected = PhaseField::encode (kInitializing ) | CountField::encode (0 );
123+ uword desired = PhaseField::encode (kInitialized ) | CountField::encode (0 );
124+ bool result = state_.compare_exchange_strong (expected, desired,
125+ std::memory_order_release);
123126 ASSERT (result);
124127 }
125128
126- static bool IsInitialized () { return state_.load () == kInitialized ; }
127- static bool IsShuttingDown () { return state_.load () == kCleaningup ; }
128-
129- static bool SetCleaningup () {
130- uint8_t expected = kInitialized ;
131- return state_.compare_exchange_strong (expected, kCleaningup );
129+ static bool IsInitialized () {
130+ return PhaseField::decode (state_.load ()) == kInitialized ;
131+ }
132+ static bool IsShuttingDown () {
133+ return PhaseField::decode (state_.load ()) == kCleaningup ;
132134 }
133135
134- static void SetUnInitialized () {
135- while (in_use_count_.load () > 0 ) {
136- OS::Sleep (1 ); // Sleep for 1 millis waiting for it to not be in use.
136+ static bool StartCleanup () {
137+ uword expected = state_.load (std::memory_order_acquire);
138+ uword desired;
139+ do {
140+ if (PhaseField::decode (expected) != kInitialized ) {
141+ return false ;
142+ }
143+ desired = PhaseField::update (kCleaningup , expected);
144+ } while (!state_.compare_exchange_weak (expected, desired,
145+ std::memory_order_relaxed));
146+
147+ while (CountField::decode (expected) != 0 ) {
148+ OS::Sleep (1 );
149+ expected = state_.load (std::memory_order_acquire);
137150 }
138- uint8_t expected = kCleaningup ;
139- bool result = state_.compare_exchange_strong (expected, kUnInitialized );
151+ return true ;
152+ }
153+
154+ static void FinishCleanup () {
155+ uword expected = PhaseField::encode (kCleaningup ) | CountField::encode (0 );
156+ uword desired = PhaseField::encode (kUnInitialized ) | CountField::encode (0 );
157+ bool result = state_.compare_exchange_strong (expected, desired,
158+ std::memory_order_release);
140159 ASSERT (result);
141160 }
142161
143162 static bool SetInUse () {
144- if (state_.load () != kInitialized ) {
145- return false ;
146- }
147- in_use_count_ += 1 ;
163+ uword expected = state_.load (std::memory_order_relaxed);
164+ uword desired;
165+ do {
166+ if (PhaseField::decode (expected) != kInitialized ) {
167+ return false ;
168+ }
169+ desired = PhaseField::encode (kInitialized ) |
170+ CountField::encode (CountField::decode (expected) + 1 );
171+ } while (!state_.compare_exchange_weak (expected, desired,
172+ std::memory_order_relaxed));
148173 return true ;
149174 }
150175
151176 static void ResetInUse () {
152- uint8_t value = state_.load ();
153- ASSERT ((value == kInitialized ) || (value == kCleaningup ));
154- in_use_count_ -= 1 ;
177+ uword expected = state_.load (std::memory_order_relaxed);
178+ uword desired;
179+ do {
180+ ASSERT (PhaseField::decode (expected) == kInitialized ||
181+ PhaseField::decode (expected) == kCleaningup );
182+ desired = CountField::update (CountField::decode (expected) - 1 , expected);
183+ } while (!state_.compare_exchange_weak (expected, desired,
184+ std::memory_order_release));
155185 }
156186
157187 private:
158- static constexpr uint8_t kUnInitialized = 0 ;
159- static constexpr uint8_t kInitializing = 1 ;
160- static constexpr uint8_t kInitialized = 2 ;
161- static constexpr uint8_t kCleaningup = 3 ;
188+ static constexpr uword kUnInitialized = 0 ;
189+ static constexpr uword kInitializing = 1 ;
190+ static constexpr uword kInitialized = 2 ;
191+ static constexpr uword kCleaningup = 3 ;
162192
163- static std::atomic<uint8_t > state_;
164- static std::atomic<uint64_t > in_use_count_;
193+ using PhaseField = BitField<uword, uword, 0 , 2 >;
194+ using CountField =
195+ BitField<uword, uword, PhaseField::kNextBit , kBitsPerWord - 2 >;
196+
197+ static std::atomic<uword> state_;
165198};
166- std::atomic<uint8_t > DartInitializationState::state_ = {kUnInitialized };
167- std::atomic<uint64_t > DartInitializationState::in_use_count_ = {0 };
199+
200+ std::atomic<uword> DartInitializationState::state_ = {
201+ PhaseField::encode (kUnInitialized ) | CountField::encode (0 )};
168202
169203#if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
170204static void CheckOffsets () {
@@ -505,18 +539,18 @@ char* Dart::DartInit(const Dart_InitializeParams* params) {
505539}
506540
507541char * Dart::Init (const Dart_InitializeParams* params) {
508- if (!DartInitializationState::SetInitializing ()) {
542+ if (!DartInitializationState::StartInit ()) {
509543 return Utils::StrDup (
510544 " Bad VM initialization state, "
511545 " already initialized or "
512546 " multiple threads initializing the VM." );
513547 }
514548 char * retval = DartInit (params);
515549 if (retval != nullptr ) {
516- DartInitializationState::ResetInitializing ();
550+ DartInitializationState::AbandonInit ();
517551 return retval;
518552 }
519- DartInitializationState::SetInitialized ();
553+ DartInitializationState::FinishInit ();
520554
521555 // The service and kernel isolates require the VM state to be initialized.
522556 // The embedder, not the VM, should trigger creation of the service and kernel
@@ -625,7 +659,7 @@ void Dart::WaitForIsolateShutdown() {
625659
626660char * Dart::Cleanup () {
627661 ASSERT (Isolate::Current () == nullptr );
628- if (!DartInitializationState::SetCleaningup ()) {
662+ if (!DartInitializationState::StartCleanup ()) {
629663 return Utils::StrDup (" VM already terminated." );
630664 }
631665 ASSERT (vm_isolate_ != nullptr );
@@ -698,7 +732,6 @@ char* Dart::Cleanup() {
698732 OS::PrintErr (" [+%" Pd64 " ms] SHUTDOWN: Deleting thread pool\n " ,
699733 UptimeMillis ());
700734 }
701- DartInitializationState::SetUnInitialized ();
702735
703736 NativeMessageHandler::Cleanup ();
704737 PortMap::Shutdown ();
@@ -794,6 +827,8 @@ char* Dart::Cleanup() {
794827 Service::SetEmbedderStreamCallbacks (nullptr , nullptr );
795828#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
796829 VirtualMemory::Cleanup ();
830+
831+ DartInitializationState::FinishCleanup ();
797832 return nullptr ;
798833}
799834
0 commit comments