From 710e610b5af86caee948428573c2f21d5a1d3153 Mon Sep 17 00:00:00 2001 From: eliau2005 Date: Tue, 13 Oct 2026 12:23:03 +0300 Subject: [PATCH 1/2] deps: V8: backport 8dcf14f490c2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original commit message: [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 Change-Id: I07d8d0c36f56c7aee40793b1db272657832ab36f 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 Auto-Submit: eliau elkouby (‫אליהו אלקובי‬‎) Commit-Queue: Patrick Thier Cr-Commit-Position: refs/heads/main@{#110612} Adapted to deps/v8: src/base/unique-array.h does not exist yet, so base::OwnedVector is used in the serializer, and the CodeSerializer override is placed for the older class layout. Refs: https://github.com/v8/v8/commit/8dcf14f490c20b23b90f9f4af56d52abdd933a0c Assisted-by: a closed-source coding agent 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 | 47 ++- deps/v8/src/parsing/parser.h | 14 +- deps/v8/src/parsing/scanner.cc | 63 +--- deps/v8/src/parsing/scanner.h | 23 +- 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 | 329 ++++++++++++++++++ ...pt-parsed-long-magic-comments-expected.txt | 13 + .../script-parsed-long-magic-comments.js | 36 ++ .../unittests/api/deserialize-unittest.cc | 204 +++++++++++ 17 files changed, 731 insertions(+), 109 deletions(-) create mode 100644 deps/v8/test/inspector/debugger/script-parsed-long-magic-comments-expected.txt create mode 100644 deps/v8/test/inspector/debugger/script-parsed-long-magic-comments.js diff --git a/common.gypi b/common.gypi index 9fc77e9445cb..b1bae4999b26 100644 --- a/common.gypi +++ b/common.gypi @@ -44,7 +44,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.15', + 'v8_embedder_string': '-node.16', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/codegen/compiler.cc b/deps/v8/src/codegen/compiler.cc index 7918e1548f8d..3115a6bddca9 100644 --- a/deps/v8/src/codegen/compiler.cc +++ b/deps/v8/src/codegen/compiler.cc @@ -2022,6 +2022,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"); @@ -2766,8 +2769,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 7f8c3152e8ac..93b002b3af5b 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 00dab82d04b4..66dedab448a3 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" @@ -3565,32 +3566,47 @@ void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope) { // ---------------------------------------------------------------------------- // Parser support -template -void Parser::HandleDebugMagicComments(IsolateT* isolate, +void Parser::HandleDebugMagicComments(Isolate* isolate, DirectHandle