Commit a9b09801 authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[ic] Improve KeyedStoreIC performance for dictionaries.

Once the KeyedStoreIC was in MEGAMORPHIC state storing to dictionary
mode objects, we'd constantly hit the slow-path implemented via the
%SetProperty runtime function, if the dictionary was created with a
null prototype, i.e. via Object.create(null). This goes against the
advice of using Object.create(null) for dictionaries (compared to
using empty object literal), which is unfortunate.

This CL addresses two issues, starting with

- adding support for null prototypes to LookupPropertyOnPrototypeChain,
  which was always hitting the slow path for null prototypes, and
- using the dedicated %AddDictionaryProperty runtime call when we
  have to grow the backing store.

These changes combined improve the micro-benchmark from

  storeToDictionary: 559 ms.
  storeToFast: 95 ms.

to

  storeToDictionary: 201 ms.
  storeToFast: 94 ms.

which reduces overhead by about 65%. This overall improves the chai test
on the web-tooling-benchmark by about 4%, which still leaves some room
for improvement.

Bug: v8:6936, v8:6985
Change-Id: I97b78961f51edb3a3e198bdb31457fd78bed947f
Reviewed-on: https://chromium-review.googlesource.com/735139Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48858}
parent 6171698f
...@@ -529,6 +529,7 @@ void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain( ...@@ -529,6 +529,7 @@ void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain(
BIND(&loop); BIND(&loop);
{ {
Node* holder = var_holder.value(); Node* holder = var_holder.value();
GotoIf(IsNull(holder), &ok_to_write);
Node* holder_map = var_holder_map.value(); Node* holder_map = var_holder_map.value();
Node* instance_type = LoadMapInstanceType(holder_map); Node* instance_type = LoadMapInstanceType(holder_map);
Label next_proto(this); Label next_proto(this);
...@@ -595,7 +596,6 @@ void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain( ...@@ -595,7 +596,6 @@ void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain(
// Bailout if it can be an integer indexed exotic case. // Bailout if it can be an integer indexed exotic case.
GotoIf(InstanceTypeEqual(instance_type, JS_TYPED_ARRAY_TYPE), bailout); GotoIf(InstanceTypeEqual(instance_type, JS_TYPED_ARRAY_TYPE), bailout);
Node* proto = LoadMapPrototype(holder_map); Node* proto = LoadMapPrototype(holder_map);
GotoIf(WordEqual(proto, NullConstant()), &ok_to_write);
var_holder.Bind(proto); var_holder.Bind(proto);
var_holder_map.Bind(LoadMap(proto)); var_holder_map.Bind(LoadMap(proto));
Goto(&loop); Goto(&loop);
...@@ -890,8 +890,14 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( ...@@ -890,8 +890,14 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
LookupPropertyOnPrototypeChain(receiver_map, p->name, &accessor, LookupPropertyOnPrototypeChain(receiver_map, p->name, &accessor,
&var_accessor_pair, &var_accessor_holder, &var_accessor_pair, &var_accessor_holder,
&readonly, slow); &readonly, slow);
Add<NameDictionary>(properties, p->name, p->value, slow); Label add_dictionary_property_slow(this);
Add<NameDictionary>(properties, p->name, p->value,
&add_dictionary_property_slow);
Return(p->value); Return(p->value);
BIND(&add_dictionary_property_slow);
TailCallRuntime(Runtime::kAddDictionaryProperty, p->context, p->receiver,
p->name, p->value);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment