Bugfix for 349874: we incorrectly believe we saw a growing store

When we set an out of bounds array index, the index might be so large that
it causes the array to go to dictionary mode. It's better to avoid
"learning" that this was a growing store in that case.

This fix also partially reverts a fix for bug 347543, as this fix is
comprehensive and satisfies that repro case as well (partial revert of
v19591).

BUG=349874
LOG=N
R=verwaest@chromium.org

Review URL: https://codereview.chromium.org/188643002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19691 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mvstanton@chromium.org 2014-03-06 13:07:51 +00:00
parent cd6f3ef088
commit 6115a006fd
9 changed files with 44 additions and 26 deletions

View File

@ -1489,11 +1489,7 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
if (instr->size()->IsConstantOperand()) {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
if (size <= Page::kMaxRegularHeapObjectSize) {
__ Allocate(size, result, temp1, temp2, deferred->entry(), flags);
} else {
__ B(deferred->entry());
}
__ Allocate(size, result, temp1, temp2, deferred->entry(), flags);
} else {
Register size = ToRegister32(instr->size());
__ Sxtw(size.X(), size);

View File

@ -5262,11 +5262,7 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
if (instr->size()->IsConstantOperand()) {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
if (size <= Page::kMaxRegularHeapObjectSize) {
__ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
} else {
__ jmp(deferred->entry());
}
__ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
} else {
Register size = ToRegister(instr->size());
__ Allocate(size,

View File

@ -5789,11 +5789,7 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
if (instr->size()->IsConstantOperand()) {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
if (size <= Page::kMaxRegularHeapObjectSize) {
__ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
} else {
__ jmp(deferred->entry());
}
__ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
} else {
Register size = ToRegister(instr->size());
__ Allocate(size, result, temp, no_reg, deferred->entry(), flags);

View File

@ -1701,7 +1701,12 @@ MaybeObject* KeyedStoreIC::Store(Handle<Object> object,
if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) {
KeyedAccessStoreMode store_mode =
GetStoreMode(receiver, key, value);
stub = StoreElementStub(receiver, store_mode);
// Use the generic stub if the store would send the receiver to
// dictionary mode.
if (!IsGrowStoreMode(store_mode) ||
!receiver->WouldConvertToSlowElements(key)) {
stub = StoreElementStub(receiver, store_mode);
}
}
}
}

View File

@ -5217,11 +5217,7 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
}
if (instr->size()->IsConstantOperand()) {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
if (size <= Page::kMaxRegularHeapObjectSize) {
__ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
} else {
__ jmp(deferred->entry());
}
__ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
} else {
Register size = ToRegister(instr->size());
__ Allocate(size,

View File

@ -13113,6 +13113,21 @@ void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
}
bool JSObject::WouldConvertToSlowElements(Handle<Object> key) {
uint32_t index;
if (HasFastElements() && key->ToArrayIndex(&index)) {
Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
uint32_t capacity = static_cast<uint32_t>(backing_store->length());
if (index >= capacity) {
if ((index - capacity) >= kMaxGap) return true;
uint32_t new_capacity = NewElementsCapacity(index + 1);
return ShouldConvertToSlowElements(new_capacity);
}
}
return false;
}
bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <=
kMaxUncheckedFastElementsLength);

View File

@ -2412,6 +2412,9 @@ class JSObject: public JSReceiver {
uint32_t arg_count,
EnsureElementsMode mode);
// Would we convert a fast elements array to dictionary mode given
// an access at key?
bool WouldConvertToSlowElements(Handle<Object> key);
// Do we want to keep the elements in fast case when increasing the
// capacity?
bool ShouldConvertToSlowElements(int new_capacity);

View File

@ -5085,11 +5085,7 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
if (instr->size()->IsConstantOperand()) {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
if (size <= Page::kMaxRegularHeapObjectSize) {
__ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
} else {
__ jmp(deferred->entry());
}
__ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
} else {
Register size = ToRegister(instr->size());
__ Allocate(size, result, temp, no_reg, deferred->entry(), flags);

View File

@ -0,0 +1,15 @@
// Copyright 2014 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: --allow-natives-syntax
// The bug 349885
function foo(a) {
a[292755462] = new Object();
}
foo(new Array(5));
foo(new Array(5));
%OptimizeFunctionOnNextCall(foo);
foo(new Array(10));