| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index df4d8fc99c650a0192a8782db7cbf302e311802e..c44dddfe5cc9f3a7e43a004364db497e0f1687c2 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -4764,11 +4764,21 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
| property->RecordTypeFeedback(oracle());
|
| CHECK_ALIVE(VisitForValue(value));
|
| HValue* value = Pop();
|
| + Handle<Map> map = property->GetReceiverType();
|
| + Handle<String> name =
|
| + Handle<String>::cast(property->key()->handle());
|
| HInstruction* store;
|
| - CHECK_ALIVE(store = BuildStoreNamed(literal,
|
| - value,
|
| - property->GetReceiverType(),
|
| - property->key()));
|
| + if (map.is_null()) {
|
| + // If we don't know the monomorphic type, do a generic store.
|
| + CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value));
|
| + } else {
|
| +#if DEBUG
|
| + Handle<AccessorPair> accessors;
|
| + Handle<JSObject> holder;
|
| + ASSERT(!LookupAccessorPair(map, name, &accessors, &holder));
|
| +#endif
|
| + CHECK_ALIVE(store = BuildStoreNamed(literal, name, value, map));
|
| + }
|
| AddInstruction(store);
|
| if (store->HasObservableSideEffects()) AddSimulate(key->id());
|
| } else {
|
| @@ -4939,20 +4949,20 @@ static int ComputeLoadStoreFieldIndex(Handle<Map> type,
|
| HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object,
|
| Handle<String> name,
|
| HValue* value,
|
| - Handle<Map> type,
|
| + Handle<Map> map,
|
| LookupResult* lookup,
|
| bool smi_and_map_check) {
|
| ASSERT(lookup->IsFound());
|
| if (smi_and_map_check) {
|
| AddInstruction(new(zone()) HCheckNonSmi(object));
|
| - AddInstruction(HCheckMaps::NewWithTransitions(object, type, zone()));
|
| + AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone()));
|
| }
|
|
|
| // If the property does not exist yet, we have to check that it wasn't made
|
| // readonly or turned into a setter by some meanwhile modifications on the
|
| // prototype chain.
|
| - if (!lookup->IsProperty() && type->prototype()->IsJSReceiver()) {
|
| - Object* proto = type->prototype();
|
| + if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) {
|
| + Object* proto = map->prototype();
|
| // First check that the prototype chain isn't affected already.
|
| LookupResult proto_result(isolate());
|
| proto->Lookup(*name, &proto_result);
|
| @@ -4971,24 +4981,24 @@ HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object,
|
| }
|
| ASSERT(proto->IsJSObject());
|
| AddInstruction(new(zone()) HCheckPrototypeMaps(
|
| - Handle<JSObject>(JSObject::cast(type->prototype())),
|
| + Handle<JSObject>(JSObject::cast(map->prototype())),
|
| Handle<JSObject>(JSObject::cast(proto))));
|
| }
|
|
|
| - int index = ComputeLoadStoreFieldIndex(type, name, lookup);
|
| + int index = ComputeLoadStoreFieldIndex(map, name, lookup);
|
| bool is_in_object = index < 0;
|
| int offset = index * kPointerSize;
|
| if (index < 0) {
|
| // Negative property indices are in-object properties, indexed
|
| // from the end of the fixed part of the object.
|
| - offset += type->instance_size();
|
| + offset += map->instance_size();
|
| } else {
|
| offset += FixedArray::kHeaderSize;
|
| }
|
| HStoreNamedField* instr =
|
| new(zone()) HStoreNamedField(object, name, value, is_in_object, offset);
|
| - if (lookup->IsTransitionToField(*type)) {
|
| - Handle<Map> transition(lookup->GetTransitionMapFromMap(*type));
|
| + if (lookup->IsTransitionToField(*map)) {
|
| + Handle<Map> transition(lookup->GetTransitionMapFromMap(*map));
|
| instr->set_transition(transition);
|
| // TODO(fschneider): Record the new map type of the object in the IR to
|
| // enable elimination of redundant checks after the transition store.
|
| @@ -5025,53 +5035,28 @@ static void LookupInPrototypes(Handle<Map> map,
|
| }
|
|
|
|
|
| -HInstruction* HGraphBuilder::BuildCallSetter(HValue* obj,
|
| - Handle<String> name,
|
| +HInstruction* HGraphBuilder::BuildCallSetter(HValue* object,
|
| HValue* value,
|
| Handle<Map> map,
|
| - Handle<Object> callback,
|
| + Handle<AccessorPair> accessors,
|
| 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));
|
| + Handle<JSFunction> function(JSFunction::cast(accessors->setter()));
|
| + AddCheckConstantFunction(holder, object, map, true);
|
| + AddInstruction(new(zone()) HPushArgument(object));
|
| AddInstruction(new(zone()) HPushArgument(value));
|
| return new(zone()) HCallConstantFunction(function, 2);
|
| }
|
|
|
|
|
| HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
|
| + Handle<String> name,
|
| 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());
|
| - if (type.is_null()) return BuildStoreNamedGeneric(object, name, value);
|
| -
|
| + Handle<Map> map) {
|
| // Handle a store to a known field.
|
| LookupResult lookup(isolate());
|
| - if (ComputeLoadStoreField(type, name, &lookup, true)) {
|
| + if (ComputeLoadStoreField(map, 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 BuildStoreNamedField(object, name, value, map, &lookup, true);
|
| }
|
|
|
| // No luck, do a generic store.
|
| @@ -5083,6 +5068,7 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
|
| HValue* object,
|
| SmallMapList* types,
|
| Handle<String> name) {
|
| + AddInstruction(new(zone()) HCheckNonSmi(object));
|
| int count = 0;
|
| int previous_field_offset = 0;
|
| bool previous_field_is_in_object = false;
|
| @@ -5118,7 +5104,7 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
|
| HInstruction* instr;
|
| if (count == types->length() && is_monomorphic_field) {
|
| AddInstruction(new(zone()) HCheckMaps(object, types, zone()));
|
| - instr = BuildLoadNamedField(object, expr, map, &lookup, false);
|
| + instr = BuildLoadNamedField(object, map, &lookup, false);
|
| } else {
|
| HValue* context = environment()->LookupContext();
|
| instr = new(zone()) HLoadNamedFieldPolymorphic(context,
|
| @@ -5215,39 +5201,58 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
|
| expr->RecordTypeFeedback(oracle(), zone());
|
| CHECK_ALIVE(VisitForValue(prop->obj()));
|
|
|
| - HValue* value = NULL;
|
| - HInstruction* instr = NULL;
|
| -
|
| if (prop->key()->IsPropertyName()) {
|
| // Named store.
|
| CHECK_ALIVE(VisitForValue(expr->value()));
|
| - value = Pop();
|
| + HValue* value = Pop();
|
| HValue* object = Pop();
|
|
|
| Literal* key = prop->key()->AsLiteral();
|
| Handle<String> name = Handle<String>::cast(key->handle());
|
| ASSERT(!name.is_null());
|
|
|
| + HInstruction* instr = NULL;
|
| SmallMapList* types = expr->GetReceiverTypes();
|
| if (expr->IsMonomorphic()) {
|
| - CHECK_ALIVE(instr = BuildStoreNamed(object,
|
| - value,
|
| - types->first(),
|
| - prop->key()));
|
| + Handle<Map> type = types->first();
|
| + Handle<AccessorPair> accessors;
|
| + Handle<JSObject> holder;
|
| + if (LookupAccessorPair(type, name, &accessors, &holder)) {
|
| + Push(object);
|
| + Push(value);
|
| + Handle<JSFunction> setter(JSFunction::cast(accessors->setter()));
|
| + AddCheckConstantFunction(holder, object, type, true);
|
| + if (TryInlineSetter(setter, expr->AssignmentId(), prop->ReturnId())) {
|
| + return;
|
| + }
|
| + Drop(2);
|
| + AddInstruction(new(zone()) HPushArgument(object));
|
| + AddInstruction(new(zone()) HPushArgument(value));
|
| + instr = new(zone()) HCallConstantFunction(setter, 2);
|
| + } else {
|
| + CHECK_ALIVE(instr = BuildStoreNamed(object,
|
| + name,
|
| + value,
|
| + type));
|
| + }
|
|
|
| } else if (types != NULL && types->length() > 1) {
|
| - HandlePolymorphicStoreNamedField(expr, object, value, types, name);
|
| - return;
|
| -
|
| + return HandlePolymorphicStoreNamedField(expr, object, value, types, name);
|
| } else {
|
| instr = BuildStoreNamedGeneric(object, name, value);
|
| }
|
|
|
| + Push(value);
|
| + instr->set_position(expr->position());
|
| + AddInstruction(instr);
|
| + if (instr->HasObservableSideEffects()) AddSimulate(expr->AssignmentId());
|
| + return ast_context()->ReturnValue(Pop());
|
| +
|
| } else {
|
| // Keyed store.
|
| CHECK_ALIVE(VisitForValue(prop->key()));
|
| CHECK_ALIVE(VisitForValue(expr->value()));
|
| - value = Pop();
|
| + HValue* value = Pop();
|
| HValue* key = Pop();
|
| HValue* object = Pop();
|
| bool has_side_effects = false;
|
| @@ -5260,11 +5265,6 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
|
| AddSimulate(expr->AssignmentId());
|
| return ast_context()->ReturnValue(Pop());
|
| }
|
| - Push(value);
|
| - instr->set_position(expr->position());
|
| - AddInstruction(instr);
|
| - if (instr->HasObservableSideEffects()) AddSimulate(expr->AssignmentId());
|
| - return ast_context()->ReturnValue(Pop());
|
| }
|
|
|
|
|
| @@ -5391,16 +5391,22 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
|
| if (prop->key()->IsPropertyName()) {
|
| // Named property.
|
| CHECK_ALIVE(VisitForValue(prop->obj()));
|
| - HValue* obj = Top();
|
| + HValue* object = Top();
|
|
|
| + Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
|
| Handle<Map> map;
|
| HInstruction* load;
|
| if (prop->IsMonomorphic()) {
|
| - Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
|
| map = prop->GetReceiverTypes()->first();
|
| - load = BuildLoadNamed(obj, prop, map, name);
|
| + Handle<AccessorPair> accessors;
|
| + Handle<JSObject> holder;
|
| + if (LookupAccessorPair(map, name, &accessors, &holder)) {
|
| + load = BuildCallGetter(object, map, accessors, holder);
|
| + } else {
|
| + load = BuildLoadNamed(object, name, prop, map);
|
| + }
|
| } else {
|
| - load = BuildLoadNamedGeneric(obj, prop);
|
| + load = BuildLoadNamedGeneric(object, name, prop);
|
| }
|
| PushAndAdd(load);
|
| if (load->HasObservableSideEffects()) AddSimulate(expr->CompoundLoadId());
|
| @@ -5414,7 +5420,22 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
|
| if (instr->HasObservableSideEffects()) AddSimulate(operation->id());
|
|
|
| HInstruction* store;
|
| - CHECK_ALIVE(store = BuildStoreNamed(obj, instr, map, prop->key()));
|
| + if (map.is_null()) {
|
| + // If we don't know the monomorphic type, do a generic store.
|
| + CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, instr));
|
| + } else {
|
| + Handle<AccessorPair> accessors;
|
| + Handle<JSObject> holder;
|
| + if (LookupAccessorPair(map, name, &accessors, &holder)) {
|
| + CHECK_ALIVE(store = BuildCallSetter(object,
|
| + instr,
|
| + map,
|
| + accessors,
|
| + holder));
|
| + } else {
|
| + CHECK_ALIVE(store = BuildStoreNamed(object, name, instr, map));
|
| + }
|
| + }
|
| AddInstruction(store);
|
| // Drop the simulated receiver and value. Return the value.
|
| Drop(2);
|
| @@ -5615,20 +5636,19 @@ void HGraphBuilder::VisitThrow(Throw* expr) {
|
|
|
|
|
| HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
|
| - Property* expr,
|
| - Handle<Map> type,
|
| + Handle<Map> map,
|
| LookupResult* lookup,
|
| bool smi_and_map_check) {
|
| if (smi_and_map_check) {
|
| AddInstruction(new(zone()) HCheckNonSmi(object));
|
| - AddInstruction(HCheckMaps::NewWithTransitions(object, type, zone()));
|
| + AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone()));
|
| }
|
|
|
| - int index = lookup->GetLocalFieldIndexFromMap(*type);
|
| + int index = lookup->GetLocalFieldIndexFromMap(*map);
|
| if (index < 0) {
|
| // Negative property indices are in-object properties, indexed
|
| // from the end of the fixed part of the object.
|
| - int offset = (index * kPointerSize) + type->instance_size();
|
| + int offset = (index * kPointerSize) + map->instance_size();
|
| return new(zone()) HLoadNamedField(object, true, offset);
|
| } else {
|
| // Non-negative property indices are in the properties array.
|
| @@ -5638,63 +5658,79 @@ HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
|
| }
|
|
|
|
|
| -HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj,
|
| +HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* object,
|
| + Handle<String> name,
|
| Property* expr) {
|
| if (expr->IsUninitialized() && !FLAG_always_opt) {
|
| AddInstruction(new(zone()) HSoftDeoptimize);
|
| current_block()->MarkAsDeoptimizing();
|
| }
|
| - ASSERT(expr->key()->IsPropertyName());
|
| - Handle<Object> name = expr->key()->AsLiteral()->handle();
|
| HValue* context = environment()->LookupContext();
|
| - return new(zone()) HLoadNamedGeneric(context, obj, name);
|
| + return new(zone()) HLoadNamedGeneric(context, object, name);
|
| }
|
|
|
|
|
| -HInstruction* HGraphBuilder::BuildCallGetter(HValue* obj,
|
| - Property* expr,
|
| +HInstruction* HGraphBuilder::BuildCallGetter(HValue* object,
|
| Handle<Map> map,
|
| - Handle<Object> callback,
|
| + Handle<AccessorPair> accessors,
|
| Handle<JSObject> holder) {
|
| - if (!callback->IsAccessorPair()) return BuildLoadNamedGeneric(obj, expr);
|
| - Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter());
|
| - Handle<JSFunction> function(Handle<JSFunction>::cast(getter));
|
| - AddCheckConstantFunction(holder, obj, map, true);
|
| - AddInstruction(new(zone()) HPushArgument(obj));
|
| + Handle<JSFunction> function(JSFunction::cast(accessors->getter()));
|
| + AddCheckConstantFunction(holder, object, map, true);
|
| + AddInstruction(new(zone()) HPushArgument(object));
|
| return new(zone()) HCallConstantFunction(function, 1);
|
| }
|
|
|
|
|
| -HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj,
|
| +bool HGraphBuilder::LookupAccessorPair(Handle<Map> map,
|
| + Handle<String> name,
|
| + Handle<AccessorPair>* accessors,
|
| + Handle<JSObject>* holder) {
|
| + LookupResult lookup(isolate());
|
| +
|
| + // Check for a JavaScript accessor directly in the map.
|
| + map->LookupDescriptor(NULL, *name, &lookup);
|
| + if (lookup.IsPropertyCallbacks()) {
|
| + Handle<Object> callback(lookup.GetValueFromMap(*map));
|
| + if (!callback->IsAccessorPair()) return false;
|
| + *accessors = Handle<AccessorPair>::cast(callback);
|
| + *holder = Handle<JSObject>();
|
| + return true;
|
| + }
|
| +
|
| + // Everything else, e.g. a field, can't be an accessor call.
|
| + if (lookup.IsFound()) return false;
|
| +
|
| + // Check for a JavaScript accessor somewhere in the proto chain.
|
| + LookupInPrototypes(map, name, &lookup);
|
| + if (lookup.IsPropertyCallbacks()) {
|
| + Handle<Object> callback(lookup.GetValue());
|
| + if (!callback->IsAccessorPair()) return false;
|
| + *accessors = Handle<AccessorPair>::cast(callback);
|
| + *holder = Handle<JSObject>(lookup.holder());
|
| + return true;
|
| + }
|
| +
|
| + // We haven't found a JavaScript accessor anywhere.
|
| + return false;
|
| +}
|
| +
|
| +
|
| +HInstruction* HGraphBuilder::BuildLoadNamed(HValue* object,
|
| + Handle<String> name,
|
| Property* expr,
|
| - Handle<Map> map,
|
| - Handle<String> name) {
|
| + Handle<Map> map) {
|
| LookupResult lookup(isolate());
|
| map->LookupDescriptor(NULL, *name, &lookup);
|
| if (lookup.IsField()) {
|
| - return BuildLoadNamedField(obj,
|
| - expr,
|
| - map,
|
| - &lookup,
|
| - true);
|
| - } else if (lookup.IsConstantFunction()) {
|
| - AddInstruction(new(zone()) HCheckNonSmi(obj));
|
| - AddInstruction(HCheckMaps::NewWithTransitions(obj, map, zone()));
|
| + return BuildLoadNamedField(object, map, &lookup, true);
|
| + }
|
| + if (lookup.IsConstantFunction()) {
|
| + AddInstruction(new(zone()) HCheckNonSmi(object));
|
| + AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone()));
|
| Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map));
|
| return new(zone()) HConstant(function, Representation::Tagged());
|
| - } else if (lookup.IsPropertyCallbacks()) {
|
| - Handle<Object> callback(lookup.GetValueFromMap(*map));
|
| - Handle<JSObject> holder;
|
| - return BuildCallGetter(obj, expr, map, callback, holder);
|
| - } else {
|
| - LookupInPrototypes(map, name, &lookup);
|
| - if (lookup.IsPropertyCallbacks()) {
|
| - Handle<Object> callback(lookup.GetValue());
|
| - Handle<JSObject> holder(lookup.holder());
|
| - return BuildCallGetter(obj, expr, map, callback, holder);
|
| - }
|
| - return BuildLoadNamedGeneric(obj, expr);
|
| }
|
| + return BuildLoadNamedGeneric(object, name, expr);
|
| }
|
|
|
|
|
| @@ -6311,26 +6347,34 @@ void HGraphBuilder::VisitProperty(Property* expr) {
|
| Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
|
| SmallMapList* types = expr->GetReceiverTypes();
|
|
|
| - HValue* obj = Pop();
|
| if (expr->IsMonomorphic()) {
|
| - instr = BuildLoadNamed(obj, expr, types->first(), name);
|
| + Handle<Map> map = types->first();
|
| + Handle<AccessorPair> accessors;
|
| + Handle<JSObject> holder;
|
| + if (LookupAccessorPair(map, name, &accessors, &holder)) {
|
| + AddCheckConstantFunction(holder, Top(), map, true);
|
| + Handle<JSFunction> getter(JSFunction::cast(accessors->getter()));
|
| + if (TryInlineGetter(getter, expr->id(), expr->ReturnId())) return;
|
| + AddInstruction(new(zone()) HPushArgument(Pop()));
|
| + instr = new(zone()) HCallConstantFunction(getter, 1);
|
| + } else {
|
| + instr = BuildLoadNamed(Pop(), name, expr, map);
|
| + }
|
| } else if (types != NULL && types->length() > 1) {
|
| - AddInstruction(new(zone()) HCheckNonSmi(obj));
|
| - HandlePolymorphicLoadNamedField(expr, obj, types, name);
|
| - return;
|
| + return HandlePolymorphicLoadNamedField(expr, Pop(), types, name);
|
| } else {
|
| - instr = BuildLoadNamedGeneric(obj, expr);
|
| + instr = BuildLoadNamedGeneric(Pop(), name, expr);
|
| }
|
|
|
| } else {
|
| CHECK_ALIVE(VisitForValue(expr->key()));
|
|
|
| HValue* key = Pop();
|
| - HValue* obj = Pop();
|
| + HValue* object = Pop();
|
|
|
| bool has_side_effects = false;
|
| HValue* load = HandleKeyedElementAccess(
|
| - obj, key, NULL, expr, expr->id(), expr->position(),
|
| + object, key, NULL, expr, expr->id(), expr->position(),
|
| false, // is_store
|
| &has_side_effects);
|
| if (has_side_effects) {
|
| @@ -6880,6 +6924,32 @@ bool HGraphBuilder::TryInlineConstruct(CallNew* expr, HValue* receiver) {
|
| }
|
|
|
|
|
| +bool HGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
|
| + int ast_id,
|
| + int return_id) {
|
| + return TryInline(CALL_AS_METHOD,
|
| + getter,
|
| + 0,
|
| + NULL,
|
| + ast_id,
|
| + return_id,
|
| + NORMAL_RETURN);
|
| +}
|
| +
|
| +
|
| +bool HGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
|
| + int ast_id,
|
| + int return_id) {
|
| + return TryInline(CALL_AS_METHOD,
|
| + setter,
|
| + 1,
|
| + NULL,
|
| + ast_id,
|
| + return_id,
|
| + NORMAL_RETURN);
|
| +}
|
| +
|
| +
|
| bool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) {
|
| if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
|
| BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
|
| @@ -7798,14 +7868,20 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
| CHECK_ALIVE(VisitForValue(prop->obj()));
|
| HValue* obj = Top();
|
|
|
| + Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
|
| Handle<Map> map;
|
| HInstruction* load;
|
| if (prop->IsMonomorphic()) {
|
| - Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
|
| map = prop->GetReceiverTypes()->first();
|
| - load = BuildLoadNamed(obj, prop, map, name);
|
| + Handle<AccessorPair> accessors;
|
| + Handle<JSObject> holder;
|
| + if (LookupAccessorPair(map, name, &accessors, &holder)) {
|
| + load = BuildCallGetter(obj, map, accessors, holder);
|
| + } else {
|
| + load = BuildLoadNamed(obj, name, prop, map);
|
| + }
|
| } else {
|
| - load = BuildLoadNamedGeneric(obj, prop);
|
| + load = BuildLoadNamedGeneric(obj, name, prop);
|
| }
|
| PushAndAdd(load);
|
| if (load->HasObservableSideEffects()) AddSimulate(expr->CountId());
|
| @@ -7814,7 +7890,22 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
| input = Pop();
|
|
|
| HInstruction* store;
|
| - CHECK_ALIVE(store = BuildStoreNamed(obj, after, map, prop->key()));
|
| + if (map.is_null()) {
|
| + // If we don't know the monomorphic type, do a generic store.
|
| + CHECK_ALIVE(store = BuildStoreNamedGeneric(obj, name, after));
|
| + } else {
|
| + Handle<AccessorPair> accessors;
|
| + Handle<JSObject> holder;
|
| + if (LookupAccessorPair(map, name, &accessors, &holder)) {
|
| + CHECK_ALIVE(store = BuildCallSetter(obj,
|
| + after,
|
| + map,
|
| + accessors,
|
| + holder));
|
| + } else {
|
| + CHECK_ALIVE(store = BuildStoreNamed(obj, name, after, map));
|
| + }
|
| + }
|
| AddInstruction(store);
|
|
|
| // Overwrite the receiver in the bailout environment with the result
|
| @@ -9199,7 +9290,6 @@ HEnvironment* HEnvironment::CopyForInlining(
|
|
|
| // Outer environment is a copy of this one without the arguments.
|
| int arity = function->scope()->num_parameters();
|
| -
|
| HEnvironment* outer = Copy();
|
| outer->Drop(arguments + 1); // Including receiver.
|
| outer->ClearHistory();
|
|
|