From 8feab2edc78b54e73b1b64e9e688c1fc6f7ac24b Mon Sep 17 00:00:00 2001 From: "verwaest@chromium.org" Date: Wed, 2 Oct 2013 17:18:13 +0000 Subject: [PATCH] Cleanup map deprecation handling in the ICs R=ulan@chromium.org Review URL: https://chromiumcodereview.appspot.com/25529002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17087 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/ic.cc | 151 +++++++++++++++++++++++++------------------------------------- 1 file changed, 61 insertions(+), 90 deletions(-) diff --git a/src/ic.cc b/src/ic.cc index f74a9a8..0dc17d5 100644 --- a/src/ic.cc +++ b/src/ic.cc @@ -539,16 +539,18 @@ void CallICBase::ReceiverToObjectIfRequired(Handle callee, } +static bool MigrateDeprecated(Handle object) { + if (!object->IsJSObject()) return false; + Handle receiver = Handle::cast(object); + if (!receiver->map()->is_deprecated()) return false; + JSObject::MigrateInstance(Handle::cast(object)); + return true; +} + + MaybeObject* CallICBase::LoadFunction(Handle object, Handle name) { - bool use_ic = FLAG_use_ic; - if (object->IsJSObject()) { - Handle receiver = Handle::cast(object); - if (receiver->map()->is_deprecated()) { - use_ic = false; - JSObject::MigrateInstance(receiver); - } - } + bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; // If the object is undefined or null it's illegal to try to get any // of its properties; throw a TypeError in that case. @@ -796,22 +798,15 @@ MaybeObject* KeyedCallIC::LoadFunction(Handle object, return CallICBase::LoadFunction(object, Handle::cast(key)); } - bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); - if (object->IsJSObject()) { - Handle receiver = Handle::cast(object); - if (receiver->map()->is_deprecated()) { - use_ic = false; - JSObject::MigrateInstance(receiver); - } - } - if (object->IsUndefined() || object->IsNull()) { return TypeError("non_object_property_call", object, key); } - ASSERT(!(use_ic && object->IsJSGlobalProxy())); + bool use_ic = MigrateDeprecated(object) + ? false : FLAG_use_ic && !object->IsAccessCheckNeeded(); if (use_ic && state() != MEGAMORPHIC) { + ASSERT(!object->IsJSGlobalProxy()); int argc = target()->arguments_count(); Handle stub = isolate()->stub_cache()->ComputeCallMegamorphic( argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); @@ -851,9 +846,7 @@ MaybeObject* LoadIC::Load(Handle object, return TypeError("non_object_property_load", object, name); } - bool use_ic = FLAG_use_ic; - - if (use_ic) { + if (FLAG_use_ic) { // Use specialized code for getting the length of strings and // string wrapper objects. The length property of string wrapper // objects is read-only and therefore always returns the length of @@ -910,17 +903,11 @@ MaybeObject* LoadIC::Load(Handle object, uint32_t index; if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { // Rewrite to the generic keyed load stub. - if (use_ic) set_target(*generic_stub()); + if (FLAG_use_ic) set_target(*generic_stub()); return Runtime::GetElementOrCharAtOrFail(isolate(), object, index); } - if (object->IsJSObject()) { - Handle receiver = Handle::cast(object); - if (receiver->map()->is_deprecated()) { - use_ic = false; - JSObject::MigrateInstance(receiver); - } - } + bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; // Named lookup in the object. LookupResult lookup(isolate()); @@ -938,21 +925,17 @@ MaybeObject* LoadIC::Load(Handle object, if (use_ic) UpdateCaches(&lookup, object, name); PropertyAttributes attr; - if (lookup.IsInterceptor() || lookup.IsHandler()) { - // Get the property. - Handle result = - Object::GetProperty(object, object, &lookup, name, &attr); - RETURN_IF_EMPTY_HANDLE(isolate(), result); - // If the property is not present, check if we need to throw an - // exception. - if (attr == ABSENT && IsUndeclaredGlobal(object)) { - return ReferenceError("not_defined", name); - } - return *result; - } - // Get the property. - return Object::GetPropertyOrFail(object, object, &lookup, name, &attr); + Handle result = + Object::GetProperty(object, object, &lookup, name, &attr); + RETURN_IF_EMPTY_HANDLE(isolate(), result); + // If the property is not present, check if we need to throw an + // exception. + if ((lookup.IsInterceptor() || lookup.IsHandler()) && + attr == ABSENT && IsUndeclaredGlobal(object)) { + return ReferenceError("not_defined", name); + } + return *result; } @@ -1349,6 +1332,10 @@ Handle KeyedLoadIC::LoadElementStub(Handle receiver) { MaybeObject* KeyedLoadIC::Load(Handle object, Handle key, ICMissMode miss_mode) { + if (MigrateDeprecated(object)) { + return Runtime::GetObjectPropertyOrFail(isolate(), object, key); + } + // Check for values that can be converted into an internalized string directly // or is representable as a smi. key = TryConvertKey(key, isolate()); @@ -1357,41 +1344,29 @@ MaybeObject* KeyedLoadIC::Load(Handle object, return LoadIC::Load(object, Handle::cast(key)); } - bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); - ASSERT(!(use_ic && object->IsJSGlobalProxy())); - - if (use_ic) { + if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { + ASSERT(!object->IsJSGlobalProxy()); Handle stub = generic_stub(); - if (miss_mode != MISS_FORCE_GENERIC) { - if (object->IsString() && key->IsNumber()) { - if (state() == UNINITIALIZED) { - stub = string_stub(); - } - } else if (object->IsJSObject()) { - Handle receiver = Handle::cast(object); - if (receiver->map()->is_deprecated()) { - use_ic = false; - JSObject::MigrateInstance(receiver); - } - - if (receiver->elements()->map() == - isolate()->heap()->non_strict_arguments_elements_map()) { - stub = non_strict_arguments_stub(); - } else if (receiver->HasIndexedInterceptor()) { - stub = indexed_interceptor_stub(); - } else if (!key->ToSmi()->IsFailure() && - (!target().is_identical_to(non_strict_arguments_stub()))) { - stub = LoadElementStub(receiver); - } - } - } else { + if (miss_mode == MISS_FORCE_GENERIC) { TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); + } else if (object->IsString() && key->IsNumber()) { + if (state() == UNINITIALIZED) stub = string_stub(); + } else if (object->IsJSObject()) { + Handle receiver = Handle::cast(object); + if (receiver->elements()->map() == + isolate()->heap()->non_strict_arguments_elements_map()) { + stub = non_strict_arguments_stub(); + } else if (receiver->HasIndexedInterceptor()) { + stub = indexed_interceptor_stub(); + } else if (!key->ToSmi()->IsFailure() && + (!target().is_identical_to(non_strict_arguments_stub()))) { + stub = LoadElementStub(receiver); + } } - if (use_ic) { - ASSERT(!stub.is_null()); - set_target(*stub); - TRACE_IC("KeyedLoadIC", key, target()); - } + + ASSERT(!stub.is_null()); + set_target(*stub); + TRACE_IC("KeyedLoadIC", key, target()); } @@ -1527,8 +1502,7 @@ MaybeObject* StoreIC::Store(Handle object, Handle name, Handle value, JSReceiver::StoreFromKeyed store_mode) { - // Handle proxies. - if (object->IsJSProxy()) { + if (MigrateDeprecated(object) || object->IsJSProxy()) { Handle result = JSReceiver::SetProperty( Handle::cast(object), name, value, NONE, strict_mode()); RETURN_IF_EMPTY_HANDLE(isolate(), result); @@ -1553,12 +1527,6 @@ MaybeObject* StoreIC::Store(Handle object, Handle receiver = Handle::cast(object); - bool use_ic = FLAG_use_ic; - if (receiver->map()->is_deprecated()) { - use_ic = false; - JSObject::MigrateInstance(receiver); - } - // Check if the given name is an array index. uint32_t index; if (name->AsArrayIndex(&index)) { @@ -1580,7 +1548,7 @@ MaybeObject* StoreIC::Store(Handle object, // properties. Slow properties might indicate redefinition of the length // property. Note that when redefined using Object.freeze, it's possible // to have fast properties but a read-only length. - if (use_ic && + if (FLAG_use_ic && receiver->IsJSArray() && name->Equals(isolate()->heap()->length_string()) && Handle::cast(receiver)->AllowsSetElementsLength() && @@ -1597,7 +1565,7 @@ MaybeObject* StoreIC::Store(Handle object, } if (receiver->IsJSGlobalProxy()) { - if (use_ic && kind() != Code::KEYED_STORE_IC) { + if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { // Generate a generic stub that goes to the runtime when we see a global // proxy as receiver. Handle stub = global_proxy_stub(); @@ -1619,7 +1587,7 @@ MaybeObject* StoreIC::Store(Handle object, // Strict mode doesn't allow setting non-existent global property. return ReferenceError("not_defined", name); } - if (use_ic) { + if (FLAG_use_ic) { if (state() == UNINITIALIZED) { Handle stub = pre_monomorphic_stub(); set_target(*stub); @@ -1994,6 +1962,11 @@ MaybeObject* KeyedStoreIC::Store(Handle object, Handle key, Handle value, ICMissMode miss_mode) { + if (MigrateDeprecated(object)) { + return Runtime::SetObjectPropertyOrFail( + isolate(), object , key, value, NONE, strict_mode()); + } + // Check for values that can be converted into an internalized string directly // or is representable as a smi. key = TryConvertKey(key, isolate()); @@ -2015,16 +1988,14 @@ MaybeObject* KeyedStoreIC::Store(Handle object, Handle heap_object = Handle::cast(object); if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; } - ASSERT(!(use_ic && object->IsJSGlobalProxy())); if (use_ic) { + ASSERT(!object->IsJSGlobalProxy()); + Handle stub = generic_stub(); if (miss_mode != MISS_FORCE_GENERIC) { if (object->IsJSObject()) { Handle receiver = Handle::cast(object); - if (receiver->map()->is_deprecated()) { - JSObject::MigrateInstance(receiver); - } bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); if (receiver->elements()->map() == isolate()->heap()->non_strict_arguments_elements_map()) { -- 2.7.4