chore: cherry-pick 2 changes from Release-1-M116 (#39648)

* chore: [22-x-y] cherry-pick 2 changes from Release-1-M116

* 1939f7b78eda from chromium
* e4669a74888d from angle

* chore: [22-x-y] cherry-pick missing changes from Release-1-M116

* chore: update patches

---------

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
This commit is contained in:
Pedro Pontes
2023-08-28 07:18:56 +01:00
committed by GitHub
parent 4938ca50f0
commit 33f9dce7c2
5 changed files with 497 additions and 0 deletions

View File

@@ -170,3 +170,4 @@ cherry-pick-933b9fad3a53.patch
cherry-pick-b03973561862.patch
cherry-pick-c60a1ab717c7.patch
networkcontext_don_t_access_url_loader_factories_during_destruction.patch
don_t_keep_pointer_to_popped_stack_memory_for_has.patch

View File

@@ -0,0 +1,84 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Rune Lillesveen <futhark@chromium.org>
Date: Tue, 15 Aug 2023 15:04:39 +0000
Subject: Don't keep pointer to popped stack memory for :has()
The sibling_features pass into UpdateFeaturesFromCombinator may be
initialized to last_compound_in_adjacent_chain_features if null. The
outer while loop in
AddFeaturesToInvalidationSetsForLogicalCombinationInHas() could then
reference to the last_compound_in_adjacent_chain_features which is
popped from the stack on every outer iteration. That caused an ASAN
failure for reading stack memory that had been popped.
Instead make sure each inner iteration restarts with the same
sibling_features pointer, which seems to have been the intent here.
(cherry picked from commit 5e213507a2f0d6e3c96904a710407b01493670bd)
Bug: 1470477
Change-Id: I260c93016f8ab0d165e4b29ca1aea810bede5b97
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4759326
Commit-Queue: Rune Lillesveen <futhark@chromium.org>
Reviewed-by: Anders Hartvoll Ruud <andruud@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1181365}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4777251
Cr-Commit-Position: refs/branch-heads/5845@{#1482}
Cr-Branched-From: 5a5dff63a4a4c63b9b18589819bebb2566c85443-refs/heads/main@{#1160321}
diff --git a/third_party/blink/renderer/core/css/rule_feature_set.cc b/third_party/blink/renderer/core/css/rule_feature_set.cc
index ec7356285d7fa45b7d9c1701be484a121c2a0017..9cb6084b7fca4fc6ff2edd8defadf8fabf2899b5 100644
--- a/third_party/blink/renderer/core/css/rule_feature_set.cc
+++ b/third_party/blink/renderer/core/css/rule_feature_set.cc
@@ -1227,6 +1227,7 @@ void RuleFeatureSet::AddFeaturesToInvalidationSetsForLogicalCombinationInHas(
descendant_features);
const CSSSelector* compound_in_logical_combination = complex;
+ InvalidationSetFeatures* inner_sibling_features = sibling_features;
InvalidationSetFeatures last_compound_in_adjacent_chain_features;
while (compound_in_logical_combination) {
AddFeaturesToInvalidationSetsForLogicalCombinationInHasContext context(
@@ -1238,14 +1239,14 @@ void RuleFeatureSet::AddFeaturesToInvalidationSetsForLogicalCombinationInHas(
last_in_compound =
SkipAddingAndGetLastInCompoundForLogicalCombinationInHas(
compound_in_logical_combination, compound_containing_has,
- sibling_features, descendant_features, previous_combinator,
- add_features_method);
+ inner_sibling_features, descendant_features,
+ previous_combinator, add_features_method);
} else {
last_in_compound =
AddFeaturesAndGetLastInCompoundForLogicalCombinationInHas(
compound_in_logical_combination, compound_containing_has,
- sibling_features, descendant_features, previous_combinator,
- add_features_method);
+ inner_sibling_features, descendant_features,
+ previous_combinator, add_features_method);
}
if (!last_in_compound)
@@ -1259,7 +1260,7 @@ void RuleFeatureSet::AddFeaturesToInvalidationSetsForLogicalCombinationInHas(
? CSSSelector::kIndirectAdjacent
: previous_combinator,
context.last_compound_in_adjacent_chain,
- last_compound_in_adjacent_chain_features, sibling_features,
+ last_compound_in_adjacent_chain_features, inner_sibling_features,
descendant_features);
}
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-sibling-chrome-crash.html b/third_party/blink/web_tests/external/wpt/css/selectors/has-sibling-chrome-crash.html
new file mode 100644
index 0000000000000000000000000000000000000000..0306e3e39272c321fc3539aa582b4e239ffe2fa1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-sibling-chrome-crash.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<title>CSS Selectors Test: Chrome crash issue 1470477</title>
+<link rel="help" href="https://crbug.com/1470477">
+<style>
+ :has(> :where(label:first-child + [a="a"]:only-of-type,
+ [a="a"]:only-of-type + label:last-child)) label:last-child {
+ margin-inline: 1em;
+ }
+</style>
+<p>PASS if this tests does not crash</p>

View File

@@ -28,3 +28,5 @@ merged_compiler_stackcheck_can_have_side_effects.patch
promise_allsettled_mark_values_array_as_cow.patch
merged_builtins_clear_fixedarray_slot_in_promise_builtins.patch
merged_compiler_check_for_read-only_property_on.patch
shared-struct_fix_for-in_enumeration.patch
merged_squashed_multiple_commits.patch

View File

@@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Samuel=20Gro=C3=9F?= <saelo@chromium.org>
Date: Thu, 17 Aug 2023 09:10:19 +0000
Subject: Merged: Squashed multiple commits.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Merged: [runtime] Recreate enum cache on map update
Revision: 1c623f9ff6e077be1c66f155485ea4005ddb6574
Merged: [runtime] Don't try to create empty enum cache.
Revision: 5516e06237c9f0013121f47319e8c253c896d52d
BUG=chromium:1470668,chromium:1472317
R=tebbi@chromium.org
Change-Id: I31d5491aba663661ba68bb55631747a195ed084e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4788990
Commit-Queue: Samuel Groß <saelo@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/branch-heads/11.6@{#32}
Cr-Branched-From: e29c028f391389a7a60ee37097e3ca9e396d6fa4-refs/heads/11.6.189@{#3}
Cr-Branched-From: 95cbef20e2aa556a1ea75431a48b36c4de6b9934-refs/heads/main@{#88340}
diff --git a/src/objects/map-updater.cc b/src/objects/map-updater.cc
index be6568aac4730d08601e883b80092bbd6ee8081a..2ebfc84d3e326abf2602a1af8309024a46cb9c9d 100644
--- a/src/objects/map-updater.cc
+++ b/src/objects/map-updater.cc
@@ -11,6 +11,7 @@
#include "src/execution/isolate.h"
#include "src/handles/handles.h"
#include "src/objects/field-type.h"
+#include "src/objects/keys.h"
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
#include "src/objects/property-details.h"
@@ -1035,6 +1036,13 @@ MapUpdater::State MapUpdater::ConstructNewMap() {
// the new descriptors to maintain descriptors sharing invariant.
split_map->ReplaceDescriptors(isolate_, *new_descriptors);
+ // If the old descriptors had an enum cache, make sure the new ones do too.
+ if (old_descriptors_->enum_cache().keys().length() > 0 &&
+ new_map->NumberOfEnumerableProperties() > 0) {
+ FastKeyAccumulator::InitializeFastPropertyEnumCache(
+ isolate_, new_map, new_map->NumberOfEnumerableProperties());
+ }
+
if (has_integrity_level_transition_) {
target_map_ = new_map;
state_ = kAtIntegrityLevelSource;

View File

@@ -0,0 +1,359 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shu-yu Guo <syg@chromium.org>
Date: Thu, 3 Nov 2022 08:48:39 -0700
Subject: Fix for-in enumeration
for-in enumeration creates an EnumCache, which is currently incorrectly
allocated in the per-thread heap. This CL preallocates the enum cache at
SharedStructType-creation time.
Also drive-by fixes typos in the enum cache code.
Bug: v8:12547, chromium:1379616
Change-Id: I1930f88844eca5ccfeebd8dfdcce4ad0bd80ee38
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3997701
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/main@{#84047}
diff --git a/src/builtins/builtins-struct.cc b/src/builtins/builtins-struct.cc
index a0d75e72086592283070d8014cd043ef3bab1ff5..e0b3831cdc69c1c0acb2ec24925adc310303856e 100644
--- a/src/builtins/builtins-struct.cc
+++ b/src/builtins/builtins-struct.cc
@@ -94,6 +94,16 @@ BUILTIN(SharedStructTypeConstructor) {
// to it.
instance_map->set_constructor_or_back_pointer(*factory->null_value());
+ // Pre-create the enum cache in the shared space, as otherwise for-in
+ // enumeration will incorrectly create an enum cache in the per-thread heap.
+ if (num_properties == 0) {
+ instance_map->SetEnumLength(0);
+ } else {
+ FastKeyAccumulator::InitializeFastPropertyEnumCache(
+ isolate, instance_map, num_properties, AllocationType::kSharedOld);
+ DCHECK_EQ(num_properties, instance_map->EnumLength());
+ }
+
return *constructor;
}
diff --git a/src/heap/factory.cc b/src/heap/factory.cc
index bcb2f6475ec357cb34f923c51e279641c644957d..d1285ab16f4113acd5cdee154f7b1ef133fd8e14 100644
--- a/src/heap/factory.cc
+++ b/src/heap/factory.cc
@@ -415,9 +415,13 @@ Handle<PrototypeInfo> Factory::NewPrototypeInfo() {
}
Handle<EnumCache> Factory::NewEnumCache(Handle<FixedArray> keys,
- Handle<FixedArray> indices) {
- auto result =
- NewStructInternal<EnumCache>(ENUM_CACHE_TYPE, AllocationType::kOld);
+ Handle<FixedArray> indices,
+ AllocationType allocation) {
+ DCHECK(allocation == AllocationType::kOld ||
+ allocation == AllocationType::kSharedOld);
+ DCHECK_EQ(allocation == AllocationType::kSharedOld,
+ keys->InSharedHeap() && indices->InSharedHeap());
+ auto result = NewStructInternal<EnumCache>(ENUM_CACHE_TYPE, allocation);
DisallowGarbageCollection no_gc;
result.set_keys(*keys);
result.set_indices(*indices);
diff --git a/src/heap/factory.h b/src/heap/factory.h
index 6c9cc2d4d8ed1e9c7e14ccb35f6ad61dfa850cfa..748a3f91c881d8bdc723a4f21fcb6adfe6d3876e 100644
--- a/src/heap/factory.h
+++ b/src/heap/factory.h
@@ -183,8 +183,9 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
Handle<PrototypeInfo> NewPrototypeInfo();
// Create a new EnumCache struct.
- Handle<EnumCache> NewEnumCache(Handle<FixedArray> keys,
- Handle<FixedArray> indices);
+ Handle<EnumCache> NewEnumCache(
+ Handle<FixedArray> keys, Handle<FixedArray> indices,
+ AllocationType allocation = AllocationType::kOld);
// Create a new Tuple2 struct.
Handle<Tuple2> NewTuple2(Handle<Object> value1, Handle<Object> value2,
diff --git a/src/objects/descriptor-array.h b/src/objects/descriptor-array.h
index 5db091cbfe166a683f3c43273aece6d3d802d448..178e6d03af4be4512fc40257365437482be654eb 100644
--- a/src/objects/descriptor-array.h
+++ b/src/objects/descriptor-array.h
@@ -65,10 +65,10 @@ class DescriptorArray
void ClearEnumCache();
inline void CopyEnumCacheFrom(DescriptorArray array);
- static void InitializeOrChangeEnumCache(Handle<DescriptorArray> descriptors,
- Isolate* isolate,
- Handle<FixedArray> keys,
- Handle<FixedArray> indices);
+ static void InitializeOrChangeEnumCache(
+ Handle<DescriptorArray> descriptors, Isolate* isolate,
+ Handle<FixedArray> keys, Handle<FixedArray> indices,
+ AllocationType allocation_if_initialize);
// Accessors for fetching instance descriptor at descriptor number.
inline Name GetKey(InternalIndex descriptor_number) const;
diff --git a/src/objects/keys.cc b/src/objects/keys.cc
index ac21fbf9c3d2d22bbd7049a620849e25d1257b4d..a0796864f1ecc6f1f32ca50635b9cb55cd04d7db 100644
--- a/src/objects/keys.cc
+++ b/src/objects/keys.cc
@@ -312,7 +312,7 @@ void TrySettingEmptyEnumCache(JSReceiver object) {
map.SetEnumLength(0);
}
-bool CheckAndInitalizeEmptyEnumCache(JSReceiver object) {
+bool CheckAndInitializeEmptyEnumCache(JSReceiver object) {
if (object.map().EnumLength() == kInvalidEnumCacheSentinel) {
TrySettingEmptyEnumCache(object);
}
@@ -342,7 +342,7 @@ void FastKeyAccumulator::Prepare() {
only_own_has_simple_elements_ = false;
}
}
- bool has_no_properties = CheckAndInitalizeEmptyEnumCache(current);
+ bool has_no_properties = CheckAndInitializeEmptyEnumCache(current);
if (has_no_properties) continue;
last_prototype = current;
has_empty_prototype_ = false;
@@ -368,7 +368,7 @@ Handle<FixedArray> ReduceFixedArrayTo(Isolate* isolate,
return isolate->factory()->CopyFixedArrayUpTo(array, length);
}
-// Initializes and directly returns the enume cache. Users of this function
+// Initializes and directly returns the enum cache. Users of this function
// have to make sure to never directly leak the enum cache.
Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate,
Handle<JSObject> object) {
@@ -398,51 +398,8 @@ Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate,
return ReduceFixedArrayTo(isolate, keys, enum_length);
}
- Handle<DescriptorArray> descriptors =
- Handle<DescriptorArray>(map->instance_descriptors(isolate), isolate);
- isolate->counters()->enum_cache_misses()->Increment();
-
- // Create the keys array.
- int index = 0;
- bool fields_only = true;
- keys = isolate->factory()->NewFixedArray(enum_length);
- for (InternalIndex i : map->IterateOwnDescriptors()) {
- DisallowGarbageCollection no_gc;
- PropertyDetails details = descriptors->GetDetails(i);
- if (details.IsDontEnum()) continue;
- Object key = descriptors->GetKey(i);
- if (key.IsSymbol()) continue;
- keys->set(index, key);
- if (details.location() != PropertyLocation::kField) fields_only = false;
- index++;
- }
- DCHECK_EQ(index, keys->length());
-
- // Optionally also create the indices array.
- Handle<FixedArray> indices = isolate->factory()->empty_fixed_array();
- if (fields_only) {
- indices = isolate->factory()->NewFixedArray(enum_length);
- index = 0;
- for (InternalIndex i : map->IterateOwnDescriptors()) {
- DisallowGarbageCollection no_gc;
- PropertyDetails details = descriptors->GetDetails(i);
- if (details.IsDontEnum()) continue;
- Object key = descriptors->GetKey(i);
- if (key.IsSymbol()) continue;
- DCHECK_EQ(PropertyKind::kData, details.kind());
- DCHECK_EQ(PropertyLocation::kField, details.location());
- FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
- indices->set(index, Smi::FromInt(field_index.GetLoadByFieldIndex()));
- index++;
- }
- DCHECK_EQ(index, indices->length());
- }
-
- DescriptorArray::InitializeOrChangeEnumCache(descriptors, isolate, keys,
- indices);
- if (map->OnlyHasSimpleProperties()) map->SetEnumLength(enum_length);
-
- return keys;
+ return FastKeyAccumulator::InitializeFastPropertyEnumCache(isolate, map,
+ enum_length);
}
template <bool fast_properties>
@@ -451,7 +408,6 @@ MaybeHandle<FixedArray> GetOwnKeysWithElements(Isolate* isolate,
GetKeysConversion convert,
bool skip_indices) {
Handle<FixedArray> keys;
- ElementsAccessor* accessor = object->GetElementsAccessor();
if (fast_properties) {
keys = GetFastEnumPropertyKeys(isolate, object);
} else {
@@ -463,6 +419,7 @@ MaybeHandle<FixedArray> GetOwnKeysWithElements(Isolate* isolate,
if (skip_indices) {
result = keys;
} else {
+ ElementsAccessor* accessor = object->GetElementsAccessor(isolate);
result = accessor->PrependElementIndices(isolate, object, keys, convert,
ONLY_ENUMERABLE);
}
@@ -518,7 +475,7 @@ MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysFast(
if (enum_length == kInvalidEnumCacheSentinel) {
Handle<FixedArray> keys;
// Try initializing the enum cache and return own properties.
- if (GetOwnKeysWithUninitializedEnumCache().ToHandle(&keys)) {
+ if (GetOwnKeysWithUninitializedEnumLength().ToHandle(&keys)) {
if (v8_flags.trace_for_in_enumerate) {
PrintF("| strings=%d symbols=0 elements=0 || prototypes>=1 ||\n",
keys->length());
@@ -534,10 +491,70 @@ MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysFast(
skip_indices_);
}
+// static
+Handle<FixedArray> FastKeyAccumulator::InitializeFastPropertyEnumCache(
+ Isolate* isolate, Handle<Map> map, int enum_length,
+ AllocationType allocation) {
+ DCHECK_EQ(kInvalidEnumCacheSentinel, map->EnumLength());
+ DCHECK_GT(enum_length, 0);
+ DCHECK_EQ(enum_length, map->NumberOfEnumerableProperties());
+ DCHECK(!map->is_dictionary_map());
+
+ Handle<DescriptorArray> descriptors =
+ Handle<DescriptorArray>(map->instance_descriptors(isolate), isolate);
+
+ // The enum cache should have been a hit if the number of enumerable
+ // properties is fewer than what's already in the cache.
+ DCHECK_LT(descriptors->enum_cache().keys().length(), enum_length);
+ isolate->counters()->enum_cache_misses()->Increment();
+
+ // Create the keys array.
+ int index = 0;
+ bool fields_only = true;
+ Handle<FixedArray> keys =
+ isolate->factory()->NewFixedArray(enum_length, allocation);
+ for (InternalIndex i : map->IterateOwnDescriptors()) {
+ DisallowGarbageCollection no_gc;
+ PropertyDetails details = descriptors->GetDetails(i);
+ if (details.IsDontEnum()) continue;
+ Object key = descriptors->GetKey(i);
+ if (key.IsSymbol()) continue;
+ keys->set(index, key);
+ if (details.location() != PropertyLocation::kField) fields_only = false;
+ index++;
+ }
+ DCHECK_EQ(index, keys->length());
+
+ // Optionally also create the indices array.
+ Handle<FixedArray> indices = isolate->factory()->empty_fixed_array();
+ if (fields_only) {
+ indices = isolate->factory()->NewFixedArray(enum_length, allocation);
+ index = 0;
+ for (InternalIndex i : map->IterateOwnDescriptors()) {
+ DisallowGarbageCollection no_gc;
+ PropertyDetails details = descriptors->GetDetails(i);
+ if (details.IsDontEnum()) continue;
+ Object key = descriptors->GetKey(i);
+ if (key.IsSymbol()) continue;
+ DCHECK_EQ(PropertyKind::kData, details.kind());
+ DCHECK_EQ(PropertyLocation::kField, details.location());
+ FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
+ indices->set(index, Smi::FromInt(field_index.GetLoadByFieldIndex()));
+ index++;
+ }
+ DCHECK_EQ(index, indices->length());
+ }
+
+ DescriptorArray::InitializeOrChangeEnumCache(descriptors, isolate, keys,
+ indices, allocation);
+ if (map->OnlyHasSimpleProperties()) map->SetEnumLength(enum_length);
+ return keys;
+}
+
MaybeHandle<FixedArray>
-FastKeyAccumulator::GetOwnKeysWithUninitializedEnumCache() {
+FastKeyAccumulator::GetOwnKeysWithUninitializedEnumLength() {
Handle<JSObject> object = Handle<JSObject>::cast(receiver_);
- // Uninitalized enum cache
+ // Uninitialized enum length
Map map = object->map();
if (object->elements() != ReadOnlyRoots(isolate_).empty_fixed_array() &&
object->elements() !=
diff --git a/src/objects/keys.h b/src/objects/keys.h
index 4497f1211a42fc6dafc906ea9076f7c44995ac4a..031c407620b6af91ef4eb4453f1415c2a608211b 100644
--- a/src/objects/keys.h
+++ b/src/objects/keys.h
@@ -174,7 +174,7 @@ class KeyAccumulator final {
};
// The FastKeyAccumulator handles the cases where there are no elements on the
-// prototype chain and forwords the complex/slow cases to the normal
+// prototype chain and forwards the complex/slow cases to the normal
// KeyAccumulator. This significantly speeds up the cases where the OWN_ONLY
// case where we do not have to walk the prototype chain.
class FastKeyAccumulator {
@@ -200,6 +200,19 @@ class FastKeyAccumulator {
MaybeHandle<FixedArray> GetKeys(
GetKeysConversion convert = GetKeysConversion::kKeepNumbers);
+ // Initialize the the enum cache for a map with all of the following:
+ // - uninitialized enum length
+ // - fast properties (i.e. !is_dictionary_map())
+ // - has >0 enumerable own properties
+ //
+ // The number of enumerable properties is passed in as an optimization, for
+ // when the caller has already computed it.
+ //
+ // Returns the keys.
+ static Handle<FixedArray> InitializeFastPropertyEnumCache(
+ Isolate* isolate, Handle<Map> map, int enum_length,
+ AllocationType allocation = AllocationType::kOld);
+
private:
void Prepare();
MaybeHandle<FixedArray> GetKeysFast(GetKeysConversion convert);
@@ -207,7 +220,7 @@ class FastKeyAccumulator {
MaybeHandle<FixedArray> GetKeysWithPrototypeInfoCache(
GetKeysConversion convert);
- MaybeHandle<FixedArray> GetOwnKeysWithUninitializedEnumCache();
+ MaybeHandle<FixedArray> GetOwnKeysWithUninitializedEnumLength();
bool MayHaveElements(JSReceiver receiver);
bool TryPrototypeInfoCache(Handle<JSReceiver> receiver);
diff --git a/src/objects/objects.cc b/src/objects/objects.cc
index a7e1833f730e6e5869cd4925cca6dc908859000c..4a90a9ba970bffc78e38cad6e9e7e9053466a138 100644
--- a/src/objects/objects.cc
+++ b/src/objects/objects.cc
@@ -4448,10 +4448,12 @@ void DescriptorArray::Replace(InternalIndex index, Descriptor* descriptor) {
// static
void DescriptorArray::InitializeOrChangeEnumCache(
Handle<DescriptorArray> descriptors, Isolate* isolate,
- Handle<FixedArray> keys, Handle<FixedArray> indices) {
+ Handle<FixedArray> keys, Handle<FixedArray> indices,
+ AllocationType allocation_if_initialize) {
EnumCache enum_cache = descriptors->enum_cache();
if (enum_cache == ReadOnlyRoots(isolate).empty_enum_cache()) {
- enum_cache = *isolate->factory()->NewEnumCache(keys, indices);
+ enum_cache = *isolate->factory()->NewEnumCache(keys, indices,
+ allocation_if_initialize);
descriptors->set_enum_cache(enum_cache);
} else {
enum_cache.set_keys(*keys);
diff --git a/test/mjsunit/shared-memory/shared-struct-surface.js b/test/mjsunit/shared-memory/shared-struct-surface.js
index 55a08ccec2a56ee9c0df5fa9a778fe22d6e7e1fb..301a8a114df16262d3ce1e228f951eb911593116 100644
--- a/test/mjsunit/shared-memory/shared-struct-surface.js
+++ b/test/mjsunit/shared-memory/shared-struct-surface.js
@@ -76,3 +76,15 @@ let S = new SharedStructType(['field']);
assertEquals(1, entries.length);
assertArrayEquals(['field', 42], entries[0]);
})();
+
+(function TestForIn() {
+ let fieldNames = [];
+ for (let i = 0; i < 512; i++) {
+ fieldNames.push('field' + i);
+ }
+ let S2 = new SharedStructType(fieldNames);
+ let s = new S2();
+ let propNames = [];
+ for (let prop in s) propNames.push(prop);
+ assertArrayEquals(propNames, fieldNames);
+})();