diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc index 6cb94ccc9f7..04afec92c9c 100644 --- a/runtime/lib/object.cc +++ b/runtime/lib/object.cc @@ -196,6 +196,19 @@ DEFINE_NATIVE_ENTRY(Type_equality, 0, 2) { return Bool::Get(type.IsEquivalent(other, TypeEquality::kSyntactical)).raw(); } +DEFINE_NATIVE_ENTRY(LibraryPrefix_isLoaded, 0, 1) { + const LibraryPrefix& prefix = + LibraryPrefix::CheckedHandle(zone, arguments->NativeArgAt(0)); + return Bool::Get(prefix.is_loaded()).raw(); +} + +DEFINE_NATIVE_ENTRY(LibraryPrefix_setLoaded, 0, 1) { + const LibraryPrefix& prefix = + LibraryPrefix::CheckedHandle(zone, arguments->NativeArgAt(0)); + prefix.set_is_loaded(true); + return Instance::null(); +} + DEFINE_NATIVE_ENTRY(Internal_inquireIs64Bit, 0, 0) { #if defined(ARCH_IS_64_BIT) return Bool::True().raw(); diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h index 24608463bb0..6ce5668eb48 100644 --- a/runtime/vm/bootstrap_natives.h +++ b/runtime/vm/bootstrap_natives.h @@ -31,6 +31,8 @@ namespace dart { V(AbstractType_toString, 1) \ V(Type_getHashCode, 1) \ V(Type_equality, 2) \ + V(LibraryPrefix_isLoaded, 1) \ + V(LibraryPrefix_setLoaded, 1) \ V(Identical_comparison, 2) \ V(Integer_bitAndFromInteger, 2) \ V(Integer_bitOrFromInteger, 2) \ diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc index a999eb1f8db..25a8d76bf83 100644 --- a/runtime/vm/clustered_snapshot.cc +++ b/runtime/vm/clustered_snapshot.cc @@ -3248,6 +3248,7 @@ class LibraryPrefixDeserializationCluster : public DeserializationCluster { ReadFromTo(prefix); prefix->ptr()->num_imports_ = d->Read(); prefix->ptr()->is_deferred_load_ = d->Read(); + prefix->ptr()->is_loaded_ = !prefix->ptr()->is_deferred_load_; } } }; diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc index 390b3aca49d..dc254d49f77 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -1097,7 +1097,11 @@ ConstantInstr::ConstantInstr(const Object& value, TokenPosition token_pos) // tables used for certain character classes are represented as TypedData, // and so those values are also neither immutable (as there are no immutable // TypedData values) or canonical. - ASSERT(value.IsTypeParameter() || value.IsArray() || value.IsTypedData()); + // + // LibraryPrefixes are also never canonicalized since their equality is + // their identity. + ASSERT(value.IsTypeParameter() || value.IsArray() || value.IsTypedData() || + value.IsLibraryPrefix()); } #endif } diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc index aba146c0dae..589ed9e8167 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc @@ -1363,9 +1363,9 @@ Fragment StreamingFlowGraphBuilder::BuildExpression(TokenPosition* position) { case kInstantiation: return BuildPartialTearoffInstantiation(position); case kLoadLibrary: + return BuildLibraryPrefixAction(position, Symbols::LoadLibrary()); case kCheckLibraryIsLoaded: - ReadUInt(); // skip library index - return BuildFutureNullValue(position); + return BuildLibraryPrefixAction(position, Symbols::CheckLoaded()); case kConstStaticInvocation: case kConstConstructorInvocation: case kConstListLiteral: @@ -4068,6 +4068,26 @@ Fragment StreamingFlowGraphBuilder::BuildPartialTearoffInstantiation( return instructions; } +Fragment StreamingFlowGraphBuilder::BuildLibraryPrefixAction( + TokenPosition* position, + const String& selector) { + const intptr_t dependency_index = ReadUInt(); + const Library& current_library = Library::Handle( + Z, Class::Handle(Z, parsed_function()->function().origin()).library()); + const Array& dependencies = Array::Handle(Z, current_library.dependencies()); + const LibraryPrefix& prefix = + LibraryPrefix::CheckedZoneHandle(Z, dependencies.At(dependency_index)); + const Function& function = + Function::ZoneHandle(Z, Library::Handle(Z, Library::CoreLibrary()) + .LookupFunctionAllowPrivate(selector)); + ASSERT(!function.IsNull()); + Fragment instructions; + instructions += Constant(prefix); + instructions += + StaticCall(TokenPosition::kNoSource, function, 1, ICData::kStatic); + return instructions; +} + Fragment StreamingFlowGraphBuilder::BuildExpressionStatement() { Fragment instructions = BuildExpression(); // read expression. instructions += Drop(); diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h index 2b1ba418ea6..c36a7c8232f 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h @@ -335,6 +335,8 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper { Fragment BuildFutureNullValue(TokenPosition* position); Fragment BuildConstantExpression(TokenPosition* position, Tag tag); Fragment BuildPartialTearoffInstantiation(TokenPosition* position); + Fragment BuildLibraryPrefixAction(TokenPosition* position, + const String& selector); Fragment BuildExpressionStatement(); Fragment BuildBlock(); diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h index 409fa7d7977..b7e6bda1f94 100644 --- a/runtime/vm/compiler/runtime_offsets_extracted.h +++ b/runtime/vm/compiler/runtime_offsets_extracted.h @@ -450,7 +450,7 @@ static constexpr dart::compiler::target::word Integer_InstanceSize = 4; static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize = 64; static constexpr dart::compiler::target::word LanguageError_InstanceSize = 28; -static constexpr dart::compiler::target::word Library_InstanceSize = 76; +static constexpr dart::compiler::target::word Library_InstanceSize = 80; static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 20; static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 28; static constexpr dart::compiler::target::word LocalVarDescriptors_InstanceSize = @@ -944,7 +944,7 @@ static constexpr dart::compiler::target::word Integer_InstanceSize = 8; static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize = 128; static constexpr dart::compiler::target::word LanguageError_InstanceSize = 48; -static constexpr dart::compiler::target::word Library_InstanceSize = 144; +static constexpr dart::compiler::target::word Library_InstanceSize = 152; static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 40; static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56; static constexpr dart::compiler::target::word LocalVarDescriptors_InstanceSize = @@ -1429,7 +1429,7 @@ static constexpr dart::compiler::target::word Integer_InstanceSize = 4; static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize = 64; static constexpr dart::compiler::target::word LanguageError_InstanceSize = 28; -static constexpr dart::compiler::target::word Library_InstanceSize = 76; +static constexpr dart::compiler::target::word Library_InstanceSize = 80; static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 20; static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 28; static constexpr dart::compiler::target::word LocalVarDescriptors_InstanceSize = @@ -1924,7 +1924,7 @@ static constexpr dart::compiler::target::word Integer_InstanceSize = 8; static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize = 128; static constexpr dart::compiler::target::word LanguageError_InstanceSize = 48; -static constexpr dart::compiler::target::word Library_InstanceSize = 144; +static constexpr dart::compiler::target::word Library_InstanceSize = 152; static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 40; static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56; static constexpr dart::compiler::target::word LocalVarDescriptors_InstanceSize = @@ -2408,7 +2408,7 @@ static constexpr dart::compiler::target::word Integer_InstanceSize = 4; static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize = 64; static constexpr dart::compiler::target::word LanguageError_InstanceSize = 28; -static constexpr dart::compiler::target::word Library_InstanceSize = 76; +static constexpr dart::compiler::target::word Library_InstanceSize = 80; static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 20; static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 28; static constexpr dart::compiler::target::word LocalVarDescriptors_InstanceSize = @@ -2896,7 +2896,7 @@ static constexpr dart::compiler::target::word Integer_InstanceSize = 8; static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize = 128; static constexpr dart::compiler::target::word LanguageError_InstanceSize = 48; -static constexpr dart::compiler::target::word Library_InstanceSize = 144; +static constexpr dart::compiler::target::word Library_InstanceSize = 152; static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 40; static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56; static constexpr dart::compiler::target::word LocalVarDescriptors_InstanceSize = @@ -3375,7 +3375,7 @@ static constexpr dart::compiler::target::word Integer_InstanceSize = 4; static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize = 64; static constexpr dart::compiler::target::word LanguageError_InstanceSize = 28; -static constexpr dart::compiler::target::word Library_InstanceSize = 76; +static constexpr dart::compiler::target::word Library_InstanceSize = 80; static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 20; static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 28; static constexpr dart::compiler::target::word LocalVarDescriptors_InstanceSize = @@ -3864,7 +3864,7 @@ static constexpr dart::compiler::target::word Integer_InstanceSize = 8; static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize = 128; static constexpr dart::compiler::target::word LanguageError_InstanceSize = 48; -static constexpr dart::compiler::target::word Library_InstanceSize = 144; +static constexpr dart::compiler::target::word Library_InstanceSize = 152; static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 40; static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56; static constexpr dart::compiler::target::word LocalVarDescriptors_InstanceSize = @@ -4384,7 +4384,7 @@ static constexpr dart::compiler::target::word AOT_KernelProgramInfo_InstanceSize = 64; static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize = 28; -static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 72; +static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 76; static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize = 20; static constexpr dart::compiler::target::word AOT_LinkedHashMap_InstanceSize = @@ -4919,7 +4919,7 @@ static constexpr dart::compiler::target::word AOT_KernelProgramInfo_InstanceSize = 128; static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize = 48; -static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 136; +static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 144; static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize = 40; static constexpr dart::compiler::target::word AOT_LinkedHashMap_InstanceSize = @@ -5458,7 +5458,7 @@ static constexpr dart::compiler::target::word AOT_KernelProgramInfo_InstanceSize = 128; static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize = 48; -static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 136; +static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 144; static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize = 40; static constexpr dart::compiler::target::word AOT_LinkedHashMap_InstanceSize = @@ -5984,7 +5984,7 @@ static constexpr dart::compiler::target::word AOT_KernelProgramInfo_InstanceSize = 64; static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize = 28; -static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 72; +static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 76; static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize = 20; static constexpr dart::compiler::target::word AOT_LinkedHashMap_InstanceSize = @@ -6512,7 +6512,7 @@ static constexpr dart::compiler::target::word AOT_KernelProgramInfo_InstanceSize = 128; static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize = 48; -static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 136; +static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 144; static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize = 40; static constexpr dart::compiler::target::word AOT_LinkedHashMap_InstanceSize = @@ -7044,7 +7044,7 @@ static constexpr dart::compiler::target::word AOT_KernelProgramInfo_InstanceSize = 128; static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize = 48; -static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 136; +static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 144; static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize = 40; static constexpr dart::compiler::target::word AOT_LinkedHashMap_InstanceSize = diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc index 74556354e9d..6c83404d48a 100644 --- a/runtime/vm/isolate_reload.cc +++ b/runtime/vm/isolate_reload.cc @@ -738,7 +738,7 @@ bool IsolateGroupReloadContext::Reload(bool force_reload, // Ensure all functions on the stack have unoptimized code. // Deoptimize all code that had optimizing decisions that are dependent on - // assumptions from field guards or CHA. + // assumptions from field guards or CHA or deferred library prefixes. // TODO(johnmccutchan): Deoptimizing dependent code here (before the reload) // is paranoid. This likely can be moved to the commit phase. ForEachIsolate([&](Isolate* isolate) { @@ -1312,6 +1312,8 @@ void IsolateReloadContext::DeoptimizeDependentCode() { } DeoptimizeTypeTestingStubs(); + + // TODO(rmacnak): Also call LibraryPrefix::InvalidateDependentCode. } void IsolateGroupReloadContext::CheckpointSharedClassTable() { diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc index 7bfd7d76db9..1d0d5437726 100644 --- a/runtime/vm/kernel_loader.cc +++ b/runtime/vm/kernel_loader.cc @@ -1305,6 +1305,7 @@ void KernelLoader::LoadLibraryImportsAndExports(Library* library, LibraryPrefix& library_prefix = LibraryPrefix::Handle(Z); const intptr_t deps_count = helper_.ReadListLength(); + const Array& deps = Array::Handle(Array::New(deps_count)); for (intptr_t dep = 0; dep < deps_count; ++dep) { LibraryDependencyHelper dependency_helper(&helper_); @@ -1388,12 +1389,21 @@ void KernelLoader::LoadLibraryImportsAndExports(Library* library, } } } + if (FLAG_enable_mirrors && dependency_helper.annotation_count_ > 0) { ASSERT(annotations_kernel_offset > 0); ns.AddMetadata(toplevel_class, TokenPosition::kNoSource, annotations_kernel_offset); } + + if (prefix.IsNull()) { + deps.SetAt(dep, ns); + } else { + deps.SetAt(dep, library_prefix); + } } + + library->set_dependencies(deps); } void KernelLoader::LoadPreliminaryClass(ClassHelper* class_helper, diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index cefce52562d..04f500e9eda 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -11081,27 +11081,6 @@ void ClassDictionaryIterator::MoveToNextClass() { } } -LibraryPrefixIterator::LibraryPrefixIterator(const Library& library) - : DictionaryIterator(library) { - Advance(); -} - -LibraryPrefixPtr LibraryPrefixIterator::GetNext() { - ASSERT(HasNext()); - int ix = next_ix_++; - Object& obj = Object::Handle(array_.At(ix)); - Advance(); - return LibraryPrefix::Cast(obj).raw(); -} - -void LibraryPrefixIterator::Advance() { - Object& obj = Object::Handle(array_.At(next_ix_)); - while (!obj.IsLibraryPrefix() && HasNext()) { - next_ix_++; - obj = array_.At(next_ix_); - } -} - static void ReportTooManyImports(const Library& lib) { const String& url = String::Handle(lib.url()); Report::MessageF(Report::kError, Script::Handle(lib.LookupScript(url)), @@ -12075,6 +12054,10 @@ void Library::set_toplevel_class(const Class& value) const { StorePointer(&raw_ptr()->toplevel_class_, value.raw()); } +void Library::set_dependencies(const Array& deps) const { + StorePointer(&raw_ptr()->dependencies_, deps.raw()); +} + void Library::set_metadata(const GrowableObjectArray& value) const { StorePointer(&raw_ptr()->metadata_, value.raw()); } @@ -12943,6 +12926,7 @@ LibraryPrefixPtr LibraryPrefix::New(const String& name, result.set_num_imports(0); result.set_importer(importer); result.StoreNonPointer(&result.raw_ptr()->is_deferred_load_, deferred_load); + result.StoreNonPointer(&result.raw_ptr()->is_loaded_, !deferred_load); result.set_imports(Array::Handle(Array::New(kInitialSize))); result.AddImport(import); return result.raw(); @@ -12970,8 +12954,7 @@ void LibraryPrefix::set_importer(const Library& value) const { const char* LibraryPrefix::ToCString() const { const String& prefix = String::Handle(name()); - return OS::SCreate(Thread::Current()->zone(), "LibraryPrefix:'%s'", - prefix.ToCString()); + return prefix.ToCString(); } void Namespace::set_metadata_field(const Field& value) const { diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 4e476209d58..bd5baa1a0f5 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -4543,7 +4543,6 @@ class DictionaryIterator : public ValueObject { int next_ix_; // Index of next element. friend class ClassDictionaryIterator; - friend class LibraryPrefixIterator; DISALLOW_COPY_AND_ASSIGN(DictionaryIterator); }; @@ -4574,16 +4573,6 @@ class ClassDictionaryIterator : public DictionaryIterator { DISALLOW_COPY_AND_ASSIGN(ClassDictionaryIterator); }; -class LibraryPrefixIterator : public DictionaryIterator { - public: - explicit LibraryPrefixIterator(const Library& library); - LibraryPrefixPtr GetNext(); - - private: - void Advance(); - DISALLOW_COPY_AND_ASSIGN(LibraryPrefixIterator); -}; - class Library : public Object { public: StringPtr name() const { return raw_ptr()->name_; } @@ -4738,6 +4727,9 @@ class Library : public Object { NamespacePtr ImportAt(intptr_t index) const; LibraryPtr ImportLibraryAt(intptr_t index) const; + ArrayPtr dependencies() const { return raw_ptr()->dependencies_; } + void set_dependencies(const Array& deps) const; + void DropDependenciesAndCaches() const; // Resolving native methods for script loaded in the library. @@ -7342,6 +7334,10 @@ class LibraryPrefix : public Instance { void AddImport(const Namespace& import) const; bool is_deferred_load() const { return raw_ptr()->is_deferred_load_; } + bool is_loaded() const { return raw_ptr()->is_loaded_; } + void set_is_loaded(bool value) const { + return StoreNonPointer(&raw_ptr()->is_loaded_, value); + } static intptr_t InstanceSize() { return RoundedAllocationSize(sizeof(LibraryPrefixLayout)); diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc index 65677896917..cc6f720fcb4 100644 --- a/runtime/vm/object_reload.cc +++ b/runtime/vm/object_reload.cc @@ -692,6 +692,29 @@ class InstanceSizeConflict : public ClassReasonForCancelling { } }; +class UnimplementedDeferredLibrary : public ReasonForCancelling { + public: + UnimplementedDeferredLibrary(Zone* zone, + const Library& from, + const Library& to, + const String& name) + : ReasonForCancelling(zone), from_(from), to_(to), name_(name) {} + + private: + const Library& from_; + const Library& to_; + const String& name_; + + StringPtr ToString() { + const String& lib_url = String::Handle(to_.url()); + from_.ToCString(); + return String::NewFormatted( + "Reloading support for deferred loading has not yet been implemented:" + " library '%s' has deferred import '%s'", + lib_url.ToCString(), name_.ToCString()); + } +}; + // This is executed before iterating over the instances. void Class::CheckReload(const Class& replacement, IsolateReloadContext* context) const { @@ -889,7 +912,23 @@ bool Class::CanReloadPreFinalized(const Class& replacement, void Library::CheckReload(const Library& replacement, IsolateReloadContext* context) const { - // Currently no library properties will prevent a reload. + // TODO(26878): If the replacement library uses deferred loading, + // reject it. We do not yet support reloading deferred libraries. + Object& object = Object::Handle(); + LibraryPrefix& prefix = LibraryPrefix::Handle(); + DictionaryIterator it(replacement); + while (it.HasNext()) { + object = it.GetNext(); + if (!object.IsLibraryPrefix()) continue; + prefix ^= object.raw(); + if (prefix.is_deferred_load()) { + const String& prefix_name = String::Handle(prefix.name()); + context->group_reload_context()->AddReasonForCancelling( + new (context->zone()) UnimplementedDeferredLibrary( + context->zone(), *this, replacement, prefix_name)); + return; + } + } } void CallSiteResetter::Reset(const ICData& ic) { diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index ee472ace028..18702888c7f 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -1305,6 +1305,7 @@ class LibraryLayout : public ObjectLayout { GrowableObjectArrayPtr used_scripts_; ArrayPtr imports_; // List of Namespaces imported without prefix. ArrayPtr exports_; // List of re-exported Namespaces. + ArrayPtr dependencies_; ExternalTypedDataPtr kernel_data_; ObjectPtr* to_snapshot(Snapshot::Kind kind) { switch (kind) { @@ -2130,6 +2131,7 @@ class LibraryPrefixLayout : public InstanceLayout { } uint16_t num_imports_; // Number of library entries in libraries_. bool is_deferred_load_; + bool is_loaded_; }; class TypeArgumentsLayout : public InstanceLayout { diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h index a5249ed9fb2..fb24834f495 100644 --- a/runtime/vm/symbols.h +++ b/runtime/vm/symbols.h @@ -44,6 +44,7 @@ class ObjectPointerVisitor; V(Call, "call") \ V(Cancel, "cancel") \ V(CastError, "_CastError") \ + V(CheckLoaded, "_checkLoaded") \ V(Class, "Class") \ V(ClassID, "ClassID") \ V(ClearAsyncThreadStackTrace, "_clearAsyncThreadStackTrace") \ @@ -206,6 +207,7 @@ class ObjectPointerVisitor; V(ListFactory, "List.") \ V(ListFilledFactory, "List.filled") \ V(ListLiteralFactory, "List._fromLiteral") \ + V(LoadLibrary, "_loadLibrary") \ V(LocalVarDescriptors, "LocalVarDescriptors") \ V(Map, "Map") \ V(MapLiteralFactory, "Map._fromLiteral") \ diff --git a/sdk/lib/_internal/vm/lib/lib_prefix.dart b/sdk/lib/_internal/vm/lib/lib_prefix.dart index 00b934c905f..5135a26926f 100644 --- a/sdk/lib/_internal/vm/lib/lib_prefix.dart +++ b/sdk/lib/_internal/vm/lib/lib_prefix.dart @@ -13,7 +13,32 @@ class _LibraryPrefix { throw "Unreachable"; } - bool isLoaded() => true; - - loadLibrary() => new Future.value(true); + bool _isLoaded() native "LibraryPrefix_isLoaded"; + void _setLoaded() native "LibraryPrefix_setLoaded"; +} + +class _DeferredNotLoadedError extends Error implements NoSuchMethodError { + final _LibraryPrefix prefix; + + _DeferredNotLoadedError(this.prefix); + + String toString() { + return "Deferred library $prefix was not loaded."; + } +} + +@pragma("vm:entry-point") +@pragma("vm:never-inline") // Don't duplicate prefix checking code. +Future _loadLibrary(_LibraryPrefix prefix) { + return new Future(() { + prefix._setLoaded(); + }); +} + +@pragma("vm:entry-point") +@pragma("vm:never-inline") // Don't duplicate prefix checking code. +void _checkLoaded(_LibraryPrefix prefix) { + if (!prefix._isLoaded()) { + throw new _DeferredNotLoadedError(prefix); + } } diff --git a/sdk_nnbd/lib/_internal/vm/lib/lib_prefix.dart b/sdk_nnbd/lib/_internal/vm/lib/lib_prefix.dart index f588ee33e4f..d8e52fdb3e0 100644 --- a/sdk_nnbd/lib/_internal/vm/lib/lib_prefix.dart +++ b/sdk_nnbd/lib/_internal/vm/lib/lib_prefix.dart @@ -11,7 +11,32 @@ class _LibraryPrefix { throw "Unreachable"; } - bool isLoaded() => true; - - loadLibrary() => new Future.value(true); + bool _isLoaded() native "LibraryPrefix_isLoaded"; + void _setLoaded() native "LibraryPrefix_setLoaded"; +} + +class _DeferredNotLoadedError extends Error implements NoSuchMethodError { + final _LibraryPrefix prefix; + + _DeferredNotLoadedError(this.prefix); + + String toString() { + return "Deferred library $prefix was not loaded."; + } +} + +@pragma("vm:entry-point") +@pragma("vm:never-inline") // Don't duplicate prefix checking code. +Future _loadLibrary(_LibraryPrefix prefix) { + return new Future(() { + prefix._setLoaded(); + }); +} + +@pragma("vm:entry-point") +@pragma("vm:never-inline") // Don't duplicate prefix checking code. +void _checkLoaded(_LibraryPrefix prefix) { + if (!prefix._isLoaded()) { + throw new _DeferredNotLoadedError(prefix); + } }