diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn index 41a4b0aa5c8..6ab1482ce29 100644 --- a/runtime/bin/BUILD.gn +++ b/runtime/bin/BUILD.gn @@ -434,7 +434,7 @@ dart_io("standalone_dart_io") { gen_snapshot_action("generate_snapshot_bin") { deps = [ - "../vm:vm_platform", + "../vm:vm_platform_stripped", ] vm_snapshot_data = "$target_gen_dir/vm_snapshot_data.bin" vm_snapshot_instructions = "$target_gen_dir/vm_snapshot_instructions.bin" @@ -442,7 +442,7 @@ gen_snapshot_action("generate_snapshot_bin") { isolate_snapshot_instructions = "$target_gen_dir/isolate_snapshot_instructions.bin" - platform_dill = "$root_out_dir/vm_platform_strong.dill" + platform_dill = "$root_out_dir/vm_platform_strong_stripped.dill" inputs = [ platform_dill, ] diff --git a/runtime/bin/dfe.cc b/runtime/bin/dfe.cc index 40a605fcce9..517df575258 100644 --- a/runtime/bin/dfe.cc +++ b/runtime/bin/dfe.cc @@ -31,10 +31,6 @@ intptr_t kPlatformStrongDillSize = 0; namespace dart { namespace bin { -#if !defined(DART_PRECOMPILED_RUNTIME) -DFE dfe; -#endif - #if defined(DART_NO_SNAPSHOT) || defined(DART_PRECOMPILER) const uint8_t* kernel_service_dill = NULL; const intptr_t kernel_service_dill_size = 0; @@ -47,6 +43,10 @@ const uint8_t* platform_strong_dill = kPlatformStrongDill; const intptr_t platform_strong_dill_size = kPlatformStrongDillSize; #endif +#if !defined(DART_PRECOMPILED_RUNTIME) +DFE dfe; +#endif + const char kKernelServiceSnapshot[] = "kernel-service.dart.snapshot"; const char kSnapshotsDirectory[] = "snapshots"; @@ -94,6 +94,9 @@ void DFE::Init() { return; } + Dart_SetDartLibrarySourcesKernel(platform_strong_dill, + platform_strong_dill_size); + if (frontend_filename_ == NULL) { // Look for the frontend snapshot next to the executable. char* dir_prefix = GetDirectoryPrefixFromExeName(); diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h index a0175842981..ef2bff1330e 100644 --- a/runtime/include/dart_api.h +++ b/runtime/include/dart_api.h @@ -3124,6 +3124,19 @@ Dart_CompileSourcesToKernel(const char* script_uri, DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies(); +/** + * Sets the kernel buffer which will be used to load Dart SDK sources + * dynamically at runtime. + * + * \param platform_kernel A buffer containing kernel which has sources for the + * Dart SDK populated. Note: The VM does not take ownership of this memory. + * + * \param platform_kernel_size The length of the platform_kernel buffer. + */ +DART_EXPORT void Dart_SetDartLibrarySourcesKernel( + const uint8_t* platform_kernel, + const intptr_t platform_kernel_size); + #define DART_KERNEL_ISOLATE_NAME "kernel-service" /* diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn index d018eb17027..e27f88616aa 100644 --- a/runtime/vm/BUILD.gn +++ b/runtime/vm/BUILD.gn @@ -98,47 +98,60 @@ library_for_all_configs("libdart_lib") { nosnapshot_sources = [] } -compile_platform("vm_legacy_platform") { - single_root_scheme = "org-dartlang-sdk" - single_root_base = rebase_path("../../") - libraries_specification_uri = "org-dartlang-sdk:///sdk/lib/libraries.json" - - outputs = [ - "$root_out_dir/vm_platform.dill", - "$root_out_dir/vm_outline.dill", - ] - - args = [ - "--legacy-mode", - "dart:core", - ] +template("gen_vm_platform") { + assert(defined(invoker.output_postfix), + "Must define output postfix (e.g., '_strong'") + compile_platform(target_name) { + output_postfix = invoker.output_postfix + if (defined(invoker.add_implicit_vm_platform_dependency)) { + add_implicit_vm_platform_dependency = + invoker.add_implicit_vm_platform_dependency + } + single_root_scheme = "org-dartlang-sdk" + single_root_base = rebase_path("../../") + libraries_specification_uri = "org-dartlang-sdk:///sdk/lib/libraries.json" + outputs = [ + "$root_out_dir/vm_platform" + output_postfix + ".dill", + "$root_out_dir/vm_outline" + output_postfix + ".dill", + ] + args = [ "dart:core" ] + if (defined(invoker.exclude_source) && invoker.exclude_source) { + args += [ "--exclude-source" ] + } + if (defined(invoker.legacy) && invoker.legacy) { + args += [ "--legacy-mode" ] + outline = "vm_outline_strong.dill" + } else { + outline = "vm_outline" + output_postfix + ".dill" + } + if (dart_platform_bytecode) { + args += [ "--bytecode" ] + } + } } -compile_platform("vm_platform") { +gen_vm_platform("vm_legacy_platform") { + exclude_source = false + legacy = true + output_postfix = "" +} + +gen_vm_platform("vm_platform") { add_implicit_vm_platform_dependency = false + exclude_source = false + output_postfix = "_strong" +} - single_root_scheme = "org-dartlang-sdk" - single_root_base = rebase_path("../../") - libraries_specification_uri = "org-dartlang-sdk:///sdk/lib/libraries.json" - - outputs = [ - "$root_out_dir/vm_platform_strong.dill", - "$root_out_dir/vm_outline_strong.dill", - ] - - args = [ - "--exclude-source", - "dart:core", - ] - - if (dart_platform_bytecode) { - args += [ "--bytecode" ] - } +gen_vm_platform("vm_platform_stripped") { + add_implicit_vm_platform_dependency = false + exclude_source = true + output_postfix = "_strong_stripped" } group("kernel_platform_files") { public_deps = [ ":vm_legacy_platform", ":vm_platform", + ":vm_platform_stripped", ] } diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc index c0e9a54e5c9..8301543d012 100644 --- a/runtime/vm/dart_api_impl.cc +++ b/runtime/vm/dart_api_impl.cc @@ -5498,6 +5498,15 @@ DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies() { return result; } +DART_EXPORT void Dart_SetDartLibrarySourcesKernel( + const uint8_t* platform_kernel, + const intptr_t platform_kernel_size) { +#if !defined(PRODUCT) + Service::SetDartLibraryKernelForSources(platform_kernel, + platform_kernel_size); +#endif +} + // --- Service support --- DART_EXPORT bool Dart_IsServiceIsolate(Dart_Isolate isolate) { diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc index 411658948c9..f88eec2f507 100644 --- a/runtime/vm/kernel_loader.cc +++ b/runtime/vm/kernel_loader.cc @@ -283,6 +283,24 @@ void KernelLoader::index_programs( subprogram_file_starts->Reverse(); } +RawString* KernelLoader::FindSourceForScript(const uint8_t* kernel_buffer, + intptr_t kernel_buffer_length, + const String& uri) { + Thread* thread = Thread::Current(); + Zone* zone = thread->zone(); + TranslationHelper translation_helper(thread); + KernelReaderHelper reader(zone, &translation_helper, kernel_buffer, + kernel_buffer_length, 0); + intptr_t source_table_size = reader.SourceTableSize(); + for (intptr_t i = 0; i < source_table_size; ++i) { + const String& source_uri = reader.SourceTableUriFor(i); + if (source_uri.EndsWith(uri)) { + return reader.GetSourceFor(i).raw(); + } + } + return String::null(); +} + void KernelLoader::InitializeFields() { const intptr_t source_table_size = helper_.SourceTableSize(); const Array& scripts = diff --git a/runtime/vm/kernel_loader.h b/runtime/vm/kernel_loader.h index a4eaaa01b9e..9b176ffb6e0 100644 --- a/runtime/vm/kernel_loader.h +++ b/runtime/vm/kernel_loader.h @@ -176,6 +176,10 @@ class KernelLoader : public ValueObject { intptr_t* p_num_classes, intptr_t* p_num_procedures); + static RawString* FindSourceForScript(const uint8_t* kernel_buffer, + intptr_t kernel_buffer_length, + const String& url); + RawLibrary* LoadLibrary(intptr_t index); void FinishTopLevelClassLoading(const Class& toplevel_class, diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 8f7faf656ca..bd4f05ba7d0 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -9086,6 +9086,25 @@ RawString* Script::Source() const { return raw_ptr()->source_; } +bool Script::IsPartOfDartColonLibrary() const { + const String& script_url = String::Handle(url()); + return (script_url.StartsWith(Symbols::DartScheme()) || + script_url.StartsWith(Symbols::DartSchemePrivate())); +} + +#if !defined(DART_PRECOMPILED_RUNTIME) +void Script::LoadSourceFromKernel(const uint8_t* kernel_buffer, + intptr_t kernel_buffer_len) const { + const char* dart_prefix = "dart:"; + const size_t dart_prefix_len = strlen(dart_prefix); + String& uri = String::Handle(url()); + uri ^= String::SubString(uri, dart_prefix_len); + String& source = String::Handle(kernel::KernelLoader::FindSourceForScript( + kernel_buffer, kernel_buffer_len, uri)); + set_source(source); +} +#endif // !defined(DART_PRECOMPILED_RUNTIME) + void Script::set_compile_time_constants(const Array& value) const { StorePointer(&raw_ptr()->compile_time_constants_, value.raw()); } @@ -18922,6 +18941,25 @@ bool String::StartsWith(const String& other) const { return true; } +bool String::EndsWith(const String& other) const { + if (other.IsNull()) { + return false; + } + const intptr_t len = this->Length(); + const intptr_t other_len = other.Length(); + const intptr_t offset = len - other_len; + + if ((other_len == 0) || (other_len > len)) { + return false; + } + for (int i = offset; i < len; i++) { + if (this->CharAt(i) != other.CharAt(i - offset)) { + return false; + } + } + return true; +} + RawInstance* String::CheckAndCanonicalize(Thread* thread, const char** error_str) const { if (IsCanonical()) { diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 029a9886977..d5fc802dd72 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -3385,6 +3385,8 @@ class Script : public Object { RawString* resolved_url() const { return raw_ptr()->resolved_url_; } bool HasSource() const; RawString* Source() const; + bool IsPartOfDartColonLibrary() const; + RawGrowableObjectArray* GenerateLineNumberArray() const; RawScript::Kind kind() const { return static_cast(raw_ptr()->kind_); @@ -3461,6 +3463,11 @@ class Script : public Object { const String& source, RawScript::Kind kind); +#if !defined(DART_PRECOMPILED_RUNTIME) + void LoadSourceFromKernel(const uint8_t* kernel_buffer, + intptr_t kernel_buffer_len) const; +#endif // !defined(DART_PRECOMPILED_RUNTIME) + private: void set_resolved_url(const String& value) const; void set_source(const String& value) const; @@ -7006,6 +7013,7 @@ class String : public Instance { intptr_t CompareTo(const String& other) const; bool StartsWith(const String& other) const; + bool EndsWith(const String& other) const; // Strings are canonicalized using the symbol table. virtual RawInstance* CheckAndCanonicalize(Thread* thread, diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc index c975c03f202..9093836ae4b 100644 --- a/runtime/vm/service.cc +++ b/runtime/vm/service.cc @@ -121,6 +121,9 @@ StreamInfo Service::logging_stream("_Logging"); StreamInfo Service::extension_stream("Extension"); StreamInfo Service::timeline_stream("Timeline"); +const uint8_t* Service::dart_library_kernel_ = NULL; +intptr_t Service::dart_library_kernel_len_ = 0; + static StreamInfo* streams_[] = { &Service::vm_stream, &Service::isolate_stream, &Service::debug_stream, &Service::gc_stream, @@ -1328,6 +1331,12 @@ int64_t Service::MaxRSS() { return info.max_rss; } +void Service::SetDartLibraryKernelForSources(const uint8_t* kernel_bytes, + intptr_t kernel_length) { + dart_library_kernel_ = kernel_bytes; + dart_library_kernel_len_ = kernel_length; +} + EmbedderServiceHandler* Service::FindRootEmbedderHandler(const char* name) { EmbedderServiceHandler* current = root_service_handler_head_; while (current != NULL) { @@ -4322,9 +4331,22 @@ static bool GetObject(Thread* thread, JSONStream* js) { // Handle heap objects. ObjectIdRing::LookupResult lookup_result; - const Object& obj = - Object::Handle(LookupHeapObject(thread, id, &lookup_result)); + Object& obj = Object::Handle(LookupHeapObject(thread, id, &lookup_result)); if (obj.raw() != Object::sentinel().raw()) { +#if !defined(DART_PRECOMPILED_RUNTIME) + // If obj is a script from dart:* and doesn't have source loaded, try and + // load the source before sending the response. + if (obj.IsScript()) { + const Script& script = Script::Cast(obj); + if (!script.HasSource() && script.IsPartOfDartColonLibrary() && + Service::HasDartLibraryKernelForSources()) { + const uint8_t* kernel_buffer = Service::dart_library_kernel(); + const intptr_t kernel_buffer_len = + Service::dart_library_kernel_length(); + script.LoadSourceFromKernel(kernel_buffer, kernel_buffer_len); + } + } +#endif // !defined(DART_PRECOMPILED_RUNTIME) // We found a heap object for this id. Return it. obj.PrintJSON(js, false); return true; diff --git a/runtime/vm/service.h b/runtime/vm/service.h index 3e54a6cb79a..4b05099aae6 100644 --- a/runtime/vm/service.h +++ b/runtime/vm/service.h @@ -184,6 +184,18 @@ class Service : public AllStatic { static int64_t CurrentRSS(); static int64_t MaxRSS(); + static void SetDartLibraryKernelForSources(const uint8_t* kernel_bytes, + intptr_t kernel_length); + static bool HasDartLibraryKernelForSources() { + return (dart_library_kernel_ != NULL); + } + + static const uint8_t* dart_library_kernel() { return dart_library_kernel_; } + + static intptr_t dart_library_kernel_length() { + return dart_library_kernel_len_; + } + private: static RawError* InvokeMethod(Isolate* isolate, const Array& message, @@ -228,11 +240,8 @@ class Service : public AllStatic { static Dart_GetVMServiceAssetsArchive get_service_assets_callback_; static Dart_EmbedderInformationCallback embedder_information_callback_; - static bool needs_isolate_events_; - static bool needs_debug_events_; - static bool needs_gc_events_; - static bool needs_echo_events_; - static bool needs_graph_events_; + static const uint8_t* dart_library_kernel_; + static intptr_t dart_library_kernel_len_; }; } // namespace dart diff --git a/utils/compile_platform.gni b/utils/compile_platform.gni index 94bce50dda5..1d30b6fda34 100644 --- a/utils/compile_platform.gni +++ b/utils/compile_platform.gni @@ -34,6 +34,11 @@ template("compile_platform") { invoker.add_implicit_vm_platform_dependency } + outline = "vm_outline_strong.dill" + if (defined(invoker.outline)) { + outline = invoker.outline + } + prebuilt_dart_action(target_name) { script = "$_dart_root/pkg/front_end/tool/_fasta/compile_platform.dart" @@ -44,7 +49,6 @@ template("compile_platform") { inputs = [] deps = [] args = [] - if (defined(invoker.deps)) { deps += invoker.deps } @@ -54,7 +58,7 @@ template("compile_platform") { } if (add_implicit_vm_platform_dependency) { - inputs += [ "$root_out_dir/vm_outline_strong.dill" ] + inputs += [ "$root_out_dir/$outline" ] deps += [ "$_dart_root/runtime/vm:vm_platform" ] } depfile = outputs[0] + ".d" @@ -73,7 +77,7 @@ template("compile_platform") { [ rebase_path(invoker.libraries_specification_uri, root_build_dir) ] } args += - [ rebase_path("$root_out_dir/vm_outline_strong.dill", root_build_dir) ] + [ rebase_path("$root_out_dir/$outline", root_build_dir) ] args += rebase_path(outputs, root_build_dir) } }