[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}
This commit is contained in:
parent
bedff08691
commit
af677f29b1
@ -8005,7 +8005,8 @@ Node* CodeStubAssembler::CheckForCapacityGrow(
|
|||||||
KeyedAccessStoreMode store_mode, Node* length, Node* key,
|
KeyedAccessStoreMode store_mode, Node* length, Node* key,
|
||||||
ParameterMode mode, bool is_js_array, Label* bailout) {
|
ParameterMode mode, bool is_js_array, Label* bailout) {
|
||||||
VARIABLE(checked_elements, MachineRepresentation::kTagged);
|
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;
|
Node* condition;
|
||||||
if (IsHoleyOrDictionaryElementsKind(kind)) {
|
if (IsHoleyOrDictionaryElementsKind(kind)) {
|
||||||
@ -8026,11 +8027,24 @@ Node* CodeStubAssembler::CheckForCapacityGrow(
|
|||||||
|
|
||||||
{
|
{
|
||||||
Node* new_elements = TryGrowElementsCapacity(
|
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);
|
checked_elements.Bind(new_elements);
|
||||||
Goto(&fits_capacity);
|
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);
|
BIND(&fits_capacity);
|
||||||
if (is_js_array) {
|
if (is_js_array) {
|
||||||
Node* new_length = IntPtrAdd(key, IntPtrOrSmiConstant(1, mode));
|
Node* new_length = IntPtrAdd(key, IntPtrOrSmiConstant(1, mode));
|
||||||
|
Loading…
Reference in New Issue
Block a user