From 4c478d9eafd56babfb9c6da56a8c946979751660 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= <targos@protonmail.com>
Date: Tue, 26 Oct 2021 18:20:06 +0200
Subject: [PATCH] deps: patch V8 to 9.4.146.24

Refs: https://github.com/v8/v8/compare/9.4.146.19...9.4.146.24
---
 deps/v8/OWNERS                                |  4 ++
 deps/v8/include/OWNERS                        |  3 ++
 deps/v8/include/v8-version.h                  |  2 +-
 deps/v8/src/execution/isolate-inl.h           |  2 +-
 deps/v8/src/heap/cppgc/marker.cc              |  8 +++-
 deps/v8/src/heap/cppgc/marking-state.h        | 41 +++++++++++++---
 deps/v8/src/ic/accessor-assembler.cc          |  4 +-
 deps/v8/src/ic/ic.cc                          |  8 +++-
 deps/v8/src/wasm/module-compiler.cc           |  8 ++--
 ...est-serialization-with-lazy-compilation.js |  3 +-
 .../heap/cppgc/ephemeron-pair-unittest.cc     | 45 +++++++++++++++++
 .../unittests/heap/cppgc/marker-unittest.cc   | 48 +++++++++++++++++++
 12 files changed, 159 insertions(+), 17 deletions(-)

diff --git a/deps/v8/OWNERS b/deps/v8/OWNERS
index f9b23f237f546e..4fcf830fcc2a30 100644
--- a/deps/v8/OWNERS
+++ b/deps/v8/OWNERS
@@ -27,6 +27,10 @@ per-file codereview.settings=file:INFRA_OWNERS
 per-file AUTHORS=file:COMMON_OWNERS
 per-file WATCHLISTS=file:COMMON_OWNERS
 
+# Needed by the auto_tag builder
+per-file WATCHLISTS=v8-ci-autoroll-builder@chops-service-accounts.iam.gserviceaccount.com
+per-file DEPS=v8-ci-autoroll-builder@chops-service-accounts.iam.gserviceaccount.com
+
 per-file ...-mips*=file:MIPS_OWNERS
 per-file ...-mips64*=file:MIPS_OWNERS
 per-file ...-ppc*=file:PPC_OWNERS
diff --git a/deps/v8/include/OWNERS b/deps/v8/include/OWNERS
index d85849d52a1219..0222513df26cd0 100644
--- a/deps/v8/include/OWNERS
+++ b/deps/v8/include/OWNERS
@@ -11,6 +11,9 @@ per-file v8-inspector.h=file:../src/inspector/OWNERS
 per-file v8-inspector-protocol.h=file:../src/inspector/OWNERS
 per-file js_protocol.pdl=file:../src/inspector/OWNERS
 
+# Needed by the auto_tag builder
+per-file v8-version.h=v8-ci-autoroll-builder@chops-service-accounts.iam.gserviceaccount.com
+
 # For branch updates:
 per-file v8-version.h=file:../INFRA_OWNERS
 per-file v8-version.h=hablich@chromium.org
diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h
index 2a87785209c619..a4ef2015e02a3d 100644
--- a/deps/v8/include/v8-version.h
+++ b/deps/v8/include/v8-version.h
@@ -11,7 +11,7 @@
 #define V8_MAJOR_VERSION 9
 #define V8_MINOR_VERSION 4
 #define V8_BUILD_NUMBER 146
-#define V8_PATCH_LEVEL 19
+#define V8_PATCH_LEVEL 24
 
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/deps/v8/src/execution/isolate-inl.h b/deps/v8/src/execution/isolate-inl.h
index 63f9ea5947c904..48950b673f2227 100644
--- a/deps/v8/src/execution/isolate-inl.h
+++ b/deps/v8/src/execution/isolate-inl.h
@@ -50,7 +50,7 @@ bool Isolate::has_pending_message() {
 }
 
 Object Isolate::pending_exception() {
-  DCHECK(has_pending_exception());
+  CHECK(has_pending_exception());
   DCHECK(!thread_local_top()->pending_exception_.IsException(this));
   return thread_local_top()->pending_exception_;
 }
diff --git a/deps/v8/src/heap/cppgc/marker.cc b/deps/v8/src/heap/cppgc/marker.cc
index 549a9fe1da8f89..0e5d9ec8f1e2f9 100644
--- a/deps/v8/src/heap/cppgc/marker.cc
+++ b/deps/v8/src/heap/cppgc/marker.cc
@@ -243,6 +243,7 @@ void MarkerBase::EnterAtomicPause(MarkingConfig::StackState stack_state) {
   }
   config_.stack_state = stack_state;
   config_.marking_type = MarkingConfig::MarkingType::kAtomic;
+  mutator_marking_state_.set_in_atomic_pause();
 
   // Lock guards against changes to {Weak}CrossThreadPersistent handles, that
   // may conflict with marking. E.g., a WeakCrossThreadPersistent may be
@@ -421,7 +422,9 @@ bool MarkerBase::ProcessWorklistsWithDeadline(
     size_t marked_bytes_deadline, v8::base::TimeTicks time_deadline) {
   StatsCollector::EnabledScope stats_scope(
       heap().stats_collector(), StatsCollector::kMarkTransitiveClosure);
+  bool saved_did_discover_new_ephemeron_pairs;
   do {
+    mutator_marking_state_.ResetDidDiscoverNewEphemeronPairs();
     if ((config_.marking_type == MarkingConfig::MarkingType::kAtomic) ||
         schedule_.ShouldFlushEphemeronPairs()) {
       mutator_marking_state_.FlushDiscoveredEphemeronPairs();
@@ -509,6 +512,8 @@ bool MarkerBase::ProcessWorklistsWithDeadline(
       }
     }
 
+    saved_did_discover_new_ephemeron_pairs =
+        mutator_marking_state_.DidDiscoverNewEphemeronPairs();
     {
       StatsCollector::EnabledScope stats_scope(
           heap().stats_collector(), StatsCollector::kMarkProcessEphemerons);
@@ -522,7 +527,8 @@ bool MarkerBase::ProcessWorklistsWithDeadline(
         return false;
       }
     }
-  } while (!mutator_marking_state_.marking_worklist().IsLocalAndGlobalEmpty());
+  } while (!mutator_marking_state_.marking_worklist().IsLocalAndGlobalEmpty() ||
+           saved_did_discover_new_ephemeron_pairs);
   return true;
 }
 
diff --git a/deps/v8/src/heap/cppgc/marking-state.h b/deps/v8/src/heap/cppgc/marking-state.h
index 17e64e6fbef2e2..5f6f0aba3720ea 100644
--- a/deps/v8/src/heap/cppgc/marking-state.h
+++ b/deps/v8/src/heap/cppgc/marking-state.h
@@ -9,6 +9,7 @@
 
 #include "include/cppgc/trace-trait.h"
 #include "include/cppgc/visitor.h"
+#include "src/base/logging.h"
 #include "src/heap/cppgc/compaction-worklists.h"
 #include "src/heap/cppgc/globals.h"
 #include "src/heap/cppgc/heap-object-header.h"
@@ -115,6 +116,16 @@ class MarkingStateBase {
     movable_slots_worklist_.reset();
   }
 
+  bool DidDiscoverNewEphemeronPairs() const {
+    return discovered_new_ephemeron_pairs_;
+  }
+
+  void ResetDidDiscoverNewEphemeronPairs() {
+    discovered_new_ephemeron_pairs_ = false;
+  }
+
+  void set_in_atomic_pause() { in_atomic_pause_ = true; }
+
  protected:
   inline void MarkAndPush(HeapObjectHeader&, TraceDescriptor);
 
@@ -150,6 +161,9 @@ class MarkingStateBase {
       movable_slots_worklist_;
 
   size_t marked_bytes_ = 0;
+  bool in_ephemeron_processing_ = false;
+  bool discovered_new_ephemeron_pairs_ = false;
+  bool in_atomic_pause_ = false;
 };
 
 MarkingStateBase::MarkingStateBase(HeapBase& heap,
@@ -286,10 +300,23 @@ void MarkingStateBase::ProcessWeakContainer(const void* object,
 void MarkingStateBase::ProcessEphemeron(const void* key, const void* value,
                                         TraceDescriptor value_desc,
                                         Visitor& visitor) {
-  // Filter out already marked keys. The write barrier for WeakMember
-  // ensures that any newly set value after this point is kept alive and does
-  // not require the callback.
-  if (HeapObjectHeader::FromObject(key).IsMarked<AccessMode::kAtomic>()) {
+  // ProcessEphemeron is not expected to find new ephemerons recursively, which
+  // would break the main marking loop.
+  DCHECK(!in_ephemeron_processing_);
+  in_ephemeron_processing_ = true;
+  // Keys are considered live even in incremental/concurrent marking settings
+  // because the write barrier for WeakMember ensures that any newly set value
+  // after this point is kept alive and does not require the callback.
+  const bool key_in_construction =
+      HeapObjectHeader::FromObject(key).IsInConstruction<AccessMode::kAtomic>();
+  const bool key_considered_as_live =
+      key_in_construction
+          ? in_atomic_pause_
+          : HeapObjectHeader::FromObject(key).IsMarked<AccessMode::kAtomic>();
+  DCHECK_IMPLIES(
+      key_in_construction && in_atomic_pause_,
+      HeapObjectHeader::FromObject(key).IsMarked<AccessMode::kAtomic>());
+  if (key_considered_as_live) {
     if (value_desc.base_object_payload) {
       MarkAndPush(value_desc.base_object_payload, value_desc);
     } else {
@@ -297,9 +324,11 @@ void MarkingStateBase::ProcessEphemeron(const void* key, const void* value,
       // should be immediately traced.
       value_desc.callback(&visitor, value);
     }
-    return;
+  } else {
+    discovered_ephemeron_pairs_worklist_.Push({key, value, value_desc});
+    discovered_new_ephemeron_pairs_ = true;
   }
-  discovered_ephemeron_pairs_worklist_.Push({key, value, value_desc});
+  in_ephemeron_processing_ = false;
 }
 
 void MarkingStateBase::AccountMarkedBytes(const HeapObjectHeader& header) {
diff --git a/deps/v8/src/ic/accessor-assembler.cc b/deps/v8/src/ic/accessor-assembler.cc
index 64d64cd017c354..f27e3b7f590a76 100644
--- a/deps/v8/src/ic/accessor-assembler.cc
+++ b/deps/v8/src/ic/accessor-assembler.cc
@@ -846,8 +846,8 @@ void AccessorAssembler::HandleLoadICSmiHandlerLoadNamedCase(
     Comment("module export");
     TNode<UintPtrT> index =
         DecodeWord<LoadHandler::ExportsIndexBits>(handler_word);
-    TNode<Module> module = LoadObjectField<Module>(
-        CAST(p->receiver()), JSModuleNamespace::kModuleOffset);
+    TNode<Module> module =
+        LoadObjectField<Module>(CAST(holder), JSModuleNamespace::kModuleOffset);
     TNode<ObjectHashTable> exports =
         LoadObjectField<ObjectHashTable>(module, Module::kExportsOffset);
     TNode<Cell> cell = CAST(LoadFixedArrayElement(exports, index));
diff --git a/deps/v8/src/ic/ic.cc b/deps/v8/src/ic/ic.cc
index a2b920a09d1bc7..68eee92cef8335 100644
--- a/deps/v8/src/ic/ic.cc
+++ b/deps/v8/src/ic/ic.cc
@@ -989,7 +989,13 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
         // We found the accessor, so the entry must exist.
         DCHECK(entry.is_found());
         int index = ObjectHashTable::EntryToValueIndex(entry);
-        return LoadHandler::LoadModuleExport(isolate(), index);
+        Handle<Smi> smi_handler =
+            LoadHandler::LoadModuleExport(isolate(), index);
+        if (holder_is_lookup_start_object) {
+          return smi_handler;
+        }
+        return LoadHandler::LoadFromPrototype(isolate(), map, holder,
+                                              smi_handler);
       }
 
       Handle<Object> accessors = lookup->GetAccessors();
diff --git a/deps/v8/src/wasm/module-compiler.cc b/deps/v8/src/wasm/module-compiler.cc
index 590c0862bcd1eb..223f51ba14587d 100644
--- a/deps/v8/src/wasm/module-compiler.cc
+++ b/deps/v8/src/wasm/module-compiler.cc
@@ -3052,13 +3052,13 @@ void CompilationStateImpl::InitializeCompilationProgressAfterDeserialization(
     }
     compilation_progress_.assign(module->num_declared_functions,
                                  kProgressAfterDeserialization);
-    uint32_t num_imported_functions = module->num_imported_functions;
     for (auto func_index : missing_functions) {
       if (FLAG_wasm_lazy_compilation) {
-        native_module_->UseLazyStub(num_imported_functions + func_index);
+        native_module_->UseLazyStub(func_index);
       }
-      compilation_progress_[func_index] = SetupCompilationProgressForFunction(
-          lazy_module, module, enabled_features, func_index);
+      compilation_progress_[declared_function_index(module, func_index)] =
+          SetupCompilationProgressForFunction(lazy_module, module,
+                                              enabled_features, func_index);
     }
   }
   auto builder = std::make_unique<CompilationUnitBuilder>(native_module_);
diff --git a/deps/v8/test/mjsunit/wasm/test-serialization-with-lazy-compilation.js b/deps/v8/test/mjsunit/wasm/test-serialization-with-lazy-compilation.js
index ad1d54a5942d67..95884c32f6a562 100644
--- a/deps/v8/test/mjsunit/wasm/test-serialization-with-lazy-compilation.js
+++ b/deps/v8/test/mjsunit/wasm/test-serialization-with-lazy-compilation.js
@@ -10,6 +10,7 @@ const num_functions = 2;
 
 function create_builder() {
   const builder = new WasmModuleBuilder();
+  builder.addImport("foo", "bar", kSig_i_v);
   for (let i = 0; i < num_functions; ++i) {
     builder.addFunction('f' + i, kSig_i_v)
         .addBody(wasmI32Const(i))
@@ -37,7 +38,7 @@ gc();
   print(arguments.callee.name);
   const module = %DeserializeWasmModule(serialized_module, wire_bytes);
 
-  const instance = new WebAssembly.Instance(module);
+  const instance = new WebAssembly.Instance(module, {foo: {bar: () => 1}});
   assertEquals(0, instance.exports.f0());
   assertEquals(1, instance.exports.f1());
 })();
diff --git a/deps/v8/test/unittests/heap/cppgc/ephemeron-pair-unittest.cc b/deps/v8/test/unittests/heap/cppgc/ephemeron-pair-unittest.cc
index 534f744e7ee1ad..b349b591cac540 100644
--- a/deps/v8/test/unittests/heap/cppgc/ephemeron-pair-unittest.cc
+++ b/deps/v8/test/unittests/heap/cppgc/ephemeron-pair-unittest.cc
@@ -242,5 +242,50 @@ TEST_F(EphemeronPairTest, EphemeronPairWithEmptyMixinValue) {
   FinishMarking();
 }
 
+namespace {
+
+class KeyWithCallback final : public GarbageCollected<KeyWithCallback> {
+ public:
+  template <typename Callback>
+  explicit KeyWithCallback(Callback callback) {
+    callback(this);
+  }
+  void Trace(Visitor*) const {}
+};
+
+class EphemeronHolderForKeyWithCallback final
+    : public GarbageCollected<EphemeronHolderForKeyWithCallback> {
+ public:
+  EphemeronHolderForKeyWithCallback(KeyWithCallback* key, GCed* value)
+      : ephemeron_pair_(key, value) {}
+  void Trace(cppgc::Visitor* visitor) const { visitor->Trace(ephemeron_pair_); }
+
+ private:
+  const EphemeronPair<KeyWithCallback, GCed> ephemeron_pair_;
+};
+
+}  // namespace
+
+TEST_F(EphemeronPairTest, EphemeronPairWithKeyInConstruction) {
+  GCed* value = MakeGarbageCollected<GCed>(GetAllocationHandle());
+  Persistent<EphemeronHolderForKeyWithCallback> holder;
+  InitializeMarker(*Heap::From(GetHeap()), GetPlatformHandle().get());
+  FinishSteps();
+  MakeGarbageCollected<KeyWithCallback>(
+      GetAllocationHandle(), [this, &holder, value](KeyWithCallback* thiz) {
+        // The test doesn't use conservative stack scanning to retain key to
+        // avoid retaining value as a side effect.
+        EXPECT_TRUE(HeapObjectHeader::FromObject(thiz).TryMarkAtomic());
+        holder = MakeGarbageCollected<EphemeronHolderForKeyWithCallback>(
+            GetAllocationHandle(), thiz, value);
+        // Finishing marking at this point will leave an ephemeron pair
+        // reachable where the key is still in construction. The GC needs to
+        // mark the value for such pairs as live in the atomic pause as they key
+        // is considered live.
+        FinishMarking();
+      });
+  EXPECT_TRUE(HeapObjectHeader::FromObject(value).IsMarked());
+}
+
 }  // namespace internal
 }  // namespace cppgc
diff --git a/deps/v8/test/unittests/heap/cppgc/marker-unittest.cc b/deps/v8/test/unittests/heap/cppgc/marker-unittest.cc
index f96e5f4a25fc97..5ed46857c8e3aa 100644
--- a/deps/v8/test/unittests/heap/cppgc/marker-unittest.cc
+++ b/deps/v8/test/unittests/heap/cppgc/marker-unittest.cc
@@ -7,12 +7,14 @@
 #include <memory>
 
 #include "include/cppgc/allocation.h"
+#include "include/cppgc/ephemeron-pair.h"
 #include "include/cppgc/internal/pointer-policies.h"
 #include "include/cppgc/member.h"
 #include "include/cppgc/persistent.h"
 #include "include/cppgc/trace-trait.h"
 #include "src/heap/cppgc/heap-object-header.h"
 #include "src/heap/cppgc/marking-visitor.h"
+#include "src/heap/cppgc/object-allocator.h"
 #include "src/heap/cppgc/stats-collector.h"
 #include "test/unittests/heap/cppgc/tests.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -44,6 +46,8 @@ class MarkerTest : public testing::TestWithHeap {
 
   Marker* marker() const { return marker_.get(); }
 
+  void ResetMarker() { marker_.reset(); }
+
  private:
   std::unique_ptr<Marker> marker_;
 };
@@ -346,6 +350,50 @@ TEST_F(MarkerTest, SentinelNotClearedOnWeakPersistentHandling) {
   EXPECT_EQ(kSentinelPointer, root->weak_child());
 }
 
+namespace {
+
+class SimpleObject final : public GarbageCollected<SimpleObject> {
+ public:
+  void Trace(Visitor*) const {}
+};
+
+class ObjectWithEphemeronPair final
+    : public GarbageCollected<ObjectWithEphemeronPair> {
+ public:
+  explicit ObjectWithEphemeronPair(AllocationHandle& handle)
+      : ephemeron_pair_(MakeGarbageCollected<SimpleObject>(handle),
+                        MakeGarbageCollected<SimpleObject>(handle)) {}
+
+  void Trace(Visitor* visitor) const {
+    // First trace the ephemeron pair. The key is not yet marked as live, so the
+    // pair should be recorded for later processing. Then strongly mark the key.
+    // Marking the key will not trigger another worklist processing iteration,
+    // as it merely continues the same loop for regular objects and will leave
+    // the main marking worklist empty. If recording the ephemeron pair doesn't
+    // as well, we will get a crash when destroying the marker.
+    visitor->Trace(ephemeron_pair_);
+    visitor->Trace(const_cast<const SimpleObject*>(ephemeron_pair_.key.Get()));
+  }
+
+ private:
+  const EphemeronPair<SimpleObject, SimpleObject> ephemeron_pair_;
+};
+
+}  // namespace
+
+TEST_F(MarkerTest, MarkerProcessesAllEphemeronPairs) {
+  static const Marker::MarkingConfig config = {
+      MarkingConfig::CollectionType::kMajor,
+      MarkingConfig::StackState::kNoHeapPointers,
+      MarkingConfig::MarkingType::kAtomic};
+  Persistent<ObjectWithEphemeronPair> obj =
+      MakeGarbageCollected<ObjectWithEphemeronPair>(GetAllocationHandle(),
+                                                    GetAllocationHandle());
+  InitializeMarker(*Heap::From(GetHeap()), GetPlatformHandle().get(), config);
+  marker()->FinishMarking(MarkingConfig::StackState::kNoHeapPointers);
+  ResetMarker();
+}
+
 // Incremental Marking
 
 class IncrementalMarkingTest : public testing::TestWithHeap {