Commit 200ad461 authored by Mythri's avatar Mythri Committed by Commit Bot

[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: 's avatarToon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59580}
parent acd2a7f1
......@@ -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,
......
......@@ -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));
}
......
......@@ -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);
}
......
......@@ -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
......
......@@ -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)
......
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