[ic] Update StoreIC to handle no feedback vector case

The uninitialized case in the StoreIC doesn't use any feedback.
We could use this path to fast path some of the named stores instead of
missing to the runtime when the feedback vector is not available.

Bug: v8:8293
Change-Id: Ib3c4f843b24a377708f8db18fae10983e5633484
Reviewed-on: https://chromium-review.googlesource.com/c/1463781
Commit-Queue: Mythri Alle <mythria@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59580}
This commit is contained in:
Mythri 2019-02-11 15:39:48 +00:00 committed by Commit Bot
parent acd2a7f1b0
commit 200ad46147
5 changed files with 38 additions and 51 deletions

View File

@ -2789,11 +2789,14 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) {
if_handler_from_stub_cache(this, &var_handler, Label::kDeferred),
try_polymorphic(this, Label::kDeferred),
try_megamorphic(this, Label::kDeferred),
try_uninitialized(this, Label::kDeferred), miss(this, Label::kDeferred);
try_uninitialized(this, Label::kDeferred), miss(this, Label::kDeferred),
no_feedback(this, Label::kDeferred);
Node* receiver_map = LoadReceiverMap(p->receiver);
GotoIf(IsDeprecatedMap(receiver_map), &miss);
GotoIf(IsUndefined(p->vector), &no_feedback);
// Check monomorphic case.
TNode<MaybeObject> feedback =
TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler,
@ -2828,12 +2831,17 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) {
BIND(&try_uninitialized);
{
// Check uninitialized case.
GotoIfNot(
Branch(
WordEqual(strong_feedback, LoadRoot(RootIndex::kuninitialized_symbol)),
&miss);
&no_feedback, &miss);
}
BIND(&no_feedback);
{
TailCallBuiltin(Builtins::kStoreIC_Uninitialized, p->context, p->receiver,
p->name, p->value, p->slot, p->vector);
}
BIND(&miss);
{
TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot,

View File

@ -2350,46 +2350,27 @@ RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
// Runtime functions don't follow the IC's calling convention.
Handle<Object> value = args.at(0);
Handle<Smi> slot = args.at<Smi>(1);
Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
Handle<HeapObject> maybe_vector = args.at<HeapObject>(2);
Handle<Object> receiver = args.at(3);
Handle<Name> key = args.at<Name>(4);
FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
FeedbackSlotKind kind = vector->GetKind(vector_slot);
if (IsStoreICKind(kind) || IsStoreOwnICKind(kind)) {
StoreIC ic(isolate, vector, vector_slot, kind);
ic.UpdateState(receiver, key);
RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
} else if (IsStoreGlobalICKind(kind)) {
DCHECK_EQ(isolate->native_context()->global_proxy(), *receiver);
receiver = isolate->global_object();
StoreGlobalIC ic(isolate, vector, vector_slot, kind);
ic.UpdateState(receiver, key);
RETURN_RESULT_OR_FAILURE(isolate, ic.Store(key, value));
} else {
DCHECK(IsKeyedStoreICKind(kind));
KeyedStoreIC ic(isolate, vector, vector_slot, kind);
ic.UpdateState(receiver, key);
RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
}
}
RUNTIME_FUNCTION(Runtime_StoreICNoFeedback_Miss) {
HandleScope scope(isolate);
DCHECK_EQ(4, args.length());
Handle<Object> value = args.at(0);
Handle<Object> receiver = args.at(1);
Handle<Name> key = args.at<Name>(2);
CONVERT_INT32_ARG_CHECKED(is_own_property_value, 3);
NamedPropertyType property_type =
static_cast<NamedPropertyType>(is_own_property_value);
// TODO(mythria): Replace StoreNamedStrict/Sloppy with StoreNamed.
// When there is no feedback vector it is OK to use the StoreNamedStrict as
// the feedback slot kind. We only need if it is StoreOwnICKind when
// installing the handler for storing const properties. This will happen only
// when feedback vector is available.
FeedbackSlotKind kind = FeedbackSlotKind::kStoreNamedStrict;
if (property_type == NamedPropertyType::kOwn) {
kind = FeedbackSlotKind::kStoreOwnNamed;
Handle<FeedbackVector> vector = Handle<FeedbackVector>();
if (!maybe_vector->IsUndefined()) {
DCHECK(maybe_vector->IsFeedbackVector());
vector = Handle<FeedbackVector>::cast(maybe_vector);
kind = vector->GetKind(vector_slot);
}
StoreIC ic(isolate, Handle<FeedbackVector>(), FeedbackSlot(), kind);
DCHECK(IsStoreICKind(kind) || IsStoreOwnICKind(kind));
StoreIC ic(isolate, vector, vector_slot, kind);
ic.UpdateState(receiver, key);
RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
}

View File

@ -1048,7 +1048,7 @@ void KeyedStoreGenericAssembler::StoreIC_Uninitialized() {
Node* vector = Parameter(Descriptor::kVector);
Node* context = Parameter(Descriptor::kContext);
Label miss(this);
Label miss(this, Label::kDeferred), store_property(this);
GotoIf(TaggedIsSmi(receiver), &miss);
Node* receiver_map = LoadMap(receiver);
@ -1058,19 +1058,29 @@ void KeyedStoreGenericAssembler::StoreIC_Uninitialized() {
GotoIf(IsSpecialReceiverInstanceType(instance_type), &miss);
// Optimistically write the state transition to the vector.
GotoIf(IsUndefined(vector), &store_property);
StoreFeedbackVectorSlot(vector, slot,
LoadRoot(RootIndex::kpremonomorphic_symbol),
SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
Goto(&store_property);
StoreICParameters p(context, receiver, name, value, slot, vector);
EmitGenericPropertyStore(receiver, receiver_map, &p, &miss);
BIND(&store_property);
{
StoreICParameters p(context, receiver, name, value, slot, vector);
EmitGenericPropertyStore(receiver, receiver_map, &p, &miss);
}
BIND(&miss);
{
Label call_runtime(this);
// Undo the optimistic state transition.
GotoIf(IsUndefined(vector), &call_runtime);
StoreFeedbackVectorSlot(vector, slot,
LoadRoot(RootIndex::kuninitialized_symbol),
SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
Goto(&call_runtime);
BIND(&call_runtime);
TailCallRuntime(Runtime::kStoreIC_Miss, context, value, slot, vector,
receiver, name);
}

View File

@ -606,19 +606,8 @@ class InterpreterStoreNamedPropertyAssembler : public InterpreterAssembler {
Node* context = GetContext();
VARIABLE(var_result, MachineRepresentation::kTagged);
Label no_feedback(this, Label::kDeferred), end(this);
GotoIf(IsUndefined(maybe_vector), &no_feedback);
var_result.Bind(CallStub(ic.descriptor(), code_target, context, object,
name, value, smi_slot, maybe_vector));
Goto(&end);
Bind(&no_feedback);
var_result.Bind(CallRuntime(Runtime::kStoreICNoFeedback_Miss, context,
value, object, name,
SmiConstant(property_type)));
Goto(&end);
Bind(&end);
// To avoid special logic in the deoptimizer to re-materialize the value in
// the accumulator, we overwrite the accumulator after the IC call. It
// doesn't really matter what we write to the accumulator here, since we

View File

@ -571,7 +571,6 @@ namespace internal {
F(StoreGlobalICNoFeedback_Miss, 2, 1) \
F(StoreGlobalIC_Slow, 5, 1) \
F(StoreIC_Miss, 5, 1) \
F(StoreICNoFeedback_Miss, 4, 1) \
F(StoreInArrayLiteralIC_Slow, 5, 1) \
F(StorePropertyWithInterceptor, 5, 1) \
F(CloneObjectIC_Miss, 4, 1)