Commit a50bc8ac authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

Reland "[ic] EmitElementStore: don't miss when hitting new space limit."

This is a reland of af677f29, fixing
an issue with negative indices.

Original change's description:
> [ic] EmitElementStore: don't miss when hitting new space limit.
>
> CSA::EmitElementStore used to bail out (IC miss) via
> CSA::CheckForCapacityGrow when the capacity hits the new space
> limit, causing the store IC to go megamorphic in my example (see
> referenced bug). With this CL, we do what TF'ed code does already:
> call into Runtime::kGrowArrayElements (in this situation), thus
> staying monomorphic.
>
> Here's a contrived test case:
>
> ////////////////////////
> let x = [];
>
> function bar() {
>   for (let i = 0; i < 50000; ++i) x[i] = i;
> }
>
> function foo() {
>   for (let i = x.length; i < 100e6; ++i) x[i] = i;
> }
>
> bar();
> foo();
> ////////////////////////
>
> This took about 4s on my machine, now it takes 3s.
>
> Bug: v8:7447
> Change-Id: I7f268fc55835f363d250613ce0357444a663051c
> Reviewed-on: https://chromium-review.googlesource.com/918723
> Commit-Queue: Georg Neis <neis@chromium.org>
> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#51297}

Bug: v8:7447, chromium:812451
Change-Id: I345b5e5b2437c4f50e42bbd87947630f24cd95eb
Reviewed-on: https://chromium-review.googlesource.com/921201
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51311}
parent 2a5791ce
......@@ -8005,7 +8005,8 @@ Node* CodeStubAssembler::CheckForCapacityGrow(
KeyedAccessStoreMode store_mode, Node* length, Node* key,
ParameterMode mode, bool is_js_array, Label* bailout) {
VARIABLE(checked_elements, MachineRepresentation::kTagged);
Label grow_case(this), no_grow_case(this), done(this);
Label grow_case(this), no_grow_case(this), done(this),
grow_bailout(this, Label::kDeferred);
Node* condition;
if (IsHoleyOrDictionaryElementsKind(kind)) {
......@@ -8022,15 +8023,29 @@ Node* CodeStubAssembler::CheckForCapacityGrow(
TaggedToParameter(LoadFixedArrayBaseLength(elements), mode);
checked_elements.Bind(elements);
Label fits_capacity(this);
// If key is negative, we will notice in Runtime::kGrowArrayElements.
GotoIf(UintPtrLessThan(key, current_capacity), &fits_capacity);
{
Node* new_elements = TryGrowElementsCapacity(
object, elements, kind, key, current_capacity, mode, bailout);
object, elements, kind, key, current_capacity, mode, &grow_bailout);
checked_elements.Bind(new_elements);
Goto(&fits_capacity);
}
BIND(&grow_bailout);
{
Node* tagged_key = mode == SMI_PARAMETERS
? key
: ChangeInt32ToTagged(TruncateWordToWord32(key));
Node* maybe_elements = CallRuntime(
Runtime::kGrowArrayElements, NoContextConstant(), object, tagged_key);
GotoIf(TaggedIsSmi(maybe_elements), bailout);
CSA_ASSERT(this, IsFixedArrayWithKind(maybe_elements, kind));
checked_elements.Bind(maybe_elements);
Goto(&fits_capacity);
}
BIND(&fits_capacity);
if (is_js_array) {
Node* new_length = IntPtrAdd(key, IntPtrOrSmiConstant(1, mode));
......
......@@ -532,17 +532,15 @@ RUNTIME_FUNCTION(Runtime_NormalizeElements) {
return *array;
}
// GrowArrayElements returns a sentinel Smi if the object was normalized.
// GrowArrayElements returns a sentinel Smi if the object was normalized or if
// the key is negative.
RUNTIME_FUNCTION(Runtime_GrowArrayElements) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_NUMBER_CHECKED(int, key, Int32, args[1]);
if (key < 0) {
return object->elements();
}
if (key < 0) return Smi::kZero;
uint32_t capacity = static_cast<uint32_t>(object->elements()->length());
uint32_t index = static_cast<uint32_t>(key);
......@@ -553,7 +551,6 @@ RUNTIME_FUNCTION(Runtime_GrowArrayElements) {
}
}
// On success, return the fixed array elements.
return object->elements();
}
......
// Copyright 2018 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.
// Flags: --expose-gc
var x = [];
function foo(x, p) {
x[p] = 5.3;
}
foo(x, 1);
foo(x, 2);
foo(x, -1);
gc();
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