From a72bede5473fd7b278457eb35349a495c65f82f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marja=20H=C3=B6ltt=C3=A4?= Date: Mon, 30 Mar 2026 09:55:56 +0200 Subject: [PATCH 1/5] deps: V8: backport ebd15783b7ba MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original commit message: [objects]: Defer CallSiteInfo creation Store the raw data in a FixedArray and create the CallSiteInfo objects only on demand. This can be further optimized to omit CallSiteInfo creation altogether in some code paths, but currently those code paths are not critically important. Change-Id: I6480862caf6b64020737527c571e3e3eac704ed3 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7673818 Commit-Queue: Marja Hölttä Reviewed-by: Leszek Swirski Cr-Commit-Position: refs/heads/main@{#106127} Refs: https://github.com/v8/v8/commit/ebd15783b7ba67a135212cf7418ca2f85ebb7502 Co-authored-by: Antoine du Hamel --- common.gypi | 2 +- deps/v8/src/execution/isolate.cc | 118 +++++++++++++++++------- deps/v8/src/execution/messages.cc | 39 +++++--- deps/v8/src/heap/factory.cc | 7 +- deps/v8/src/heap/factory.h | 2 +- deps/v8/src/objects/call-site-info.cc | 30 ++++++ deps/v8/src/objects/call-site-info.h | 7 ++ deps/v8/src/objects/debug-objects-inl.h | 14 +-- deps/v8/src/objects/debug-objects.h | 4 +- deps/v8/src/objects/debug-objects.tq | 8 +- deps/v8/src/objects/fixed-array.cc | 36 +++++++- deps/v8/src/objects/fixed-array.h | 13 +++ 12 files changed, 211 insertions(+), 69 deletions(-) diff --git a/common.gypi b/common.gypi index a982da03f78b..f47719bed4cb 100644 --- a/common.gypi +++ b/common.gypi @@ -42,7 +42,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.29', + 'v8_embedder_string': '-node.30', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/execution/isolate.cc b/deps/v8/src/execution/isolate.cc index 06fa14bf6b10..9cf07d5a83f5 100644 --- a/deps/v8/src/execution/isolate.cc +++ b/deps/v8/src/execution/isolate.cc @@ -878,18 +878,21 @@ class CallSiteBuilder { // framework and library code, and stack depth tends to be more than // a dozen frames, so we over-allocate a bit here to avoid growing // the elements array in the common case. - elements_ = isolate->factory()->NewFixedArray(std::min(64, limit)); + elements_ = isolate->factory()->NewFixedArray(CallSiteInfo::Fields::kCount * + std::min(64, limit)); } void SetPrevFrameAsConstructCall() { if (skipped_prev_frame_) return; DCHECK_GT(index_, 0); - Tagged info = - Tagged::cast(elements_->get(index_ - 1)); + int base_index = (index_ - 1) * CallSiteInfo::Fields::kCount; + int flags = + Smi::ToInt(elements_->get(base_index + CallSiteInfo::Fields::kFlags)); #if V8_ENABLE_WEBASSEMBLY - if (info->IsWasm()) return; + if (flags & CallSiteInfo::kIsWasm) return; #endif - info->set_flags(info->flags() | CallSiteInfo::kIsConstructor); + elements_->set(base_index + CallSiteInfo::Fields::kFlags, + Smi::FromInt(flags | CallSiteInfo::kIsConstructor)); } bool Visit(FrameSummary const& summary) { @@ -1051,7 +1054,8 @@ class CallSiteBuilder { bool Full() { return index_ >= limit_; } Handle Build() { - return FixedArray::RightTrimOrEmpty(isolate_, elements_, index_); + return FixedArray::RightTrimOrEmpty(isolate_, elements_, + CallSiteInfo::Fields::kCount * index_); } private: @@ -1116,17 +1120,42 @@ class CallSiteBuilder { void AppendFrame(DirectHandle> receiver_or_instance, DirectHandle> function, - DirectHandle code, int offset, int flags, + DirectHandle code_obj, int offset, int flags, DirectHandle parameters) { if (IsTheHole(*receiver_or_instance, isolate_)) { // TODO(jgruber): Fix all cases in which frames give us a hole value // (e.g. the receiver in RegExp constructor frames). receiver_or_instance = isolate_->factory()->undefined_value(); } - auto info = isolate_->factory()->NewCallSiteInfo( - Cast(receiver_or_instance), function, code, offset, flags, - parameters); - elements_ = FixedArray::SetAndGrow(isolate_, elements_, index_++, info); + + int base_index = index_ * CallSiteInfo::Fields::kCount; + + // Set the last field first and grow the array if needed. + static_assert(CallSiteInfo::Fields::kFlags == + CallSiteInfo::Fields::kCount - 1); + elements_ = FixedArray::SetAndGrow( + isolate_, elements_, base_index + CallSiteInfo::Fields::kFlags, + Smi::FromInt(flags)); + + elements_->set(base_index + CallSiteInfo::Fields::kReceiver, + *receiver_or_instance); + elements_->set(base_index + CallSiteInfo::Fields::kFunction, *function); + + if (DirectHandle code; TryCast(code_obj, &code)) { + elements_->set(base_index + CallSiteInfo::Fields::kCode, code->wrapper()); + } else if (DirectHandle bytecode; + TryCast(code_obj, &bytecode)) { + elements_->set(base_index + CallSiteInfo::Fields::kCode, + bytecode->wrapper()); + } else { + elements_->set(base_index + CallSiteInfo::Fields::kCode, + *isolate_->factory()->undefined_value()); + } + + elements_->set(base_index + CallSiteInfo::Fields::kOffset, + Smi::FromInt(offset)); + + index_++; skipped_prev_frame_ = false; } @@ -1442,13 +1471,18 @@ Handle CaptureSimpleStackTrace(Isolate* isolate, int limit, } DirectHandle GetDetailedStackTraceFromCallSiteInfos( - Isolate* isolate, DirectHandle call_site_infos, int limit) { - auto frames = isolate->factory()->NewFixedArray( - std::min(limit, call_site_infos->length())); - int index = 0; - for (int i = 0; i < call_site_infos->length() && index < limit; ++i) { - DirectHandle call_site_info( - Cast(call_site_infos->get(i)), isolate); + Isolate* isolate, DirectHandle raw_data_for_call_site_infos, + uint32_t limit) { + uint32_t call_site_infos_len = + raw_data_for_call_site_infos->length() / + CallSiteInfo::Fields::kCount; + auto frames = + isolate->factory()->NewFixedArray(std::min(limit, call_site_infos_len)); + uint32_t index = 0; + for (uint32_t i = 0; i < call_site_infos_len && index < limit; ++i) { + DirectHandle call_site_info = + CallSiteInfo::ConstructFromRawData(isolate, + raw_data_for_call_site_infos, i); if (call_site_info->IsAsync()) { break; } @@ -1519,14 +1553,19 @@ MaybeDirectHandle Isolate::CaptureAndSetErrorStack( stack_trace_for_uncaught_exceptions_frame_limit_, stack_trace_for_uncaught_exceptions_options_); } else { - auto call_site_infos = + auto raw_data_for_call_site_infos = Cast(call_site_infos_or_formatted_stack); stack_trace = GetDetailedStackTraceFromCallSiteInfos( - this, call_site_infos, - stack_trace_for_uncaught_exceptions_frame_limit_); - if (stack_trace_limit < call_site_infos->length()) { + this, raw_data_for_call_site_infos, + static_cast( + stack_trace_for_uncaught_exceptions_frame_limit_)); + DCHECK_GE(stack_trace_limit, 0); + if (static_cast(stack_trace_limit) * + CallSiteInfo::Fields::kCount < + raw_data_for_call_site_infos->length()) { call_site_infos_or_formatted_stack = FixedArray::RightTrimOrEmpty( - this, call_site_infos, stack_trace_limit); + this, raw_data_for_call_site_infos, + stack_trace_limit * CallSiteInfo::Fields::kCount); } // Notify the debugger. OnStackTraceCaptured(stack_trace); @@ -1556,17 +1595,27 @@ Handle Isolate::GetSimpleStackTrace( ErrorUtils::StackPropertyLookupResult lookup = ErrorUtils::GetErrorStackProperty(this, maybe_error_object); + Handle raw_data; if (IsFixedArray(*lookup.error_stack)) { - return Cast(lookup.error_stack); - } - if (!IsErrorStackData(*lookup.error_stack)) { + raw_data = Cast(lookup.error_stack); + } else if (IsErrorStackData(*lookup.error_stack)) { + auto error_stack_data = Cast(lookup.error_stack); + if (!error_stack_data->HasRawDataForCallSiteInfos()) { + return factory()->empty_fixed_array(); + } + raw_data = handle(error_stack_data->raw_data_for_call_site_infos(), this); + } else { return factory()->empty_fixed_array(); } - auto error_stack_data = Cast(lookup.error_stack); - if (!error_stack_data->HasCallSiteInfos()) { - return factory()->empty_fixed_array(); + + int frame_count = raw_data->length() / CallSiteInfo::Fields::kCount; + Handle call_site_infos = factory()->NewFixedArray(frame_count); + for (int i = 0; i < frame_count; ++i) { + DirectHandle call_site_info = + CallSiteInfo::ConstructFromRawData(this, raw_data, i); + call_site_infos->set(i, *call_site_info); } - return handle(error_stack_data->call_site_infos(), this); + return call_site_infos; } Address Isolate::GetAbstractPC(int* line, int* column) { @@ -3168,8 +3217,11 @@ void Isolate::PrintCurrentStackTrace( this, FixedArray::kMaxLength, SKIP_NONE, factory()->undefined_value()); IncrementalStringBuilder builder(this); - for (int i = 0; i < frames->length(); ++i) { - DirectHandle frame(Cast(frames->get(i)), this); + uint32_t frame_count = + frames->length() / CallSiteInfo::Fields::kCount; + for (uint32_t i = 0; i < frame_count; ++i) { + DirectHandle frame = + CallSiteInfo::ConstructFromRawData(this, frames, i); if (should_include_frame_callback) { Tagged raw_script_name = frame->GetScriptNameOrSourceURL(); @@ -3193,7 +3245,7 @@ void Isolate::PrintCurrentStackTrace( SerializeCallSiteInfo(this, frame, &builder); } - if (i != frames->length() - 1) builder.AppendCharacter('\n'); + if (i != frame_count - 1) builder.AppendCharacter('\n'); } DirectHandle stack_trace = builder.Finish().ToHandleChecked(); diff --git a/deps/v8/src/execution/messages.cc b/deps/v8/src/execution/messages.cc index b24aafc1be43..ad3913afc30a 100644 --- a/deps/v8/src/execution/messages.cc +++ b/deps/v8/src/execution/messages.cc @@ -24,6 +24,7 @@ #include "src/parsing/parse-info.h" #include "src/parsing/parsing.h" #include "src/roots/roots.h" +#include "src/sandbox/indirect-pointer-inl.h" #include "src/strings/string-builder-inl.h" namespace v8 { @@ -202,15 +203,16 @@ namespace { // Convert the raw frames as written by Isolate::CaptureSimpleStackTrace into // a JSArray of JSCallSite objects. -MaybeDirectHandle GetStackFrames(Isolate* isolate, - DirectHandle frames) { - int frame_count = frames->length(); +MaybeDirectHandle GetStackFrames( + Isolate* isolate, DirectHandle raw_data_for_call_site_infos) { + uint32_t frame_count = raw_data_for_call_site_infos->length() / + CallSiteInfo::Fields::kCount; DirectHandle constructor = isolate->callsite_function(); DirectHandle sites = isolate->factory()->NewFixedArray(frame_count); - for (int i = 0; i < frame_count; ++i) { - DirectHandle frame(Cast(frames->get(i)), - isolate); + for (uint32_t i = 0; i < frame_count; ++i) { + DirectHandle frame = CallSiteInfo::ConstructFromRawData( + isolate, raw_data_for_call_site_infos, i); DirectHandle site; ASSIGN_RETURN_ON_EXCEPTION(isolate, site, JSObject::New(constructor, constructor, @@ -292,7 +294,7 @@ MaybeDirectHandle ErrorUtils::FormatStackTrace( return isolate->factory()->empty_string(); } DCHECK(IsFixedArray(*raw_stack)); - auto elems = Cast(raw_stack); + auto raw_data_for_call_site_infos = Cast(raw_stack); const bool in_recursion = isolate->formatting_stack_trace(); const bool has_overflowed = i::StackLimitCheck{isolate}.HasOverflowed(); @@ -303,8 +305,9 @@ MaybeDirectHandle ErrorUtils::FormatStackTrace( PrepareStackTraceScope scope(isolate); DirectHandle sites; - ASSIGN_RETURN_ON_EXCEPTION(isolate, sites, - GetStackFrames(isolate, elems)); + ASSIGN_RETURN_ON_EXCEPTION( + isolate, sites, + GetStackFrames(isolate, raw_data_for_call_site_infos)); DirectHandle result; ASSIGN_RETURN_ON_EXCEPTION( @@ -329,8 +332,9 @@ MaybeDirectHandle ErrorUtils::FormatStackTrace( isolate->CountUsage(v8::Isolate::kErrorPrepareStackTrace); DirectHandle sites; - ASSIGN_RETURN_ON_EXCEPTION(isolate, sites, - GetStackFrames(isolate, elems)); + ASSIGN_RETURN_ON_EXCEPTION( + isolate, sites, + GetStackFrames(isolate, raw_data_for_call_site_infos)); constexpr int argc = 2; std::array, argc> args; @@ -359,12 +363,16 @@ MaybeDirectHandle ErrorUtils::FormatStackTrace( RETURN_ON_EXCEPTION(isolate, AppendErrorString(isolate, error, &builder)); - for (int i = 0; i < elems->length(); ++i) { + int elems_len = raw_data_for_call_site_infos->length() / + CallSiteInfo::Fields::kCount; + for (int i = 0; i < elems_len; ++i) { builder.AppendCStringLiteral("\n at "); - DirectHandle frame(Cast(elems->get(i)), - isolate); + DirectHandle frame = CallSiteInfo::ConstructFromRawData( + isolate, raw_data_for_call_site_infos, i); + // TODO(marja): Avoid CallSiteInfo creation since we serialize it right + // away. v8::TryCatch try_catch(reinterpret_cast(isolate)); SerializeCallSiteInfo(isolate, frame, &builder); @@ -1165,7 +1173,8 @@ MaybeDirectHandle ErrorUtils::GetFormattedStack( isolate, formatted_stack, FormatStackTrace( isolate, error_object, - direct_handle(error_stack_data->call_site_infos(), isolate))); + direct_handle(error_stack_data->raw_data_for_call_site_infos(), + isolate))); error_stack_data->set_formatted_stack(*formatted_stack); return formatted_stack; } diff --git a/deps/v8/src/heap/factory.cc b/deps/v8/src/heap/factory.cc index 32b47dee39ff..2fc11e822292 100644 --- a/deps/v8/src/heap/factory.cc +++ b/deps/v8/src/heap/factory.cc @@ -1589,13 +1589,14 @@ DirectHandle Factory::NewInterceptorInfo( } DirectHandle Factory::NewErrorStackData( - DirectHandle> call_site_infos_or_formatted_stack, + DirectHandle> + raw_data_for_call_site_infos_or_formatted_stack, DirectHandle stack_trace) { Tagged error_stack_data = NewStructInternal( ERROR_STACK_DATA_TYPE, AllocationType::kYoung); DisallowGarbageCollection no_gc; - error_stack_data->set_call_site_infos_or_formatted_stack( - *call_site_infos_or_formatted_stack, SKIP_WRITE_BARRIER); + error_stack_data->set_raw_data_for_call_site_infos_or_formatted_stack( + *raw_data_for_call_site_infos_or_formatted_stack, SKIP_WRITE_BARRIER); error_stack_data->set_stack_trace(*stack_trace, SKIP_WRITE_BARRIER); return direct_handle(error_stack_data, isolate()); } diff --git a/deps/v8/src/heap/factory.h b/deps/v8/src/heap/factory.h index 67abd4458664..bba53c6a5872 100644 --- a/deps/v8/src/heap/factory.h +++ b/deps/v8/src/heap/factory.h @@ -472,7 +472,7 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase { DirectHandle NewErrorStackData( DirectHandle> - call_site_infos_or_formatted_stack, + raw_data_for_call_site_infos_or_formatted_stack, DirectHandle stack_trace); Handle