@@ -1033,7 +1033,7 @@ inline ThrowCompletionOr<Value> get_global(Interpreter& interpreter, IdentifierT
10331033
10341034 // OPTIMIZATION: For global var bindings, if the shape of the global object hasn't changed,
10351035 // we can use the cached property offset.
1036- if (&shape == cache.entries [0 ].shape ) {
1036+ if (&shape == cache.entries [0 ].shape && (!shape. is_dictionary () || shape. dictionary_generation () == cache. entries [ 0 ]. shape_dictionary_generation . value ()) ) {
10371037 auto value = binding_object.get_direct (cache.entries [0 ].property_offset .value ());
10381038 if (value.is_accessor ())
10391039 return TRY (call (vm, value.as_accessor ().getter (), js_undefined ()));
@@ -1085,6 +1085,10 @@ inline ThrowCompletionOr<Value> get_global(Interpreter& interpreter, IdentifierT
10851085 if (cacheable_metadata.type == CacheableGetPropertyMetadata::Type::GetOwnProperty) {
10861086 cache.entries [0 ].shape = shape;
10871087 cache.entries [0 ].property_offset = cacheable_metadata.property_offset .value ();
1088+
1089+ if (shape.is_dictionary ()) {
1090+ cache.entries [0 ].shape_dictionary_generation = shape.dictionary_generation ();
1091+ }
10881092 }
10891093 return value;
10901094 }
@@ -1140,6 +1144,13 @@ ThrowCompletionOr<void> put_by_property_key(VM& vm, Value base, Value this_value
11401144 bool can_use_cache = [&]() -> bool {
11411145 if (&object->shape () != cache.shape ) [[unlikely]]
11421146 return false ;
1147+
1148+ if (cache.shape ->is_dictionary ()) {
1149+ VERIFY (cache.shape_dictionary_generation .has_value ());
1150+ if (object->shape ().dictionary_generation () != cache.shape_dictionary_generation .value ()) [[unlikely]]
1151+ return false ;
1152+ }
1153+
11431154 auto cached_prototype_chain_validity = cache.prototype_chain_validity .ptr ();
11441155 if (!cached_prototype_chain_validity) [[unlikely]]
11451156 return false ;
@@ -1159,6 +1170,13 @@ ThrowCompletionOr<void> put_by_property_key(VM& vm, Value base, Value this_value
11591170 case PropertyLookupCache::Entry::Type::ChangeOwnProperty: {
11601171 if (cache.shape != &object->shape ()) [[unlikely]]
11611172 break ;
1173+
1174+ if (cache.shape ->is_dictionary ()) {
1175+ VERIFY (cache.shape_dictionary_generation .has_value ());
1176+ if (cache.shape ->dictionary_generation () != cache.shape_dictionary_generation .value ())
1177+ break ;
1178+ }
1179+
11621180 auto value_in_object = object->get_direct (cache.property_offset .value ());
11631181 if (value_in_object.is_accessor ()) [[unlikely]] {
11641182 (void )TRY (call (vm, value_in_object.as_accessor ().setter (), this_value, value));
@@ -1175,6 +1193,13 @@ ThrowCompletionOr<void> put_by_property_key(VM& vm, Value base, Value this_value
11751193 auto cached_shape = cache.shape .ptr ();
11761194 if (!cached_shape) [[unlikely]]
11771195 break ;
1196+
1197+ if (cache.shape ->is_dictionary ()) {
1198+ VERIFY (cache.shape_dictionary_generation .has_value ());
1199+ if (object->shape ().dictionary_generation () != cache.shape_dictionary_generation .value ())
1200+ break ;
1201+ }
1202+
11781203 // The cache is invalid if the prototype chain has been mutated, since such a mutation could have added a setter for the property.
11791204 auto cached_prototype_chain_validity = cache.prototype_chain_validity .ptr ();
11801205 if (cached_prototype_chain_validity && !cached_prototype_chain_validity->is_valid ()) [[unlikely]]
@@ -1209,6 +1234,9 @@ ThrowCompletionOr<void> put_by_property_key(VM& vm, Value base, Value this_value
12091234 if (cacheable_metadata.prototype ) {
12101235 cache.prototype_chain_validity = *cacheable_metadata.prototype ->shape ().prototype_chain_validity ();
12111236 }
1237+ if (cache.shape ->is_dictionary ()) {
1238+ cache.shape_dictionary_generation = cache.shape ->dictionary_generation ();
1239+ }
12121240 }
12131241
12141242 // If internal_set() caused object's shape change, we can no longer be sure
@@ -1225,13 +1253,21 @@ ThrowCompletionOr<void> put_by_property_key(VM& vm, Value base, Value this_value
12251253 cache.type = PropertyLookupCache::Entry::Type::ChangeOwnProperty;
12261254 cache.shape = object->shape ();
12271255 cache.property_offset = cacheable_metadata.property_offset .value ();
1256+
1257+ if (cache.shape ->is_dictionary ()) {
1258+ cache.shape_dictionary_generation = cache.shape ->dictionary_generation ();
1259+ }
12281260 break ;
12291261 case CacheableSetPropertyMetadata::Type::ChangePropertyInPrototypeChain:
12301262 cache.type = PropertyLookupCache::Entry::Type::ChangePropertyInPrototypeChain;
12311263 cache.shape = object->shape ();
12321264 cache.property_offset = cacheable_metadata.property_offset .value ();
12331265 cache.prototype = *cacheable_metadata.prototype ;
12341266 cache.prototype_chain_validity = *cacheable_metadata.prototype ->shape ().prototype_chain_validity ();
1267+
1268+ if (cache.shape ->is_dictionary ()) {
1269+ cache.shape_dictionary_generation = cache.shape ->dictionary_generation ();
1270+ }
12351271 break ;
12361272 case CacheableSetPropertyMetadata::Type::NotCacheable:
12371273 break ;
@@ -2294,7 +2330,7 @@ ThrowCompletionOr<void> SetGlobal::execute_impl(Bytecode::Interpreter& interpret
22942330 if (cache.environment_serial_number == declarative_record.environment_serial_number ()) {
22952331 // OPTIMIZATION: For global var bindings, if the shape of the global object hasn't changed,
22962332 // we can use the cached property offset.
2297- if (&shape == cache.entries [0 ].shape ) {
2333+ if (&shape == cache.entries [0 ].shape && (!shape. is_dictionary () || shape. dictionary_generation () == cache. entries [ 0 ]. shape_dictionary_generation . value ()) ) {
22982334 auto value = binding_object.get_direct (cache.entries [0 ].property_offset .value ());
22992335 if (value.is_accessor ())
23002336 TRY (call (vm, value.as_accessor ().setter (), &binding_object, src));
@@ -2363,6 +2399,10 @@ ThrowCompletionOr<void> SetGlobal::execute_impl(Bytecode::Interpreter& interpret
23632399 if (cacheable_metadata.type == CacheableSetPropertyMetadata::Type::ChangeOwnProperty) {
23642400 cache.entries [0 ].shape = shape;
23652401 cache.entries [0 ].property_offset = cacheable_metadata.property_offset .value ();
2402+
2403+ if (shape.is_dictionary ()) {
2404+ cache.entries [0 ].shape_dictionary_generation = shape.dictionary_generation ();
2405+ }
23662406 }
23672407 return {};
23682408 }
0 commit comments