[ic] Update Clone/StoreInArrayLiteral builtins to handle no feedback case

Updates CloneIC builtin to take the CloneIC_slow path when there is no
feedback vector. Also fixes the CloneIC_Slow to handle proxies correctly.

StoreInArrayLiteralIC doesn't change the behaviour but just makes it
consistent with other ICs.

Bug: v8:8293
Change-Id: Ib824b3ef06db1595ce06f04669857bb957cbe072
Reviewed-on: https://chromium-review.googlesource.com/c/1475750
Commit-Queue: Mythri Alle <mythria@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59682}
This commit is contained in:
Mythri 2019-02-19 10:11:33 +00:00 committed by Commit Bot
parent e4ca64ded6
commit a508efa61d
4 changed files with 40 additions and 34 deletions

View File

@ -297,6 +297,8 @@ Node* ConstructorBuiltinsAssembler::EmitCreateRegExpLiteral(
Node* context) {
Label call_runtime(this, Label::kDeferred), end(this);
GotoIf(IsUndefined(feedback_vector), &call_runtime);
VARIABLE(result, MachineRepresentation::kTagged);
TNode<Object> literal_site =
CAST(LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));

View File

@ -3092,6 +3092,9 @@ void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) {
Node* array_map = LoadReceiverMap(p->receiver);
GotoIf(IsDeprecatedMap(array_map), &miss);
GotoIf(IsUndefined(p->vector), &miss);
TNode<MaybeObject> feedback =
TryMonomorphicCase(p->slot, p->vector, array_map, &if_handler,
&var_handler, &try_polymorphic);
@ -3497,6 +3500,7 @@ void AccessorAssembler::GenerateCloneObjectIC_Slow() {
{
Label cont(this);
GotoIf(IsJSObjectInstanceType(type), &cont);
GotoIf(InstanceTypeEqual(type, JS_PROXY_TYPE), &call_runtime);
GotoIfNot(IsStringInstanceType(type), &done);
Branch(SmiEqual(LoadStringLengthAsSmi(CAST(source)), SmiConstant(0)), &done,
&call_runtime);
@ -3531,10 +3535,13 @@ void AccessorAssembler::GenerateCloneObjectIC() {
TVARIABLE(MaybeObject, var_handler);
Label if_handler(this, &var_handler);
Label miss(this, Label::kDeferred), try_polymorphic(this, Label::kDeferred),
try_megamorphic(this, Label::kDeferred);
try_megamorphic(this, Label::kDeferred), slow(this, Label::kDeferred);
TNode<Map> source_map = LoadMap(UncheckedCast<HeapObject>(source));
GotoIf(IsDeprecatedMap(source_map), &miss);
GotoIf(IsUndefined(vector), &slow);
TNode<MaybeObject> feedback = TryMonomorphicCase(
slot, vector, source_map, &if_handler, &var_handler, &try_polymorphic);
@ -3651,6 +3658,11 @@ void AccessorAssembler::GenerateCloneObjectIC() {
GotoIfNot(
WordEqual(strong_feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
&miss);
Goto(&slow);
}
BIND(&slow);
{
TailCallBuiltin(Builtins::kCloneObjectIC_Slow, context, source, flags, slot,
vector);
}

View File

@ -694,19 +694,8 @@ IGNITION_HANDLER(StaInArrayLiteral, InterpreterAssembler) {
Node* context = GetContext();
VARIABLE(var_result, MachineRepresentation::kTagged);
Label no_feedback(this, Label::kDeferred), end(this);
GotoIf(IsUndefined(feedback_vector), &no_feedback);
var_result.Bind(CallBuiltin(Builtins::kStoreInArrayLiteralIC, context, array,
index, value, smi_slot, feedback_vector));
Goto(&end);
BIND(&no_feedback);
var_result.Bind(CallRuntime(Runtime::kStoreInArrayLiteralIC_Miss, context,
value, smi_slot, feedback_vector, array, index));
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
@ -2432,22 +2421,10 @@ IGNITION_HANDLER(CreateRegExpLiteral, InterpreterAssembler) {
Node* context = GetContext();
VARIABLE(result, MachineRepresentation::kTagged);
Label no_feedback(this, Label::kDeferred), end(this);
GotoIf(IsUndefined(feedback_vector), &no_feedback);
ConstructorBuiltinsAssembler constructor_assembler(state());
result.Bind(constructor_assembler.EmitCreateRegExpLiteral(
feedback_vector, slot_id, pattern, flags, context));
Goto(&end);
BIND(&no_feedback);
{
result.Bind(CallRuntime(Runtime::kCreateRegExpLiteral, context,
feedback_vector, SmiTag(slot_id), pattern, flags));
Goto(&end);
}
BIND(&end);
SetAccumulator(result.value());
Dispatch();
}
@ -2613,18 +2590,8 @@ IGNITION_HANDLER(CloneObject, InterpreterAssembler) {
Node* context = GetContext();
Variable var_result(this, MachineRepresentation::kTagged);
Label no_feedback(this), end(this);
GotoIf(IsUndefined(maybe_feedback_vector), &no_feedback);
var_result.Bind(CallBuiltin(Builtins::kCloneObjectIC, context, source,
smi_flags, smi_slot, maybe_feedback_vector));
Goto(&end);
BIND(&no_feedback);
var_result.Bind(CallRuntime(Runtime::kCloneObjectIC_Miss, context, source,
smi_flags, smi_slot, maybe_feedback_vector));
Goto(&end);
BIND(&end);
SetAccumulator(var_result.value());
Dispatch();
}

View File

@ -0,0 +1,25 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var p = new Proxy({a: 1, b: 2}, {
ownKeys() { return ['a', 'b']; }
});
// clone and return a
function f(a) {
var y = {...a}
return y;
}
// Call with different maps to force it into megamorphic state
f({a: 1, b: 2});
f({a1: 1, b1: 3});
f({a2: 1, b2: 3});
f({a3: 1, b3: 4});
f({a4: 1, b4: 5});
// Test that y was initialized correctly in the slow path
var clone = f(p);
assertEquals(clone.a, 1);
assertEquals(clone.b, 2);