[vm/snapshots] Finalize and sort all classes in snapshots with compilation trace
This ensures that core-jit snapshots used in Fuchsia (built according
to the compilation trace) would have properly sorted cids without any
gaps with non-finalized classes. This enables merging of cid ranges in
more cases and more efficient cid checks.
Issue: https://github.com/dart-lang/sdk/issues/36428
Change-Id: I7b696ccb7d5ffa80f190bcfc9e1b7229937f16b6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103403
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index af9741e..c1f304b 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -420,10 +420,18 @@
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 39b29ff..3b8f4d2 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_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 29b1fad..9fa7585 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -2172,32 +2172,9 @@
}
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 9bf957d..df1859d 100644
--- a/runtime/vm/native_api_impl.cc
+++ b/runtime/vm/native_api_impl.cc
@@ -217,4 +217,24 @@
#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 84843f7c..8045887 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -12228,6 +12228,39 @@
}
#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 bb7200a..08216a2 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -4024,6 +4024,8 @@
// 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