[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>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
93481167a6
commit
e3edfd36b2
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user