| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 2ba79b9bf5142e270acb0470ee5ea9b7f6d355fe..791cf8bb470805fa0df553ed8500f5511c2059d0 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -4946,11 +4946,18 @@ static bool ComputeLoadStoreField(Handle<Map> type,
|
| Handle<String> name,
|
| LookupResult* lookup,
|
| bool is_store) {
|
| - type->LookupTransitionOrDescriptor(NULL, *name, lookup);
|
| + // If we directly find a field, the access can be inlined.
|
| + type->LookupDescriptor(NULL, *name, lookup);
|
| if (lookup->IsField()) return true;
|
| - return is_store &&
|
| - lookup->IsTransitionToField(*type) &&
|
| - (type->unused_property_fields() > 0);
|
| +
|
| + // For a load, we are out of luck if there is no such field.
|
| + if (!is_store) return false;
|
| +
|
| + // 2nd chance: A store into a non-existent field can still be inlined if we
|
| + // have a matching transition and some room left in the object.
|
| + type->LookupTransition(NULL, *name, lookup);
|
| + return lookup->IsTransitionToField(*type) &&
|
| + (type->unused_property_fields() > 0);
|
| }
|
|
|
|
|
| @@ -5042,21 +5049,71 @@ HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object,
|
| }
|
|
|
|
|
| +static void LookupInPrototypes(Handle<Map> map,
|
| + Handle<String> name,
|
| + LookupResult* lookup) {
|
| + while (map->prototype()->IsJSObject()) {
|
| + Handle<JSObject> holder(JSObject::cast(map->prototype()));
|
| + if (!holder->HasFastProperties()) break;
|
| + map = Handle<Map>(holder->map());
|
| + map->LookupDescriptor(*holder, *name, lookup);
|
| + if (lookup->IsFound()) return;
|
| + }
|
| + lookup->NotFound();
|
| +}
|
| +
|
| +
|
| +HInstruction* HGraphBuilder::BuildCallSetter(HValue* obj,
|
| + Handle<String> name,
|
| + HValue* value,
|
| + Handle<Map> map,
|
| + Handle<Object> callback,
|
| + Handle<JSObject> holder) {
|
| + if (!callback->IsAccessorPair()) {
|
| + return BuildStoreNamedGeneric(obj, name, value);
|
| + }
|
| + Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter());
|
| + Handle<JSFunction> function(Handle<JSFunction>::cast(setter));
|
| + AddCheckConstantFunction(holder, obj, map, true);
|
| + AddInstruction(new(zone()) HPushArgument(obj));
|
| + AddInstruction(new(zone()) HPushArgument(value));
|
| + return new(zone()) HCallConstantFunction(function, 2);
|
| +}
|
| +
|
| +
|
| HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
|
| HValue* value,
|
| Handle<Map> type,
|
| Expression* key) {
|
| + // If we don't know the monomorphic type, do a generic store.
|
| Handle<String> name = Handle<String>::cast(key->AsLiteral()->handle());
|
| - ASSERT(!name.is_null());
|
| + if (type.is_null()) return BuildStoreNamedGeneric(object, name, value);
|
|
|
| + // Handle a store to a known field.
|
| LookupResult lookup(isolate());
|
| - bool is_monomorphic = !type.is_null() &&
|
| - ComputeLoadStoreField(type, name, &lookup, true);
|
| + if (ComputeLoadStoreField(type, name, &lookup, true)) {
|
| + // true = needs smi and map check.
|
| + return BuildStoreNamedField(object, name, value, type, &lookup, true);
|
| + }
|
| +
|
| + // Handle a known setter directly in the receiver.
|
| + type->LookupDescriptor(NULL, *name, &lookup);
|
| + if (lookup.IsPropertyCallbacks()) {
|
| + Handle<Object> callback(lookup.GetValueFromMap(*type));
|
| + Handle<JSObject> holder;
|
| + return BuildCallSetter(object, name, value, type, callback, holder);
|
| + }
|
| +
|
| + // Handle a known setter somewhere in the prototype chain.
|
| + LookupInPrototypes(type, name, &lookup);
|
| + if (lookup.IsPropertyCallbacks()) {
|
| + Handle<Object> callback(lookup.GetValue());
|
| + Handle<JSObject> holder(lookup.holder());
|
| + return BuildCallSetter(object, name, value, type, callback, holder);
|
| + }
|
|
|
| - return is_monomorphic
|
| - ? BuildStoreNamedField(object, name, value, type, &lookup,
|
| - true) // Needs smi and map check.
|
| - : BuildStoreNamedGeneric(object, name, value);
|
| + // No luck, do a generic store.
|
| + return BuildStoreNamedGeneric(object, name, value);
|
| }
|
|
|
|
|
| @@ -5632,20 +5689,6 @@ HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj,
|
| }
|
|
|
|
|
| -static void LookupInPrototypes(Handle<Map> map,
|
| - Handle<String> name,
|
| - LookupResult* lookup) {
|
| - while (map->prototype()->IsJSObject()) {
|
| - Handle<JSObject> holder(JSObject::cast(map->prototype()));
|
| - if (!holder->HasFastProperties()) break;
|
| - map = Handle<Map>(holder->map());
|
| - map->LookupDescriptor(*holder, *name, lookup);
|
| - if (lookup->IsFound()) return;
|
| - }
|
| - lookup->NotFound();
|
| -}
|
| -
|
| -
|
| HInstruction* HGraphBuilder::BuildCallGetter(HValue* obj,
|
| Property* expr,
|
| Handle<Map> map,
|
|
|