Browse Source

chore: cherry-pick 3 changes from 1-M132 (#45700)

chore: [33-x-y] cherry-pick 3 changes from 1-M132

* 9209292e7898 from v8
* 97e828af5cbc from v8
* ca504d096c39 from v8

Co-authored-by: John Kleinschmidt <[email protected]>
Pedro Pontes 1 month ago
parent
commit
32d08728ee

+ 3 - 0
patches/v8/.patches

@@ -4,4 +4,7 @@ fix_disable_scope_reuse_associated_dchecks.patch
 fix_compiler_failure_on_older_clang.patch
 cherry-pick-3c2d220ad025.patch
 merged_reland_lower_the_maximum_js_parameter_count.patch
+cherry-pick-9209292e7898.patch
+cherry-pick-97e828af5cbc.patch
+cherry-pick-ca504d096c39.patch
 cherry-pick-8131c09bc129.patch

+ 74 - 0
patches/v8/cherry-pick-9209292e7898.patch

@@ -0,0 +1,74 @@
+From 9209292e7898a05a98d271c3c597a09d66819292 Mon Sep 17 00:00:00 2001
+From: Darius Mercadier <[email protected]>
+Date: Wed, 08 Jan 2025 14:37:24 +0100
+Subject: [PATCH] Merged: [turbofan] Fix CallWithSpread bug when array prototype has changed
+
+Bug: chromium:385386138
+(cherry picked from commit 1be46f0e2e71159a74d8614f9ac108d334797729)
+
+Change-Id: I8b0c95c4072652e6b9ccab792b6685e0e0dcfbb9
+Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6172284
+Auto-Submit: Darius Mercadier <[email protected]>
+Commit-Queue: Darius Mercadier <[email protected]>
+Reviewed-by: Nico Hartmann <[email protected]>
+Cr-Commit-Position: refs/branch-heads/13.2@{#58}
+Cr-Branched-From: 24068c59cedad9ee976ddc05431f5f497b1ebd71-refs/heads/13.2.152@{#1}
+Cr-Branched-From: 6054ba94db0969220be4f94dc1677fc4696bdc4f-refs/heads/main@{#97085}
+---
+
+diff --git a/src/compiler/js-call-reducer.cc b/src/compiler/js-call-reducer.cc
+index a29bd4a..08fd278 100644
+--- a/src/compiler/js-call-reducer.cc
++++ b/src/compiler/js-call-reducer.cc
+@@ -5226,6 +5226,18 @@
+   DCHECK_EQ(static_cast<Node*>(arguments_list)->opcode(),
+             IrOpcode::kJSCreateEmptyLiteralArray);
+ 
++  // Check that arguments_list's prototype is still an array prototype.
++  TNode<Map> map = LoadMap(TNode<HeapObject>::UncheckedCast(arguments_list));
++  TNode<HeapObject> proto = TNode<HeapObject>::UncheckedCast(
++      LoadField(AccessBuilder::ForMapPrototype(), map));
++  TNode<HeapObject> initial_array_prototype =
++      HeapConstant(broker()
++                       ->target_native_context()
++                       .initial_array_prototype(broker())
++                       .object());
++  TNode<Boolean> check = ReferenceEqual(proto, initial_array_prototype);
++  CheckIf(check, DeoptimizeReason::kWrongMap, p.feedback());
++
+   // Turn the JSCallWithArrayLike or JSCallWithSpread roughly into:
+   //
+   //      "arguments_list array is still empty?"
+diff --git a/test/mjsunit/compiler/regress-385386138.js b/test/mjsunit/compiler/regress-385386138.js
+new file mode 100644
+index 0000000..72dadea
+--- /dev/null
++++ b/test/mjsunit/compiler/regress-385386138.js
+@@ -0,0 +1,27 @@
++// 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 --turbofan --no-always-turbofan
++
++function foo() {
++  let val = [];
++  val.__proto__ = RegExp();
++  return Math.max(...val);
++}
++
++%PrepareFunctionForOptimization(foo);
++assertThrows(() => foo(), TypeError,
++             "Spread syntax requires ...iterable[Symbol.iterator] to be a function");
++
++%OptimizeFunctionOnNextCall(foo);
++assertThrows(() => foo(), TypeError,
++             "Spread syntax requires ...iterable[Symbol.iterator] to be a function");
++assertUnoptimized(foo);
++
++
++%OptimizeFunctionOnNextCall(foo);
++assertThrows(() => foo(), TypeError,
++             "Spread syntax requires ...iterable[Symbol.iterator] to be a function");
++// TF should not have speculatively optimized CallWithSpread.
++assertOptimized(foo);

+ 94 - 0
patches/v8/cherry-pick-97e828af5cbc.patch

@@ -0,0 +1,94 @@
+From 97e828af5cbcf50c3ff0064a4a5c22e18c18b4b5 Mon Sep 17 00:00:00 2001
+From: Olivier Flückiger <[email protected]>
+Date: Wed, 08 Jan 2025 16:06:43 +0100
+Subject: [PATCH] Merged: [maglev] regalloc: handle non-loop resumable_loops
+
+Resumable loops which are not loops can be either:
+
+1. An unreachable loop with only a back-edge
+2. A fall-through to a resumable loop with a dead back-edge
+
+Only (1) starts with an empty register state.
+
+Fixed: 386143468
+(cherry picked from commit b44bd24761f1a2eae131bd90be15b5a68cc70f83)
+
+Change-Id: I9ebb028fe17c6f1de00825837acec6f8169dbf67
+Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6172463
+Auto-Submit: Olivier Flückiger <[email protected]>
+Reviewed-by: Toon Verwaest <[email protected]>
+Commit-Queue: Toon Verwaest <[email protected]>
+Cr-Commit-Position: refs/branch-heads/13.2@{#60}
+Cr-Branched-From: 24068c59cedad9ee976ddc05431f5f497b1ebd71-refs/heads/13.2.152@{#1}
+Cr-Branched-From: 6054ba94db0969220be4f94dc1677fc4696bdc4f-refs/heads/main@{#97085}
+---
+
+diff --git a/src/maglev/maglev-interpreter-frame-state.cc b/src/maglev/maglev-interpreter-frame-state.cc
+index 7d904bb..dce7517 100644
+--- a/src/maglev/maglev-interpreter-frame-state.cc
++++ b/src/maglev/maglev-interpreter-frame-state.cc
+@@ -1370,6 +1370,23 @@
+   }
+ }
+ 
++bool MergePointInterpreterFrameState::IsUnreachable() const {
++  DCHECK_EQ(predecessors_so_far_, predecessor_count_);
++  if (predecessor_count_ > 1) {
++    return false;
++  }
++  // This should actually only support predecessor_count == 1, but we
++  // currently don't eliminate resumable loop headers (and subsequent code
++  // until the next resume) that end up being unreachable from JumpLoop.
++  if (predecessor_count_ == 0) {
++    DCHECK(is_resumable_loop());
++    return true;
++  }
++  DCHECK_EQ(predecessor_count_, 1);
++  DCHECK_IMPLIES(is_loop(), predecessor_at(0)->control_node()->Is<JumpLoop>());
++  return is_loop();
++}
++
+ }  // namespace maglev
+ }  // namespace internal
+ }  // namespace v8
+diff --git a/src/maglev/maglev-interpreter-frame-state.h b/src/maglev/maglev-interpreter-frame-state.h
+index d8e618f..3d04b93 100644
+--- a/src/maglev/maglev-interpreter-frame-state.h
++++ b/src/maglev/maglev-interpreter-frame-state.h
+@@ -948,6 +948,8 @@
+            predecessors_so_far_ == 0;
+   }
+ 
++  bool IsUnreachable() const;
++
+   BasicBlockType basic_block_type() const {
+     return kBasicBlockTypeBits::decode(bitfield_);
+   }
+diff --git a/src/maglev/maglev-regalloc.cc b/src/maglev/maglev-regalloc.cc
+index 00456fa..a1d24ed 100644
+--- a/src/maglev/maglev-regalloc.cc
++++ b/src/maglev/maglev-regalloc.cc
+@@ -157,7 +157,7 @@
+   }
+ 
+   // Drop all values on resumable loop headers.
+-  if (target->has_state() && target->state()->is_resumable_loop()) return false;
++  if (target->is_loop() && target->state()->is_resumable_loop()) return false;
+ 
+   // TODO(verwaest): This should be true but isn't because we don't yet
+   // eliminate dead code.
+@@ -409,13 +409,9 @@
+       if (block->state()->is_exception_handler()) {
+         // Exceptions start from a blank state of register values.
+         ClearRegisterValues();
+-      } else if (block->state()->is_resumable_loop() &&
+-                 block->state()->predecessor_count() <= 1) {
++      } else if (block->state()->IsUnreachable()) {
+         // Loops that are only reachable through JumpLoop start from a blank
+         // state of register values.
+-        // This should actually only support predecessor_count == 1, but we
+-        // currently don't eliminate resumable loop headers (and subsequent code
+-        // until the next resume) that end up being unreachable from JumpLoop.
+         ClearRegisterValues();
+       } else {
+         InitializeRegisterValues(block->state()->register_state());

+ 43 - 0
patches/v8/cherry-pick-ca504d096c39.patch

@@ -0,0 +1,43 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Toon Verwaest <[email protected]>
+Date: Tue, 7 Jan 2025 13:35:04 +0100
+Subject: Merged: [compiler] Check max-args when calling bound functions
+
+Bug: 385155406
+(cherry picked from commit d35770876597b8c25de3c483b9368686f3a9fda8)
+
+Change-Id: I98c7166588f4099c5665ff94dc65da5c25be7535
+Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6175036
+Reviewed-by: Leszek Swirski <[email protected]>
+Commit-Queue: Leszek Swirski <[email protected]>
+Auto-Submit: Toon Verwaest <[email protected]>
+Cr-Commit-Position: refs/branch-heads/13.2@{#62}
+Cr-Branched-From: 24068c59cedad9ee976ddc05431f5f497b1ebd71-refs/heads/13.2.152@{#1}
+Cr-Branched-From: 6054ba94db0969220be4f94dc1677fc4696bdc4f-refs/heads/main@{#97085}
+
+diff --git a/src/compiler/js-call-reducer.cc b/src/compiler/js-call-reducer.cc
+index 7c248c80a519708eaa2a25e9289fd6094ed52424..c96910c0c12d8fc12fc21621227a6671896f23ab 100644
+--- a/src/compiler/js-call-reducer.cc
++++ b/src/compiler/js-call-reducer.cc
+@@ -4651,6 +4651,9 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
+       // succeed.
+       FixedArrayRef bound_arguments = function.bound_arguments(broker());
+       const int bound_arguments_length = bound_arguments.length();
++      if (arity + bound_arguments_length > Code::kMaxArguments) {
++        return NoChange();
++      }
+       static constexpr int kInlineSize = 16;  // Arbitrary.
+       base::SmallVector<Node*, kInlineSize> args;
+       for (int i = 0; i < bound_arguments_length; ++i) {
+diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc
+index ea49bb803ac043ad88853dace478c66b496f5735..04ae603717a39357bc4460cafb1713a6a4666544 100644
+--- a/src/compiler/js-inlining.cc
++++ b/src/compiler/js-inlining.cc
+@@ -250,6 +250,7 @@ FrameState JSInliner::CreateArtificialFrameState(
+     Node* context, Node* callee) {
+   const int parameter_count_with_receiver =
+       parameter_count + JSCallOrConstructNode::kReceiverOrNewTargetInputCount;
++  CHECK_LE(parameter_count_with_receiver, kMaxUInt16);
+   const FrameStateFunctionInfo* state_info =
+       common()->CreateFrameStateFunctionInfo(frame_state_type,
+                                              parameter_count_with_receiver, 0,