From 69c6070601652ef95db943871f2a8d6f1e665bce Mon Sep 17 00:00:00 2001 From: eliau2005 Date: Thu, 29 Oct 2026 22:57:58 +0200 Subject: [PATCH 1/2] deps: V8: backport 5ba8aab1ec1b Original commit message: Reland "[parser] Create debug magic comment values as source substrings" This is a reland of commit 8dcf14f490c20b23b90f9f4af56d52abdd933a0c Changes since the original: The original made every value with at least SlicedString::kMinLength characters a SlicedString of the source, including usual source URLs like //# sourceURL=inside-direct-eval.js. Heap snapshots name sliced strings "(sliced string)" instead of by their contents, so DevTools' heap snapshot ContextAnalyzer, which reads the name of the script's source_url node, showed "(sliced string)" instead of the source URL. The source URL is now always a sequential copy of its value, as before the original (which internalized it), since it is used as the script name (stack traces, profiles, heap snapshots). The debug ID is also copied, since it is short. Only the sourceMappingURL value is a substring of the source, which covers the case the original was about (huge inline source maps). A huge sourceURL or debugId value is copied onto the heap as before the original. Added a regression test that a source URL longer than SlicedString::kMinLength is sequential (script, streaming and direct eval) and that heap snapshots name the source_url node by it, and updated the existing tests accordingly. Original change's description: > [parser] Create debug magic comment values as source substrings > > The values of the //# sourceURL, sourceMappingURL and debugId magic > comments were copied into LiteralBuffers while scanning and then > internalized. An inline source map (sourceMappingURL=data:...) can be > tens of MiB, so this allocated a string of that size on the heap in a > non-throwing allocation, e.g. aborting a Node.js worker with a small > old-generation limit even though the (external) source fits. > > The scanner now only records the source locations of these values, and > the values are created as substrings of the script source: > - On the main thread, when parsing finishes. > - For background and streaming compiles, where the source is not > available while parsing, the locations are kept in the > BackgroundCompileTask and the substrings are created in > FinalizeScript after the source is set. Locations outside of the > source provided by the embedder are ignored. > > The semantics are unchanged: the last comment wins, trailing garbage or > an empty value removes the value, and a source map URL provided through > the API takes precedence. > > Since these values are now usually SlicedStrings of the script source, > the code serializer serializes all sliced strings as sequential > strings (one-byte if their contents are, even if their parent is > two-byte). The script source is an attached object, and off-thread > deserialization attaches a placeholder for it, so a serialized slice > of it would not be valid. > > Consuming a code cache still materializes these values as sequential > strings, e.g. on Node.js's NODE_COMPILE_CACHE path, so a huge cached > value can still be large on the heap there. Keeping them as substrings > of the source when deserializing requires a code cache format change > and is left for a follow-up. > > This also removes the LiteralBuffer copies of the values. > > R=leszeks@chromium.org, verwaest@chromium.org > > Bug: 566467883 > Refs: https://github.com/nodejs/node/issues/64155 > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/8472768 > Reviewed-by: Leszek Swirski > Reviewed-by: Patrick Thier > Cr-Commit-Position: refs/heads/main@{#110612} R=leszeks@chromium.org, verwaest@chromium.org, pthier@chromium.org Bug: 566467883 Change-Id: I76eec1fdaf71526afdd881d0d4a2b117c32d3ba8 Refs: https://github.com/nodejs/node/issues/64155 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/8579167 Reviewed-by: Patrick Thier Commit-Queue: Patrick Thier Reviewed-by: Toon Verwaest Cr-Commit-Position: refs/heads/main@{#111132} Adapted to deps/v8: this also includes the upstream refactor b0f6ad031f03 ("[parser] Factor magic comment value scanning into a helper"), which the reland is based on. src/base/unique-array.h does not exist yet, so base::OwnedVector is used in the serializer, the serializer keeps the 15.6 external string handling (without the later SBXCHECK hardening), and the CodeSerializer override is placed for the older class layout. The inspector test is not included because deps/v8 does not ship test/inspector. Refs: https://github.com/v8/v8/commit/5ba8aab1ec1bf4376a16fa263be52e8752bbc761 Refs: https://github.com/v8/v8/commit/b0f6ad031f0303f279663760d3dd998a5e061e54 Signed-off-by: eliau2005 --- common.gypi | 2 +- deps/v8/src/codegen/compiler.cc | 11 +- deps/v8/src/codegen/compiler.h | 4 + deps/v8/src/parsing/literal-buffer.cc | 18 - deps/v8/src/parsing/literal-buffer.h | 3 - deps/v8/src/parsing/parser.cc | 52 ++- deps/v8/src/parsing/parser.h | 15 +- deps/v8/src/parsing/scanner.cc | 116 +++--- deps/v8/src/parsing/scanner.h | 29 +- deps/v8/src/snapshot/code-serializer.h | 6 + deps/v8/src/snapshot/serializer.cc | 56 ++- deps/v8/src/snapshot/serializer.h | 7 + deps/v8/test/cctest/cctest.h | 4 +- deps/v8/test/cctest/test-api.cc | 372 ++++++++++++++++++ deps/v8/test/cctest/test-heap-profiler.cc | 31 ++ .../unittests/api/deserialize-unittest.cc | 210 ++++++++++ 16 files changed, 802 insertions(+), 134 deletions(-) diff --git a/common.gypi b/common.gypi index a8dbd9ba13e4..5e100167a421 100644 --- a/common.gypi +++ b/common.gypi @@ -50,7 +50,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.10', + 'v8_embedder_string': '-node.11', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/codegen/compiler.cc b/deps/v8/src/codegen/compiler.cc index 0a3599ee41c4..2f8ffee6a90f 100644 --- a/deps/v8/src/codegen/compiler.cc +++ b/deps/v8/src/codegen/compiler.cc @@ -2024,6 +2024,9 @@ void BackgroundCompileTask::Run( parser.ParseOnBackground(isolate, &info, script_, start_position_, end_position_, function_literal_id_); parser.UpdateStatistics(script_, &use_counts_, &total_preparse_skipped_); + if (toplevel_script_compilation) { + debug_magic_comment_locations_ = parser.debug_magic_comment_locations(); + } TRACE_EVENT(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCodeBackground"); @@ -2767,8 +2770,14 @@ MaybeHandle BackgroundCompileTask::FinalizeScript( { DisallowGarbageCollection no_gc; SetScriptFieldsFromDetails(isolate, *script, script_details, &no_gc); - LOG(isolate, ScriptDetails(*script)); } + // After SetScriptFieldsFromDetails, so that a source map URL provided + // through the API takes precedence. The locations come from the streamed + // source; the embedder is expected to pass the same source here, but an + // out-of-bounds location is ignored. + Parser::SetDebugMagicCommentFields(isolate, script, source, + debug_magic_comment_locations_); + LOG(isolate, ScriptDetails(*script)); } ReportStatistics(isolate); diff --git a/deps/v8/src/codegen/compiler.h b/deps/v8/src/codegen/compiler.h index cfa6af01010b..429be4cc70ec 100644 --- a/deps/v8/src/codegen/compiler.h +++ b/deps/v8/src/codegen/compiler.h @@ -24,6 +24,7 @@ #include "src/objects/debug-objects.h" #include "src/parsing/parse-info.h" #include "src/parsing/pending-compilation-error-handler.h" +#include "src/parsing/scanner.h" // For Scanner::DebugMagicCommentLocations. #include "src/snapshot/code-serializer.h" #include "src/utils/allocation.h" #include "src/zone/zone.h" @@ -649,6 +650,9 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask { DeferredFinalizationJobDataList jobs_to_retry_finalization_on_main_thread_; base::SmallVector use_counts_; int total_preparse_skipped_ = 0; + // The source is not available on the background thread, so the debug magic + // comment values are created from these locations when finalizing. + Scanner::DebugMagicCommentLocations debug_magic_comment_locations_; // Single function data for top-level function compilation. MaybeIndirectHandle input_shared_info_; diff --git a/deps/v8/src/parsing/literal-buffer.cc b/deps/v8/src/parsing/literal-buffer.cc index 32ff27eb10a8..bfc7e762e523 100644 --- a/deps/v8/src/parsing/literal-buffer.cc +++ b/deps/v8/src/parsing/literal-buffer.cc @@ -5,29 +5,11 @@ #include "src/parsing/literal-buffer.h" #include "src/base/strings.h" -#include "src/execution/isolate.h" -#include "src/execution/local-isolate.h" -#include "src/heap/factory.h" -#include "src/objects/objects.h" -#include "src/objects/string.h" #include "src/utils/memcopy.h" namespace v8 { namespace internal { -template -DirectHandle LiteralBuffer::Internalize(IsolateT* isolate) const { - if (is_one_byte()) { - return isolate->factory()->InternalizeString(one_byte_literal()); - } - return isolate->factory()->InternalizeString(two_byte_literal()); -} - -template DirectHandle LiteralBuffer::Internalize( - Isolate* isolate) const; -template DirectHandle LiteralBuffer::Internalize( - LocalIsolate* isolate) const; - size_t LiteralBuffer::NewCapacity(size_t min_capacity) { return min_capacity < (kMaxGrowth / (kGrowthFactor - 1)) ? min_capacity * kGrowthFactor diff --git a/deps/v8/src/parsing/literal-buffer.h b/deps/v8/src/parsing/literal-buffer.h index b6d7c9e00d09..1f0dff493662 100644 --- a/deps/v8/src/parsing/literal-buffer.h +++ b/deps/v8/src/parsing/literal-buffer.h @@ -98,9 +98,6 @@ class LiteralBuffer final { is_one_byte_ = true; } - template - DirectHandle Internalize(IsolateT* isolate) const; - private: static constexpr size_t kInitialCapacity = 256; static constexpr size_t kGrowthFactor = 4; diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc index 388e4f1c96e7..60f140ef5f89 100644 --- a/deps/v8/src/parsing/parser.cc +++ b/deps/v8/src/parsing/parser.cc @@ -20,6 +20,7 @@ #include "src/common/message-template.h" #include "src/common/scoped-modification.h" #include "src/compiler-dispatcher/lazy-compile-dispatcher.h" +#include "src/heap/factory-inl.h" #include "src/heap/local-heap-inl.h" #include "src/heap/parked-scope.h" #include "src/logging/counters.h" @@ -3572,32 +3573,50 @@ void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope) { // ---------------------------------------------------------------------------- // Parser support -template -void Parser::HandleDebugMagicComments(IsolateT* isolate, +void Parser::HandleDebugMagicComments(Isolate* isolate, DirectHandle