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, ...@@ -248,12 +248,7 @@ static void LookupForRead(Handle<Object> object,
bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
Handle<String> name) { Handle<String> name) {
if (target()->is_keyed_stub()) { if (!IsNameCompatibleWithMonomorphicPrototypeFailure(name)) return false;
// 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;
}
InlineCacheHolderFlag cache_holder = InlineCacheHolderFlag cache_holder =
Code::ExtractCacheHolderFromFlags(target()->flags()); Code::ExtractCacheHolderFromFlags(target()->flags());
...@@ -336,6 +331,18 @@ void IC::TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name) { ...@@ -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) { void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
if (!name->IsString()) return; if (!name->IsString()) return;
if (state() != MONOMORPHIC) { if (state() != MONOMORPHIC) {
...@@ -352,8 +359,9 @@ void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) { ...@@ -352,8 +359,9 @@ void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
// because of changes in the prototype chain to avoid hitting it // because of changes in the prototype chain to avoid hitting it
// again. // again.
if (TryRemoveInvalidPrototypeDependentStub( if (TryRemoveInvalidPrototypeDependentStub(
receiver, Handle<String>::cast(name))) { receiver, Handle<String>::cast(name)) &&
return MarkMonomorphicPrototypeFailure(); TryMarkMonomorphicPrototypeFailure(name)) {
return;
} }
// The builtins object is special. It only changes when JavaScript // The builtins object is special. It only changes when JavaScript
...@@ -1184,8 +1192,9 @@ static bool LookupForWrite(Handle<JSObject> receiver, ...@@ -1184,8 +1192,9 @@ static bool LookupForWrite(Handle<JSObject> receiver,
// entirely by the migration above. // entirely by the migration above.
receiver->map()->LookupTransition(*holder, *name, lookup); receiver->map()->LookupTransition(*holder, *name, lookup);
if (!lookup->IsTransition()) return false; if (!lookup->IsTransition()) return false;
ic->MarkMonomorphicPrototypeFailure(); return ic->TryMarkMonomorphicPrototypeFailure(name);
} }
return true; return true;
} }
......
...@@ -96,8 +96,14 @@ class IC { ...@@ -96,8 +96,14 @@ class IC {
// Compute the current IC state based on the target stub, receiver and name. // Compute the current IC state based on the target stub, receiver and name.
void UpdateState(Handle<Object> receiver, Handle<Object> name); void UpdateState(Handle<Object> receiver, Handle<Object> name);
void MarkMonomorphicPrototypeFailure() {
state_ = MONOMORPHIC_PROTOTYPE_FAILURE; 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. // 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