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:
parent
cd6f3ef088
commit
6115a006fd
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
15
test/mjsunit/regress/regress-349885.js
Normal file
15
test/mjsunit/regress/regress-349885.js
Normal 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));
|
Loading…
Reference in New Issue
Block a user