diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc index af9741e55b8..c1f304b3a23 100644 --- a/runtime/bin/gen_snapshot.cc +++ b/runtime/bin/gen_snapshot.cc @@ -420,10 +420,18 @@ static void MaybeLoadCode() { if ((load_compilation_trace_filename != NULL) && ((snapshot_kind == kCoreJIT) || (snapshot_kind == kAppJIT))) { + // Finalize all classes. This ensures that there are no non-finalized + // classes in the gaps between cid ranges. Such classes prevent merging of + // cid ranges. + Dart_Handle result = Dart_FinalizeAllClasses(); + CHECK_RESULT(result); + // Sort classes to have better cid ranges. + result = Dart_SortClasses(); + CHECK_RESULT(result); uint8_t* buffer = NULL; intptr_t size = 0; ReadFile(load_compilation_trace_filename, &buffer, &size); - Dart_Handle result = Dart_LoadCompilationTrace(buffer, size); + result = Dart_LoadCompilationTrace(buffer, size); free(buffer); CHECK_RESULT(result); } diff --git a/runtime/include/dart_native_api.h b/runtime/include/dart_native_api.h index 39b29fffdd8..3b8f4d28761 100644 --- a/runtime/include/dart_native_api.h +++ b/runtime/include/dart_native_api.h @@ -170,4 +170,9 @@ DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_CompileAll(); DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_ReadAllBytecode(); +/** + * Finalizes all classes. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_FinalizeAllClasses(); + #endif /* INCLUDE_DART_NATIVE_API_H_ */ /* NOLINT */ diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc index 29b1fad2d40..9fa7585a338 100644 --- a/runtime/vm/compiler/aot/precompiler.cc +++ b/runtime/vm/compiler/aot/precompiler.cc @@ -2172,32 +2172,9 @@ void Precompiler::Obfuscate() { } void Precompiler::FinalizeAllClasses() { - Library& lib = Library::Handle(Z); - Class& cls = Class::Handle(Z); - - for (intptr_t i = 0; i < libraries_.Length(); i++) { - lib ^= libraries_.At(i); - if (!lib.Loaded()) { - String& uri = String::Handle(Z, lib.url()); - String& msg = String::Handle( - Z, - String::NewFormatted("Library '%s' is not loaded. " - "Did you forget to call Dart_FinalizeLoading?", - uri.ToCString())); - Jump(Error::Handle(Z, ApiError::New(msg))); - } - - ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); - while (it.HasNext()) { - cls = it.GetNextClass(); - if (cls.IsDynamicClass()) { - continue; // class 'dynamic' is in the read-only VM isolate. - } - error_ = cls.EnsureIsFinalized(T); - if (!error_.IsNull()) { - Jump(error_); - } - } + error_ = Library::FinalizeAllClasses(); + if (!error_.IsNull()) { + Jump(error_); } I->set_all_classes_finalized(true); } diff --git a/runtime/vm/native_api_impl.cc b/runtime/vm/native_api_impl.cc index 9bf957db11d..df1859d47c7 100644 --- a/runtime/vm/native_api_impl.cc +++ b/runtime/vm/native_api_impl.cc @@ -217,4 +217,24 @@ DART_EXPORT Dart_Handle Dart_ReadAllBytecode() { #endif // defined(DART_PRECOMPILED_RUNTIME) } +DART_EXPORT Dart_Handle Dart_FinalizeAllClasses() { +#if defined(DART_PRECOMPILED_RUNTIME) + return Api::NewError("%s: All classes are already finalized in AOT runtime.", + CURRENT_FUNC); +#else + DARTSCOPE(Thread::Current()); + API_TIMELINE_DURATION(T); + Dart_Handle result = Api::CheckAndFinalizePendingClasses(T); + if (Api::IsError(result)) { + return result; + } + CHECK_CALLBACK_STATE(T); + const Error& error = Error::Handle(T->zone(), Library::FinalizeAllClasses()); + if (!error.IsNull()) { + return Api::NewHandle(T, error.raw()); + } + return Api::Success(); +#endif // defined(DART_PRECOMPILED_RUNTIME) +} + } // namespace dart diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 84843f7c516..8045887ece0 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -12228,6 +12228,39 @@ RawError* Library::CompileAll(bool ignore_error /* = false */) { } #if !defined(DART_PRECOMPILED_RUNTIME) + +RawError* Library::FinalizeAllClasses() { + Thread* thread = Thread::Current(); + ASSERT(thread->IsMutatorThread()); + Zone* zone = thread->zone(); + Error& error = Error::Handle(zone); + const GrowableObjectArray& libs = GrowableObjectArray::Handle( + Isolate::Current()->object_store()->libraries()); + Library& lib = Library::Handle(zone); + Class& cls = Class::Handle(zone); + for (int i = 0; i < libs.Length(); i++) { + lib ^= libs.At(i); + if (!lib.Loaded()) { + String& uri = String::Handle(zone, lib.url()); + String& msg = String::Handle( + zone, + String::NewFormatted("Library '%s' is not loaded. " + "Did you forget to call Dart_FinalizeLoading?", + uri.ToCString())); + return ApiError::New(msg); + } + ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); + while (it.HasNext()) { + cls = it.GetNextClass(); + error = cls.EnsureIsFinalized(thread); + if (!error.IsNull()) { + return error.raw(); + } + } + } + return Error::null(); +} + RawError* Library::ReadAllBytecode() { Thread* thread = Thread::Current(); ASSERT(thread->IsMutatorThread()); diff --git a/runtime/vm/object.h b/runtime/vm/object.h index bb7200a291d..08216a25a19 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -4024,6 +4024,8 @@ class Library : public Object { // Eagerly compile all classes and functions in the library. static RawError* CompileAll(bool ignore_error = false); #if !defined(DART_PRECOMPILED_RUNTIME) + // Finalize all classes in all libraries. + static RawError* FinalizeAllClasses(); // Eagerly read all bytecode. static RawError* ReadAllBytecode(); #endif