deps: patch V8 to 12.9.202.26

Refs: https://github.com/v8/v8/compare/12.9.202.19...12.9.202.26
PR-URL: https://github.com/nodejs/node/pull/55161
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
This commit is contained in:
Node.js GitHub Bot 2024-10-09 09:32:15 +02:00 committed by GitHub
parent 755b89772d
commit 54b5ec94e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 176 additions and 36 deletions

View File

@ -11,7 +11,7 @@
#define V8_MAJOR_VERSION 12
#define V8_MINOR_VERSION 9
#define V8_BUILD_NUMBER 202
#define V8_PATCH_LEVEL 19
#define V8_PATCH_LEVEL 26
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)

View File

@ -566,8 +566,8 @@ DEFINE_BOOL(maglev_inlining, true,
"enable inlining in the maglev optimizing compiler")
DEFINE_BOOL(maglev_loop_peeling, true,
"enable loop peeling in the maglev optimizing compiler")
DEFINE_BOOL(maglev_optimistic_peeled_loops, true,
"enable aggressive optimizations for loops (loop SPeeling) in the "
DEFINE_BOOL(maglev_optimistic_peeled_loops, false,
"enable speculation on loop state using peeling as fallback in the "
"maglev optimizing compiler")
DEFINE_INT(maglev_loop_peeling_max_size, 200,
"max loop size for loop peeling in the maglev optimizing compiler")
@ -582,6 +582,7 @@ DEFINE_BOOL(maglev_destroy_on_background, true,
DEFINE_BOOL(maglev_inline_api_calls, false,
"Inline CallApiCallback builtin into generated code")
DEFINE_EXPERIMENTAL_FEATURE(maglev_licm, "loop invariant code motion")
DEFINE_WEAK_IMPLICATION(maglev_future, maglev_optimistic_peeled_loops)
DEFINE_WEAK_IMPLICATION(maglev_future, maglev_speculative_hoist_phi_untagging)
DEFINE_WEAK_IMPLICATION(maglev_future, maglev_inline_api_calls)
DEFINE_WEAK_IMPLICATION(maglev_future, maglev_escape_analysis)
@ -2499,7 +2500,7 @@ DEFINE_BOOL_READONLY(fast_map_update, false,
DEFINE_INT(max_valid_polymorphic_map_count, 4,
"maximum number of valid maps to track in POLYMORPHIC state")
DEFINE_BOOL(
clone_object_sidestep_transitions, true,
clone_object_sidestep_transitions, false,
"support sidestep transitions for dependency tracking object clone maps")
DEFINE_WEAK_IMPLICATION(future, clone_object_sidestep_transitions)

View File

@ -1370,7 +1370,14 @@ DeoptFrame MaglevGraphBuilder::GetDeoptFrameForLazyDeoptHelper(
current_source_position_, GetParentDeoptFrame());
ret.frame_state()->ForEachValue(
*compilation_unit_, [this](ValueNode* node, interpreter::Register reg) {
AddDeoptUse(node);
// Receiver and closure values have to be materialized, even if
// they don't otherwise escape.
if (reg == interpreter::Register::receiver() ||
reg == interpreter::Register::function_closure()) {
node->add_use();
} else {
AddDeoptUse(node);
}
});
AddDeoptUse(ret.closure());
return ret;
@ -6965,15 +6972,21 @@ void MaglevGraphBuilder::VisitDeletePropertySloppy() {
void MaglevGraphBuilder::VisitGetSuperConstructor() {
ValueNode* active_function = GetAccumulator();
ValueNode* map_proto;
// TODO(victorgomes): Maybe BuildLoadTaggedField should support constants
// instead.
if (compiler::OptionalHeapObjectRef constant =
TryGetConstant(active_function)) {
map_proto = GetConstant(constant->map(broker()).prototype(broker()));
} else {
ValueNode* map =
BuildLoadTaggedField(active_function, HeapObject::kMapOffset);
map_proto = BuildLoadTaggedField(map, Map::kPrototypeOffset);
compiler::MapRef map = constant->map(broker());
if (map.is_stable()) {
broker()->dependencies()->DependOnStableMap(map);
ValueNode* map_proto = GetConstant(map.prototype(broker()));
StoreRegister(iterator_.GetRegisterOperand(0), map_proto);
return;
}
}
ValueNode* map =
BuildLoadTaggedField(active_function, HeapObject::kMapOffset);
ValueNode* map_proto = BuildLoadTaggedField(map, Map::kPrototypeOffset);
StoreRegister(iterator_.GetRegisterOperand(0), map_proto);
}

View File

@ -620,26 +620,32 @@ class ParserBase {
return instance_members_scope != nullptr;
}
DeclarationScope* EnsureStaticElementsScope(ParserBase* parser,
int beg_pos) {
DeclarationScope* EnsureStaticElementsScope(ParserBase* parser, int beg_pos,
int info_id) {
if (!has_static_elements()) {
static_elements_scope = parser->NewFunctionScope(
FunctionKind::kClassStaticInitializerFunction);
static_elements_scope->SetLanguageMode(LanguageMode::kStrict);
static_elements_scope->set_start_position(beg_pos);
static_elements_function_id = parser->GetNextInfoId();
static_elements_function_id = info_id;
// Actually consume the id. The id that was passed in might be an
// earlier id in case of computed property names.
parser->GetNextInfoId();
}
return static_elements_scope;
}
DeclarationScope* EnsureInstanceMembersScope(ParserBase* parser,
int beg_pos) {
int beg_pos, int info_id) {
if (!has_instance_members()) {
instance_members_scope = parser->NewFunctionScope(
FunctionKind::kClassMembersInitializerFunction);
instance_members_scope->SetLanguageMode(LanguageMode::kStrict);
instance_members_scope->set_start_position(beg_pos);
instance_members_function_id = parser->GetNextInfoId();
instance_members_function_id = info_id;
// Actually consume the id. The id that was passed in might be an
// earlier id in case of computed property names.
parser->GetNextInfoId();
}
return instance_members_scope;
}
@ -1321,7 +1327,7 @@ class ParserBase {
ParseFunctionFlags flags, bool is_static,
bool* has_seen_constructor);
ExpressionT ParseMemberInitializer(ClassInfo* class_info, int beg_pos,
bool is_static);
int info_id, bool is_static);
BlockT ParseClassStaticBlock(ClassInfo* class_info);
ObjectLiteralPropertyT ParseObjectPropertyDefinition(
ParsePropertyInfo* prop_info, bool* has_seen_proto);
@ -2624,6 +2630,8 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassInfo* class_info,
DCHECK_NOT_NULL(class_info);
DCHECK_EQ(prop_info->position, PropertyPosition::kClassLiteral);
int next_info_id = PeekNextInfoId();
Token::Value name_token = peek();
int property_beg_pos = peek_position();
int name_token_position = property_beg_pos;
@ -2667,12 +2675,18 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassInfo* class_info,
// field.
DCHECK_IMPLIES(prop_info->is_computed_name, !prop_info->is_private);
if (!prop_info->is_computed_name) {
if (prop_info->is_computed_name) {
if (!has_error() && next_info_id != PeekNextInfoId() &&
!(prop_info->is_static ? class_info->has_static_elements()
: class_info->has_instance_members())) {
impl()->ReindexComputedMemberName(name_expression);
}
} else {
CheckClassFieldName(prop_info->name, prop_info->is_static);
}
ExpressionT value = ParseMemberInitializer(class_info, property_beg_pos,
prop_info->is_static);
ExpressionT value = ParseMemberInitializer(
class_info, property_beg_pos, next_info_id, prop_info->is_static);
ExpectSemicolon();
ClassLiteralPropertyT result;
@ -2786,11 +2800,12 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassInfo* class_info,
template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberInitializer(
ClassInfo* class_info, int beg_pos, bool is_static) {
ClassInfo* class_info, int beg_pos, int info_id, bool is_static) {
FunctionParsingScope body_parsing_scope(impl());
DeclarationScope* initializer_scope =
is_static ? class_info->EnsureStaticElementsScope(this, beg_pos)
: class_info->EnsureInstanceMembersScope(this, beg_pos);
is_static
? class_info->EnsureStaticElementsScope(this, beg_pos, info_id)
: class_info->EnsureInstanceMembersScope(this, beg_pos, info_id);
if (Check(Token::kAssign)) {
FunctionState initializer_state(&function_state_, &scope_,
@ -2811,7 +2826,7 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseClassStaticBlock(
Consume(Token::kStatic);
DeclarationScope* initializer_scope =
class_info->EnsureStaticElementsScope(this, position());
class_info->EnsureStaticElementsScope(this, position(), PeekNextInfoId());
FunctionState initializer_state(&function_state_, &scope_, initializer_scope);
FunctionParsingScope body_parsing_scope(impl());

View File

@ -2735,6 +2735,13 @@ void Parser::ReindexArrowFunctionFormalParameters(
}
}
void Parser::ReindexComputedMemberName(Expression* computed_name) {
// Make space for the member initializer function above the computed property
// name.
AstFunctionLiteralIdReindexer reindexer(stack_limit_, 1);
reindexer.Reindex(computed_name);
}
void Parser::PrepareGeneratorVariables() {
// Calling a generator returns a generator object. That object is stored
// in a temporary variable, a definition that is used by "yield"

View File

@ -894,6 +894,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
}
void ReindexArrowFunctionFormalParameters(ParserFormalParameters* parameters);
void ReindexComputedMemberName(Expression* computed_name);
void DeclareArrowFunctionFormalParameters(
ParserFormalParameters* parameters, Expression* params,
const Scanner::Location& params_loc);

View File

@ -1556,6 +1556,8 @@ class PreParser : public ParserBase<PreParser> {
V8_INLINE void ReindexArrowFunctionFormalParameters(
PreParserFormalParameters* parameters) {}
V8_INLINE void ReindexComputedMemberName(
const PreParserExpression& expression) {}
V8_INLINE void DeclareFormalParameters(
const PreParserFormalParameters* parameters) {
if (!parameters->is_simple) parameters->scope->SetHasNonSimpleParameters();

View File

@ -1206,7 +1206,6 @@ class WasmGraphBuildingInterface {
void BrOnNonNull(FullDecoder* decoder, const Value& ref_object, Value* result,
uint32_t depth, bool /* drop_null_on_fallthrough */) {
result->node = ref_object.node;
SsaEnv* false_env = ssa_env_;
SsaEnv* true_env = Split(decoder->zone(), false_env);
false_env->SetNotMerged();
@ -1214,6 +1213,8 @@ class WasmGraphBuildingInterface {
builder_->BrOnNull(ref_object.node, ref_object.type);
builder_->SetControl(false_env->control);
ScopedSsaEnv scoped_env(this, true_env);
// Make sure the TypeGuard has the right Control dependency.
SetAndTypeNode(result, builder_->TypeGuard(ref_object.node, result->type));
BrOrRet(decoder, depth);
}

View File

@ -294,6 +294,10 @@ void AsyncStreamingDecoder::Finish(bool can_use_compiled_module) {
if (!full_wire_bytes_.back().empty()) {
size_t total_length = 0;
for (auto& bytes : full_wire_bytes_) total_length += bytes.size();
if (ok()) {
// {DecodeSectionLength} enforces this with graceful error reporting.
CHECK_LE(total_length, max_module_size());
}
auto all_bytes = base::OwnedVector<uint8_t>::NewForOverwrite(total_length);
uint8_t* ptr = all_bytes.begin();
for (auto& bytes : full_wire_bytes_) {
@ -627,6 +631,18 @@ std::unique_ptr<AsyncStreamingDecoder::DecodingState>
AsyncStreamingDecoder::DecodeSectionLength::NextWithValue(
AsyncStreamingDecoder* streaming) {
TRACE_STREAMING("DecodeSectionLength(%zu)\n", value_);
// Check if this section fits into the overall module length limit.
// Note: {this->module_offset_} is the position of the section ID byte,
// {streaming->module_offset_} is the start of the section's payload (i.e.
// right after the just-decoded section length varint).
// The latter can already exceed the max module size, when the previous
// section barely fit into it, and this new section's ID or length crossed
// the threshold.
uint32_t payload_start = streaming->module_offset();
size_t max_size = max_module_size();
if (payload_start > max_size || max_size - payload_start < value_) {
return streaming->ToErrorState();
}
SectionBuffer* buf =
streaming->CreateNewBuffer(module_offset_, section_id_, value_,
buffer().SubVector(0, bytes_consumed_));

View File

@ -2016,10 +2016,11 @@ uint32_t max_table_init_entries() {
// {max_module_size} is declared in wasm-limits.h.
size_t max_module_size() {
// Clamp the value of --wasm-max-module-size between 16 and just below 2GB.
// Clamp the value of --wasm-max-module-size between 16 and the maximum
// that the implementation supports.
constexpr size_t kMin = 16;
constexpr size_t kMax = RoundDown<kSystemPointerSize>(size_t{kMaxInt});
static_assert(kMin <= kV8MaxWasmModuleSize && kV8MaxWasmModuleSize <= kMax);
constexpr size_t kMax = kV8MaxWasmModuleSize;
static_assert(kMin <= kV8MaxWasmModuleSize);
return std::clamp(v8_flags.wasm_max_module_size.value(), kMin, kMax);
}

View File

@ -202,8 +202,8 @@ GET_FIRST_ARGUMENT_AS(Tag)
#undef GET_FIRST_ARGUMENT_AS
i::wasm::ModuleWireBytes GetFirstArgumentAsBytes(
const v8::FunctionCallbackInfo<v8::Value>& info, ErrorThrower* thrower,
bool* is_shared) {
const v8::FunctionCallbackInfo<v8::Value>& info, size_t max_length,
ErrorThrower* thrower, bool* is_shared) {
DCHECK(i::ValidateCallbackInfo(info));
const uint8_t* start = nullptr;
size_t length = 0;
@ -234,7 +234,6 @@ i::wasm::ModuleWireBytes GetFirstArgumentAsBytes(
if (length == 0) {
thrower->CompileError("BufferSource argument is empty");
}
size_t max_length = i::wasm::max_module_size();
if (length > max_length) {
// The spec requires a CompileError for implementation-defined limits, see
// https://webassembly.github.io/spec/js-api/index.html#limits.
@ -637,7 +636,8 @@ void WebAssemblyCompileImpl(const v8::FunctionCallbackInfo<v8::Value>& info) {
new AsyncCompilationResolver(isolate, context, promise_resolver));
bool is_shared = false;
auto bytes = GetFirstArgumentAsBytes(info, &thrower, &is_shared);
auto bytes = GetFirstArgumentAsBytes(info, i::wasm::max_module_size(),
&thrower, &is_shared);
if (thrower.error()) {
resolver->OnCompilationFailed(thrower.Reify());
return;
@ -669,8 +669,11 @@ void WasmStreamingCallbackForTesting(
v8::WasmStreaming::Unpack(info.GetIsolate(), info.Data());
bool is_shared = false;
// We don't check the buffer length up front, to allow d8 to test that the
// streaming decoder implementation handles overly large inputs correctly.
size_t unlimited = std::numeric_limits<size_t>::max();
i::wasm::ModuleWireBytes bytes =
GetFirstArgumentAsBytes(info, &thrower, &is_shared);
GetFirstArgumentAsBytes(info, unlimited, &thrower, &is_shared);
if (thrower.error()) {
streaming->Abort(Utils::ToLocal(thrower.Reify()));
return;
@ -771,7 +774,8 @@ void WebAssemblyValidateImpl(const v8::FunctionCallbackInfo<v8::Value>& info) {
ErrorThrower thrower(i_isolate, "WebAssembly.validate()");
bool is_shared = false;
auto bytes = GetFirstArgumentAsBytes(info, &thrower, &is_shared);
auto bytes = GetFirstArgumentAsBytes(info, i::wasm::max_module_size(),
&thrower, &is_shared);
v8::ReturnValue<v8::Value> return_value = info.GetReturnValue();
@ -850,7 +854,8 @@ void WebAssemblyModuleImpl(const v8::FunctionCallbackInfo<v8::Value>& info) {
}
bool is_shared = false;
auto bytes = GetFirstArgumentAsBytes(info, &thrower, &is_shared);
auto bytes = GetFirstArgumentAsBytes(info, i::wasm::max_module_size(),
&thrower, &is_shared);
if (thrower.error()) {
return;
@ -1168,7 +1173,8 @@ void WebAssemblyInstantiateImpl(
}
bool is_shared = false;
auto bytes = GetFirstArgumentAsBytes(info, &thrower, &is_shared);
auto bytes = GetFirstArgumentAsBytes(info, i::wasm::max_module_size(),
&thrower, &is_shared);
if (thrower.error()) {
resolver->OnInstantiationFailed(thrower.Reify());
return;

View File

@ -0,0 +1,18 @@
// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Flags: --allow-natives-syntax --no-lazy-feedback-allocation
class C extends Array {
constructor() {
(() => (() => super())())();
}
}
%PrepareFunctionForOptimization(C);
new C();
new C();
%OptimizeFunctionOnNextCall(C);
new C();
C.__proto__ = [1];
assertThrows(() => { new C() }, TypeError);

View File

@ -0,0 +1,9 @@
// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
try {
new class {
static [function(){}] = [].trigger_error();
}
} catch (e) {}

View File

@ -0,0 +1,7 @@
// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
assertThrows(`new class {
static [{aaa(){}];
};`);

View File

@ -0,0 +1,43 @@
// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
let builder = new WasmModuleBuilder();
let struct0 = builder.addStruct([makeField(kWasmI32, true)]);
let return_struct0 = builder.addType(makeSig([], [wasmRefType(struct0)]));
builder.addFunction("makeStruct", return_struct0)
.exportFunc()
.addBody([
kExprI32Const, 42,
kGCPrefix, kExprStructNew, struct0,
]);
let callee = builder.addFunction("callee", makeSig([wasmRefType(struct0)], [kWasmI32]))
.addBody([
kExprLocalGet, 0,
kGCPrefix, kExprStructGet, struct0, 0,
]);
builder.addFunction("main", makeSig([wasmRefNullType(struct0)], [kWasmI32]))
.exportFunc()
.addBody([
kExprBlock, return_struct0,
kExprLocalGet, 0,
kExprBrOnNonNull, 0,
kExprUnreachable,
kExprEnd,
kExprCallFunction, callee.index,
]);
let instance = builder.instantiate();
let obj = instance.exports.makeStruct();
instance.exports.main(obj);
%WasmTierUpFunction(instance.exports.main);
assertEquals(42, instance.exports.main(obj));