From da292abec657f0569355c58d6e94e17a89d0464c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Wed, 18 Jun 2025 08:50:41 +0200 Subject: [PATCH] deps: V8: cherry-pick 3d750c2aa9ef Original commit message: [explicit-resource-management] Fix disposal for context variable This CL adds disposable variable when `using` or `await_using` is referenced by the closure. Bug: 409478039 Change-Id: I162915ea53f5b9f17892fa88d288a94bd50cc46f Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6444591 Reviewed-by: Shu-yu Guo Commit-Queue: Rezvan Mahdavi Hezaveh Cr-Commit-Position: refs/heads/main@{#99746} Refs: https://github.com/v8/v8/commit/3d750c2aa9ef3d44660a977baf4839fc1e9df217 --- common.gypi | 2 +- deps/v8/src/interpreter/bytecode-generator.cc | 46 +++++++++++-------- deps/v8/src/interpreter/bytecode-generator.h | 1 + .../harmony/regress/regress-409478039.js | 24 ++++++++++ 4 files changed, 53 insertions(+), 20 deletions(-) create mode 100644 deps/v8/test/mjsunit/harmony/regress/regress-409478039.js diff --git a/common.gypi b/common.gypi index 5bffe1c6eee7d8..9c3707d46cb053 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,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.17', + 'v8_embedder_string': '-node.21', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/interpreter/bytecode-generator.cc b/deps/v8/src/interpreter/bytecode-generator.cc index a7e07e7fc8ce6c..7925cbd196b393 100644 --- a/deps/v8/src/interpreter/bytecode-generator.cc +++ b/deps/v8/src/interpreter/bytecode-generator.cc @@ -4688,6 +4688,22 @@ void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable, } } +void BytecodeGenerator::AddDisposableValue(VariableMode mode) { + if (mode == VariableMode::kUsing) { + RegisterList args = register_allocator()->NewRegisterList(2); + builder() + ->MoveRegister(current_disposables_stack(), args[0]) + .StoreAccumulatorInRegister(args[1]) + .CallRuntime(Runtime::kAddDisposableValue, args); + } else if (mode == VariableMode::kAwaitUsing) { + RegisterList args = register_allocator()->NewRegisterList(2); + builder() + ->MoveRegister(current_disposables_stack(), args[0]) + .StoreAccumulatorInRegister(args[1]) + .CallRuntime(Runtime::kAddAsyncDisposableValue, args); + } +} + void BytecodeGenerator::BuildVariableAssignment( Variable* variable, Token::Value op, HoleCheckMode hole_check_mode, LookupHoistingMode lookup_hoisting_mode) { @@ -4727,19 +4743,7 @@ void BytecodeGenerator::BuildVariableAssignment( // elide subsequent checks. RememberHoleCheckInCurrentBlock(variable); } - if (mode == VariableMode::kUsing) { - RegisterList args = register_allocator()->NewRegisterList(2); - builder() - ->MoveRegister(current_disposables_stack(), args[0]) - .StoreAccumulatorInRegister(args[1]) - .CallRuntime(Runtime::kAddDisposableValue, args); - } else if (mode == VariableMode::kAwaitUsing) { - RegisterList args = register_allocator()->NewRegisterList(2); - builder() - ->MoveRegister(current_disposables_stack(), args[0]) - .StoreAccumulatorInRegister(args[1]) - .CallRuntime(Runtime::kAddAsyncDisposableValue, args); - } + AddDisposableValue(mode); } builder()->StoreAccumulatorInRegister(destination); } else if (variable->throw_on_const_assignment(language_mode()) && @@ -4780,12 +4784,16 @@ void BytecodeGenerator::BuildVariableAssignment( builder()->LoadAccumulatorWithRegister(value_temp); } - if (mode != VariableMode::kConst || op == Token::kInit) { - if (op == Token::kInit && - variable->HasHoleCheckUseInSameClosureScope()) { - // After initializing a variable it won't be the hole anymore, so - // elide subsequent checks. - RememberHoleCheckInCurrentBlock(variable); + if ((mode != VariableMode::kConst && mode != VariableMode::kUsing && + mode != VariableMode::kAwaitUsing) || + op == Token::kInit) { + if (op == Token::kInit) { + if (variable->HasHoleCheckUseInSameClosureScope()) { + // After initializing a variable it won't be the hole anymore, so + // elide subsequent checks. + RememberHoleCheckInCurrentBlock(variable); + } + AddDisposableValue(mode); } builder()->StoreContextSlot(context_reg, variable, depth); } else if (variable->throw_on_const_assignment(language_mode())) { diff --git a/deps/v8/src/interpreter/bytecode-generator.h b/deps/v8/src/interpreter/bytecode-generator.h index ac35c58727bf49..5a4670e44a13d6 100644 --- a/deps/v8/src/interpreter/bytecode-generator.h +++ b/deps/v8/src/interpreter/bytecode-generator.h @@ -294,6 +294,7 @@ class BytecodeGenerator final : public AstVisitor { Variable* GetPotentialVariableInAccumulator(); + void AddDisposableValue(VariableMode mode); void BuildVariableLoad(Variable* variable, HoleCheckMode hole_check_mode, TypeofMode typeof_mode = TypeofMode::kNotInside); void BuildVariableLoadForAccumulatorValue( diff --git a/deps/v8/test/mjsunit/harmony/regress/regress-409478039.js b/deps/v8/test/mjsunit/harmony/regress/regress-409478039.js new file mode 100644 index 00000000000000..aab8a9343d4551 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/regress/regress-409478039.js @@ -0,0 +1,24 @@ +// Copyright 2025 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: --js-staging + +var log = []; +class Test { + [Symbol.dispose]() { + log.push(42); + } + + f() { + log.push(43); + } +} + +{ + using listener = new Test(); + g = () => listener; +} +g().f(); + +assertEquals(log, [42, 43]);