Monomorphic prototype failures should be reserved for already-seen keys.

We incorrectly mark a KeyedStoreIC miss as a monomorphic prototype
failure even though it's the first time a particular (string) key has
been seen.

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

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20407 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 061a5126
......@@ -248,12 +248,7 @@ static void LookupForRead(Handle<Object> object,
bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
Handle<String> name) {
if (target()->is_keyed_stub()) {
// Determine whether the failure is due to a name failure.
if (!name->IsName()) return false;
Name* stub_name = target()->FindFirstName();
if (*name != stub_name) return false;
}
if (!IsNameCompatibleWithMonomorphicPrototypeFailure(name)) return false;
InlineCacheHolderFlag cache_holder =
Code::ExtractCacheHolderFromFlags(target()->flags());
......@@ -336,6 +331,18 @@ void IC::TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name) {
}
bool IC::IsNameCompatibleWithMonomorphicPrototypeFailure(Handle<Object> name) {
if (target()->is_keyed_stub()) {
// Determine whether the failure is due to a name failure.
if (!name->IsName()) return false;
Name* stub_name = target()->FindFirstName();
if (*name != stub_name) return false;
}
return true;
}
void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
if (!name->IsString()) return;
if (state() != MONOMORPHIC) {
......@@ -352,8 +359,9 @@ void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
// because of changes in the prototype chain to avoid hitting it
// again.
if (TryRemoveInvalidPrototypeDependentStub(
receiver, Handle<String>::cast(name))) {
return MarkMonomorphicPrototypeFailure();
receiver, Handle<String>::cast(name)) &&
TryMarkMonomorphicPrototypeFailure(name)) {
return;
}
// The builtins object is special. It only changes when JavaScript
......@@ -1184,8 +1192,9 @@ static bool LookupForWrite(Handle<JSObject> receiver,
// entirely by the migration above.
receiver->map()->LookupTransition(*holder, *name, lookup);
if (!lookup->IsTransition()) return false;
ic->MarkMonomorphicPrototypeFailure();
return ic->TryMarkMonomorphicPrototypeFailure(name);
}
return true;
}
......
......@@ -96,8 +96,14 @@ class IC {
// Compute the current IC state based on the target stub, receiver and name.
void UpdateState(Handle<Object> receiver, Handle<Object> name);
void MarkMonomorphicPrototypeFailure() {
bool IsNameCompatibleWithMonomorphicPrototypeFailure(Handle<Object> name);
bool TryMarkMonomorphicPrototypeFailure(Handle<Object> name) {
if (IsNameCompatibleWithMonomorphicPrototypeFailure(name)) {
state_ = MONOMORPHIC_PROTOTYPE_FAILURE;
return true;
}
return false;
}
// Clear the inline cache to initial state.
......
// 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.
function f(a) {
a[a.length] = 1;
}
function g(a, i, v) {
a[i] = v;
}
f([]); // f KeyedStoreIC goes to 1.GROW
o = {};
g(o); // We've added property "undefined" to o
o = {}; // A transition on property "undefined" exists from {}
f(o); // Store should go generic.
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