Browse Source

chore: cherry-pick 27bc67f761e6 from v8 (#32740)

* chore: cherry-pick 27bc67f761e6 from v8

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Jeremy Rose 3 years ago
parent
commit
5f3eae7119
2 changed files with 254 additions and 0 deletions
  1. 1 0
      patches/v8/.patches
  2. 253 0
      patches/v8/cherry-pick-27bc67f761e6.patch

+ 1 - 0
patches/v8/.patches

@@ -18,3 +18,4 @@ cherry-pick-5d2b5e7c006c.patch
 merged_allow_compiled_module_invalidation_at_wasmstreaming_finish.patch
 version_9_6_180_13_cherry-pick.patch
 cherry-pick-418c276ef228.patch
+cherry-pick-27bc67f761e6.patch

+ 253 - 0
patches/v8/cherry-pick-27bc67f761e6.patch

@@ -0,0 +1,253 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jakob Gruber <[email protected]>
+Date: Thu, 13 Jan 2022 08:01:37 +0100
+Subject: Merged: [maps] Lock map_updater_access in
+ CompleteInobjectSlackTracking
+
+CompleteInobjectSlackTracking potentially shrinks multiple maps, and
+the relation between these maps should be preserved in a concurrent
+environment. Thus it is not enough to make each modification
+atomically, but all related map modifications must be within a
+critical section.
+
+We do this by locking the map_updater_access mutex
+CompleteInobjectSlackTracking, and hence moving the function to the
+MapUpdater class.
+
+(cherry picked from commit 4b8d04897cba70cac45eea33d78fa2354dfe2bd7)
+
+No-Try: true
+No-Presubmit: true
+No-Treechecks: true
+Bug: chromium:1274445,v8:7990
+Change-Id: If99bb8b55e03180128ee397d845fa4c269c4241e
+Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3379819
+Reviewed-by: Igor Sheludko <[email protected]>
+Commit-Queue: Jakob Gruber <[email protected]>
+Cr-Original-Commit-Position: refs/heads/main@{#78597}
+Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3406537
+Cr-Commit-Position: refs/branch-heads/9.8@{#16}
+Cr-Branched-From: e218afa8473132b56a9e1532be7920dd130aeb7e-refs/heads/9.8.177@{#1}
+Cr-Branched-From: 86ebfc969cde382122a4d429f2380f06175ea2a8-refs/heads/main@{#78312}
+
+diff --git a/src/objects/js-function-inl.h b/src/objects/js-function-inl.h
+index bae63f6ef9672958914ce4daaf41e948b7b0697d..7fdc6f1b93942df03d3eb61147f2c2e22e4de984 100644
+--- a/src/objects/js-function-inl.h
++++ b/src/objects/js-function-inl.h
+@@ -15,6 +15,7 @@
+ #include "src/ic/ic.h"
+ #include "src/init/bootstrapper.h"
+ #include "src/objects/feedback-cell-inl.h"
++#include "src/objects/map-updater.h"
+ #include "src/objects/shared-function-info-inl.h"
+ 
+ // Has to be the last include (doesn't have include guards):
+@@ -126,7 +127,7 @@ bool JSFunction::IsInOptimizationQueue() {
+ void JSFunction::CompleteInobjectSlackTrackingIfActive() {
+   if (!has_prototype_slot()) return;
+   if (has_initial_map() && initial_map().IsInobjectSlackTrackingInProgress()) {
+-    initial_map().CompleteInobjectSlackTracking(GetIsolate());
++    MapUpdater::CompleteInobjectSlackTracking(GetIsolate(), initial_map());
+   }
+ }
+ 
+diff --git a/src/objects/map-inl.h b/src/objects/map-inl.h
+index d170341b9a05c7d0ae555713bcd1a671be4642e9..8afafc0a8a5b79e89a65ac286c331afecc5a5568 100644
+--- a/src/objects/map-inl.h
++++ b/src/objects/map-inl.h
+@@ -12,6 +12,7 @@
+ #include "src/objects/field-type.h"
+ #include "src/objects/instance-type-inl.h"
+ #include "src/objects/js-function-inl.h"
++#include "src/objects/map-updater.h"
+ #include "src/objects/map.h"
+ #include "src/objects/objects-inl.h"
+ #include "src/objects/property.h"
+@@ -828,7 +829,7 @@ void Map::InobjectSlackTrackingStep(Isolate* isolate) {
+   int counter = construction_counter();
+   set_construction_counter(counter - 1);
+   if (counter == kSlackTrackingCounterEnd) {
+-    CompleteInobjectSlackTracking(isolate);
++    MapUpdater::CompleteInobjectSlackTracking(isolate, *this);
+   }
+ }
+ 
+diff --git a/src/objects/map-updater.cc b/src/objects/map-updater.cc
+index feb060fa5184e1533895b41989b8e35109036f6a..3ed7fa3af1a7aec18fbe77997a76f1ce01c33ebb 100644
+--- a/src/objects/map-updater.cc
++++ b/src/objects/map-updater.cc
+@@ -301,21 +301,50 @@ MapUpdater::State MapUpdater::Normalize(const char* reason) {
+   return state_;  // Done.
+ }
+ 
+-void MapUpdater::ShrinkInstanceSize(base::SharedMutex* map_updater_access,
+-                                    Map map, int slack) {
++// static
++void MapUpdater::CompleteInobjectSlackTracking(Isolate* isolate,
++                                               Map initial_map) {
++  DisallowGarbageCollection no_gc;
++  // Has to be an initial map.
++  DCHECK(initial_map.GetBackPointer().IsUndefined(isolate));
++
++  const int slack = initial_map.ComputeMinObjectSlack(isolate);
+   DCHECK_GE(slack, 0);
++
++  TransitionsAccessor transitions(isolate, initial_map, &no_gc);
++  TransitionsAccessor::TraverseCallback callback;
++  if (slack != 0) {
++    // Resize the initial map and all maps in its transition tree.
++    callback = [slack](Map map) {
+ #ifdef DEBUG
+-  int old_visitor_id = Map::GetVisitorId(map);
+-  int new_unused = map.UnusedPropertyFields() - slack;
++      int old_visitor_id = Map::GetVisitorId(map);
++      int new_unused = map.UnusedPropertyFields() - slack;
+ #endif
++      map.set_instance_size(map.InstanceSizeFromSlack(slack));
++      map.set_construction_counter(Map::kNoSlackTracking);
++      DCHECK_EQ(old_visitor_id, Map::GetVisitorId(map));
++      DCHECK_EQ(new_unused, map.UnusedPropertyFields());
++    };
++  } else {
++    // Stop slack tracking for this map.
++    callback = [](Map map) {
++      map.set_construction_counter(Map::kNoSlackTracking);
++    };
++  }
+ 
+   {
+-    base::SharedMutexGuard<base::kExclusive> mutex_guard(map_updater_access);
+-    map.set_instance_size(map.InstanceSizeFromSlack(slack));
++    // The map_updater_access lock is taken here to guarantee atomicity of all
++    // related map changes (instead of guaranteeing only atomicity of each
++    // single map change). This is needed e.g. by InstancesNeedsRewriting,
++    // which expects certain relations between maps to hold.
++    //
++    // Note: Avoid locking the full_transition_array_access lock inside this
++    // call to TraverseTransitionTree to prevent dependencies between the two
++    // locks.
++    base::SharedMutexGuard<base::kExclusive> mutex_guard(
++        isolate->map_updater_access());
++    transitions.TraverseTransitionTree(callback);
+   }
+-  map.set_construction_counter(Map::kNoSlackTracking);
+-  DCHECK_EQ(old_visitor_id, Map::GetVisitorId(map));
+-  DCHECK_EQ(new_unused, map.UnusedPropertyFields());
+ }
+ 
+ MapUpdater::State MapUpdater::TryReconfigureToDataFieldInplace() {
+diff --git a/src/objects/map-updater.h b/src/objects/map-updater.h
+index c901782bf176600aa08df210d55301045d4b5e2e..2fc66d0c3709b87ea0e7aa96a2943eea4ecefc6e 100644
+--- a/src/objects/map-updater.h
++++ b/src/objects/map-updater.h
+@@ -80,8 +80,9 @@ class V8_EXPORT_PRIVATE MapUpdater {
+                               Representation new_representation,
+                               Handle<FieldType> new_field_type);
+ 
+-  static void ShrinkInstanceSize(base::SharedMutex* map_updater_access, Map map,
+-                                 int slack);
++  // Completes inobject slack tracking for the transition tree starting at the
++  // initial map.
++  static void CompleteInobjectSlackTracking(Isolate* isolate, Map initial_map);
+ 
+  private:
+   enum State {
+diff --git a/src/objects/map.cc b/src/objects/map.cc
+index 50d5728b0e13edf4f1052f2014f9e32c4056a512..84b2444ca2d61a8b4300ff30bd6ab2a93448ad60 100644
+--- a/src/objects/map.cc
++++ b/src/objects/map.cc
+@@ -2200,28 +2200,6 @@ int Map::ComputeMinObjectSlack(Isolate* isolate) {
+   return slack;
+ }
+ 
+-void Map::CompleteInobjectSlackTracking(Isolate* isolate) {
+-  DisallowGarbageCollection no_gc;
+-  // Has to be an initial map.
+-  DCHECK(GetBackPointer().IsUndefined(isolate));
+-
+-  int slack = ComputeMinObjectSlack(isolate);
+-  TransitionsAccessor transitions(isolate, *this, &no_gc);
+-  TransitionsAccessor::TraverseCallback callback;
+-  if (slack != 0) {
+-    // Resize the initial map and all maps in its transition tree.
+-    callback = [&](Map map) {
+-      MapUpdater::ShrinkInstanceSize(isolate->map_updater_access(), map, slack);
+-    };
+-  } else {
+-    callback = [](Map map) {
+-      // Stop slack tracking for this map.
+-      map.set_construction_counter(Map::kNoSlackTracking);
+-    };
+-  }
+-  transitions.TraverseTransitionTree(callback);
+-}
+-
+ void Map::SetInstanceDescriptors(Isolate* isolate, DescriptorArray descriptors,
+                                  int number_of_own_descriptors) {
+   set_instance_descriptors(descriptors, kReleaseStore);
+diff --git a/src/objects/map.h b/src/objects/map.h
+index 355d86a332412a3e1c24cdf5ad866cc8871ba4f1..16435e4a3507d93c832e0cd77cf82535d3d51938 100644
+--- a/src/objects/map.h
++++ b/src/objects/map.h
+@@ -352,10 +352,6 @@ class Map : public HeapObject {
+   int ComputeMinObjectSlack(Isolate* isolate);
+   inline int InstanceSizeFromSlack(int slack) const;
+ 
+-  // Completes inobject slack tracking for the transition tree starting at this
+-  // initial map.
+-  V8_EXPORT_PRIVATE void CompleteInobjectSlackTracking(Isolate* isolate);
+-
+   // Tells whether the object in the prototype property will be used
+   // for instances created from this function.  If the prototype
+   // property is set to a value that is not a JSObject, the prototype
+diff --git a/src/runtime/runtime-object.cc b/src/runtime/runtime-object.cc
+index 42bbb10d92e90640d2a7f61beba758cb752ae87b..add7cd191064686396de76912c5799d9bb3d487b 100644
+--- a/src/runtime/runtime-object.cc
++++ b/src/runtime/runtime-object.cc
+@@ -1002,7 +1002,7 @@ RUNTIME_FUNCTION(Runtime_CompleteInobjectSlackTrackingForMap) {
+   DCHECK_EQ(1, args.length());
+ 
+   CONVERT_ARG_HANDLE_CHECKED(Map, initial_map, 0);
+-  initial_map->CompleteInobjectSlackTracking(isolate);
++  MapUpdater::CompleteInobjectSlackTracking(isolate, *initial_map);
+ 
+   return ReadOnlyRoots(isolate).undefined_value();
+ }
+diff --git a/src/runtime/runtime-test.cc b/src/runtime/runtime-test.cc
+index fb5949e2c90966a240ccfb1b61a01017a816f313..6c1df05ca95feb3f40db70f652a55b59450aa6aa 100644
+--- a/src/runtime/runtime-test.cc
++++ b/src/runtime/runtime-test.cc
+@@ -1274,7 +1274,7 @@ RUNTIME_FUNCTION(Runtime_CompleteInobjectSlackTracking) {
+   DCHECK_EQ(1, args.length());
+ 
+   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
+-  object->map().CompleteInobjectSlackTracking(isolate);
++  MapUpdater::CompleteInobjectSlackTracking(isolate, object->map());
+ 
+   return ReadOnlyRoots(isolate).undefined_value();
+ }
+diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
+index 5a12729d929a36fbcc89d0d2586c0cbfee72309c..f6373286cf99176b440db6965e657580321a6380 100644
+--- a/test/cctest/test-api.cc
++++ b/test/cctest/test-api.cc
+@@ -62,6 +62,7 @@
+ #include "src/objects/js-array-inl.h"
+ #include "src/objects/js-promise-inl.h"
+ #include "src/objects/lookup.h"
++#include "src/objects/map-updater.h"
+ #include "src/objects/module-inl.h"
+ #include "src/objects/objects-inl.h"
+ #include "src/objects/string-inl.h"
+@@ -2972,9 +2973,9 @@ TEST(InternalFieldsSubclassing) {
+         CHECK_LE(i_value->map().GetInObjectProperties(), kMaxNofProperties);
+       }
+ 
+-      // Make Sure we get the precise property count.
+-      i_value->map().FindRootMap(i_isolate).CompleteInobjectSlackTracking(
+-          i_isolate);
++      // Make sure we get the precise property count.
++      i::MapUpdater::CompleteInobjectSlackTracking(
++          i_isolate, i_value->map().FindRootMap(i_isolate));
+       // TODO(cbruni): fix accounting to make this condition true.
+       // CHECK_EQ(0, i_value->map()->UnusedPropertyFields());
+       if (in_object_only) {