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:
parent
755b89772d
commit
54b5ec94e0
2
deps/v8/include/v8-version.h
vendored
2
deps/v8/include/v8-version.h
vendored
@ -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.)
|
||||
|
7
deps/v8/src/flags/flag-definitions.h
vendored
7
deps/v8/src/flags/flag-definitions.h
vendored
@ -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)
|
||||
|
||||
|
27
deps/v8/src/maglev/maglev-graph-builder.cc
vendored
27
deps/v8/src/maglev/maglev-graph-builder.cc
vendored
@ -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);
|
||||
}
|
||||
|
||||
|
41
deps/v8/src/parsing/parser-base.h
vendored
41
deps/v8/src/parsing/parser-base.h
vendored
@ -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());
|
||||
|
7
deps/v8/src/parsing/parser.cc
vendored
7
deps/v8/src/parsing/parser.cc
vendored
@ -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"
|
||||
|
1
deps/v8/src/parsing/parser.h
vendored
1
deps/v8/src/parsing/parser.h
vendored
@ -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);
|
||||
|
2
deps/v8/src/parsing/preparser.h
vendored
2
deps/v8/src/parsing/preparser.h
vendored
@ -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();
|
||||
|
3
deps/v8/src/wasm/graph-builder-interface.cc
vendored
3
deps/v8/src/wasm/graph-builder-interface.cc
vendored
@ -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);
|
||||
}
|
||||
|
||||
|
16
deps/v8/src/wasm/streaming-decoder.cc
vendored
16
deps/v8/src/wasm/streaming-decoder.cc
vendored
@ -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_));
|
||||
|
7
deps/v8/src/wasm/wasm-engine.cc
vendored
7
deps/v8/src/wasm/wasm-engine.cc
vendored
@ -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);
|
||||
}
|
||||
|
||||
|
22
deps/v8/src/wasm/wasm-js.cc
vendored
22
deps/v8/src/wasm/wasm-js.cc
vendored
@ -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;
|
||||
|
18
deps/v8/test/mjsunit/maglev/regress-369630648.js
vendored
Normal file
18
deps/v8/test/mjsunit/maglev/regress-369630648.js
vendored
Normal 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);
|
9
deps/v8/test/mjsunit/regress/regress-363538434.js
vendored
Normal file
9
deps/v8/test/mjsunit/regress/regress-363538434.js
vendored
Normal 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) {}
|
7
deps/v8/test/mjsunit/regress/regress-366323452.js
vendored
Normal file
7
deps/v8/test/mjsunit/regress/regress-366323452.js
vendored
Normal 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(){}];
|
||||
};`);
|
43
deps/v8/test/mjsunit/regress/wasm/regress-368241691.js
vendored
Normal file
43
deps/v8/test/mjsunit/regress/wasm/regress-368241691.js
vendored
Normal 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));
|
Loading…
x
Reference in New Issue
Block a user