[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:
parent
acd2a7f1b0
commit
200ad46147
@ -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,
|
||||
|
47
src/ic/ic.cc
47
src/ic/ic.cc
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user