diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn index 508413c138f..f62aa1d5547 100644 --- a/runtime/BUILD.gn +++ b/runtime/BUILD.gn @@ -10,6 +10,8 @@ import("//build/config/sysroot.gni") assert(!dart_enable_aot_patching || !dart_dynamic_modules, "dart_enable_aot_patching must be built without dart_dynamic_modules.") +assert(!dart_enable_shorebird_interpreter || !dart_dynamic_modules, + "dart_enable_shorebird_interpreter must be built without dart_dynamic_modules.") config("dart_public_config") { include_dirs = [ @@ -233,6 +235,12 @@ config("dart_config") { if (dart_dynamic_modules) { defines += [ "DART_DYNAMIC_MODULES" ] } + if (dart_dynamic_modules || dart_enable_shorebird_interpreter) { + defines += [ "DART_BYTECODE_INTERPRETER=1" ] + } + if (dart_enable_shorebird_interpreter) { + defines += [ "DART_SHOREBIRD_INTERPRETER" ] + } if (dart_enable_aot_patching) { defines += [ "DART_ENABLE_AOT_PATCHING" ] diff --git a/runtime/bin/dart_api_win.c b/runtime/bin/dart_api_win.c index c31ae50174f..b3a3681e062 100644 --- a/runtime/bin/dart_api_win.c +++ b/runtime/bin/dart_api_win.c @@ -387,6 +387,7 @@ typedef Dart_Handle (*Dart_LibraryHandleErrorType)(Dart_Handle, Dart_Handle); typedef Dart_Handle (*Dart_LoadLibraryFromKernelType)(const uint8_t*, intptr_t); typedef Dart_Handle (*Dart_LoadLibraryType)(Dart_Handle); typedef Dart_Handle (*Dart_LoadLibraryFromBytecodeType)(Dart_Handle); +typedef Dart_Handle (*Dart_ReloadBytecodePatchType)(const uint8_t*, intptr_t); typedef Dart_Handle (*Dart_FinalizeLoadingType)(bool); typedef Dart_Handle (*Dart_GetPeerType)(Dart_Handle, void**); typedef Dart_Handle (*Dart_SetPeerType)(Dart_Handle, void*); @@ -741,6 +742,7 @@ static Dart_LibraryHandleErrorType Dart_LibraryHandleErrorFn = NULL; static Dart_LoadLibraryFromKernelType Dart_LoadLibraryFromKernelFn = NULL; static Dart_LoadLibraryType Dart_LoadLibraryFn = NULL; static Dart_LoadLibraryFromBytecodeType Dart_LoadLibraryFromBytecodeFn = NULL; +static Dart_ReloadBytecodePatchType Dart_ReloadBytecodePatchFn = NULL; static Dart_FinalizeLoadingType Dart_FinalizeLoadingFn = NULL; static Dart_GetPeerType Dart_GetPeerFn = NULL; static Dart_SetPeerType Dart_SetPeerFn = NULL; @@ -1313,6 +1315,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { Dart_LoadLibraryFromBytecodeFn = (Dart_LoadLibraryFromBytecodeType)GetProcAddress( process, "Dart_LoadLibraryFromBytecode"); + Dart_ReloadBytecodePatchFn = (Dart_ReloadBytecodePatchType)GetProcAddress( + process, "Dart_ReloadBytecodePatch"); Dart_FinalizeLoadingFn = (Dart_FinalizeLoadingType)GetProcAddress( process, "Dart_FinalizeLoading"); Dart_GetPeerFn = (Dart_GetPeerType)GetProcAddress(process, "Dart_GetPeer"); @@ -2544,6 +2548,11 @@ Dart_Handle Dart_LoadLibraryFromBytecode(Dart_Handle bytecode_buffer) { return Dart_LoadLibraryFromBytecodeFn(bytecode_buffer); } +Dart_Handle Dart_ReloadBytecodePatch(const uint8_t* bytecode_buffer, + intptr_t bytecode_buffer_size) { + return Dart_ReloadBytecodePatchFn(bytecode_buffer, bytecode_buffer_size); +} + Dart_Handle Dart_FinalizeLoading(bool complete_futures) { return Dart_FinalizeLoadingFn(complete_futures); } diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h index 225e4ccabcd..40725796b2a 100644 --- a/runtime/include/dart_api.h +++ b/runtime/include/dart_api.h @@ -3767,6 +3767,26 @@ Dart_LoadLibrary(Dart_Handle kernel_buffer); DART_EXPORT DART_API_WARN_UNUSED_RESULT Dart_Handle Dart_LoadLibraryFromBytecode(Dart_Handle bytecode_buffer); +/** + * Applies a Dart bytecode reload patch to the current isolate group. + * + * The buffer must contain a bytecode delta/full-snapshot payload generated for + * the Dart bytecode interpreter. The VM copies the buffer before applying the + * reload, so the caller retains ownership of the input. This API does not use + * DART_DYNAMIC_MODULES and does not install downloaded native executable code. + * + * Requires there to be a current isolate. + * + * \param bytecode_buffer The bytecode patch buffer. + * \param bytecode_buffer_size Length of the passed in buffer. + * + * \return Success if the bytecode reload patch was applied. Otherwise, returns + * an error. + */ +DART_EXPORT DART_API_WARN_UNUSED_RESULT Dart_Handle +Dart_ReloadBytecodePatch(const uint8_t* bytecode_buffer, + intptr_t bytecode_buffer_size); + /** * Indicates that all outstanding load requests have been satisfied. * This finalizes all the new classes loaded and optionally completes @@ -4272,6 +4292,13 @@ typedef struct { const char* obfuscation_map_hash; const char* target_os; const char* target_arch; + /* + * Optional execution mode expected by the embedder. Missing artifacts are + * treated as "native-aot" for backward compatibility. iOS App Store builds + * must use the no-DDM interpreter patch mode, not native AOT snapshot text or + * DART_DYNAMIC_MODULES. + */ + const char* runtime_mode; } Dart_AotPatchInstallOptions; typedef bool (*Dart_AotPatchKeyCallback)(const char* key_id, @@ -4283,7 +4310,7 @@ typedef bool (*Dart_AotPatchKeyCallback)(const char* key_id, * Returns whether this VM was built with compact AOT patching support. * * This feature is intentionally independent of DART_DYNAMIC_MODULES and does - * not enable the bytecode interpreter. + * not include the dynamic-module runtime. */ DART_EXPORT bool Dart_AotPatchingEnabled(void); @@ -4301,9 +4328,9 @@ DART_EXPORT void Dart_SetAotPatchKeyCallback(Dart_AotPatchKeyCallback callback); * artifact key id, then decrypts the AES-256-GCM compact payload into an owned * buffer. A success result means the artifact is accepted for embedder * installation. The caller owns `patch_payload_buffer` and must release it with - * Dart_FreeAotPatchPayload. iOS-safe AOT patch loading maps patched isolate - * snapshot data/instructions before isolate startup; this API does not mutate - * live executable code. + * Dart_FreeAotPatchPayload. On iOS, native AOT patch payloads are rejected; the + * App Store-safe path is an interpreter payload executed by already-reviewed VM + * code and remains independent of DART_DYNAMIC_MODULES. */ DART_EXPORT DART_API_WARN_UNUSED_RESULT Dart_Handle Dart_InstallAotPatch(const uint8_t* patch_buffer, diff --git a/runtime/runtime_args.gni b/runtime/runtime_args.gni index f78139be8c7..7c6f604a3f1 100644 --- a/runtime/runtime_args.gni +++ b/runtime/runtime_args.gni @@ -75,8 +75,14 @@ declare_args() { # Whether to support dynamic loading and interpretation of Dart bytecode. dart_dynamic_modules = false + # Whether to support Shorebird's no-DDM bytecode interpreter path. This + # enables VM bytecode loading/interpreting without defining + # DART_DYNAMIC_MODULES or exposing the dynamic module Dart package API. + dart_enable_shorebird_interpreter = false + # Whether to expose the compact AOT patch installation API. This is separate - # from dart_dynamic_modules and must not pull in the bytecode interpreter. + # from dart_dynamic_modules; iOS may combine it with + # dart_enable_shorebird_interpreter for App Store-safe patch payloads. dart_enable_aot_patching = false } diff --git a/runtime/tests/vm/dart/exported_symbols_test.dart b/runtime/tests/vm/dart/exported_symbols_test.dart index 3eb1c671534..84b91e9a38e 100644 --- a/runtime/tests/vm/dart/exported_symbols_test.dart +++ b/runtime/tests/vm/dart/exported_symbols_test.dart @@ -287,6 +287,7 @@ main() { "Dart_PrepareToAbort", "Dart_PropagateError", "Dart_RecordTimelineEvent", + "Dart_ReloadBytecodePatch", "Dart_RegisterHeapSamplingCallback", "Dart_RegisterIsolateServiceRequestCallback", "Dart_RegisterRootServiceRequestCallback", diff --git a/runtime/vm/app_snapshot.cc b/runtime/vm/app_snapshot.cc index 496798daf5e..5a1d2c6271e 100644 --- a/runtime/vm/app_snapshot.cc +++ b/runtime/vm/app_snapshot.cc @@ -2595,6 +2595,11 @@ class CodeSerializationCluster : public SerializationCluster { #if defined(DART_PRECOMPILER) auto const calls_array = code->untag()->static_calls_target_table_; if (calls_array != Array::null()) { +#if defined(DART_SHOREBIRD_INTERPRETER) + // Keep the full table in Shorebird interpreter snapshots. Runtime + // static-call resolution needs Function targets, not just Code reachability. + s->Push(calls_array); +#else // Some Code entries in the static calls target table may only be // accessible via here, so push the Code objects. array_ = calls_array; @@ -2616,6 +2621,7 @@ class CodeSerializationCluster : public SerializationCluster { s->Push(destination); } } +#endif // defined(DART_SHOREBIRD_INTERPRETER) } #else UNREACHABLE(); @@ -2922,6 +2928,10 @@ class CodeSerializationCluster : public SerializationCluster { if (kind == Snapshot::kFullJIT) { WriteField(code, deopt_info_array_); WriteField(code, static_calls_target_table_); +#if defined(DART_SHOREBIRD_INTERPRETER) + } else if (kind == Snapshot::kFullAOT) { + WriteField(code, static_calls_target_table_); +#endif } #if !defined(PRODUCT) @@ -3048,6 +3058,10 @@ class CodeDeserializationCluster : public DeserializationCluster { code->untag()->deopt_info_array_ = static_cast(d->ReadRef()); code->untag()->static_calls_target_table_ = static_cast(d->ReadRef()); +#elif defined(DART_SHOREBIRD_INTERPRETER) + ASSERT(d->kind() == Snapshot::kFullAOT); + code->untag()->static_calls_target_table_ = + static_cast(d->ReadRef()); #endif // !DART_PRECOMPILED_RUNTIME #if !defined(PRODUCT) @@ -3099,7 +3113,7 @@ class CodeDeserializationCluster : public DeserializationCluster { intptr_t deferred_stop_index_; }; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) #if !defined(DART_PRECOMPILED_RUNTIME) class BytecodeSerializationCluster : public SerializationCluster { public: @@ -3172,7 +3186,7 @@ class BytecodeDeserializationCluster : public DeserializationCluster { } } }; -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) #if !defined(DART_PRECOMPILED_RUNTIME) class ObjectPoolSerializationCluster : public SerializationCluster { @@ -8220,7 +8234,7 @@ SerializationCluster* Serializer::NewClusterForClass(intptr_t cid, return new (Z) KernelProgramInfoSerializationCluster(); case kCodeCid: return new (Z) CodeSerializationCluster(heap_); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) case kBytecodeCid: return new (Z) BytecodeSerializationCluster(); #endif @@ -9461,7 +9475,7 @@ DeserializationCluster* Deserializer::ReadCluster() { ASSERT(!is_canonical); ASSERT(!is_deeply_immutable); return new (Z) CodeDeserializationCluster(); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) case kBytecodeCid: ASSERT(!is_canonical); ASSERT(!is_deeply_immutable); diff --git a/runtime/vm/bytecode_reader.cc b/runtime/vm/bytecode_reader.cc index 16fcc57fcd3..5d3f99a1bf3 100644 --- a/runtime/vm/bytecode_reader.cc +++ b/runtime/vm/bytecode_reader.cc @@ -5,7 +5,7 @@ #include "vm/bytecode_reader.h" #include "vm/globals.h" -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) #include "vm/bit_vector.h" #include "vm/bootstrap.h" @@ -23,6 +23,7 @@ #include "vm/hash_table.h" #include "vm/longjump.h" #include "vm/object.h" +#include "vm/os.h" #include "vm/object_store.h" #include "vm/resolver.h" #include "vm/reusable_handles.h" @@ -119,6 +120,22 @@ FunctionPtr BytecodeLoader::LoadBytecode(bool load_code) { return Function::RawCast(bytecode_reader.ReadObject()); } +intptr_t BytecodeLoader::LoadBytecodePatch() { + ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter()); + + if (bytecode_component_array_.IsNull()) { + BytecodeReaderHelper component_reader(thread_, binary_); + bytecode_component_array_ = component_reader.ReadBytecodeComponent(); + } + + BytecodeComponentData bytecode_component(bytecode_component_array_); + BytecodeReaderHelper bytecode_reader(thread_, &bytecode_component); + AlternativeReadingScope alt(&bytecode_reader.reader(), + bytecode_component.GetLibraryIndexOffset()); + return bytecode_reader.ReadLoadedLibraryBytecodePatch( + bytecode_component.GetNumLibraries()); +} + void BytecodeLoader::LoadPendingCode() { ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter()); ASSERT(!bytecode_component_array_.IsNull()); @@ -2577,6 +2594,318 @@ void BytecodeReaderHelper::ReadLibraryDeclarations( } } +intptr_t BytecodeReaderHelper::ReadLoadedLibraryBytecodePatch( + intptr_t num_libraries) { + intptr_t installed_functions = 0; + auto& library = Library::Handle(Z); + auto& uri = String::Handle(Z); + + for (intptr_t i = 0; i < num_libraries; ++i) { + uri ^= ReadObject(); + const intptr_t library_offset = + bytecode_component_->GetLibrariesOffset() + reader_.ReadUInt(); + + library = Library::LookupLibrary(thread_, uri); + if (library.IsNull()) { + continue; + } + + AlternativeReadingScope alt(&reader_, library_offset); + ReadLoadedLibraryPatchDeclaration(library, &installed_functions); + } + + return installed_functions; +} + +void BytecodeReaderHelper::ReadLoadedLibraryPatchDeclaration( + const Library& library, + intptr_t* installed_functions) { + reader_.ReadUInt(); // Flags. + + ReadObject(); // Library name. + ReadObject(); // Script. + + const intptr_t num_classes = reader_.ReadUInt(); + auto& cls = Class::Handle(Z); + auto& name = String::Handle(Z); + + for (intptr_t i = 0; i < num_classes; ++i) { + name ^= ReadObject(); + const intptr_t class_offset = + bytecode_component_->GetClassesOffset() + reader_.ReadUInt(); + + if (i == 0) { + cls = library.toplevel_class(); + } else { + cls = library.LookupClass(name); + } + if (cls.IsNull()) { + continue; + } + + AlternativeReadingScope alt(&reader_, class_offset); + ReadLoadedClassPatchDeclaration(cls, installed_functions); + } +} + +void BytecodeReaderHelper::ReadLoadedClassPatchDeclaration( + const Class& cls, + intptr_t* installed_functions) { + const int kHasTypeParamsFlag = 1 << 2; + const int kHasTypeArgumentsFlag = 1 << 3; + const int kHasSourcePositionsFlag = 1 << 5; + const int kHasAnnotationsFlag = 1 << 6; + + const intptr_t flags = reader_.ReadUInt(); + + ReadObject(); // Script. + + if ((flags & kHasSourcePositionsFlag) != 0) { + reader_.ReadPosition(); + reader_.ReadPosition(); + } + + if ((flags & kHasTypeArgumentsFlag) != 0) { + reader_.ReadUInt(); + } + + if ((flags & kHasTypeParamsFlag) != 0) { + SkipTypeParametersDeclaration(); + } + + ReadObject(); // Super type. + + const intptr_t num_interfaces = reader_.ReadUInt(); + for (intptr_t i = 0; i < num_interfaces; ++i) { + ReadObject(); + } + + if ((flags & kHasAnnotationsFlag) != 0) { + SkipAnnotations(); + } + + const intptr_t members_offset = + bytecode_component_->GetMembersOffset() + reader_.ReadUInt(); + AlternativeReadingScope alt(&reader_, members_offset); + ReadLoadedMembersPatch(cls, installed_functions); +} + +void BytecodeReaderHelper::ReadLoadedMembersPatch( + const Class& cls, + intptr_t* installed_functions) { + reader_.ReadUInt(); // Total function count, including field accessors. + ReadLoadedFieldPatchDeclarations(cls, installed_functions); + ReadLoadedFunctionPatchDeclarations(cls, installed_functions); +} + +void BytecodeReaderHelper::ReadLoadedFieldPatchDeclarations( + const Class& cls, + intptr_t* installed_functions) { + const int kIsStaticFlag = 1 << 0; + const int kIsLateFlag = 1 << 3; + const int kHasGetterFlag = 1 << 8; + const int kHasSetterFlag = 1 << 9; + const int kHasNontrivialInitializerFlag = 1 << 11; + const int kHasInitializerCodeFlag = 1 << 12; + const int kHasSourcePositionsFlag = 1 << 13; + const int kHasAnnotationsFlag = 1 << 14; + const int kHasCustomScriptFlag = 1 << 16; + + const intptr_t num_fields = reader_.ReadListLength(); + auto& name = String::Handle(Z); + auto& field = Field::Handle(Z); + auto& initializer = Function::Handle(Z); + + for (intptr_t i = 0; i < num_fields; ++i) { + const intptr_t flags = reader_.ReadUInt(); + const bool has_nontrivial_initializer = + (flags & kHasNontrivialInitializerFlag) != 0; + const bool is_static = (flags & kIsStaticFlag) != 0; + const bool is_late = (flags & kIsLateFlag) != 0; + + name ^= ReadObject(); + ReadObject(); // Field type. + field = cls.LookupField(name); + + if ((flags & kHasCustomScriptFlag) != 0) { + ReadObject(); + } + + if ((flags & kHasSourcePositionsFlag) != 0) { + reader_.ReadPosition(); + reader_.ReadPosition(); + } + + if (!has_nontrivial_initializer) { + ReadObject(); + } + + if ((flags & kHasInitializerCodeFlag) != 0) { + const intptr_t code_offset = + bytecode_component_->GetCodesOffset() + reader_.ReadUInt(); + if (!field.IsNull() && (is_static || is_late)) { + initializer = field.EnsureInitializerFunction(); + InstallLoadedFunctionPatch(initializer, code_offset, + installed_functions); + } + } + + if ((flags & kHasGetterFlag) != 0) { + ReadObject(); + } + if ((flags & kHasSetterFlag) != 0) { + ReadObject(); + } + + if ((flags & kHasAnnotationsFlag) != 0) { + SkipAnnotations(); + } + } +} + +void BytecodeReaderHelper::ReadLoadedFunctionPatchDeclarations( + const Class& cls, + intptr_t* installed_functions) { + const int kIsStaticFlag = 1 << 0; + const int kIsAbstractFlag = 1 << 1; + const int kIsGetterFlag = 1 << 2; + const int kIsConstructorFlag = 1 << 4; + const int kIsFactoryFlag = 1 << 5; + const int kHasOptionalPositionalParamsFlag = 1 << 7; + const int kHasOptionalNamedParamsFlag = 1 << 8; + const int kHasTypeParamsFlag = 1 << 9; + const int kHasParameterFlagsFlag = 1 << 10; + const int kIsNativeFlag = 1 << 19; + const int kHasSourcePositionsFlag = 1 << 20; + const int kHasAnnotationsFlag = 1 << 21; + const int kHasCustomScriptFlag = 1 << 23; + + const intptr_t num_functions = reader_.ReadListLength(); + auto& name = String::Handle(Z); + auto& function = Function::Handle(Z); + auto& error = Error::Handle(Z); + + for (intptr_t i = 0; i < num_functions; ++i) { + const intptr_t flags = reader_.ReadUInt(); + const bool is_static = (flags & kIsStaticFlag) != 0; + const bool is_constructor = + (flags & (kIsConstructorFlag | kIsFactoryFlag)) != 0; + const bool has_optional_named_params = + (flags & kHasOptionalNamedParamsFlag) != 0; + + name ^= ReadObject(); + + if ((flags & kHasCustomScriptFlag) != 0) { + ReadObject(); + } + + if ((flags & kHasSourcePositionsFlag) != 0) { + reader_.ReadPosition(); + reader_.ReadPosition(); + } + + if (is_constructor) { + name = ConstructorName(cls, name); + } + + error = is_constructor ? cls.EnsureIsAllocateFinalized(thread_) + : cls.EnsureIsFinalized(thread_); + if (!error.IsNull()) { + Exceptions::PropagateError(error); + UNREACHABLE(); + } + function = Resolver::ResolveFunction(Z, cls, name); + if (function.IsNull() && ((flags & kIsGetterFlag) != 0)) { + String& method_name = String::Handle(Z, Field::NameFromGetter(name)); + function = Resolver::ResolveFunction(Z, cls, method_name); + if (!function.IsNull()) { + function = Function::Handle(Z, function.ptr()).GetMethodExtractor(name); + } + } + + FunctionType& signature = FunctionType::Handle(Z); + if (function.IsNull()) { + signature = FunctionType::null(); + } else { + signature = function.signature(); + } + FunctionTypeScope function_type_scope(this, signature); + + if ((flags & kHasTypeParamsFlag) != 0) { + SkipTypeParametersDeclaration(); + } + + const intptr_t num_implicit_params = is_static ? 0 : 1; + const intptr_t num_params = num_implicit_params + reader_.ReadUInt(); + intptr_t num_required_params = num_params; + if ((flags & (kHasOptionalPositionalParamsFlag | + kHasOptionalNamedParamsFlag)) != 0) { + num_required_params = num_implicit_params + reader_.ReadUInt(); + } + + for (intptr_t param_index = num_implicit_params; param_index < num_params; + ++param_index) { + name ^= ReadObject(); + USE(name); + ReadObject(); + } + + if ((flags & kHasParameterFlagsFlag) != 0) { + RELEASE_ASSERT(has_optional_named_params); + const intptr_t length = reader_.ReadUInt(); + for (intptr_t j = 0; j < length; j++) { + reader_.ReadUInt(); + } + } + + ReadObject(); // Result type. + + if ((flags & kIsNativeFlag) != 0) { + ReadObject(); + } + + if ((flags & kIsAbstractFlag) == 0) { + const intptr_t code_offset = + bytecode_component_->GetCodesOffset() + reader_.ReadUInt(); + InstallLoadedFunctionPatch(function, code_offset, installed_functions); + } + + if ((flags & kHasAnnotationsFlag) != 0) { + SkipAnnotations(); + } + } +} + +void BytecodeReaderHelper::InstallLoadedFunctionPatch( + const Function& function, + intptr_t code_offset, + intptr_t* installed_functions) { + if (function.IsNull() || function.is_abstract()) { + return; + } + + OS::PrintErr("Dart bytecode patch: installing %s\n", + function.ToFullyQualifiedCString()); + ReadCode(function, code_offset); + *installed_functions += 1; +} + +void BytecodeReaderHelper::SkipTypeParametersDeclaration() { + const intptr_t num_type_params = reader_.ReadUInt(); + ASSERT(num_type_params > 0); + for (intptr_t i = 0; i < num_type_params; ++i) { + ReadObject(); + } + for (intptr_t i = 0; i < num_type_params; ++i) { + ReadObject(); + ReadObject(); + } +} + +void BytecodeReaderHelper::SkipAnnotations() { + reader_.ReadUInt(); +} + void BytecodeReaderHelper::ReadPendingCode( const GrowableObjectArray& pending_objects) { auto& obj = Object::Handle(Z); @@ -3167,4 +3496,4 @@ LocalVarDescriptorsPtr BytecodeReader::ComputeLocalVarDescriptors( } // namespace bytecode } // namespace dart -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) diff --git a/runtime/vm/bytecode_reader.h b/runtime/vm/bytecode_reader.h index cbe089e3557..b3a19e3212c 100644 --- a/runtime/vm/bytecode_reader.h +++ b/runtime/vm/bytecode_reader.h @@ -6,7 +6,7 @@ #define RUNTIME_VM_BYTECODE_READER_H_ #include "vm/globals.h" -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) #include "vm/bit_vector.h" #include "vm/constants_kbc.h" @@ -24,6 +24,7 @@ class BytecodeLoader { ~BytecodeLoader(); FunctionPtr LoadBytecode(bool load_code = true); + intptr_t LoadBytecodePatch(); void LoadPendingCode(); TypedDataBasePtr binary() const { return binary_.ptr(); } @@ -250,6 +251,7 @@ class BytecodeReaderHelper : public ValueObject { void ReadLibraryDeclarations(intptr_t num_libraries, const GrowableObjectArray& pending_objects, bool load_code); + intptr_t ReadLoadedLibraryBytecodePatch(intptr_t num_libraries); void ReadPendingCode(const GrowableObjectArray& pending_objects); void FindModifiedLibraries(BitVector* modified_libs, intptr_t num_libraries); @@ -368,6 +370,20 @@ class BytecodeReaderHelper : public ValueObject { }; void ReadClosureDeclaration(const Function& function, intptr_t closureIndex); + void ReadLoadedLibraryPatchDeclaration(const Library& library, + intptr_t* installed_functions); + void ReadLoadedClassPatchDeclaration(const Class& cls, + intptr_t* installed_functions); + void ReadLoadedMembersPatch(const Class& cls, intptr_t* installed_functions); + void ReadLoadedFieldPatchDeclarations(const Class& cls, + intptr_t* installed_functions); + void ReadLoadedFunctionPatchDeclarations(const Class& cls, + intptr_t* installed_functions); + void InstallLoadedFunctionPatch(const Function& function, + intptr_t code_offset, + intptr_t* installed_functions); + void SkipTypeParametersDeclaration(); + void SkipAnnotations(); FunctionTypePtr ReadFunctionSignature(const FunctionType& signature, const Function& closure_function, bool has_optional_positional_params, @@ -773,5 +789,5 @@ class BytecodeRecordedCoverageIterator : ValueObject { } // namespace bytecode } // namespace dart -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) #endif // RUNTIME_VM_BYTECODE_READER_H_ diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc index 9e69ace6375..a484b318358 100644 --- a/runtime/vm/class_finalizer.cc +++ b/runtime/vm/class_finalizer.cc @@ -439,7 +439,7 @@ AbstractTypePtr ClassFinalizer::FinalizeType(const AbstractType& type, } } -#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) #if defined(TARGET_ARCH_X64) static bool IsPotentialExactGeneric(const AbstractType& type) { @@ -531,7 +531,7 @@ void ClassFinalizer::FinalizeMemberTypes(const Class& cls) { } } } -#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) void ClassFinalizer::FinalizeTypesInClass(const Class& cls) { Thread* thread = Thread::Current(); @@ -541,7 +541,7 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) { return; } -#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) Zone* zone = thread->zone(); SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock()); if (cls.is_type_finalized()) { @@ -603,7 +603,7 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) { #else UNREACHABLE(); -#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) } #if !defined(DART_PRECOMPILED_RUNTIME) @@ -700,7 +700,7 @@ void ClassFinalizer::FinalizeClass(const Class& cls) { return; } -#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) UNREACHABLE(); #else Thread* thread = Thread::Current(); @@ -724,7 +724,7 @@ void ClassFinalizer::FinalizeClass(const Class& cls) { (cls.kernel_offset() > 0)); if (!cls.is_loaded()) { if (cls.is_declared_in_bytecode()) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) bytecode::BytecodeReader::FinishClassLoading(cls); #else UNREACHABLE(); @@ -772,7 +772,7 @@ void ClassFinalizer::FinalizeClass(const Class& cls) { cls.set_is_allocate_finalized(); } #endif // defined(DART_PRECOMPILED_RUNTIME) -#endif // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) } #if !defined(DART_PRECOMPILED_RUNTIME) @@ -830,7 +830,7 @@ ErrorPtr ClassFinalizer::AllocateFinalizeClass(const Class& cls) { #endif // !defined(DART_PRECOMPILED_RUNTIME) -#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) ErrorPtr ClassFinalizer::LoadClassMembers(const Class& cls) { ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter()); ASSERT(!cls.is_finalized()); @@ -894,7 +894,7 @@ void ClassFinalizer::PrintClassInformation(const Class& cls) { } } #endif // !defined(PRODUCT) -#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) #if !defined(DART_PRECOMPILED_RUNTIME) diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h index 333a875acad..09b54ddec2e 100644 --- a/runtime/vm/class_finalizer.h +++ b/runtime/vm/class_finalizer.h @@ -65,13 +65,13 @@ class ClassFinalizer : public AllStatic { static ErrorPtr AllocateFinalizeClass(const Class& cls); #endif // !defined(DART_PRECOMPILED_RUNTIME) -#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) // Completes loading of the class, this populates the function // and fields of the class. // // Returns Error::null() if there is no loading error. static ErrorPtr LoadClassMembers(const Class& cls); -#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) #if !defined(DART_PRECOMPILED_RUNTIME) // Verify that the classes have been properly prefinalized. This is @@ -90,7 +90,7 @@ class ClassFinalizer : public AllStatic { const TypeParameters& type_params, FinalizationKind finalization); -#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) static void FinalizeMemberTypes(const Class& cls); #if !defined(PRODUCT) static void PrintClassInformation(const Class& cls); diff --git a/runtime/vm/code_patcher.cc b/runtime/vm/code_patcher.cc index 54e044a9d26..7ee26a66a0c 100644 --- a/runtime/vm/code_patcher.cc +++ b/runtime/vm/code_patcher.cc @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. #include "vm/code_patcher.h" -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) #include "vm/constants_kbc.h" #endif #include "vm/cpu.h" @@ -64,7 +64,7 @@ bool MatchesPattern(uword end, const int16_t* pattern, intptr_t size) { return true; } -#if !defined(PRODUCT) && defined(DART_DYNAMIC_MODULES) +#if !defined(PRODUCT) && defined(DART_BYTECODE_INTERPRETER) uint32_t BytecodePatcher::AddBreakpointAt(uword return_address, const Bytecode& bytecode) { @@ -110,6 +110,6 @@ void BytecodePatcher::RemoveBreakpointAtWithMutatorsStopped( static_cast(opcode))); *instr = opcode; } -#endif // !defined(PRODUCT) && defined(DART_DYNAMIC_MODULES) +#endif // !defined(PRODUCT) && defined(DART_BYTECODE_INTERPRETER) } // namespace dart diff --git a/runtime/vm/code_patcher.h b/runtime/vm/code_patcher.h index 2132fd482ad..fa184f76d4a 100644 --- a/runtime/vm/code_patcher.h +++ b/runtime/vm/code_patcher.h @@ -94,7 +94,7 @@ class CodePatcher : public AllStatic { static intptr_t GetSubtypeTestCachePoolIndex(uword return_address); }; -#if !defined(PRODUCT) && defined(DART_DYNAMIC_MODULES) +#if !defined(PRODUCT) && defined(DART_BYTECODE_INTERPRETER) class BytecodePatcher : public AllStatic { public: // Patch call instruction prior to return_address to add a breakpoint. @@ -118,7 +118,7 @@ class BytecodePatcher : public AllStatic { const Bytecode& bytecode, uint32_t opcode); }; -#endif // !defined(PRODUCT) && defined(DART_DYNAMIC_MODULES) +#endif // !defined(PRODUCT) && defined(DART_BYTECODE_INTERPRETER) // Beginning from [end - size] we compare [size] bytes with [pattern]. All // [0..255] values in [pattern] have to match, negative values are skipped. diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc index 4f7fabedab5..0f5800b918c 100644 --- a/runtime/vm/compiler/aot/precompiler.cc +++ b/runtime/vm/compiler/aot/precompiler.cc @@ -603,7 +603,7 @@ void Precompiler::DoCompileAll() { IG->object_store()->set_simple_instance_of_true_function(null_function); IG->object_store()->set_simple_instance_of_false_function( null_function); -#if !defined(DART_DYNAMIC_MODULES) +#if !defined(DART_BYTECODE_INTERPRETER) IG->object_store()->set_async_star_stream_controller(null_class); #endif IG->object_store()->set_native_assets_library(null_library); @@ -1953,14 +1953,14 @@ void Precompiler::TraceForRetainedFunctions() { function.DropUncompiledImplicitClosureFunction(); bool retained = possibly_retained_functions_.ContainsKey(function); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) // Retain abstract functions annotated with entry point // pragmas as they can be used as targets of interface calls. if (function.is_abstract() && functions_with_entry_point_pragmas_.ContainsKey(function)) { retained = true; } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) if (retained) { AddTypesOf(function); } @@ -2066,6 +2066,7 @@ void Precompiler::FinalizeDispatchTable() { void Precompiler::ReplaceFunctionStaticCallEntries() { PRECOMPILER_TIMER_SCOPE(this, ReplaceFunctionStaticCallEntries); + class StaticCallTableEntryFixer : public CodeVisitor { public: explicit StaticCallTableEntryFixer(Zone* zone) @@ -2106,6 +2107,19 @@ void Precompiler::ReplaceFunctionStaticCallEntries() { ASSERT(view.Get() == Code::null()); ASSERT(target_function_.HasCode()); +#if defined(DART_SHOREBIRD_INTERPRETER) + if (target_function_.IsShorebirdPatchable()) { + // Keep patchable functions as Function targets. Runtime dispatch will + // read the current Function::entry_point, which can point at + // InterpretCall after a bytecode patch is loaded. + if (FLAG_trace_precompiler) { + THR_Print("Kept patchable static call entry for %s in \"%s\"\n", + target_function_.ToFullyQualifiedCString(), + code.ToCString()); + } + continue; + } +#endif target_code_ = target_function_.CurrentCode(); ASSERT(!target_code_.IsStubCode()); view.Set(target_code_); @@ -2583,13 +2597,13 @@ void Precompiler::DropTransitiveUserDefinedConstants() { if (cls.constants() == Array::null()) { continue; } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) // Retain constant tables of exported classes to allow constant // canonicalization at runtime. if (HasApiUse(cls)) { continue; } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) typedef UnorderedHashSet CanonicalInstancesSet; @@ -2929,6 +2943,7 @@ void Precompiler::DiscardCodeObjects() { loading_unit_(LoadingUnit::Handle(zone)), static_calls_target_table_(Array::Handle(zone)), kind_and_offset_(Smi::Handle(zone)), + function_target_(Function::Handle(zone)), call_target_(Code::Handle(zone)), targets_of_calls_via_code_( GrowableObjectArray::Handle(zone, GrowableObjectArray::New())), @@ -2947,6 +2962,16 @@ void Precompiler::DiscardCodeObjects() { kind_and_offset_ = view.Get(); auto const kind = Code::KindField::decode(kind_and_offset_.Value()); if (kind == Code::kCallViaCode) { +#if defined(DART_SHOREBIRD_INTERPRETER) + function_target_ = + view.Get(); + if (!function_target_.IsNull()) { + ASSERT(function_target_.HasCode()); + call_target_ = function_target_.CurrentCode(); + targets_of_calls_via_code_.Add(call_target_); + continue; + } +#endif call_target_ = Code::RawCast(view.Get()); ASSERT(!call_target_.IsNull()); @@ -3070,6 +3095,7 @@ void Precompiler::DiscardCodeObjects() { LoadingUnit& loading_unit_; Array& static_calls_target_table_; Smi& kind_and_offset_; + Function& function_target_; Code& call_target_; GrowableObjectArray& targets_of_calls_via_code_; const FunctionSet& functions_to_retain_; diff --git a/runtime/vm/compiler/assembler/disassembler_kbc.cc b/runtime/vm/compiler/assembler/disassembler_kbc.cc index 86fba501a11..b49ff4ca280 100644 --- a/runtime/vm/compiler/assembler/disassembler_kbc.cc +++ b/runtime/vm/compiler/assembler/disassembler_kbc.cc @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. #include "vm/globals.h" -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) #include "vm/compiler/assembler/disassembler_kbc.h" @@ -583,4 +583,4 @@ void KernelBytecodeDisassembler::PrintLocalVariablesInfo( } // namespace dart -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) diff --git a/runtime/vm/compiler/assembler/disassembler_kbc.h b/runtime/vm/compiler/assembler/disassembler_kbc.h index f76e238ae60..a075bdfbc6b 100644 --- a/runtime/vm/compiler/assembler/disassembler_kbc.h +++ b/runtime/vm/compiler/assembler/disassembler_kbc.h @@ -6,7 +6,7 @@ #define RUNTIME_VM_COMPILER_ASSEMBLER_DISASSEMBLER_KBC_H_ #include "vm/globals.h" -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) #include "vm/compiler/assembler/disassembler.h" @@ -114,6 +114,6 @@ class KernelBytecodeDisassembler : public AllStatic { } // namespace dart -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) #endif // RUNTIME_VM_COMPILER_ASSEMBLER_DISASSEMBLER_KBC_H_ diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc index e4ed59db32c..3f97345918c 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc @@ -3516,9 +3516,18 @@ void FlowGraphCompiler::EmitMoveConst(const compiler::ffi::NativeLocation& dst, } bool FlowGraphCompiler::CanPcRelativeCall(const Function& target) const { - return FLAG_precompiled_mode && !FLAG_force_indirect_calls && - (LoadingUnit::LoadingUnitOf(function()) == - LoadingUnit::LoadingUnitOf(target)); + const bool can_pc_relative = + FLAG_precompiled_mode && !FLAG_force_indirect_calls && + (LoadingUnit::LoadingUnitOf(function()) == + LoadingUnit::LoadingUnitOf(target)); +#if defined(DART_SHOREBIRD_INTERPRETER) + // Shorebird's interpreter patching updates Function::entry_point at runtime. + // Keep only explicitly patchable entry points indirect so patched functions + // are observed without rewriting executable AOT instructions. + return can_pc_relative && !target.IsShorebirdPatchable(); +#else + return can_pc_relative; +#endif } bool FlowGraphCompiler::CanPcRelativeCall(const Code& target) const { diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc index 7e64c0712f1..b1f1c3df5d0 100644 --- a/runtime/vm/compiler/backend/il_arm.cc +++ b/runtime/vm/compiler/backend/il_arm.cc @@ -809,7 +809,7 @@ void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // R0: Closure with a cached entry point. __ ldr(R2, compiler::FieldAddress( R0, compiler::target::Closure::entry_point_offset())); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) ASSERT(FUNCTION_REG != R2); __ ldr(FUNCTION_REG, compiler::FieldAddress( R0, compiler::target::Closure::function_offset())); diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc index d08b3d5534d..298c3a37b86 100644 --- a/runtime/vm/compiler/backend/il_arm64.cc +++ b/runtime/vm/compiler/backend/il_arm64.cc @@ -652,7 +652,7 @@ void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // R0: Closure with a cached entry point. __ LoadFieldFromOffset(R2, R0, compiler::target::Closure::entry_point_offset()); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) ASSERT(FUNCTION_REG != R2); __ LoadCompressedFieldFromOffset( FUNCTION_REG, R0, compiler::target::Closure::function_offset()); diff --git a/runtime/vm/compiler/backend/il_riscv.cc b/runtime/vm/compiler/backend/il_riscv.cc index b58f6a51caa..4fb7484790a 100644 --- a/runtime/vm/compiler/backend/il_riscv.cc +++ b/runtime/vm/compiler/backend/il_riscv.cc @@ -690,7 +690,7 @@ void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // T0: Closure with a cached entry point. __ LoadFieldFromOffset(A1, T0, compiler::target::Closure::entry_point_offset()); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) ASSERT(FUNCTION_REG != A1); __ LoadCompressedFieldFromOffset( FUNCTION_REG, T0, compiler::target::Closure::function_offset()); diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc index 25dfbcfe309..6518037bcf5 100644 --- a/runtime/vm/compiler/backend/il_x64.cc +++ b/runtime/vm/compiler/backend/il_x64.cc @@ -6528,7 +6528,7 @@ void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // RAX: Closure with cached entry point. __ movq(RCX, compiler::FieldAddress( RAX, compiler::target::Closure::entry_point_offset())); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) ASSERT(FUNCTION_REG != RCX); __ LoadCompressed(FUNCTION_REG, compiler::FieldAddress( diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h index 4806629d4f3..1f005484282 100644 --- a/runtime/vm/compiler/runtime_offsets_extracted.h +++ b/runtime/vm/compiler/runtime_offsets_extracted.h @@ -20069,7 +20069,11 @@ static constexpr dart::compiler::target::word AOT_Closure_elements_start_offset = 0x28; static constexpr dart::compiler::target::word AOT_Closure_element_size = 0x8; static constexpr dart::compiler::target::word AOT_Code_elements_start_offset = +#if defined(DART_SHOREBIRD_INTERPRETER) + 0x80; +#else 0x78; +#endif static constexpr dart::compiler::target::word AOT_Code_element_size = 0x4; static constexpr dart::compiler::target::word AOT_Context_elements_start_offset = 0x18; diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc index 6416a8f0734..50b878d5834 100644 --- a/runtime/vm/compiler/stub_code_compiler.cc +++ b/runtime/vm/compiler/stub_code_compiler.cc @@ -230,14 +230,14 @@ void StubCodeCompiler::GenerateInitLateInstanceFieldStub(bool is_final) { if (!FLAG_precompiled_mode) { __ LoadCompressedFieldFromOffset(CODE_REG, FUNCTION_REG, target::Function::code_offset()); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) // InterpretCall stub needs arguments descriptor for all function calls. __ LoadObject(ARGS_DESC_REG, ArgumentsDescriptorBoxed(/*type_args_len=*/0, /*num_arguments=*/1)); #else // Load a GC-safe value for the arguments descriptor (unused but tagged). __ LoadImmediate(ARGS_DESC_REG, 0); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } if (FLAG_target_thread_sanitizer) { __ TsanFuncEntry(); @@ -2481,7 +2481,7 @@ void StubCodeCompiler::GenerateResumeStub() { static_assert((kStackTrace != CODE_REG) && (kStackTrace != PP), "should not interfere"); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) Label resume_interpreter; __ CompareWithMemoryValue( kResumePc, @@ -2489,7 +2489,7 @@ void StubCodeCompiler::GenerateResumeStub() { compiler::target::Thread:: resume_interpreter_adjusted_entry_point_offset())); __ BranchIf(EQUAL, &resume_interpreter); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) // Set return address as if suspended Dart function called // stub with kResumePc as a return address. @@ -2516,7 +2516,7 @@ void StubCodeCompiler::GenerateResumeStub() { __ Ret(); } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) // This case is used when Dart frame is still on the stack. if (FLAG_precompiled_mode) { @@ -2535,7 +2535,7 @@ void StubCodeCompiler::GenerateResumeStub() { __ PopRegister(CallingConventions::kReturnReg); // Get result. __ LeaveDartFrame(); __ Ret(); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } void StubCodeCompiler::GenerateReturnStub( diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc index fedda55fe9b..6215afdeb98 100644 --- a/runtime/vm/compiler/stub_code_compiler_arm.cc +++ b/runtime/vm/compiler/stub_code_compiler_arm.cc @@ -572,6 +572,17 @@ void StubCodeCompiler::GenerateCallStaticFunctionStub() { __ LoadImmediate(R0, 0); __ PushList((1 << R0) | (1 << ARGS_DESC_REG)); __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); +#if defined(DART_PRECOMPILED_RUNTIME) && defined(DART_SHOREBIRD_INTERPRETER) + // Get Function object result and restore arguments descriptor array. + __ PopList((1 << R0) | (1 << ARGS_DESC_REG)); + // Remove the stub frame. + __ LeaveStubFrame(); + // Jump through Function::entry_point so bytecode-attached functions enter + // the interpreter without rewriting executable AOT instructions. + __ LoadCompressedFieldFromOffset(CODE_REG, FUNCTION_REG, + target::Function::code_offset()); + __ Branch(FieldAddress(FUNCTION_REG, target::Function::entry_point_offset())); +#else // Get Code object result and restore arguments descriptor array. __ PopList((1 << R0) | (1 << ARGS_DESC_REG)); // Remove the stub frame. @@ -579,6 +590,7 @@ void StubCodeCompiler::GenerateCallStaticFunctionStub() { // Jump to the dart function. __ mov(CODE_REG, Operand(R0)); __ Branch(FieldAddress(R0, target::Code::entry_point_offset())); +#endif } // Called from a static call only when an invalid code has been entered @@ -1290,7 +1302,7 @@ void StubCodeCompiler::GenerateInvokeDartCodeStub() { // R2 : address of first argument. // R3 : current thread. void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub() { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) SPILLS_LR_TO_FRAME(__ EnterFrame((1 << FP) | (1 << LR), 0)); // Push code object to PC marker slot. @@ -1416,7 +1428,7 @@ void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub() { #else __ Stop("Not using Dart dynamic modules"); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // Helper to generate space allocation of context stub. @@ -2696,7 +2708,7 @@ void StubCodeCompiler::GenerateLazyCompileStub() { // R4: Arguments descriptor. // R0: Function. void StubCodeCompiler::GenerateInterpretCallStub() { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) __ EnterStubFrame(); @@ -2770,7 +2782,7 @@ void StubCodeCompiler::GenerateInterpretCallStub() { #else __ Stop("Not using Dart dynamic modules"); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // R9: Contains an ICData. diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc index fea54932ce6..637dfe16180 100644 --- a/runtime/vm/compiler/stub_code_compiler_arm64.cc +++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc @@ -795,6 +795,20 @@ void StubCodeCompiler::GenerateCallStaticFunctionStub() { __ Push(ARGS_DESC_REG); __ Push(ZR); __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); +#if defined(DART_PRECOMPILED_RUNTIME) && defined(DART_SHOREBIRD_INTERPRETER) + // Get Function object result and restore arguments descriptor array. + __ Pop(FUNCTION_REG); + __ Pop(ARGS_DESC_REG); + // Remove the stub frame. + __ LeaveStubFrame(); + // Jump through Function::entry_point so bytecode-attached functions enter + // the interpreter without rewriting executable AOT instructions. + __ LoadCompressedFieldFromOffset(CODE_REG, FUNCTION_REG, + target::Function::code_offset()); + __ LoadFieldFromOffset(TMP, FUNCTION_REG, + target::Function::entry_point_offset()); + __ br(TMP); +#else // Get Code object result and restore arguments descriptor array. __ Pop(CODE_REG); __ Pop(ARGS_DESC_REG); @@ -803,6 +817,7 @@ void StubCodeCompiler::GenerateCallStaticFunctionStub() { // Jump to the dart function. __ LoadFieldFromOffset(R0, CODE_REG, target::Code::entry_point_offset()); __ br(R0); +#endif } // Called from a static call only when an invalid code has been entered @@ -1617,7 +1632,7 @@ void StubCodeCompiler::GenerateInvokeDartCodeStub() { // R2 : address of first argument. // R3 : current thread. void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub() { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) __ Comment("InvokeDartCodeFromBytecodeStub"); // Copy the C stack pointer (CSP/R31) into the stack pointer we'll actually @@ -1755,7 +1770,7 @@ void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub() { #else __ Stop("Not using Dart dynamic modules"); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // Helper to generate space allocation of context stub. @@ -3098,7 +3113,7 @@ void StubCodeCompiler::GenerateLazyCompileStub() { // R4: Arguments descriptor. // R0: Function. void StubCodeCompiler::GenerateInterpretCallStub() { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) __ SetPrologueOffset(); __ EnterStubFrame(); @@ -3186,7 +3201,7 @@ void StubCodeCompiler::GenerateInterpretCallStub() { #else __ Stop("Not using Dart dynamic modules"); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // R5: Contains an ICData. diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc index 22ebe800c2b..9f5e4246360 100644 --- a/runtime/vm/compiler/stub_code_compiler_ia32.cc +++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc @@ -1134,7 +1134,7 @@ void StubCodeCompiler::GenerateInvokeDartCodeStub() { // ESP + 12: address of first argument. // ESP + 16 : current thread. void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub() { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const intptr_t kTargetCodeOffset = 2 * target::kWordSize; const intptr_t kArgumentsDescOffset = 3 * target::kWordSize; const intptr_t kArgumentsOffset = 4 * target::kWordSize; @@ -1254,7 +1254,7 @@ void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub() { #else __ Stop("Not using Dart dynamic modules"); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // Helper to generate space allocation of context stub. @@ -2432,7 +2432,7 @@ void StubCodeCompiler::GenerateLazyCompileStub() { // EDX: Arguments descriptor. // EAX: Function. void StubCodeCompiler::GenerateInterpretCallStub() { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) __ EnterStubFrame(); @@ -2505,7 +2505,7 @@ void StubCodeCompiler::GenerateInterpretCallStub() { #else __ Stop("Not using Dart dynamic modules"); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // ECX: Contains an ICData. diff --git a/runtime/vm/compiler/stub_code_compiler_riscv.cc b/runtime/vm/compiler/stub_code_compiler_riscv.cc index 4d9e01a96f5..b0fbfb8042f 100644 --- a/runtime/vm/compiler/stub_code_compiler_riscv.cc +++ b/runtime/vm/compiler/stub_code_compiler_riscv.cc @@ -619,6 +619,20 @@ void StubCodeCompiler::GenerateCallStaticFunctionStub() { Address(SP, 1 * target::kWordSize)); // Preserve args descriptor. __ sx(ZR, Address(SP, 0 * target::kWordSize)); // Result slot. __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); +#if defined(DART_PRECOMPILED_RUNTIME) && defined(DART_SHOREBIRD_INTERPRETER) + __ lx(FUNCTION_REG, Address(SP, 0 * target::kWordSize)); // Result. + __ lx(ARGS_DESC_REG, + Address(SP, 1 * target::kWordSize)); // Restore args descriptor. + __ addi(SP, SP, 2 * target::kWordSize); + __ LeaveStubFrame(); + // Jump through Function::entry_point so bytecode-attached functions enter + // the interpreter without rewriting executable AOT instructions. + __ LoadCompressedFieldFromOffset(CODE_REG, FUNCTION_REG, + target::Function::code_offset()); + __ LoadFieldFromOffset(TMP, FUNCTION_REG, + target::Function::entry_point_offset()); + __ jr(TMP); +#else __ lx(CODE_REG, Address(SP, 0 * target::kWordSize)); // Result. __ lx(ARGS_DESC_REG, Address(SP, 1 * target::kWordSize)); // Restore args descriptor. @@ -627,6 +641,7 @@ void StubCodeCompiler::GenerateCallStaticFunctionStub() { // Jump to the dart function. __ LoadFieldFromOffset(TMP, CODE_REG, target::Code::entry_point_offset()); __ jr(TMP); +#endif } // Called from a static call only when an invalid code has been entered diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc index 2f147baab1e..443d66c4116 100644 --- a/runtime/vm/compiler/stub_code_compiler_x64.cc +++ b/runtime/vm/compiler/stub_code_compiler_x64.cc @@ -804,6 +804,16 @@ void StubCodeCompiler::GenerateCallStaticFunctionStub() { // Setup space on stack for return value. __ pushq(Immediate(0)); __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); +#if defined(DART_PRECOMPILED_RUNTIME) && defined(DART_SHOREBIRD_INTERPRETER) + __ popq(FUNCTION_REG); // Get Function object result. + __ popq(ARGS_DESC_REG); // Restore arguments descriptor array. + // Remove the stub frame as we are about to jump to the dart function. + __ LeaveStubFrame(); + + __ LoadCompressed( + CODE_REG, FieldAddress(FUNCTION_REG, target::Function::code_offset())); + __ jmp(FieldAddress(FUNCTION_REG, target::Function::entry_point_offset())); +#else __ popq(CODE_REG); // Get Code object result. __ popq(ARGS_DESC_REG); // Restore arguments descriptor array. // Remove the stub frame as we are about to jump to the dart function. @@ -811,6 +821,7 @@ void StubCodeCompiler::GenerateCallStaticFunctionStub() { __ movq(RBX, FieldAddress(CODE_REG, target::Code::entry_point_offset())); __ jmp(RBX); +#endif } // Called from a static call only when an invalid code has been entered @@ -1606,7 +1617,7 @@ void StubCodeCompiler::GenerateInvokeDartCodeStub() { // RDX : address of first argument. // RCX : current thread. void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub() { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) __ EnterFrame(0); const Register kTargetReg = CallingConventions::kArg1Reg; @@ -1750,7 +1761,7 @@ void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub() { #else __ Stop("Not using Dart dynamic modules"); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // Helper to generate space allocation of context stub. @@ -3022,7 +3033,7 @@ void StubCodeCompiler::GenerateLazyCompileStub() { // ARGS_DESC_REG: Arguments descriptor. // FUNCTION_REG: Function. void StubCodeCompiler::GenerateInterpretCallStub() { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) __ EnterStubFrame(); @@ -3106,7 +3117,7 @@ void StubCodeCompiler::GenerateInterpretCallStub() { #else __ Stop("Not using Dart dynamic modules"); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // RBX: Contains an ICData. diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc index 586c517f7ef..773a33d7074 100644 --- a/runtime/vm/dart_api_impl.cc +++ b/runtime/vm/dart_api_impl.cc @@ -39,6 +39,7 @@ #include "vm/heap/verifier.h" #include "vm/image_snapshot.h" #include "vm/isolate_reload.h" +#include "vm/json_stream.h" #include "vm/kernel_isolate.h" #include "vm/lockers.h" #include "vm/mach_o.h" @@ -5600,7 +5601,7 @@ DART_EXPORT Dart_Handle Dart_LoadScriptFromKernel(const uint8_t* buffer, DART_EXPORT Dart_Handle Dart_LoadScriptFromBytecode(const uint8_t* buffer, intptr_t buffer_size) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) DARTSCOPE(Thread::Current()); API_TIMELINE_DURATION(T); StackZone zone(T); @@ -5634,9 +5635,9 @@ DART_EXPORT Dart_Handle Dart_LoadScriptFromBytecode(const uint8_t* buffer, return Api::NewHandle(T, library.ptr()); #else return Api::NewError( - "%s: Cannot load bytecode as dynamic modules are disabled.", + "%s: Cannot load bytecode because the bytecode interpreter is disabled.", CURRENT_FUNC); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } DART_EXPORT DART_API_WARN_UNUSED_RESULT Dart_Handle @@ -5998,7 +5999,7 @@ DART_EXPORT Dart_Handle Dart_LoadLibrary(Dart_Handle kernel_buffer) { DART_EXPORT Dart_Handle Dart_LoadLibraryFromBytecode(Dart_Handle bytecode_buffer) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) DARTSCOPE(Thread::Current()); const ExternalTypedData& td = Api::UnwrapExternalTypedDataHandle(Z, bytecode_buffer); @@ -6014,9 +6015,101 @@ Dart_LoadLibraryFromBytecode(Dart_Handle bytecode_buffer) { return Api::NewHandle(T, Class::Handle(function.Owner()).library()); #else return Api::NewError( - "%s: Cannot load bytecode as dynamic modules are disabled.", + "%s: Cannot load bytecode because the bytecode interpreter is disabled.", CURRENT_FUNC); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) +} + +DART_EXPORT Dart_Handle +Dart_ReloadBytecodePatch(const uint8_t* bytecode_buffer, + intptr_t bytecode_buffer_size) { +#if defined(DART_SHOREBIRD_INTERPRETER) && defined(DART_BYTECODE_INTERPRETER) && \ + defined(DART_PRECOMPILED_RUNTIME) + Thread* thread = Thread::Current(); + DARTSCOPE(thread); + API_TIMELINE_DURATION(thread); + + if (bytecode_buffer == nullptr) { + RETURN_NULL_ERROR(bytecode_buffer); + } + if (bytecode_buffer_size <= 0) { + return Api::NewError("Bytecode patch buffer must not be empty."); + } + if (!Dart_IsBytecode(bytecode_buffer, bytecode_buffer_size)) { + return Api::NewError( + "Bytecode patch buffer is not a Dart bytecode program."); + } + + uint8_t* owned_buffer = reinterpret_cast( + malloc(Utils::Maximum(bytecode_buffer_size, 1))); + if (owned_buffer == nullptr) { + return Api::NewError("Failed to allocate Dart bytecode patch buffer."); + } + memmove(owned_buffer, bytecode_buffer, bytecode_buffer_size); + + const ExternalTypedData& typed_data = ExternalTypedData::Handle( + thread->zone(), ExternalTypedData::New(kExternalTypedDataUint8ArrayCid, + owned_buffer, + bytecode_buffer_size)); + intptr_t installed_functions = 0; + { + SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock()); + bytecode::BytecodeLoader loader(thread, typed_data); + installed_functions = loader.LoadBytecodePatch(); + } + + if (installed_functions == 0) { + free(owned_buffer); + return Api::NewError( + "Dart bytecode patch did not match any loaded app functions."); + } + return Api::Success(); +#elif defined(DART_SUPPORT_RELOAD) && defined(DART_BYTECODE_INTERPRETER) + Thread* thread = Thread::Current(); + DARTSCOPE(thread); + API_TIMELINE_DURATION(thread); + + if (bytecode_buffer == nullptr) { + RETURN_NULL_ERROR(bytecode_buffer); + } + if (bytecode_buffer_size <= 0) { + return Api::NewError("Bytecode patch buffer must not be empty."); + } + if (!Dart_IsBytecode(bytecode_buffer, bytecode_buffer_size)) { + return Api::NewError( + "Bytecode patch buffer is not a Dart bytecode program."); + } + + IsolateGroup* isolate_group = thread->isolate_group(); + CHECK_ISOLATE_GROUP(isolate_group); + if (isolate_group->IsReloading()) { + return Api::NewError("A Dart bytecode patch reload is already active."); + } + if (!isolate_group->CanReload()) { + return Api::NewError( + "The current isolate group cannot apply a Dart bytecode patch reload."); + } + + uint8_t* owned_buffer = reinterpret_cast( + malloc(Utils::Maximum(bytecode_buffer_size, 1))); + if (owned_buffer == nullptr) { + return Api::NewError("Failed to allocate Dart bytecode patch buffer."); + } + memmove(owned_buffer, bytecode_buffer, bytecode_buffer_size); + + JSONStream js; + const bool success = isolate_group->ReloadKernel( + &js, /*force_reload=*/false, owned_buffer, bytecode_buffer_size); + if (!success) { + return Api::NewError("Dart bytecode patch reload failed: %s", + js.ToCString()); + } + return Api::Success(); +#else + return Api::NewError( + "%s: Dart bytecode patch reload is not enabled in this VM.", + CURRENT_FUNC); +#endif // defined(DART_SUPPORT_RELOAD) && defined(DART_BYTECODE_INTERPRETER) } // Finalizes classes and invokes Dart core library function that completes @@ -7297,6 +7390,18 @@ Dart_AotPatchKeyCallback g_aot_patch_key_callback = nullptr; #endif #if defined(DART_ENABLE_AOT_PATCHING) +static constexpr const char* kAotPatchRuntimeModeNativeAot = "native-aot"; +static constexpr const char* kAotPatchRuntimeModeInterpreter = + "dart-bytecode-interpreter"; +static constexpr const char* kAotPatchRuntimeModeDynamicModules = + "dart-dynamic-modules"; +static constexpr const char* kAotPatchRuntimeModeDynamicModulesLegacy = + "dynamic-modules"; +static constexpr const char* kAotPatchPayloadKindEmpty = "empty"; +static constexpr const char* kAotPatchPayloadKindFullSnapshot = + "full-snapshot"; +static constexpr const char* kAotPatchPayloadKindBinaryDiff = "binary-diff-v1"; + struct AotPatchJsonString { const char* chars; intptr_t length; @@ -7404,6 +7509,154 @@ static char* CopyAotPatchJsonString(Thread* thread, return copy; } +static bool AotPatchRuntimeModeNameEquals(const char* actual, + const char* expected) { + return actual != nullptr && strcmp(actual, expected) == 0; +} + +static bool IsAotPatchRuntimeModeDynamicModules(const char* runtime_mode) { + return AotPatchRuntimeModeNameEquals(runtime_mode, + kAotPatchRuntimeModeDynamicModules) || + AotPatchRuntimeModeNameEquals( + runtime_mode, kAotPatchRuntimeModeDynamicModulesLegacy); +} + +static bool IsAotPatchRuntimeModeDynamicModules( + const AotPatchJsonString& runtime_mode) { + return AotPatchJsonStringEquals(runtime_mode, + kAotPatchRuntimeModeDynamicModules) || + AotPatchJsonStringEquals(runtime_mode, + kAotPatchRuntimeModeDynamicModulesLegacy); +} + +static bool IsAotPatchRuntimeModeInterpreter(const char* runtime_mode) { + return AotPatchRuntimeModeNameEquals(runtime_mode, + kAotPatchRuntimeModeInterpreter); +} + +static bool IsAotPatchRuntimeModeInterpreter( + const AotPatchJsonString& runtime_mode) { + return AotPatchJsonStringEquals(runtime_mode, + kAotPatchRuntimeModeInterpreter); +} + +static bool IsAotPatchRuntimeModeSupported(const char* runtime_mode) { + return AotPatchRuntimeModeNameEquals(runtime_mode, + kAotPatchRuntimeModeNativeAot) || + AotPatchRuntimeModeNameEquals(runtime_mode, + kAotPatchRuntimeModeInterpreter); +} + +static bool IsAotPatchRuntimeModeSupported( + const AotPatchJsonString& runtime_mode) { + return AotPatchJsonStringEquals(runtime_mode, + kAotPatchRuntimeModeNativeAot) || + AotPatchJsonStringEquals(runtime_mode, + kAotPatchRuntimeModeInterpreter); +} + +static Dart_Handle ValidateAotPatchRuntimeMode( + const char* json, + intptr_t json_length, + const Dart_AotPatchInstallOptions* options) { + AotPatchJsonString runtime_mode; + const bool has_runtime_mode = + FindAotPatchJsonString(json, json_length, "runtime_mode", &runtime_mode); + + if (options->runtime_mode != nullptr) { + if (IsAotPatchRuntimeModeDynamicModules(options->runtime_mode)) { + return Api::NewError( + "DART_DYNAMIC_MODULES is not supported for AOT patch artifacts."); + } + if (!IsAotPatchRuntimeModeSupported(options->runtime_mode)) { + return Api::NewError("Unsupported AOT patch runtime mode \"%s\".", + options->runtime_mode); + } + if (has_runtime_mode) { + if (!AotPatchJsonStringEquals(runtime_mode, options->runtime_mode)) { + return Api::NewError( + "AOT patch artifact field \"runtime_mode\" does not match."); + } + } else if (!AotPatchRuntimeModeNameEquals(options->runtime_mode, + kAotPatchRuntimeModeNativeAot)) { + return Api::NewError( + "AOT patch artifact is missing field " + "\"runtime_mode\"."); + } + } + + if (has_runtime_mode) { + if (IsAotPatchRuntimeModeDynamicModules(runtime_mode)) { + return Api::NewError( + "DART_DYNAMIC_MODULES is not supported for AOT patch artifacts."); + } + if (!IsAotPatchRuntimeModeSupported(runtime_mode)) { + return Api::NewError("Unsupported AOT patch runtime mode."); + } + } + + const bool is_native_aot = + !has_runtime_mode || + AotPatchJsonStringEquals(runtime_mode, kAotPatchRuntimeModeNativeAot); + if (strcmp(options->target_os, "ios") == 0 && is_native_aot) { + return Api::NewError( + "iOS AOT patches must use the no-DDM interpreter runtime mode."); + } + return Api::Success(); +} + +static bool IsAotPatchPayloadKindSupported( + const AotPatchJsonString& payload_kind) { + return AotPatchJsonStringEquals(payload_kind, kAotPatchPayloadKindEmpty) || + AotPatchJsonStringEquals(payload_kind, + kAotPatchPayloadKindFullSnapshot) || + AotPatchJsonStringEquals(payload_kind, + kAotPatchPayloadKindBinaryDiff); +} + +static bool AotPatchEffectiveRuntimeModeIsInterpreter( + const char* json, + intptr_t json_length, + const Dart_AotPatchInstallOptions* options) { + if (options->runtime_mode != nullptr) { + return IsAotPatchRuntimeModeInterpreter(options->runtime_mode); + } + + AotPatchJsonString runtime_mode; + return FindAotPatchJsonString(json, json_length, "runtime_mode", + &runtime_mode) && + IsAotPatchRuntimeModeInterpreter(runtime_mode); +} + +static Dart_Handle ValidateAotPatchPayloadKind( + const char* json, + intptr_t json_length, + const Dart_AotPatchInstallOptions* options) { + const bool is_interpreter = + AotPatchEffectiveRuntimeModeIsInterpreter(json, json_length, options); + AotPatchJsonString payload_kind; + if (!FindAotPatchJsonString(json, json_length, "payload_kind", + &payload_kind)) { + if (is_interpreter) { + return Api::NewError( + "Dart bytecode interpreter AOT patches must declare payload_kind " + "\"full-snapshot\"."); + } + return Api::Success(); + } + if (!IsAotPatchPayloadKindSupported(payload_kind)) { + return Api::NewError("Unsupported AOT patch payload kind."); + } + if (is_interpreter && + !AotPatchJsonStringEquals(payload_kind, + kAotPatchPayloadKindFullSnapshot)) { + return Api::NewError( + "Dart bytecode interpreter AOT patches must use payload_kind " + "\"full-snapshot\" until runtime reconstruction is available."); + } + return Api::Success(); +} + struct AotPatchOwnedBuffer { uint8_t* data = nullptr; intptr_t length = 0; @@ -7518,7 +7771,9 @@ static Dart_Handle BuildAotPatchMetadataAad(const char* json, APPEND_FIELD("flavor_id", true); APPEND_FIELD("license_type", true); APPEND_FIELD("obfuscation_map_hash", false); + APPEND_FIELD("offline_expires_at", false); APPEND_FIELD("patch_snapshot_hash", true); + APPEND_FIELD("runtime_mode", false); APPEND_FIELD("sdk_hash", true); APPEND_FIELD("target_arch", true); APPEND_FIELD("target_os", true); @@ -7635,6 +7890,10 @@ Dart_InstallAotPatch(const uint8_t* patch_buffer, options->obfuscation_map_hash); if (Api::IsError(result)) return result; } + result = ValidateAotPatchRuntimeMode(json, patch_buffer_length, options); + if (Api::IsError(result)) return result; + result = ValidateAotPatchPayloadKind(json, patch_buffer_length, options); + if (Api::IsError(result)) return result; AotPatchJsonString key_id; if (!FindAotPatchJsonString(json, patch_buffer_length, "key_id", &key_id)) { diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc index d2e0c746680..ceb5ffa9432 100644 --- a/runtime/vm/dart_api_impl_test.cc +++ b/runtime/vm/dart_api_impl_test.cc @@ -10959,6 +10959,40 @@ TEST_CASE(DartAPI_AotPatchingConfiguration) { "tag_base64": "W8uOg/f+g2SS3Ahxfaeuyg==", "aad_sha256": "1a0c6003fec49bbc26fbaaf0a6dfcd557061b4ae5f22e4b1114afe3b1a8d9796" } +})json"; + const char ios_native_patch[] = R"json({ + "format": "open-aot-vmcode-encrypted-v1", + "metadata": { + "app_id": "app.test", + "app_build_id": "1", + "base_flavor_id": "free", + "base_license_type": "free", + "flavor_id": "pro", + "license_type": "pro", + "sdk_hash": "sdk", + "base_snapshot_hash": "cae662172fd450bb0cd710a769079c05bfc5d8e35efa6576edc7d0377afdd4a2", + "patch_snapshot_hash": "05d9426b9dd03e5cc3404aab6c7c45ac24e0b90e840f4bd6da83c342430533dc", + "target_os": "ios", + "target_arch": "arm64" + } +})json"; + const char ios_interpreter_compact_patch[] = R"json({ + "format": "open-aot-vmcode-encrypted-v1", + "metadata": { + "app_id": "app.test", + "app_build_id": "1", + "base_flavor_id": "free", + "base_license_type": "free", + "flavor_id": "pro", + "license_type": "pro", + "sdk_hash": "sdk", + "base_snapshot_hash": "cae662172fd450bb0cd710a769079c05bfc5d8e35efa6576edc7d0377afdd4a2", + "patch_snapshot_hash": "05d9426b9dd03e5cc3404aab6c7c45ac24e0b90e840f4bd6da83c342430533dc", + "target_os": "ios", + "target_arch": "arm64", + "runtime_mode": "dart-bytecode-interpreter" + }, + "payload_kind": "binary-diff-v1" })json"; Dart_AotPatchInstallOptions options = {}; options.app_id = "app.test"; @@ -10987,6 +11021,35 @@ TEST_CASE(DartAPI_AotPatchingConfiguration) { EXPECT_EQ(13, patch_payload_length); EXPECT_EQ(0, memcmp("patch-payload", patch_payload, patch_payload_length)); Dart_FreeAotPatchPayload(patch_payload); + + Dart_AotPatchInstallOptions ios_options = options; + ios_options.target_os = "ios"; + ios_options.target_arch = "arm64"; + ios_options.runtime_mode = "native-aot"; + result = + Dart_InstallAotPatch(reinterpret_cast(ios_native_patch), + strlen(ios_native_patch), &ios_options, + &patch_payload, &patch_payload_length); + EXPECT_ERROR(result, + "iOS AOT patches must use the no-DDM interpreter runtime mode"); + + Dart_AotPatchInstallOptions ios_interpreter_options = ios_options; + ios_interpreter_options.runtime_mode = "dart-bytecode-interpreter"; + result = Dart_InstallAotPatch( + reinterpret_cast(ios_interpreter_compact_patch), + strlen(ios_interpreter_compact_patch), &ios_interpreter_options, + &patch_payload, &patch_payload_length); + EXPECT_ERROR(result, + "Dart bytecode interpreter AOT patches must use payload_kind " + "\"full-snapshot\""); + + Dart_AotPatchInstallOptions dynamic_modules_options = options; + dynamic_modules_options.runtime_mode = "dart-dynamic-modules"; + result = Dart_InstallAotPatch(reinterpret_cast(patch), + strlen(patch), &dynamic_modules_options, + &patch_payload, &patch_payload_length); + EXPECT_ERROR(result, + "DART_DYNAMIC_MODULES is not supported for AOT patch artifacts"); Dart_SetAotPatchKeyCallback(nullptr); #else EXPECT(!Dart_AotPatchingEnabled()); @@ -10997,6 +11060,22 @@ TEST_CASE(DartAPI_AotPatchingConfiguration) { #endif } +TEST_CASE(DartAPI_BytecodePatchReloadConfiguration) { +#if defined(DART_SUPPORT_RELOAD) && defined(DART_BYTECODE_INTERPRETER) + Dart_Handle result = Dart_ReloadBytecodePatch(nullptr, 0); + EXPECT_ERROR(result, "bytecode_buffer"); + + const uint8_t invalid_patch[] = {0x00, 0x01, 0x02, 0x03}; + result = Dart_ReloadBytecodePatch(invalid_patch, sizeof(invalid_patch)); + EXPECT_ERROR(result, "not a Dart bytecode program"); +#else + const uint8_t invalid_patch[] = {0x00, 0x01, 0x02, 0x03}; + Dart_Handle result = + Dart_ReloadBytecodePatch(invalid_patch, sizeof(invalid_patch)); + EXPECT_ERROR(result, "Dart bytecode patch reload is not enabled"); +#endif +} + TEST_CASE(DartAPI_UserTags) { Dart_Handle default_tag = Dart_GetDefaultUserTag(); EXPECT_VALID(default_tag); diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc index e10e872f1b0..21f51adab97 100644 --- a/runtime/vm/dart_entry.cc +++ b/runtime/vm/dart_entry.cc @@ -139,14 +139,14 @@ ObjectPtr DartEntry::InvokeFunction(const Function& function, ASSERT(thread->IsDartMutatorThread()); ASSERT(!function.IsNull()); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (function.IsInterpreted()) { // SuspendLongJumpScope suspend_long_jump_scope(thread); TransitionToGenerated transition(thread); return Interpreter::Current()->Call(function, arguments_descriptor, arguments, thread); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) #if !defined(DART_PRECOMPILED_RUNTIME) if (!function.HasCode()) { diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc index e8e80e2e794..9f6bee69915 100644 --- a/runtime/vm/debugger.cc +++ b/runtime/vm/debugger.cc @@ -500,7 +500,7 @@ ActivationFrame::Relation ActivationFrame::CompareTo(bool is_interpreted, if (fp == other_fp) { return kSelf; } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (is_interpreted) { // Unlike compiled code, interpreted stacks grow towards higher addresses. return fp > other_fp ? kCallee : kCaller; @@ -641,7 +641,7 @@ void ActivationFrame::PrintContextLevelError(const char* message) { OS::PrintErr("context_level_ %" Px "\n", context_level_); OS::PrintErr("token_pos_ %s\n", token_pos_.ToCString()); if (IsInterpreted() && bytecode().HasLocalVariablesInfo()) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) Zone* const zone = Thread::Current()->zone(); ZoneTextBuffer buffer(zone); KernelBytecodeDisassembler::PrintLocalVariablesInfo( @@ -672,7 +672,7 @@ intptr_t ActivationFrame::ContextLevel() { ASSERT(IsInterpreted() || !code().is_optimized()); bool found = false; if (IsInterpreted()) { -#if defined(DART_DYNAMIC_MODULES) && !defined(PRODUCT) && \ +#if defined(DART_BYTECODE_INTERPRETER) && !defined(PRODUCT) && \ !defined(DART_PRECOMPILED_RUNTIME) const intptr_t pc_offset = pc() - PayloadStart(); DEBUG_ONLY(intptr_t closest_start = 0); @@ -1475,7 +1475,7 @@ CodeBreakpoint::~CodeBreakpoint() { void CodeBreakpoint::Enable() { if (enabled_count_ == 0) { if (bytecode_ != Bytecode::null()) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) ASSERT_EQUAL(saved_opcode_, kMaxUint32); saved_opcode_ = BytecodePatcher::AddBreakpointAt(pc_, Bytecode::Handle(bytecode_)); @@ -1492,7 +1492,7 @@ void CodeBreakpoint::Enable() { void CodeBreakpoint::Disable() { if (enabled_count_ == 1) { if (bytecode_ != Bytecode::null()) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) BytecodePatcher::RemoveBreakpointAt(pc_, Bytecode::Handle(bytecode_), saved_opcode_); saved_opcode_ = kMaxUint32; @@ -2318,11 +2318,11 @@ static TokenPosition ResolveBreakpointPos(const Function& func, Zone* zone = Thread::Current()->zone(); Script& script = Script::Handle(zone, func.script()); PcDescriptors& desc = PcDescriptors::Handle(zone); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) auto& bytecode = Bytecode::Handle(zone); #endif if (func.HasBytecode()) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) bytecode = func.GetBytecode(); ASSERT(!bytecode.IsNull()); if (!bytecode.HasSourcePositions()) { @@ -2345,7 +2345,7 @@ static TokenPosition ResolveBreakpointPos(const Function& func, intptr_t best_line = INT_MAX; if (func.HasBytecode()) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) // Only compiled code has synthetic token positions. ASSERT(!requested_token_pos.IsSynthetic()); bytecode::BytecodeSourcePositionsIterator iter(zone, bytecode); @@ -2424,7 +2424,7 @@ static TokenPosition ResolveBreakpointPos(const Function& func, uword lowest_pc_offset = kUwordMax; if (func.HasBytecode()) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) bytecode::BytecodeSourcePositionsIterator iter(zone, bytecode); while (iter.MoveNext()) { const TokenPosition& pos = iter.TokenPos(); @@ -2528,7 +2528,7 @@ void GroupDebugger::MakeCodeBreakpointAtUnsafe(Thread* thread, // Find the safe point with the lowest compiled code address // that maps to the token position of the source breakpoint. if (func.HasBytecode()) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) bytecode = func.GetBytecode(); ASSERT(!bytecode.IsNull()); if (!bytecode.HasSourcePositions()) { @@ -3497,7 +3497,7 @@ void Debugger::EnterSingleStepMode() { void Debugger::ResetSteppingFramePointer() { stepping_fp_ = 0; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) stepping_fp_from_interpreted_frame_ = false; #endif } @@ -3533,7 +3533,7 @@ bool Debugger::MatchesLastSteppingInformation(ActivationFrame* frame) { void Debugger::SetSyncSteppingFramePointer(ActivationFrame* frame) { stepping_fp_ = frame->fp(); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) stepping_fp_from_interpreted_frame_ = frame->IsInterpreted(); #endif } @@ -3963,7 +3963,7 @@ static bool IsAtAsyncJump(ActivationFrame* top_frame) { return false; } if (top_frame->IsInterpreted()) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const auto& bytecode = top_frame->bytecode(); ASSERT(bytecode.HasSourcePositions()); const uword pc_offset = top_frame->pc() - bytecode.PayloadStart(); @@ -3998,7 +3998,7 @@ static bool IsAtAsyncJump(ActivationFrame* top_frame) { return false; } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) static ActivationFrame::Relation CompareTopDartFrameTo(uword other_fp, bool is_interpreted) { StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames, @@ -4041,7 +4041,7 @@ ErrorPtr Debugger::PauseStepping() { // interested in. If we saved the frame pointer of a stack frame // the user is interested in, we ignore the single step if we are // in a callee of that frame. -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) auto const relation = stepping_fp_from_interpreted_frame_ == frame->IsInterpreted() ? frame->CompareTo(stepping_fp_) diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h index 8f19de89116..69f20cb77b2 100644 --- a/runtime/vm/debugger.h +++ b/runtime/vm/debugger.h @@ -218,7 +218,7 @@ class CodeBreakpoint { // Used by GroupDebugger to find CodeBreakpoint associated with // particular function. FunctionPtr function() const { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (bytecode_ != Bytecode::null()) { return Bytecode::Handle(bytecode_).function(); } @@ -1011,7 +1011,7 @@ class Debugger { // frame corresponds to this fp value, or if the top frame is // lower on the stack. uword stepping_fp_; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) bool stepping_fp_from_interpreted_frame_ = false; #endif diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc index 9adf2ed8e2f..4bf102312de 100644 --- a/runtime/vm/exceptions.cc +++ b/runtime/vm/exceptions.cc @@ -587,13 +587,13 @@ NO_SANITIZE_SAFE_STACK // This function manipulates the safestack pointer. // in the previous frames. StackResource::Unwind(thread); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) Interpreter* interpreter = thread->interpreter(); if ((interpreter != nullptr) && interpreter->HasFrame(frame_pointer)) { interpreter->JumpToFrame(program_counter, stack_pointer, frame_pointer, thread); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) // If execution exited generated code through FFI then exit the safepoint // and transition back to kThreadInGenerated execution state. JumpToFrame diff --git a/runtime/vm/ffi_trampolines_arm64.S b/runtime/vm/ffi_trampolines_arm64.S index db4d4a791b1..cc25bc2b512 100644 --- a/runtime/vm/ffi_trampolines_arm64.S +++ b/runtime/vm/ffi_trampolines_arm64.S @@ -12,11 +12,11 @@ #define LOCAL_SYMBOL(x) .L##x #endif -#if defined(__aarch64__) && (defined(SIMULATOR_FFI) || (defined(DART_DYNAMIC_MODULES) && !defined(DART_PRECOMPILED_RUNTIME))) +#if defined(__aarch64__) && (defined(SIMULATOR_FFI) || (defined(DART_BYTECODE_INTERPRETER) && !defined(DART_PRECOMPILED_RUNTIME))) .text -#if defined(DART_DYNAMIC_MODULES) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_BYTECODE_INTERPRETER) && !defined(DART_PRECOMPILED_RUNTIME) #if defined(__APPLE__) .globl _FfiCallTrampoline @@ -73,7 +73,7 @@ LOCAL_SYMBOL(copy1): .size FfiCallTrampoline,.-FfiCallTrampoline #endif -#endif // defined(DART_DYNAMIC_MODULES) && !defined(DART_PRECOMPILED_RUNTIME) +#endif // defined(DART_BYTECODE_INTERPRETER) && !defined(DART_PRECOMPILED_RUNTIME) #if defined(SIMULATOR_FFI) @@ -216,4 +216,4 @@ SimulatorFfiCallbackTrampolineEnd: #endif // defined(SIMULATOR_FFI) -#endif // defined(__aarch64__) && (defined(SIMULATOR_FFI) || (defined(DART_DYNAMIC_MODULES) && !defined(DART_PRECOMPILED_RUNTIME))) +#endif // defined(__aarch64__) && (defined(SIMULATOR_FFI) || (defined(DART_BYTECODE_INTERPRETER) && !defined(DART_PRECOMPILED_RUNTIME))) diff --git a/runtime/vm/gdb_helpers.cc b/runtime/vm/gdb_helpers.cc index 8cf64bf5a4d..5a245b4ee74 100644 --- a/runtime/vm/gdb_helpers.cc +++ b/runtime/vm/gdb_helpers.cc @@ -87,7 +87,7 @@ void _printGeneratedStackTrace(uword fp, uword sp, uword pc) { } } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) // Like _printDartStackTrace, but works in the interpreter loop. // Must be called with the current interpreter fp, sp, and pc. // Note that sp[0] is not modified, but sp[1] will be trashed. @@ -107,7 +107,7 @@ void _printInterpreterStackTrace(ObjectPtr* fp, thread->set_execution_state(Thread::kThreadInGenerated); thread->set_top_exit_frame_info(0); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) class PrintObjectPointersVisitor : public ObjectPointerVisitor { public: diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h index dfe3945167e..b5b5b3acbac 100644 --- a/runtime/vm/globals.h +++ b/runtime/vm/globals.h @@ -87,6 +87,26 @@ const intptr_t kDefaultNewGenSemiMaxSize = (kWordSize <= 4) ? 8 : 16; #error DART_PRECOMPILED_RUNTIME and DART_NOSNAPSHOT are mutually exclusive #endif // defined(DART_PRECOMPILED_RUNTIME) && defined(DART_NOSNAPSHOT) +#if defined(DART_DYNAMIC_MODULES) && defined(DART_SHOREBIRD_INTERPRETER) +#error DART_DYNAMIC_MODULES and DART_SHOREBIRD_INTERPRETER are mutually exclusive +#endif + +#if (defined(DART_DYNAMIC_MODULES) || defined(DART_SHOREBIRD_INTERPRETER)) && \ + !defined(DART_BYTECODE_INTERPRETER) +#define DART_BYTECODE_INTERPRETER 1 +#endif + +#if defined(DART_SHOREBIRD_INTERPRETER) && \ + defined(DART_BYTECODE_INTERPRETER) && !defined(PRODUCT) && \ + !defined(DART_PRECOMPILED_RUNTIME) +#define DART_ENABLE_BYTECODE_PATCH_RELOAD 1 +#endif + +#if defined(DART_ENABLE_BYTECODE_PATCH_RELOAD) || \ + (!defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)) +#define DART_SUPPORT_RELOAD 1 +#endif + #if defined(DART_PRECOMPILED_RUNTIME) #define NOT_IN_PRECOMPILED(code) #define ONLY_IN_PRECOMPILED(code) code diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc index f58905a0935..607de196c16 100644 --- a/runtime/vm/heap/marker.cc +++ b/runtime/vm/heap/marker.cc @@ -734,7 +734,7 @@ void GCMarker::Prologue() { isolate_group_->ReleaseStoreBuffers(); new_marking_stack_.PushAll(tlab_deferred_marking_stack_.PopAll()); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) isolate_group_->ForEachIsolate( [&](Isolate* isolate) { Thread* mutator_thread = isolate->mutator_thread(); @@ -746,7 +746,7 @@ void GCMarker::Prologue() { } }, /*at_safepoint=*/true); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } void GCMarker::Epilogue() {} diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc index fee078fb472..489fc3c06b5 100644 --- a/runtime/vm/interpreter.cc +++ b/runtime/vm/interpreter.cc @@ -6,7 +6,7 @@ #include #include "vm/globals.h" -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) #include "vm/interpreter.h" @@ -44,7 +44,7 @@ DEFINE_FLAG(uint64_t, 100 * MB, "Maximum size in bytes of the interpreter trace file"); -#if defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_SHOREBIRD_INTERPRETER) constexpr bool kDefaultCheckDynamicCalls = true; #else constexpr bool kDefaultCheckDynamicCalls = false; @@ -4827,4 +4827,4 @@ void Interpreter::VisitObjectPointers(ObjectPointerVisitor* visitor) { } // namespace dart -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) diff --git a/runtime/vm/interpreter.h b/runtime/vm/interpreter.h index dfbbde9305c..c2cf7adc64d 100644 --- a/runtime/vm/interpreter.h +++ b/runtime/vm/interpreter.h @@ -6,7 +6,7 @@ #define RUNTIME_VM_INTERPRETER_H_ #include "vm/globals.h" -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) #include "platform/utils.h" #include "vm/class_table.h" @@ -326,6 +326,6 @@ class Interpreter { } // namespace dart -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) #endif // RUNTIME_VM_INTERPRETER_H_ diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc index 52b9a1580f2..83e7cf3531b 100644 --- a/runtime/vm/isolate.cc +++ b/runtime/vm/isolate.cc @@ -70,11 +70,11 @@ DECLARE_FLAG(int, old_gen_growth_time_ratio); // Reload flags. DECLARE_FLAG(int, reload_every); -#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) DECLARE_FLAG(bool, check_reloaded); DECLARE_FLAG(bool, reload_every_back_off); DECLARE_FLAG(bool, trace_reload); -#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#endif // defined(DART_SUPPORT_RELOAD) static void DeterministicModeHandler(bool value) { if (value) { @@ -315,7 +315,7 @@ IsolateGroup::IsolateGroup(std::shared_ptr source, mutators_(), start_time_micros_(OS::GetCurrentMonotonicMicros()), is_system_isolate_group_(source->flags.is_system_isolate), -#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) last_reload_timestamp_(OS::GetCurrentTimeMillis()), reload_every_n_stack_overflow_checks_(FLAG_reload_every), #endif @@ -392,10 +392,10 @@ IsolateGroup::IsolateGroup(std::shared_ptr source, : IsolateGroup(source, embedder_data, nullptr, api_flags) {} IsolateGroup::~IsolateGroup() { -#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) RELEASE_ASSERT(group_reload_context_ == nullptr); RELEASE_ASSERT(program_reload_context_ == nullptr); -#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#endif // defined(DART_SUPPORT_RELOAD) // Ensure we destroy the heap before the other members. heap_ = nullptr; @@ -789,12 +789,12 @@ Bequest::~Bequest() { } void IsolateGroup::RegisterClass(const Class& cls) { -#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) if (IsReloading()) { program_reload_context()->RegisterClass(cls); return; } -#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#endif // defined(DART_SUPPORT_RELOAD) if (cls.IsTopLevel()) { class_table()->RegisterTopLevel(cls); } else { @@ -872,7 +872,7 @@ void IsolateGroup::RegisterStaticField(const Field& field, } void IsolateGroup::FreeStaticField(const Field& field) { -#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) // This can only be called during hot-reload. ASSERT(program_reload_context() != nullptr); #endif @@ -1385,7 +1385,7 @@ ErrorPtr IsolateMessageHandler::HandleLibMessage(const Array& message) { } case Isolate::kCheckForReload: { // [ OOB, kCheckForReload, ignored ] -#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) { ReloadParticipationScope allow_reload(T); T->CheckForSafepoint(); @@ -2075,7 +2075,7 @@ void Isolate::BuildName(const char* name_prefix) { } } -#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) bool IsolateGroup::CanReload() { // We only call this method on the mutator thread. Normally the caller is // inside of the "reloadSources" service OOB message handler. Though @@ -2172,7 +2172,7 @@ void IsolateGroup::DeleteReloadContext() { delete program_reload_context_; program_reload_context_ = nullptr; } -#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#endif // defined(DART_SUPPORT_RELOAD) const char* Isolate::MakeRunnable() { MutexLocker ml(&mutex_); @@ -2565,7 +2565,7 @@ void Isolate::LowLevelShutdown() { } } -#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) void IsolateGroup::MaybeIncreaseReloadEveryNStackOverflowChecks() { if (FLAG_reload_every_back_off) { if (reload_every_n_stack_overflow_checks_ < 5000) { @@ -2580,7 +2580,7 @@ void IsolateGroup::MaybeIncreaseReloadEveryNStackOverflowChecks() { } } } -#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#endif // defined(DART_SUPPORT_RELOAD) void Isolate::Shutdown() { Thread* thread = Thread::Current(); @@ -2601,7 +2601,7 @@ void Isolate::Shutdown() { #endif } -#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) if (FLAG_check_reloaded && is_runnable() && !Isolate::IsSystemIsolate(this)) { if (!group()->HasAttemptedReload()) { FATAL( @@ -2609,7 +2609,7 @@ void Isolate::Shutdown() { "--check-reloaded is enabled.\n"); } } -#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#endif // defined(DART_SUPPORT_RELOAD) // Then, proceed with low-level teardown. Isolate::UnMarkIsolateReady(this); @@ -2985,13 +2985,13 @@ void IsolateGroup::VisitSharedPointers(ObjectPointerVisitor* visitor, #endif break; case kReloadContext: -#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) if (program_reload_context() != nullptr) { program_reload_context()->VisitObjectPointers(visitor); program_reload_context()->group_reload_context()->VisitObjectPointers( visitor); } -#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#endif // defined(DART_SUPPORT_RELOAD) break; case kLoadedBlobs: if (source()->loaded_blobs_ != nullptr) { diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h index e5e6f00ee41..d08b8e6fdb2 100644 --- a/runtime/vm/isolate.h +++ b/runtime/vm/isolate.h @@ -523,8 +523,7 @@ class IsolateGroup : public IntrusiveDListEntry { isolate_group_flags_.UpdateBool(value); } -#if !defined(PRODUCT) -#if !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) bool HasAttemptedReload() const { return isolate_group_flags_.Read(); } @@ -537,8 +536,7 @@ class IsolateGroup : public IntrusiveDListEntry { } #else bool HasAttemptedReload() const { return false; } -#endif // !defined(DART_PRECOMPILED_RUNTIME) -#endif // !defined(PRODUCT) +#endif // defined(DART_SUPPORT_RELOAD) bool has_seen_oom() const { return isolate_group_flags_.Read(); @@ -587,9 +585,9 @@ class IsolateGroup : public IntrusiveDListEntry { Mutex* unlinked_call_map_mutex() { return &unlinked_call_map_mutex_; } #endif -#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) Mutex* initializer_functions_mutex() { return &initializer_functions_mutex_; } -#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) SafepointRwLock* shared_field_initializer_rwlock() { return &shared_field_initializer_rwlock_; @@ -678,7 +676,7 @@ class IsolateGroup : public IntrusiveDListEntry { void PrintMemoryUsageJSON(JSONStream* stream); #endif -#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) // By default the reload context is deleted. This parameter allows // the caller to delete is separately if it is still needed. bool ReloadSources(JSONStream* js, @@ -710,10 +708,10 @@ class IsolateGroup : public IntrusiveDListEntry { bool CanReload(); #else bool CanReload() { return false; } -#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#endif // defined(DART_SUPPORT_RELOAD) bool IsReloading() const { -#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) return group_reload_context_ != nullptr; #else return false; @@ -926,7 +924,7 @@ class IsolateGroup : public IntrusiveDListEntry { bool is_system_isolate_group_; bool bootstrapping_ = true; -#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) int64_t last_reload_timestamp_; std::shared_ptr group_reload_context_; // Per-isolate-group copy of FLAG_reload_every. @@ -992,9 +990,9 @@ class IsolateGroup : public IntrusiveDListEntry { Mutex unlinked_call_map_mutex_; #endif -#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) Mutex initializer_functions_mutex_; -#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) // Ensure exclusive execution of shared field initializers. SafepointRwLock shared_field_initializer_rwlock_; diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc index af2e06af416..468b2d6f5ac 100644 --- a/runtime/vm/isolate_reload.cc +++ b/runtime/vm/isolate_reload.cc @@ -11,7 +11,7 @@ #include "vm/bytecode_reader.h" #include "vm/compiler/jit/compiler.h" #include "vm/dart_api_impl.h" -#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) #include "vm/hash.h" #endif #include "vm/hash_table.h" @@ -38,7 +38,7 @@ namespace dart { DEFINE_FLAG(int, reload_every, 0, "Reload every N stack overflow checks."); DEFINE_FLAG(bool, trace_reload, false, "Trace isolate reloading"); -#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) DEFINE_FLAG(bool, trace_reload_verbose, false, @@ -735,7 +735,7 @@ class KernelDeltaProgram : public DeltaProgram { std::unique_ptr kernel_program_; }; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) class BytecodeDeltaProgram : public DeltaProgram { public: explicit BytecodeDeltaProgram(const ExternalTypedData& typed_data) @@ -769,7 +769,7 @@ class BytecodeDeltaProgram : public DeltaProgram { private: bytecode::BytecodeLoader loader_; }; -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) std::unique_ptr DeltaProgram::ReadFromTypedData( const ExternalTypedData& typed_data) { @@ -781,12 +781,12 @@ std::unique_ptr DeltaProgram::ReadFromTypedData( } return std::make_unique(std::move(kernel_program)); } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (Dart_IsBytecode(reinterpret_cast(typed_data.DataAddr(0)), typed_data.LengthInBytes())) { return std::make_unique(typed_data); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) return nullptr; } @@ -2194,12 +2194,12 @@ ErrorPtr ProgramReloadContext::RunInvalidationVisitors() { StackZone stack_zone(thread); Zone* zone = stack_zone.GetZone(); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) Interpreter* interpreter = thread->interpreter(); if (interpreter != nullptr) { interpreter->ClearLookupCache(); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) GrowableArray functions(4 * KB); GrowableArray kernel_infos(KB); @@ -2275,9 +2275,9 @@ void ProgramReloadContext::InvalidateFunctions( Library& owning_lib = Library::Handle(zone); Code& code = Code::Handle(zone); Field& field = Field::Handle(zone); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) Bytecode& bytecode = Bytecode::Handle(zone); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock()); for (intptr_t i = 0; i < functions.length(); i++) { @@ -2316,12 +2316,12 @@ void ProgramReloadContext::InvalidateFunctions( // they're held. resetter.ZeroEdgeCounters(func); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (func.HasBytecode()) { bytecode = func.GetBytecode(); resetter.RebindBytecode(bytecode); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) if (stub_code) { // Nothing to reset. @@ -2925,6 +2925,6 @@ void ProgramReloadContext::RestoreClassHierarchyInvariants() { } } -#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#endif // defined(DART_SUPPORT_RELOAD) } // namespace dart diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h index 4aa2bf5229d..593b2dfb226 100644 --- a/runtime/vm/isolate_reload.h +++ b/runtime/vm/isolate_reload.h @@ -30,7 +30,7 @@ DECLARE_FLAG(bool, trace_reload_verbose); #define VTIR_Print(format, ...) \ if (FLAG_trace_reload_verbose) Log::Current()->Print(format, ##__VA_ARGS__) -#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_SUPPORT_RELOAD) namespace dart { @@ -458,6 +458,6 @@ class CallSiteResetter : public ValueObject { } // namespace dart -#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) +#endif // defined(DART_SUPPORT_RELOAD) #endif // RUNTIME_VM_ISOLATE_RELOAD_H_ diff --git a/runtime/vm/line_starts_reader.cc b/runtime/vm/line_starts_reader.cc index 3606322e608..7391df040b0 100644 --- a/runtime/vm/line_starts_reader.cc +++ b/runtime/vm/line_starts_reader.cc @@ -2,7 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) #include "vm/line_starts_reader.h" #include "vm/object.h" @@ -71,4 +71,4 @@ bool LineStartsReader::TokenRangeAtLine(intptr_t line_number, } // namespace dart -#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) diff --git a/runtime/vm/line_starts_reader.h b/runtime/vm/line_starts_reader.h index ef7828de0e4..1d57941e087 100644 --- a/runtime/vm/line_starts_reader.h +++ b/runtime/vm/line_starts_reader.h @@ -5,7 +5,7 @@ #ifndef RUNTIME_VM_LINE_STARTS_READER_H_ #define RUNTIME_VM_LINE_STARTS_READER_H_ -#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) #include @@ -56,5 +56,5 @@ class LineStartsReader : public ValueObject { } // namespace dart -#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) #endif // RUNTIME_VM_LINE_STARTS_READER_H_ diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h index 5ced9ba6871..8de6cd2b0b0 100644 --- a/runtime/vm/native_arguments.h +++ b/runtime/vm/native_arguments.h @@ -188,7 +188,7 @@ class NativeArguments { friend class NativeEntry; friend class Simulator; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) NativeArguments(Thread* thread, int argc_tag, ObjectPtr* argv, @@ -198,7 +198,7 @@ class NativeArguments { argv_(argv), retval_(retval) {} NativeArguments() = default; -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) // Since this function is passed an ObjectPtr directly, we need to be // exceedingly careful when we use it. If there are any other side diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 6256dba1e6a..5ec3090d0ff 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -469,7 +469,7 @@ static type SpecialCharacter(type value) { return '\0'; } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) static BytecodePtr CreateVMInternalBytecode(KernelBytecode::Opcode opcode) { const KBCInstr* instructions = nullptr; intptr_t instructions_size = 0; @@ -487,7 +487,7 @@ static BytecodePtr CreateVMInternalBytecode(KernelBytecode::Opcode opcode) { #endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) return bytecode.ptr(); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) void Object::InitNullAndBool(IsolateGroup* isolate_group) { Thread* thread = Thread::Current(); @@ -1151,7 +1151,7 @@ void Object::Init(IsolateGroup* isolate_group) { // synthetic_getter_parameter_names_ object needs to be created earlier as // VM isolate snapshot reader references it before Object::FinalizeVMIsolate. -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) Roots::implicit_getter_bytecode().initRO( CreateVMInternalBytecode(KernelBytecode::kVMInternal_ImplicitGetter)); Roots::implicit_setter_bytecode().initRO( @@ -1203,7 +1203,7 @@ void Object::Init(IsolateGroup* isolate_group) { Roots::implicit_static_closure_bytecode().initRO(Bytecode::null()); Roots::implicit_instance_closure_bytecode().initRO(Bytecode::null()); Roots::implicit_constructor_closure_bytecode().initRO(Bytecode::null()); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) Roots::uninitialized_index().initRO( TypedData::New(kTypedDataUint32ArrayCid, @@ -2920,7 +2920,7 @@ ClassPtr Class::New(IsolateGroup* isolate_group, bool register_class) { return result.ptr(); } -#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) static void ReportTooManyTypeArguments(const Class& cls) { Report::MessageF(Report::kError, Script::Handle(cls.script()), cls.token_pos(), Report::AtLocation, @@ -2929,10 +2929,10 @@ static void ReportTooManyTypeArguments(const Class& cls) { String::Handle(cls.Name()).ToCString()); UNREACHABLE(); } -#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) void Class::set_num_type_arguments(intptr_t value) const { -#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) UNREACHABLE(); #else if (!Utils::IsInt(16, value)) { @@ -2944,7 +2944,7 @@ void Class::set_num_type_arguments(intptr_t value) const { DEBUG_ASSERT(old_value == kUnknownNumTypeArguments || old_value == value); StoreNonPointer( &untag()->num_type_arguments_, value); -#endif // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) } void Class::set_num_type_arguments_unsafe(intptr_t value) const { @@ -3781,7 +3781,7 @@ FunctionPtr Class::CreateInvocationDispatcher( signature ^= ClassFinalizer::FinalizeType(signature); invocation.SetSignature(signature); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) #if defined(DART_PRECOMPILED_RUNTIME) const bool attach_bytecode = true; #else @@ -3799,7 +3799,7 @@ FunctionPtr Class::CreateInvocationDispatcher( UNREACHABLE(); } } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) return invocation.ptr(); } @@ -3853,7 +3853,7 @@ FunctionPtr Function::CreateMethodExtractor(const String& getter_name) const { signature ^= ClassFinalizer::FinalizeType(signature); extractor.SetSignature(signature); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) #if defined(DART_PRECOMPILED_RUNTIME) const bool attach_bytecode = true; #else @@ -3873,7 +3873,7 @@ FunctionPtr Function::CreateMethodExtractor(const String& getter_name) const { extractor.AttachBytecode(Object::method_extractor_without_ita_bytecode()); } } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) owner.AddFunction(extractor); @@ -4086,7 +4086,7 @@ StringPtr Function::CreateDynamicInvocationForwarderName(const String& name) { return Symbols::FromConcat(Thread::Current(), Symbols::DynamicPrefix(), name); } -#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) FunctionPtr Function::CreateDynamicInvocationForwarder( const String& mangled_name) const { Thread* thread = Thread::Current(); @@ -4114,7 +4114,7 @@ FunctionPtr Function::CreateDynamicInvocationForwarder( // blocks inlining and can't take Function-s only Code objects. forwarder.set_is_visible(false); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (HasBytecode()) { forwarder.ClearBytecode(); } @@ -4132,7 +4132,7 @@ FunctionPtr Function::CreateDynamicInvocationForwarder( forwarder.InheritKernelOffsetFrom(*this); forwarder.SetForwardingTarget(*this); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) #if defined(DART_PRECOMPILED_RUNTIME) // Allow the creation of a lazily created interpreted dynamic invocation // forwarders for compiled code that does not already have one created, @@ -4273,7 +4273,7 @@ bool Function::NeedsDynamicInvocationForwarder() const { void Function::ReadParameterCovariance( BitVector* is_covariant, BitVector* is_generic_covariant_impl) const { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (is_declared_in_bytecode()) { bytecode::BytecodeReader::ReadParameterCovariance( *this, is_covariant, is_generic_covariant_impl); @@ -4971,7 +4971,7 @@ static ObjectPtr LoadExpressionEvaluationFunction( const ExternalTypedData& kernel_buffer, const Class& klass) { Zone* zone = thread->zone(); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (Dart_IsBytecode( reinterpret_cast(kernel_buffer.DataAddr(0)), kernel_buffer.LengthInBytes())) { @@ -4981,7 +4981,7 @@ static ObjectPtr LoadExpressionEvaluationFunction( loader.LoadBytecode(); return loader.GetExpressionEvaluationFunction(); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) std::unique_ptr kernel_pgm = kernel::Program::ReadFromTypedData(kernel_buffer); @@ -5139,7 +5139,7 @@ ObjectPtr Instance::EvaluateCompiledExpression( void Class::EnsureDeclarationLoaded() const { if (!is_declaration_loaded()) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) // Loading of class declaration can be postponed until needed // if class comes from bytecode. if (is_declared_in_bytecode()) { @@ -5154,7 +5154,7 @@ void Class::EnsureDeclarationLoaded() const { ASSERT(is_type_finalized()); return; } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) #if defined(DART_PRECOMPILED_RUNTIME) UNREACHABLE(); #else @@ -5165,7 +5165,7 @@ void Class::EnsureDeclarationLoaded() const { // Ensure that top level parsing of the class has been done. ErrorPtr Class::EnsureIsFinalized(Thread* thread) const { -#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) RELEASE_ASSERT(is_finalized()); return Error::null(); #else @@ -5191,7 +5191,7 @@ ErrorPtr Class::EnsureIsFinalized(Thread* thread) const { } } return error.ptr(); -#endif // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) } // Ensure that code outdated by finalized class is cleaned up, new instance of @@ -5973,12 +5973,12 @@ void Class::set_is_loaded(bool value) const { set_state_bits(IsLoadedBit::update(value, state_bits())); } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) void Class::set_is_declared_in_bytecode(bool value) const { ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter()); set_state_bits(IsDeclaredInBytecodeBit::update(value, state_bits())); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) void Class::set_is_finalized() const { ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter()); @@ -8133,18 +8133,53 @@ bool Function::HasCode() const { return untag()->code() != StubCode::LazyCompile().ptr(); } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_SHOREBIRD_INTERPRETER) +bool Function::IsShorebirdPatchable() const { + if (IsNull() || !has_pragma()) { + return false; + } + + Thread* thread = dart::Thread::Current(); + Object& options = Object::Handle(thread->zone()); + if (!Library::FindPragma(thread, /*only_core=*/false, *this, + Symbols::vm_entry_point(), /*multiple=*/false, + &options)) { + return false; + } + + return options.ptr() == Bool::null() || options.ptr() == Bool::True().ptr() || + options.ptr() == Symbols::call().ptr(); +} +#endif + +#if defined(DART_BYTECODE_INTERPRETER) void Function::AttachBytecode(const Bytecode& value) const { ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter()); ASSERT(!value.IsNull()); // Finish setting up code before activating it. value.set_function(*this); - ASSERT(untag()->ic_data_array_or_bytecode() == Object::null()); + ASSERT(untag()->ic_data_array_or_bytecode() == Object::null() || + untag()->ic_data_array_or_bytecode()->IsBytecode()); untag()->set_ic_data_array_or_bytecode(value.ptr()); // Set the code entry_point to InterpretCall stub. SetInstructions(StubCode::InterpretCall()); + + if (!IsImplicitClosureFunction() && HasImplicitClosureFunction()) { + const Function& closure_function = + Function::Handle(ImplicitClosureFunction()); + if (closure_function.IsImplicitStaticClosureFunction()) { + closure_function.AttachBytecode(Object::implicit_static_closure_bytecode()); +#if defined(DART_PRECOMPILED_RUNTIME) + const Closure& closure = + Closure::Handle(closure_function.implicit_static_closure()); + if (!closure.IsNull()) { + closure.set_entry_point(closure_function.entry_point()); + } +#endif + } + } } void Function::ClearBytecode() const { @@ -8157,7 +8192,7 @@ bool Function::IsInterpreted(FunctionPtr function) { return function->untag()->code() == StubCode::InterpretCall().ptr(); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) bool Function::HasCode(FunctionPtr function) { NoSafepointScope no_safepoint; @@ -8166,16 +8201,16 @@ bool Function::HasCode(FunctionPtr function) { } void Function::ClearCode() const { -#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) UNREACHABLE(); #else ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter()); ClearCodeSafe(); -#endif // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) } void Function::ClearCodeSafe() const { -#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) UNREACHABLE(); #else // This may get called when lazily creating dynamic invocation forwarders @@ -8186,7 +8221,7 @@ void Function::ClearCodeSafe() const { untag()->set_unoptimized_code(Code::null()); #endif // !defined(DART_PRECOMPILED_RUNTIME) SetInstructionsSafe(StubCode::LazyCompile()); -#endif // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) } void Function::EnsureHasCompiledUnoptimizedCode() const { @@ -8896,7 +8931,7 @@ StringPtr FunctionType::ParameterNameAt(intptr_t index) const { void FunctionType::SetParameterNameAt(intptr_t index, const String& value) const { -#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) UNREACHABLE(); #else ASSERT(!value.IsNull() && value.IsSymbol()); @@ -8931,7 +8966,7 @@ void Function::CreateNameArray(Heap::Space space) const { } void FunctionType::CreateNameArrayIncludingFlags(Heap::Space space) const { -#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) UNREACHABLE(); #else const intptr_t num_named_parameters = NumOptionalNamedParameters(); @@ -10613,7 +10648,7 @@ FunctionPtr Function::ImplicitClosureFunction() const { return implicit_closure_function(); } -#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) // In AOT mode all implicit closures are pre-created. FATAL("Cannot create implicit closure in AOT!"); return Function::null(); @@ -10823,7 +10858,7 @@ FunctionPtr Function::ImplicitClosureFunction() const { } } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) #if defined(DART_PRECOMPILED_RUNTIME) const bool attach_bytecode = true; #else @@ -11097,7 +11132,7 @@ ClassPtr Function::Owner(FunctionPtr function) { return PatchClass::RawCast(owner)->untag()->wrapped_class(); } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) bool Function::is_declared_in_bytecode() const { return Class::Handle(Owner()).is_declared_in_bytecode(); } @@ -11105,7 +11140,7 @@ bool Function::is_declared_in_bytecode() const { void Function::InheritKernelOffsetFrom(const Function& src) const { #if defined(DART_PRECOMPILED_RUNTIME) -#if !defined(DART_DYNAMIC_MODULES) +#if !defined(DART_BYTECODE_INTERPRETER) UNREACHABLE(); #endif #else @@ -11115,7 +11150,7 @@ void Function::InheritKernelOffsetFrom(const Function& src) const { void Function::InheritKernelOffsetFrom(const Field& src) const { #if defined(DART_PRECOMPILED_RUNTIME) -#if !defined(DART_DYNAMIC_MODULES) +#if !defined(DART_BYTECODE_INTERPRETER) UNREACHABLE(); #endif #else @@ -11551,7 +11586,7 @@ void Function::RestoreICDataMap( } TypedDataPtr Function::GetCoverageArray() const { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (HasBytecode()) { #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) const auto& bytecode = Bytecode::Handle(GetBytecode()); @@ -11570,7 +11605,7 @@ TypedDataPtr Function::GetCoverageArray() const { } void Function::set_ic_data_array(const Array& value) const { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) ASSERT(!HasBytecode()); #endif untag()->set_ic_data_array_or_bytecode( @@ -11580,7 +11615,7 @@ void Function::set_ic_data_array(const Array& value) const { ArrayPtr Function::ic_data_array() const { ObjectPtr value = untag()->ic_data_array_or_bytecode(); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (value->IsBytecode()) { return Array::null(); } @@ -11757,7 +11792,7 @@ bool Function::HasDynamicCallers(Zone* zone) const { } bool Function::PrologueNeedsArgumentsDescriptor() const { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) // Entering interpreter needs arguments descriptor. if (is_declared_in_bytecode()) { return true; @@ -12235,7 +12270,7 @@ uint32_t Field::Hash() const { return String::HashRawSymbol(name()); } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) bool Field::is_declared_in_bytecode() const { return Class::Handle(Owner()).is_declared_in_bytecode(); } @@ -12617,7 +12652,7 @@ FunctionPtr Field::EnsureInitializerFunction() const { Zone* zone = thread->zone(); Function& initializer = Function::Handle(zone, InitializerFunction()); if (initializer.IsNull()) { -#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) UNREACHABLE(); #else SafepointMutexLocker ml( @@ -12632,7 +12667,7 @@ FunctionPtr Field::EnsureInitializerFunction() const { return initializer.ptr(); } -#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) FunctionPtr Field::CreateFieldInitializerFunction(Thread* thread) const { Zone* zone = thread->zone(); @@ -12712,7 +12747,7 @@ void Field::SetInitializerFunction(const Function& initializer) const { initializer.ptr()); } -#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) bool Field::HasInitializerFunction() const { return untag()->initializer_function() != Function::null(); @@ -12836,7 +12871,7 @@ ObjectPtr Field::EvaluateInitializer() const { #if !defined(DART_PRECOMPILED_RUNTIME) if (is_static() && is_const()) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (is_declared_in_bytecode()) { const auto& initializer = Function::Handle(InitializerFunction()); ASSERT(!initializer.IsNull()); @@ -12847,7 +12882,7 @@ ObjectPtr Field::EvaluateInitializer() const { ASSERT(pool.Length() == 1); return pool.ObjectAt(0); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) return kernel::EvaluateStaticConstFieldInitializer(*this); } #endif // !defined(DART_PRECOMPILED_RUNTIME) @@ -13599,7 +13634,7 @@ void Script::set_source(const String& value) const { TypedDataViewPtr Script::kernel_constant_coverage() const { return TypedDataView::RawCast(untag()->constant_coverage()); } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) ArrayPtr Script::collected_constant_coverage() const { return Array::RawCast(untag()->constant_coverage()); } @@ -13616,7 +13651,7 @@ bool Script::HasCollectedConstantCoverage() const { return untag()->constant_coverage()->IsArray() || untag()->constant_coverage()->IsImmutableArray(); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) #endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) TypedDataPtr Script::line_starts() const { @@ -13662,7 +13697,7 @@ void Script::CollectDebugTokenPositions() const { if (kernel_program_info() != Object::null()) { kernel::CollectScriptTokenPositionsFromKernel(*this, &token_positions); } else { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) bytecode::BytecodeReader::CollectScriptTokenPositionsFromBytecode( *this, &token_positions); #else @@ -13678,11 +13713,11 @@ void Script::CollectDebugTokenPositions() const { ArrayPtr Script::CollectConstConstructorCoverageFrom() const { #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (HasCollectedConstantCoverage()) { return Array::RawCast(untag()->constant_coverage()); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) return CollectConstConstructorCoverageFromKernel(); #else return Object::empty_array().ptr(); @@ -13758,7 +13793,7 @@ bool Script::GetTokenLocation(const TokenPosition& token_pos, intptr_t* line, intptr_t* column) const { ASSERT(line != nullptr); -#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) // Scripts in the AOT snapshot do not have a line starts array. return false; #else @@ -13769,7 +13804,7 @@ bool Script::GetTokenLocation(const TokenPosition& token_pos, if (line_starts_data.IsNull()) return false; LineStartsReader line_starts_reader(line_starts_data); return line_starts_reader.LocationForPosition(token_pos.Pos(), line, column); -#endif // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) } intptr_t Script::GetTokenLength(const TokenPosition& token_pos) const { @@ -13797,7 +13832,7 @@ bool Script::TokenRangeAtLine(intptr_t line_number, TokenPosition* first_token_index, TokenPosition* last_token_index) const { ASSERT(first_token_index != nullptr && last_token_index != nullptr); -#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) // Scripts in the AOT snapshot do not have a line starts array. return false; #else @@ -13826,7 +13861,7 @@ bool Script::TokenRangeAtLine(intptr_t line_number, ASSERT(last_token_index->Serialize() <= source_length); #endif return true; -#endif // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) } // Returns the index in the given source string for the given (1-based) absolute @@ -18163,7 +18198,7 @@ void Code::set_deopt_info_array(const Array& array) const { } void Code::set_static_calls_target_table(const Array& value) const { -#if defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_SHOREBIRD_INTERPRETER) UNREACHABLE(); #else untag()->set_static_calls_target_table(value.ptr()); @@ -18233,7 +18268,7 @@ TypedDataPtr Code::GetDeoptInfoAtPc(uword pc, } intptr_t Code::BinarySearchInSCallTable(uword pc) const { -#if defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_SHOREBIRD_INTERPRETER) UNREACHABLE(); #else NoSafepointScope no_safepoint; @@ -18259,7 +18294,7 @@ intptr_t Code::BinarySearchInSCallTable(uword pc) const { } FunctionPtr Code::GetStaticCallTargetFunctionAt(uword pc) const { -#if defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_SHOREBIRD_INTERPRETER) UNREACHABLE(); return Function::null(); #else @@ -18960,7 +18995,7 @@ void Code::DumpSourcePositions(bool relative_addresses) const { void Bytecode::Disassemble(DisassemblyFormatter* formatter) const { #if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER) -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (!FLAG_support_disassembler) { return; } @@ -18972,7 +19007,7 @@ void Bytecode::Disassemble(DisassemblyFormatter* formatter) const { KernelBytecodeDisassembler::Disassemble(start, start + size, formatter, *this); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) #endif // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER) } @@ -19001,7 +19036,7 @@ BytecodePtr Bytecode::New(uword instructions, } TokenPosition Bytecode::GetTokenIndexOfPC(uword return_address) const { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (!HasSourcePositions()) { return TokenPosition::kNoSource; } @@ -19024,7 +19059,7 @@ TokenPosition Bytecode::GetTokenIndexOfPC(uword return_address) const { } intptr_t Bytecode::GetTryIndexAtPc(uword return_address) const { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) intptr_t try_index = -1; const uword pc_offset = return_address - PayloadStart(); const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); @@ -19053,7 +19088,7 @@ intptr_t Bytecode::GetTryIndexAtPc(uword return_address) const { } uword Bytecode::GetInstructionBefore(uword return_address) const { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const uword start = PayloadStart(); // return_address could be the end of the bytecode instructions // if the last instruction is Throw. @@ -19076,7 +19111,7 @@ uword Bytecode::GetInstructionBefore(uword return_address) const { #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) LocalVarDescriptorsPtr Bytecode::GetLocalVarDescriptors() const { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) Zone* zone = Thread::Current()->zone(); auto& var_descs = LocalVarDescriptors::Handle(zone, var_descriptors()); if (var_descs.IsNull()) { @@ -19094,7 +19129,7 @@ LocalVarDescriptorsPtr Bytecode::GetLocalVarDescriptors() const { } TypedDataPtr Bytecode::EnsureCoverageArray(Thread* thread) const { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) // Should only be called for bytecode with RecordCoverage instructions. ASSERT(HasRecordedCoverage()); if (coverage_array() == TypedData::null()) { @@ -19188,7 +19223,7 @@ const char* Bytecode::FullyQualifiedName() const { } BytecodePtr Bytecode::FindBytecode(uword pc) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) class SlowFindBytecodeVisitor : public ObjectVisitor { public: explicit SlowFindBytecodeVisitor(uword pc) @@ -27024,7 +27059,7 @@ const char* StackTrace::ToCString() const { // A visible frame ends any gap we might be in. in_gap = false; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (code_object.IsBytecode()) { const auto& bytecode = Bytecode::Cast(code_object); function = bytecode.function(); @@ -27038,7 +27073,7 @@ const char* StackTrace::ToCString() const { } continue; } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) ASSERT(code_object.IsCode()); code ^= code_object.ptr(); diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 6b3515bff4d..b927f5ad044 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -1772,14 +1772,14 @@ class Class : public Object { bool is_loaded() const { return IsLoadedBit::decode(state_bits()); } void set_is_loaded(bool value) const; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) bool is_declared_in_bytecode() const { return IsDeclaredInBytecodeBit::decode(state_bits()); } void set_is_declared_in_bytecode(bool value) const; #else bool is_declared_in_bytecode() const { return false; } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) uint16_t num_native_fields() const { return untag()->num_native_fields_; } void set_num_native_fields(uint16_t value) const { @@ -3176,6 +3176,10 @@ class Function : public Object { bool HasCode() const; static bool HasCode(FunctionPtr function); +#if defined(DART_SHOREBIRD_INTERPRETER) + bool IsShorebirdPatchable() const; +#endif + static intptr_t code_offset() { return OFFSET_OF(UntaggedFunction, code_); } uword entry_point() const { return EntryPointOf(ptr()); } @@ -3199,7 +3203,7 @@ class Function : public Object { return OFFSET_OF(UntaggedFunction, unchecked_entry_point_); } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) void AttachBytecode(const Bytecode& bytecode) const; void ClearBytecode() const; inline BytecodePtr GetBytecode() const; @@ -3537,11 +3541,11 @@ class Function : public Object { #undef DEFINE_GETTERS_AND_SETTERS -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) bool is_declared_in_bytecode() const; #else bool is_declared_in_bytecode() const { return false; } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) intptr_t kernel_offset() const { #if defined(DART_PRECOMPILED_RUNTIME) @@ -4034,7 +4038,7 @@ class Function : public Object { static StringPtr CreateDynamicInvocationForwarderName(const String& name); -#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) FunctionPtr CreateDynamicInvocationForwarder( const String& mangled_name) const; @@ -4507,11 +4511,11 @@ class Field : public Object { return untag()->kind_bits_.Read(); } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) bool is_declared_in_bytecode() const; #else bool is_declared_in_bytecode() const { return false; } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) intptr_t kernel_offset() const { #if defined(DART_PRECOMPILED_RUNTIME) @@ -4832,10 +4836,10 @@ class Field : public Object { return OFFSET_OF(UntaggedField, initializer_function_); } -#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) FunctionPtr CreateFieldInitializerFunction(Thread* thread) const; void SetInitializerFunction(const Function& initializer) const; -#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) // Constructs getter and setter names for fields and vice versa. static StringPtr GetterName(const String& field_name); @@ -5067,19 +5071,19 @@ class Script : public Object { ArrayPtr CollectConstConstructorCoverageFrom() const; #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) void set_collected_constant_coverage(const Array& value) const; -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) #endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) private: #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) TypedDataViewPtr kernel_constant_coverage() const; ArrayPtr CollectConstConstructorCoverageFromKernel() const; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) ArrayPtr collected_constant_coverage() const; bool HasCollectedConstantCoverage() const; -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) #endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) void set_debug_positions(const Array& value) const; @@ -7122,7 +7126,7 @@ class Code : public Object { void set_static_calls_target_table(const Array& value) const; ArrayPtr static_calls_target_table() const { -#if defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_SHOREBIRD_INTERPRETER) UNREACHABLE(); return nullptr; #else @@ -13555,7 +13559,7 @@ void Object::setPtr(ObjectPtr value, intptr_t default_cid) { set_vtable(builtin_vtables_[cid]); } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) BytecodePtr Function::GetBytecode() const { return GetBytecode(ptr()); } @@ -13571,7 +13575,7 @@ bool Function::HasBytecode() const { bool Function::HasBytecode(FunctionPtr function) { return function.untag()->ic_data_array_or_bytecode()->IsBytecode(); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) intptr_t Field::HostOffset() const { ASSERT(is_instance()); // Valid only for dart instance fields. diff --git a/runtime/vm/object_graph_copy.cc b/runtime/vm/object_graph_copy.cc index 4a35a5d4a5c..8bc37456a0c 100644 --- a/runtime/vm/object_graph_copy.cc +++ b/runtime/vm/object_graph_copy.cc @@ -1133,7 +1133,7 @@ class RetainingPath { Function& function = Function::Handle(zone_); #if !defined(DART_PRECOMPILED_RUNTIME) && !defined(PRODUCT) Code& code = Code::Handle(zone_); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) Bytecode& bytecode = Bytecode::Handle(zone_); #endif LocalVarDescriptors& var_descriptors = LocalVarDescriptors::Handle(zone_); @@ -1194,12 +1194,12 @@ class RetainingPath { // Attempt to convert "instance <- Context+ <- Closure" into // "instance <- local var name in Closure". if (function.is_declared_in_bytecode()) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) bytecode = function.GetBytecode(); var_descriptors = bytecode.GetLocalVarDescriptors(); #else UNREACHABLE(); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } else { if (!function.ForceOptimize()) { function.EnsureHasCompiledUnoptimizedCode(); diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc index 782c2afadfc..c7b0924bde9 100644 --- a/runtime/vm/object_reload.cc +++ b/runtime/vm/object_reload.cc @@ -844,7 +844,7 @@ void CallSiteResetter::Reset(const ICData& ic) { } } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) static ArrayPtr PrepareNoSuchMethodErrorArguments(const Function& target, bool incompatible_arguments) { InvocationMirror::Kind kind = InvocationMirror::Kind::kMethod; @@ -891,10 +891,10 @@ static ArrayPtr PrepareNoSuchMethodErrorArguments(const Function& target, args.SetAt(6, Object::null_object()); return args.ptr(); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) void CallSiteResetter::RebindBytecode(const Bytecode& bytecode) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) pool_ = bytecode.object_pool(); ASSERT(!pool_.IsNull()); @@ -991,7 +991,7 @@ void CallSiteResetter::RebindBytecode(const Bytecode& bytecode) { } #else UNREACHABLE(); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } #endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc index 53025869e3b..87ec59be772 100644 --- a/runtime/vm/profiler.cc +++ b/runtime/vm/profiler.cc @@ -509,7 +509,7 @@ void Profiler::DumpStackTrace(uword sp, uword fp, uword pc, bool for_crash) { StackFrame::DumpCurrentTrace(); } else if (thread->execution_state() == Thread::kThreadInGenerated) { // No exit frame, walk from the crash's registers. -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (thread->vm_tag() == VMTag::kDartInterpretedTagId) { Interpreter* interpreter = thread->interpreter(); sp = interpreter->get_sp(); @@ -517,7 +517,7 @@ void Profiler::DumpStackTrace(uword sp, uword fp, uword pc, bool for_crash) { pc = interpreter->get_pc(); StackFrame::DumpCurrentTrace(sp, fp, pc); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) if (thread->vm_tag() == VMTag::kDartTagId) { StackFrame::DumpCurrentTrace(sp, fp, pc); } @@ -1098,7 +1098,7 @@ class ProfilerDartStackWalker : public ProfilerStackWalker { } bool IsInterpretedFrame() const { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) Interpreter* interpreter = thread_->interpreter(); return (interpreter != nullptr) && interpreter->HasFrame(reinterpret_cast(fp_)); @@ -1366,7 +1366,7 @@ void Profiler::SampleThread(Thread* thread, lr = simulator->get_lr(); } #endif -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (thread->vm_tag() == VMTag::kDartInterpretedTagId) { sp = 0; pc = thread->interpreter()->get_pc(); diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc index 05d7b50dedd..d76a5230585 100644 --- a/runtime/vm/profiler_service.cc +++ b/runtime/vm/profiler_service.cc @@ -1101,7 +1101,7 @@ class ProfileBuilder : public ValueObject { } } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (profile_code->code().IsBytecode()) { const auto& bytecode = Bytecode::CheckedHandle(zone, profile_code->code().ptr()); diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc index fa7c8fb3fa9..08fdf2f0d77 100644 --- a/runtime/vm/program_visitor.cc +++ b/runtime/vm/program_visitor.cc @@ -384,6 +384,16 @@ void ProgramVisitor::BindStaticCalls(Thread* thread) { // Cf. runtime entry PatchStaticCall called from CallStaticFunction // stub. const auto& fun = Function::Cast(target_); +#if defined(DART_SHOREBIRD_INTERPRETER) + if (FLAG_precompiled_mode) { + // Precompiler::ReplaceFunctionStaticCallEntries has already converted + // non-patchable Function targets to Code targets. Any remaining + // Function target must stay indirect so runtime dispatch observes the + // current Function::entry_point without executable writes. + only_call_via_code = false; + continue; + } +#endif ASSERT(!FLAG_precompiled_mode || fun.HasCode()); target_code_ = fun.HasCode() ? fun.CurrentCode() : StubCode::CallStaticFunction().ptr(); diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index 52d54c74f06..90145b6a2e6 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -2058,8 +2058,12 @@ class UntaggedCode : public UntaggedObject { POINTER_FIELD(CodeSourceMapPtr, code_source_map) NOT_IN_PRECOMPILED(POINTER_FIELD(InstructionsPtr, active_instructions)) NOT_IN_PRECOMPILED(POINTER_FIELD(ArrayPtr, deopt_info_array)) - // (code-offset, function, code) triples. - NOT_IN_PRECOMPILED(POINTER_FIELD(ArrayPtr, static_calls_target_table)) + // (code-offset, function, code) triples. Normally omitted from the + // precompiled runtime, but retained for Shorebird interpreter patching so + // static calls can resolve the current Function::entry_point at runtime. +#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_SHOREBIRD_INTERPRETER) + POINTER_FIELD(ArrayPtr, static_calls_target_table) +#endif // If return_address_metadata_ is a Smi, it is the offset to the prologue. // Else, return_address_metadata_ is null. NOT_IN_PRODUCT(POINTER_FIELD(ObjectPtr, return_address_metadata)) @@ -2068,7 +2072,7 @@ class UntaggedCode : public UntaggedObject { #if !defined(PRODUCT) VISIT_TO(comments); -#elif defined(DART_PRECOMPILED_RUNTIME) +#elif defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_SHOREBIRD_INTERPRETER) VISIT_TO(code_source_map); #else VISIT_TO(static_calls_target_table); diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc index b00099eed89..78db2bffe74 100644 --- a/runtime/vm/raw_object_fields.cc +++ b/runtime/vm/raw_object_fields.cc @@ -211,7 +211,11 @@ namespace dart { F(TypedDataView, typed_data_) \ F(TypedDataView, offset_in_bytes_) +#if defined(DART_SHOREBIRD_INTERPRETER) +#define AOT_CLASSES_AND_FIELDS(F) F(Code, static_calls_target_table_) +#else #define AOT_CLASSES_AND_FIELDS(F) +#endif #define AOT_NON_PRODUCT_CLASSES_AND_FIELDS(F) \ F(Class, direct_implementors_) \ diff --git a/runtime/vm/resolver.cc b/runtime/vm/resolver.cc index 3380829c40b..d82494b3f59 100644 --- a/runtime/vm/resolver.cc +++ b/runtime/vm/resolver.cc @@ -22,7 +22,7 @@ static FunctionPtr ResolveDynamicAnyArgsWithCustomLookup( const String& function_name, bool allow_add, std::function lookup) { -#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES) +#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_BYTECODE_INTERPRETER) // No methods can be added in the precompiled runtime unless dynamic // modules are enabled. In this case, calls from dynamic modules may // necessitate the creation of (interpreted) forwarders, even for @@ -69,7 +69,7 @@ static FunctionPtr ResolveDynamicAnyArgsWithCustomLookup( SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock()); function = lookup(cls, *demangled_name); } -#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES) +#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_BYTECODE_INTERPRETER) if (allow_add && is_dyn_call && !function.IsNull()) { // In JIT mode or if dynamic modules are enabled, lazily create a dyn:* // forwarder if one is required. diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc index 023ca158d2c..c23ae2378b2 100644 --- a/runtime/vm/runtime_entry.cc +++ b/runtime/vm/runtime_entry.cc @@ -637,7 +637,7 @@ static void ThrowIfError(const Object& result) { // Return value: newly allocated object. DEFINE_RUNTIME_ENTRY(AllocateObject, 2) { const Class& cls = Class::CheckedHandle(zone, arguments.ArgAt(0)); -#if defined(DART_DYNAMIC_MODULES) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_BYTECODE_INTERPRETER) && !defined(DART_PRECOMPILED_RUNTIME) if (!cls.is_allocate_finalized()) { const Error& error = Error::Handle(zone, cls.EnsureIsAllocateFinalized(thread)); @@ -1004,13 +1004,13 @@ DEFINE_RUNTIME_ENTRY(CloneSuspendState, 1) { // Allocate a new SubtypeTestCache for use in interpreted implicit setters. // Return value: newly allocated SubtypeTestCache. DEFINE_RUNTIME_ENTRY(AllocateSubtypeTestCache, 0) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const auto& cache = SubtypeTestCache::Handle( zone, SubtypeTestCache::New(SubtypeTestCache::kMaxInputs)); arguments.SetReturn(cache); #else UNREACHABLE(); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // Invoke field getter before dispatch. @@ -1018,7 +1018,7 @@ DEFINE_RUNTIME_ENTRY(AllocateSubtypeTestCache, 0) { // Arg1: field name (may be demangled during call). // Return value: field value. DEFINE_RUNTIME_ENTRY(GetFieldForDispatch, 2) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); String& name = String::CheckedHandle(zone, arguments.ArgAt(1)); const Class& receiver_class = Class::Handle(zone, receiver.clazz()); @@ -1043,7 +1043,7 @@ DEFINE_RUNTIME_ENTRY(GetFieldForDispatch, 2) { arguments.SetReturn(result); #else UNREACHABLE(); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // Converts arguments descriptor passed to an implicit closure @@ -1053,7 +1053,7 @@ DEFINE_RUNTIME_ENTRY(GetFieldForDispatch, 2) { // Arg2: new type args length // Return value: target arguments descriptor DEFINE_RUNTIME_ENTRY(AdjustArgumentsDesciptorForImplicitClosure, 3) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const auto& descriptor = Array::CheckedHandle(zone, arguments.ArgAt(0)); const auto& target = Function::CheckedHandle(zone, arguments.ArgAt(1)); intptr_t type_args_len = Smi::CheckedHandle(zone, arguments.ArgAt(2)).Value(); @@ -1079,7 +1079,7 @@ DEFINE_RUNTIME_ENTRY(AdjustArgumentsDesciptorForImplicitClosure, 3) { arguments.SetReturn(result); #else UNREACHABLE(); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // Converts type arguments passed to a constructor tear-off @@ -1088,7 +1088,7 @@ DEFINE_RUNTIME_ENTRY(AdjustArgumentsDesciptorForImplicitClosure, 3) { // Arg1: type arguments // Return value: instance type arguments DEFINE_RUNTIME_ENTRY(ConvertToInstanceTypeArguments, 2) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const auto& cls = Class::CheckedHandle(zone, arguments.ArgAt(0)); const auto& type_args = TypeArguments::CheckedHandle(zone, arguments.ArgAt(1)); @@ -1097,7 +1097,7 @@ DEFINE_RUNTIME_ENTRY(ConvertToInstanceTypeArguments, 2) { arguments.SetReturn(result); #else UNREACHABLE(); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // Check that arguments are valid for the given closure. @@ -1105,7 +1105,7 @@ DEFINE_RUNTIME_ENTRY(ConvertToInstanceTypeArguments, 2) { // Arg1: arguments descriptor // Return value: whether the arguments are valid DEFINE_RUNTIME_ENTRY(ClosureArgumentsValid, 2) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const auto& closure = Closure::CheckedHandle(zone, arguments.ArgAt(0)); const auto& descriptor = Array::CheckedHandle(zone, arguments.ArgAt(1)); @@ -1122,7 +1122,7 @@ DEFINE_RUNTIME_ENTRY(ClosureArgumentsValid, 2) { } #else UNREACHABLE(); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // Resolve 'call' function of receiver. @@ -1130,7 +1130,7 @@ DEFINE_RUNTIME_ENTRY(ClosureArgumentsValid, 2) { // Arg1: arguments descriptor // Return value: 'call' function'. DEFINE_RUNTIME_ENTRY(ResolveCallFunction, 2) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); const Array& descriptor = Array::CheckedHandle(zone, arguments.ArgAt(1)); ArgumentsDescriptor args_desc(descriptor); @@ -1143,14 +1143,14 @@ DEFINE_RUNTIME_ENTRY(ResolveCallFunction, 2) { arguments.SetReturn(call_function); #else UNREACHABLE(); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // Resolve external method call from the interpreter. // Arg0: function. // Arg1: pool index to store resolved trampoline and native function. DEFINE_RUNTIME_ENTRY(ResolveExternalCall, 2) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const auto& function = Function::CheckedHandle(zone, arguments.ArgAt(0)); const intptr_t pool_index = Smi::CheckedHandle(zone, arguments.ArgAt(1)).Value(); @@ -1194,10 +1194,10 @@ DEFINE_RUNTIME_ENTRY(ResolveExternalCall, 2) { pool.SetRawValueAt(pool_index + 1, reinterpret_cast(target_function)); #else UNREACHABLE(); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } -#if defined(DART_DYNAMIC_MODULES) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_BYTECODE_INTERPRETER) && !defined(DART_PRECOMPILED_RUNTIME) struct FfiCallArguments { uword stack_area; @@ -1442,13 +1442,13 @@ static uword ResolveFfiNativeTarget(Thread* thread, const Function& function) { return static_cast(Integer::Cast(result).Value()); } -#endif // defined(DART_DYNAMIC_MODULES) && !defined(DART_PRECOMPILED_RUNTIME) +#endif // defined(DART_BYTECODE_INTERPRETER) && !defined(DART_PRECOMPILED_RUNTIME) // Perform FFI call from the interpreter. // Arg0: function. // Arg1: constant pool index to store resolved target. DEFINE_RUNTIME_ENTRY(FfiCall, 2) { -#if defined(DART_DYNAMIC_MODULES) && !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_BYTECODE_INTERPRETER) && !defined(DART_PRECOMPILED_RUNTIME) const auto& function = Function::CheckedZoneHandle(zone, arguments.ArgAt(0)); const intptr_t pool_index = Smi::CheckedHandle(zone, arguments.ArgAt(1)).Value(); @@ -1533,7 +1533,7 @@ DEFINE_RUNTIME_ENTRY(FfiCall, 2) { Object::Handle(zone, ReceiveFfiCallResult(thread, marshaller, &args))); #else UNREACHABLE(); -#endif // defined(DART_DYNAMIC_MODULES) && !defined(DART_PRECOMPILED_RUNTIME) +#endif // defined(DART_BYTECODE_INTERPRETER) && !defined(DART_PRECOMPILED_RUNTIME) } // Check that argument types are valid for the given function. @@ -1542,7 +1542,7 @@ DEFINE_RUNTIME_ENTRY(FfiCall, 2) { // Arg2: arguments // Return value: whether the arguments are valid DEFINE_RUNTIME_ENTRY(CheckFunctionArgumentTypes, 3) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const auto& function = Function::CheckedHandle(zone, arguments.ArgAt(0)); const auto& descriptor = Array::CheckedHandle(zone, arguments.ArgAt(1)); const auto& args = Array::CheckedHandle(zone, arguments.ArgAt(2)); @@ -1560,7 +1560,7 @@ DEFINE_RUNTIME_ENTRY(CheckFunctionArgumentTypes, 3) { } #else UNREACHABLE(); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // Helper routine for tracing a type check. @@ -1608,7 +1608,7 @@ static void PrintTypeCheck(const char* message, } } -#if defined(TARGET_ARCH_IA32) || defined(DART_DYNAMIC_MODULES) +#if defined(TARGET_ARCH_IA32) || defined(DART_BYTECODE_INTERPRETER) static BoolPtr CheckHashBasedSubtypeTestCache( Zone* zone, Thread* thread, @@ -1660,7 +1660,7 @@ static BoolPtr CheckHashBasedSubtypeTestCache( return Bool::null(); } -#endif // defined(TARGET_ARCH_IA32) || defined(DART_DYNAMIC_MODULES) +#endif // defined(TARGET_ARCH_IA32) || defined(DART_BYTECODE_INTERPRETER) // This updates the type test cache, an array containing 8 elements: // - instance class (or function if the instance is a closure) @@ -1897,7 +1897,7 @@ DEFINE_RUNTIME_ENTRY(TypeCheck, 7) { ASSERT(mode == kTypeCheckFromInline); #endif -#if defined(TARGET_ARCH_IA32) || defined(DART_DYNAMIC_MODULES) +#if defined(TARGET_ARCH_IA32) || defined(DART_BYTECODE_INTERPRETER) // Hash-based caches are not handled by the inline AssertAssignable // on IA32 and in the interpreter. if ((mode == kTypeCheckFromInline) && cache.IsHash()) { @@ -1911,7 +1911,7 @@ DEFINE_RUNTIME_ENTRY(TypeCheck, 7) { return; } } -#endif // defined(TARGET_ARCH_IA32) || defined(DART_DYNAMIC_MODULES) +#endif // defined(TARGET_ARCH_IA32) || defined(DART_BYTECODE_INTERPRETER) // This is guaranteed on the calling side. ASSERT(!dst_type.IsDynamicType()); @@ -2175,7 +2175,20 @@ DEFINE_RUNTIME_ENTRY(ReThrow, 3) { // Patches static call in optimized code with the target's entry point. // Compiles target if necessary. DEFINE_RUNTIME_ENTRY(PatchStaticCall, 0) { -#if !defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_PRECOMPILED_RUNTIME) && defined(DART_SHOREBIRD_INTERPRETER) + DartFrameIterator iterator(thread, + StackFrameIterator::kNoCrossThreadIteration); + StackFrame* caller_frame = iterator.NextFrame(); + ASSERT(caller_frame != nullptr); + ASSERT(!caller_frame->is_interpreted()); + const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode()); + ASSERT(!caller_code.IsNull()); + const Function& target_function = Function::Handle( + zone, caller_code.GetStaticCallTargetFunctionAt(caller_frame->pc())); + RELEASE_ASSERT(!target_function.IsNull()); + ASSERT(target_function.HasCode()); + arguments.SetReturn(target_function); +#elif !defined(DART_PRECOMPILED_RUNTIME) DartFrameIterator iterator(thread, StackFrameIterator::kNoCrossThreadIteration); StackFrame* caller_frame = iterator.NextFrame(); @@ -2252,7 +2265,7 @@ DEFINE_RUNTIME_ENTRY(SingleStepHandler, 0) { } DEFINE_RUNTIME_ENTRY(ResumptionBreakpointHandler, 0) { -#if defined(DART_DYNAMIC_MODULES) && !defined(PRODUCT) +#if defined(DART_BYTECODE_INTERPRETER) && !defined(PRODUCT) isolate->debugger()->ResumptionBreakpoint(); #else UNREACHABLE(); @@ -3459,7 +3472,7 @@ DEFINE_RUNTIME_ENTRY(SwitchableCallMiss, 2) { // Returns: target function (can only be null in AOT runtime) // Modifies the instance call table in current interpreter. DEFINE_RUNTIME_ENTRY(InterpretedInstanceCallMissHandler, 3) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); const String& target_name = String::CheckedHandle(zone, arguments.ArgAt(1)); const Array& arg_desc = Array::CheckedHandle(zone, arguments.ArgAt(2)); @@ -3491,7 +3504,7 @@ DEFINE_RUNTIME_ENTRY(InterpretedInstanceCallMissHandler, 3) { arguments.SetReturn(target_function); #else UNREACHABLE(); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } #if defined(DART_PRECOMPILED_RUNTIME) @@ -3739,7 +3752,7 @@ DEFINE_RUNTIME_ENTRY(NoSuchMethodError, 1) { // Arg2: arguments descriptor array. // Arg3: arguments array. DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethod, 4) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); const String& original_function_name = String::CheckedHandle(zone, arguments.ArgAt(1)); @@ -3763,7 +3776,7 @@ DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethod, 4) { arguments.SetReturn(result); #else UNREACHABLE(); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) @@ -3976,13 +3989,13 @@ DEFINE_RUNTIME_ENTRY(InterruptOrStackOverflow, 0) { uword stack_overflow_flags = thread->GetAndClearStackOverflowFlags(); bool interpreter_stack_overflow = false; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) Interpreter* interpreter = thread->interpreter(); if (interpreter != nullptr) { interpreter_stack_overflow = interpreter->get_sp() >= interpreter->overflow_stack_limit(); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) // If an interrupt happens at the same time as a stack overflow, we // process the stack overflow now and leave the interrupt for next @@ -3993,13 +4006,13 @@ DEFINE_RUNTIME_ENTRY(InterruptOrStackOverflow, 0) { OS::PrintErr("Stack overflow\n"); OS::PrintErr(" Native SP = %" Px ", stack limit = %" Px "\n", stack_pos, thread->saved_stack_limit()); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (thread->interpreter() != nullptr) { OS::PrintErr(" Interpreter SP = %" Px ", stack limit = %" Px "\n", thread->interpreter()->get_sp(), thread->interpreter()->overflow_stack_limit()); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) OS::PrintErr("Call stack:\n"); OS::PrintErr("size | frame\n"); @@ -4821,7 +4834,7 @@ DEFINE_LEAF_RUNTIME_ENTRY(MemoryMove, /*argument_count=*/3, static_cast(memmove)); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) // Interpret a function call. Should be called only for non-jitted functions. // argc indicates the number of arguments, including the type arguments. // argv points to the first argument. @@ -4867,10 +4880,10 @@ extern "C" uword /*ObjectPtr*/ InterpretCall(uword /*FunctionPtr*/ function_in, } return static_cast(result); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) uword RuntimeEntry::InterpretCallEntry() { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) uword entry = reinterpret_cast(InterpretCall); #if defined(DART_INCLUDE_SIMULATOR) if (FLAG_use_simulator) { @@ -4881,7 +4894,7 @@ uword RuntimeEntry::InterpretCallEntry() { return entry; #else return 0; -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // Restore suspended interpreter frame and resume execution. @@ -4890,7 +4903,7 @@ uword RuntimeEntry::InterpretCallEntry() { // Arg1: exception // Arg2: stack trace DEFINE_RUNTIME_ENTRY(ResumeInterpreter, 3) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const Instance& value = Instance::CheckedHandle(zone, arguments.ArgAt(0)); const Instance& exception = Instance::CheckedHandle(zone, arguments.ArgAt(1)); const Instance& stack_trace = @@ -4928,14 +4941,14 @@ DEFINE_RUNTIME_ENTRY(ResumeInterpreter, 3) { arguments.SetReturn(result); #else UNREACHABLE(); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } // Lazily allocates a coverage array for bytecode prior to recording coverage. // // Arg0: Bytecode object that needs an allocated coverage array. DEFINE_RUNTIME_ENTRY(AllocateBytecodeCoverageArray, 1) { -#if defined(DART_DYNAMIC_MODULES) && !defined(PRODUCT) && \ +#if defined(DART_BYTECODE_INTERPRETER) && !defined(PRODUCT) && \ !defined(DART_PRECOMPILED_RUNTIME) const auto& bytecode = Bytecode::CheckedHandle(zone, arguments.ArgAt(0)); const auto& coverage_array = @@ -4943,7 +4956,7 @@ DEFINE_RUNTIME_ENTRY(AllocateBytecodeCoverageArray, 1) { arguments.SetReturn(coverage_array); #else UNREACHABLE(); -#endif // defined(DART_DYNAMIC_MODULES) && !defined(PRODUCT) && +#endif // defined(DART_BYTECODE_INTERPRETER) && !defined(PRODUCT) && // !defined(DART_PRECOMPILED_RUNTIME) } diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc index 7d1ecdc90fb..b12c25ce858 100644 --- a/runtime/vm/service.cc +++ b/runtime/vm/service.cc @@ -2199,7 +2199,7 @@ static ObjectPtr LookupHeapObjectCode(char** parts, int num_parts) { if (!code.IsNull()) { return code.ptr(); } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const auto& bytecode = Bytecode::Handle(Bytecode::FindBytecode(pc)); if (!bytecode.IsNull()) { return bytecode.ptr(); diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc index 18a21b4b5c2..71e19587896 100644 --- a/runtime/vm/service_test.cc +++ b/runtime/vm/service_test.cc @@ -456,7 +456,7 @@ ISOLATE_UNIT_TEST_CASE(Service_LocalVarDescriptors) { EXPECT(!function_c.IsNull()); LocalVarDescriptors& descriptors = LocalVarDescriptors::Handle(); if (function_c.IsInterpreted()) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const Bytecode& bytecode_c = Bytecode::Handle(function_c.GetBytecode()); EXPECT(!bytecode_c.IsNull()); descriptors = bytecode_c.var_descriptors(); diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc index 8dcad28e23d..4fc4d90bf07 100644 --- a/runtime/vm/source_report.cc +++ b/runtime/vm/source_report.cc @@ -443,7 +443,7 @@ void SourceReport::PrintPossibleBreakpointsData(JSONObject* jsobj, BitVector possible(zone(), func_length); if (func.HasBytecode()) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) const auto& bytecode = Bytecode::Handle(zone(), func.GetBytecode()); // Currently, every source position is a possible breakpoint. bytecode::BytecodeSourcePositionsIterator iter(zone(), bytecode); diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc index 4912b3c10d6..1b0cd381862 100644 --- a/runtime/vm/stack_frame.cc +++ b/runtime/vm/stack_frame.cc @@ -176,7 +176,7 @@ const char* StackFrame::ToCString() const { const char* name = nullptr; uword start = 0; if (is_interpreted()) { -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (IsEntryFrame()) { name = "[Interpreter] Entry frame"; } else if (IsExitFrame()) { @@ -192,7 +192,7 @@ const char* StackFrame::ToCString() const { } #else UNREACHABLE(); -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } else if (IsEntryFrame()) { name = "[Stub] Entry frame"; } else if (IsExitFrame()) { @@ -606,7 +606,7 @@ void StackFrameIterator::SetupLastExitFrameData() { frames_.fp_ = exit_marker; frames_.sp_ = 0; frames_.pc_ = 0; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) frames_.CheckIfInterpreted(exit_marker); #endif frames_.Unpoison(); @@ -622,7 +622,7 @@ void StackFrameIterator::SetupNextExitFrameData() { frames_.fp_ = exit_marker; frames_.sp_ = 0; frames_.pc_ = 0; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) frames_.CheckIfInterpreted(exit_marker); #endif frames_.Unpoison(); @@ -657,7 +657,7 @@ StackFrameIterator::StackFrameIterator(uword last_fp, frames_.fp_ = last_fp; frames_.sp_ = 0; frames_.pc_ = 0; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) frames_.CheckIfInterpreted(last_fp); #endif frames_.Unpoison(); @@ -680,7 +680,7 @@ StackFrameIterator::StackFrameIterator(uword fp, frames_.fp_ = fp; frames_.sp_ = sp; frames_.pc_ = pc; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) frames_.CheckIfInterpreted(fp); #endif frames_.Unpoison(); @@ -753,14 +753,14 @@ StackFrame* StackFrameIterator::NextFrame() { return current_frame_; } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) void StackFrameIterator::FrameSetIterator::CheckIfInterpreted( uword exit_marker) { Interpreter* interpreter = thread_->interpreter(); is_interpreted_ = (interpreter != nullptr) && interpreter->HasFrame(exit_marker); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) // Tell MemorySanitizer that generated code initializes part of the stack. void StackFrameIterator::FrameSetIterator::Unpoison() { @@ -794,7 +794,7 @@ StackFrame* StackFrameIterator::FrameSetIterator::NextFrame(bool validate) { frame->sp_ = sp_; frame->fp_ = fp_; frame->pc_ = pc_; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) frame->is_interpreted_ = is_interpreted(); #endif sp_ = frame->GetCallerSp(); @@ -810,7 +810,7 @@ ExitFrame* StackFrameIterator::NextExitFrame() { exit_.sp_ = frames_.sp_; exit_.fp_ = frames_.fp_; exit_.pc_ = frames_.pc_; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) exit_.is_interpreted_ = frames_.is_interpreted(); #endif frames_.sp_ = exit_.GetCallerSp(); @@ -827,7 +827,7 @@ EntryFrame* StackFrameIterator::NextEntryFrame() { entry_.sp_ = frames_.sp_; entry_.fp_ = frames_.fp_; entry_.pc_ = frames_.pc_; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) entry_.is_interpreted_ = frames_.is_interpreted(); #endif SetupNextExitFrameData(); // Setup data for next exit frame in chain. diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h index bba02d7084a..f67eefa5956 100644 --- a/runtime/vm/stack_frame.h +++ b/runtime/vm/stack_frame.h @@ -112,7 +112,7 @@ class StackFrame : public ValueObject { virtual bool IsEntryFrame() const { return false; } virtual bool IsExitFrame() const { return false; } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) bool is_interpreted() const { return is_interpreted_; } #else bool is_interpreted() const { return false; } @@ -182,7 +182,7 @@ class StackFrame : public ValueObject { uword pc_; Thread* thread_; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) bool is_interpreted_ = false; #endif @@ -308,7 +308,7 @@ class StackFrameIterator { explicit FrameSetIterator(Thread* thread) : fp_(0), sp_(0), pc_(0), stack_frame_(thread), thread_(thread) {} -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) bool is_interpreted() const { return is_interpreted_; } void CheckIfInterpreted(uword exit_marker); #else @@ -323,7 +323,7 @@ class StackFrameIterator { StackFrame stack_frame_; // Singleton frame returned by NextFrame(). Thread* thread_; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) bool is_interpreted_ = false; #endif diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc index 4d982818b7f..48878c357ee 100644 --- a/runtime/vm/stack_trace.cc +++ b/runtime/vm/stack_trace.cc @@ -342,33 +342,33 @@ void AsyncAwareStackUnwinder::Unwind( code_ = SuspendState::Cast(awaiter_frame_.next).GetCodeObject(); pc_offset = pc - code_.PayloadStart(); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (pc == StubCode::ResumeInterpreter().EntryPoint()) { bytecode_ = Interpreter::Current()->GetSuspendedLocation( SuspendState::Cast(awaiter_frame_.next), &pc_offset); ASSERT(!bytecode_.IsNull()); code_ = Code::null(); } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } else { // This is an asynchronous continuation represented by a closure which // will handle successful completion. This function is not yet executing // so we have to use artificial marker offset (1). -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (function_.IsInterpreted()) { bytecode_ = function_.GetBytecode(); code_ = Code::null(); pc_offset = StackTraceUtils::kFutureListenerPcOffset; } else { -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) code_ = function_.EnsureHasCode(); RELEASE_ASSERT(!code_.IsNull()); pc_offset = (function_.entry_point() + StackTraceUtils::kFutureListenerPcOffset) - code_.PayloadStart(); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) } handle_frame(gap_frame); diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc index f7b6bd7f266..e1a6e064dbc 100644 --- a/runtime/vm/stub_code.cc +++ b/runtime/vm/stub_code.cc @@ -137,7 +137,7 @@ bool StubCode::InInvocationStub(Thread* T, Roots* roots = T->isolate_group()->roots(); if (roots == nullptr) return false; -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (is_interpreted_frame) { // Recognize special marker set up by interpreter in entry frame. return Interpreter::IsEntryFrameMarker( @@ -151,7 +151,7 @@ bool StubCode::InInvocationStub(Thread* T, return true; } } -#endif // defined(DART_DYNAMIC_MODULES) +#endif // defined(DART_BYTECODE_INTERPRETER) const Code& stub = roots->x_stub_handle(kInvokeDartCodeIndex); uword entry = Code::StubEntryPointOf(stub.ptr()); uword size = Code::StubPayloadSizeOf(stub.ptr()); diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc index 887450d21cf..1029eb7b1b5 100644 --- a/runtime/vm/thread.cc +++ b/runtime/vm/thread.cc @@ -47,7 +47,7 @@ Thread::~Thread() { ASSERT(!ActiveMutatorStolenField::decode(safepoint_state_)); ASSERT(deopt_context_ == nullptr); // No deopt in progress when thread is deleted. -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) delete interpreter_; interpreter_ = nullptr; #endif @@ -1135,7 +1135,7 @@ void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor, visitor->VisitPointer(reinterpret_cast(&active_stacktrace_)); visitor->VisitPointer(reinterpret_cast(&sticky_error_)); -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) if (interpreter() != nullptr) { interpreter()->VisitObjectPointers(visitor); } @@ -1409,7 +1409,7 @@ bool Thread::TopErrorHandlerIsSetJump() const { // False positives: simulator stack and native stack are unordered. return true; #else -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) // False positives: interpreter stack and native stack are unordered. if ((interpreter_ != nullptr) && interpreter_->HasFrame(top_exit_frame_info_)) return true; @@ -1425,7 +1425,7 @@ bool Thread::TopErrorHandlerIsExitFrame() const { // False positives: simulator stack and native stack are unordered. return true; #else -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) // False positives: interpreter stack and native stack are unordered. if ((interpreter_ != nullptr) && interpreter_->HasFrame(top_exit_frame_info_)) return true; diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h index dbc055b1801..28cc0656453 100644 --- a/runtime/vm/thread.h +++ b/runtime/vm/thread.h @@ -1325,7 +1325,7 @@ class Thread : public ThreadState, public IntrusiveDListEntry { #endif } -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) Interpreter* interpreter() const { return interpreter_; } void set_interpreter(Interpreter* value) { interpreter_ = value; } @@ -1646,7 +1646,7 @@ class Thread : public ThreadState, public IntrusiveDListEntry { HeapProfileSampler heap_sampler_; #endif -#if defined(DART_DYNAMIC_MODULES) +#if defined(DART_BYTECODE_INTERPRETER) Interpreter* interpreter_ = nullptr; bytecode::BytecodeLoader* bytecode_loader_ = nullptr; #endif