[ic] Always use generic ICs for growing element stores on arguments

In certain corner-cases we would grow a FAST_ELEMENTS packed backing store of a
JS_ARGUMENTS_TYPE object without converting to holey elements kinds. As a side
effect you could then read out the_hole.

BUG=v8:5772

Review-Url: https://codereview.chromium.org/2597013004
Cr-Commit-Position: refs/heads/master@{#41921}
This commit is contained in:
cbruni 2016-12-22 06:10:51 -08:00 committed by Commit bot
parent b9b6e0b06d
commit f73973092c
4 changed files with 51 additions and 10 deletions

View File

@ -2422,17 +2422,14 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
} }
Handle<Map> old_receiver_map; Handle<Map> old_receiver_map;
bool sloppy_arguments_elements = false; bool is_arguments = false;
bool key_is_valid_index = false; bool key_is_valid_index = false;
KeyedAccessStoreMode store_mode = STANDARD_STORE; KeyedAccessStoreMode store_mode = STANDARD_STORE;
if (use_ic && object->IsJSObject()) { if (use_ic && object->IsJSObject()) {
Handle<JSObject> receiver = Handle<JSObject>::cast(object); Handle<JSObject> receiver = Handle<JSObject>::cast(object);
old_receiver_map = handle(receiver->map(), isolate()); old_receiver_map = handle(receiver->map(), isolate());
sloppy_arguments_elements = is_arguments = receiver->IsJSArgumentsObject();
!is_sloppy(language_mode()) && if (!is_arguments) {
receiver->elements()->map() ==
isolate()->heap()->sloppy_arguments_elements_map();
if (!sloppy_arguments_elements) {
key_is_valid_index = key->IsSmi() && Smi::cast(*key)->value() >= 0; key_is_valid_index = key->IsSmi() && Smi::cast(*key)->value() >= 0;
if (key_is_valid_index) { if (key_is_valid_index) {
uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value()); uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value());
@ -2449,7 +2446,7 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
if (use_ic) { if (use_ic) {
if (!old_receiver_map.is_null()) { if (!old_receiver_map.is_null()) {
if (sloppy_arguments_elements) { if (is_arguments) {
TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver"); TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver");
} else if (key_is_valid_index) { } else if (key_is_valid_index) {
// We should go generic if receiver isn't a dictionary, but our // We should go generic if receiver isn't a dictionary, but our

View File

@ -138,8 +138,9 @@ TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
TYPE_CHECKER(Foreign, FOREIGN_TYPE) TYPE_CHECKER(Foreign, FOREIGN_TYPE)
TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE) TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE) TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
TYPE_CHECKER(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE) TYPE_CHECKER(JSArgumentsObject, JS_ARGUMENTS_TYPE)
TYPE_CHECKER(JSArray, JS_ARRAY_TYPE) TYPE_CHECKER(JSArray, JS_ARRAY_TYPE)
TYPE_CHECKER(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE)
TYPE_CHECKER(JSBoundFunction, JS_BOUND_FUNCTION_TYPE) TYPE_CHECKER(JSBoundFunction, JS_BOUND_FUNCTION_TYPE)
TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE) TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE) TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE)
@ -148,14 +149,14 @@ TYPE_CHECKER(JSError, JS_ERROR_TYPE)
TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE) TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE) TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE)
TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE) TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
TYPE_CHECKER(JSMapIterator, JS_MAP_ITERATOR_TYPE)
TYPE_CHECKER(JSMap, JS_MAP_TYPE) TYPE_CHECKER(JSMap, JS_MAP_TYPE)
TYPE_CHECKER(JSMapIterator, JS_MAP_ITERATOR_TYPE)
TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE) TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
TYPE_CHECKER(JSModuleNamespace, JS_MODULE_NAMESPACE_TYPE) TYPE_CHECKER(JSModuleNamespace, JS_MODULE_NAMESPACE_TYPE)
TYPE_CHECKER(JSPromise, JS_PROMISE_TYPE) TYPE_CHECKER(JSPromise, JS_PROMISE_TYPE)
TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE) TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE)
TYPE_CHECKER(JSSet, JS_SET_TYPE) TYPE_CHECKER(JSSet, JS_SET_TYPE)
TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE)
TYPE_CHECKER(JSStringIterator, JS_STRING_ITERATOR_TYPE) TYPE_CHECKER(JSStringIterator, JS_STRING_ITERATOR_TYPE)
TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE) TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE)
TYPE_CHECKER(JSValue, JS_VALUE_TYPE) TYPE_CHECKER(JSValue, JS_VALUE_TYPE)

View File

@ -1043,6 +1043,7 @@ template <class C> inline bool Is(Object* obj);
V(FreeSpace) \ V(FreeSpace) \
V(JSReceiver) \ V(JSReceiver) \
V(JSObject) \ V(JSObject) \
V(JSArgumentsObject) \
V(JSContextExtensionObject) \ V(JSContextExtensionObject) \
V(JSGeneratorObject) \ V(JSGeneratorObject) \
V(JSModuleNamespace) \ V(JSModuleNamespace) \

View File

@ -0,0 +1,42 @@
// Copyright 2016 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
(function sloppyPackedArguments() {
function f(a) {
for (var i = 0; i < 2; i++) {
a[i] = 0;
}
}
var boom;
function g() {
var a = arguments;
f(a);
boom = a[5];
assertEquals(undefined, boom);
}
f([]);
g(1);
})();
(function strictPackedArguments() {
"use strict";
function f(a) {
for (var i = 0; i < 2; i++) {
a[i] = 0;
}
}
var boom;
function g() {
var a = arguments;
f(a);
boom = a[5];
assertEquals(undefined, boom);
}
f([]);
g(1);
})();