| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 4746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4757 switch (property->kind()) { | 4757 switch (property->kind()) { |
| 4758 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 4758 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 4759 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 4759 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
| 4760 // Fall through. | 4760 // Fall through. |
| 4761 case ObjectLiteral::Property::COMPUTED: | 4761 case ObjectLiteral::Property::COMPUTED: |
| 4762 if (key->handle()->IsSymbol()) { | 4762 if (key->handle()->IsSymbol()) { |
| 4763 if (property->emit_store()) { | 4763 if (property->emit_store()) { |
| 4764 property->RecordTypeFeedback(oracle()); | 4764 property->RecordTypeFeedback(oracle()); |
| 4765 CHECK_ALIVE(VisitForValue(value)); | 4765 CHECK_ALIVE(VisitForValue(value)); |
| 4766 HValue* value = Pop(); | 4766 HValue* value = Pop(); |
| 4767 Handle<Map> map = property->GetReceiverType(); |
| 4768 Handle<String> name = |
| 4769 Handle<String>::cast(property->key()->handle()); |
| 4767 HInstruction* store; | 4770 HInstruction* store; |
| 4768 CHECK_ALIVE(store = BuildStoreNamed(literal, | 4771 if (map.is_null()) { |
| 4769 value, | 4772 // If we don't know the monomorphic type, do a generic store. |
| 4770 property->GetReceiverType(), | 4773 CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value)); |
| 4771 property->key())); | 4774 } else { |
| 4775 #if DEBUG |
| 4776 Handle<AccessorPair> accessors; |
| 4777 Handle<JSObject> holder; |
| 4778 ASSERT(!LookupAccessorPair(map, name, &accessors, &holder)); |
| 4779 #endif |
| 4780 CHECK_ALIVE(store = BuildStoreNamed(literal, name, value, map)); |
| 4781 } |
| 4772 AddInstruction(store); | 4782 AddInstruction(store); |
| 4773 if (store->HasObservableSideEffects()) AddSimulate(key->id()); | 4783 if (store->HasObservableSideEffects()) AddSimulate(key->id()); |
| 4774 } else { | 4784 } else { |
| 4775 CHECK_ALIVE(VisitForEffect(value)); | 4785 CHECK_ALIVE(VisitForEffect(value)); |
| 4776 } | 4786 } |
| 4777 break; | 4787 break; |
| 4778 } | 4788 } |
| 4779 // Fall through. | 4789 // Fall through. |
| 4780 case ObjectLiteral::Property::PROTOTYPE: | 4790 case ObjectLiteral::Property::PROTOTYPE: |
| 4781 case ObjectLiteral::Property::SETTER: | 4791 case ObjectLiteral::Property::SETTER: |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4932 } else { | 4942 } else { |
| 4933 Map* transition = lookup->GetTransitionMapFromMap(*type); | 4943 Map* transition = lookup->GetTransitionMapFromMap(*type); |
| 4934 return transition->PropertyIndexFor(*name) - type->inobject_properties(); | 4944 return transition->PropertyIndexFor(*name) - type->inobject_properties(); |
| 4935 } | 4945 } |
| 4936 } | 4946 } |
| 4937 | 4947 |
| 4938 | 4948 |
| 4939 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, | 4949 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, |
| 4940 Handle<String> name, | 4950 Handle<String> name, |
| 4941 HValue* value, | 4951 HValue* value, |
| 4942 Handle<Map> type, | 4952 Handle<Map> map, |
| 4943 LookupResult* lookup, | 4953 LookupResult* lookup, |
| 4944 bool smi_and_map_check) { | 4954 bool smi_and_map_check) { |
| 4945 ASSERT(lookup->IsFound()); | 4955 ASSERT(lookup->IsFound()); |
| 4946 if (smi_and_map_check) { | 4956 if (smi_and_map_check) { |
| 4947 AddInstruction(new(zone()) HCheckNonSmi(object)); | 4957 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 4948 AddInstruction(HCheckMaps::NewWithTransitions(object, type, zone())); | 4958 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
| 4949 } | 4959 } |
| 4950 | 4960 |
| 4951 // If the property does not exist yet, we have to check that it wasn't made | 4961 // If the property does not exist yet, we have to check that it wasn't made |
| 4952 // readonly or turned into a setter by some meanwhile modifications on the | 4962 // readonly or turned into a setter by some meanwhile modifications on the |
| 4953 // prototype chain. | 4963 // prototype chain. |
| 4954 if (!lookup->IsProperty() && type->prototype()->IsJSReceiver()) { | 4964 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { |
| 4955 Object* proto = type->prototype(); | 4965 Object* proto = map->prototype(); |
| 4956 // First check that the prototype chain isn't affected already. | 4966 // First check that the prototype chain isn't affected already. |
| 4957 LookupResult proto_result(isolate()); | 4967 LookupResult proto_result(isolate()); |
| 4958 proto->Lookup(*name, &proto_result); | 4968 proto->Lookup(*name, &proto_result); |
| 4959 if (proto_result.IsProperty()) { | 4969 if (proto_result.IsProperty()) { |
| 4960 // If the inherited property could induce readonly-ness, bail out. | 4970 // If the inherited property could induce readonly-ness, bail out. |
| 4961 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) { | 4971 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) { |
| 4962 Bailout("improper object on prototype chain for store"); | 4972 Bailout("improper object on prototype chain for store"); |
| 4963 return NULL; | 4973 return NULL; |
| 4964 } | 4974 } |
| 4965 // We only need to check up to the preexisting property. | 4975 // We only need to check up to the preexisting property. |
| 4966 proto = proto_result.holder(); | 4976 proto = proto_result.holder(); |
| 4967 } else { | 4977 } else { |
| 4968 // Otherwise, find the top prototype. | 4978 // Otherwise, find the top prototype. |
| 4969 while (proto->GetPrototype()->IsJSObject()) proto = proto->GetPrototype(); | 4979 while (proto->GetPrototype()->IsJSObject()) proto = proto->GetPrototype(); |
| 4970 ASSERT(proto->GetPrototype()->IsNull()); | 4980 ASSERT(proto->GetPrototype()->IsNull()); |
| 4971 } | 4981 } |
| 4972 ASSERT(proto->IsJSObject()); | 4982 ASSERT(proto->IsJSObject()); |
| 4973 AddInstruction(new(zone()) HCheckPrototypeMaps( | 4983 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 4974 Handle<JSObject>(JSObject::cast(type->prototype())), | 4984 Handle<JSObject>(JSObject::cast(map->prototype())), |
| 4975 Handle<JSObject>(JSObject::cast(proto)))); | 4985 Handle<JSObject>(JSObject::cast(proto)))); |
| 4976 } | 4986 } |
| 4977 | 4987 |
| 4978 int index = ComputeLoadStoreFieldIndex(type, name, lookup); | 4988 int index = ComputeLoadStoreFieldIndex(map, name, lookup); |
| 4979 bool is_in_object = index < 0; | 4989 bool is_in_object = index < 0; |
| 4980 int offset = index * kPointerSize; | 4990 int offset = index * kPointerSize; |
| 4981 if (index < 0) { | 4991 if (index < 0) { |
| 4982 // Negative property indices are in-object properties, indexed | 4992 // Negative property indices are in-object properties, indexed |
| 4983 // from the end of the fixed part of the object. | 4993 // from the end of the fixed part of the object. |
| 4984 offset += type->instance_size(); | 4994 offset += map->instance_size(); |
| 4985 } else { | 4995 } else { |
| 4986 offset += FixedArray::kHeaderSize; | 4996 offset += FixedArray::kHeaderSize; |
| 4987 } | 4997 } |
| 4988 HStoreNamedField* instr = | 4998 HStoreNamedField* instr = |
| 4989 new(zone()) HStoreNamedField(object, name, value, is_in_object, offset); | 4999 new(zone()) HStoreNamedField(object, name, value, is_in_object, offset); |
| 4990 if (lookup->IsTransitionToField(*type)) { | 5000 if (lookup->IsTransitionToField(*map)) { |
| 4991 Handle<Map> transition(lookup->GetTransitionMapFromMap(*type)); | 5001 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
| 4992 instr->set_transition(transition); | 5002 instr->set_transition(transition); |
| 4993 // TODO(fschneider): Record the new map type of the object in the IR to | 5003 // TODO(fschneider): Record the new map type of the object in the IR to |
| 4994 // enable elimination of redundant checks after the transition store. | 5004 // enable elimination of redundant checks after the transition store. |
| 4995 instr->SetGVNFlag(kChangesMaps); | 5005 instr->SetGVNFlag(kChangesMaps); |
| 4996 } | 5006 } |
| 4997 return instr; | 5007 return instr; |
| 4998 } | 5008 } |
| 4999 | 5009 |
| 5000 | 5010 |
| 5001 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, | 5011 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 5018 Handle<JSObject> holder(JSObject::cast(map->prototype())); | 5028 Handle<JSObject> holder(JSObject::cast(map->prototype())); |
| 5019 if (!holder->HasFastProperties()) break; | 5029 if (!holder->HasFastProperties()) break; |
| 5020 map = Handle<Map>(holder->map()); | 5030 map = Handle<Map>(holder->map()); |
| 5021 map->LookupDescriptor(*holder, *name, lookup); | 5031 map->LookupDescriptor(*holder, *name, lookup); |
| 5022 if (lookup->IsFound()) return; | 5032 if (lookup->IsFound()) return; |
| 5023 } | 5033 } |
| 5024 lookup->NotFound(); | 5034 lookup->NotFound(); |
| 5025 } | 5035 } |
| 5026 | 5036 |
| 5027 | 5037 |
| 5028 HInstruction* HGraphBuilder::BuildCallSetter(HValue* obj, | 5038 HInstruction* HGraphBuilder::BuildCallSetter(HValue* object, |
| 5029 Handle<String> name, | |
| 5030 HValue* value, | 5039 HValue* value, |
| 5031 Handle<Map> map, | 5040 Handle<Map> map, |
| 5032 Handle<Object> callback, | 5041 Handle<AccessorPair> accessors, |
| 5033 Handle<JSObject> holder) { | 5042 Handle<JSObject> holder) { |
| 5034 if (!callback->IsAccessorPair()) { | 5043 Handle<JSFunction> function(JSFunction::cast(accessors->setter())); |
| 5035 return BuildStoreNamedGeneric(obj, name, value); | 5044 AddCheckConstantFunction(holder, object, map, true); |
| 5036 } | 5045 AddInstruction(new(zone()) HPushArgument(object)); |
| 5037 Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter()); | |
| 5038 Handle<JSFunction> function(Handle<JSFunction>::cast(setter)); | |
| 5039 AddCheckConstantFunction(holder, obj, map, true); | |
| 5040 AddInstruction(new(zone()) HPushArgument(obj)); | |
| 5041 AddInstruction(new(zone()) HPushArgument(value)); | 5046 AddInstruction(new(zone()) HPushArgument(value)); |
| 5042 return new(zone()) HCallConstantFunction(function, 2); | 5047 return new(zone()) HCallConstantFunction(function, 2); |
| 5043 } | 5048 } |
| 5044 | 5049 |
| 5045 | 5050 |
| 5046 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, | 5051 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, |
| 5052 Handle<String> name, |
| 5047 HValue* value, | 5053 HValue* value, |
| 5048 Handle<Map> type, | 5054 Handle<Map> map) { |
| 5049 Expression* key) { | |
| 5050 // If we don't know the monomorphic type, do a generic store. | |
| 5051 Handle<String> name = Handle<String>::cast(key->AsLiteral()->handle()); | |
| 5052 if (type.is_null()) return BuildStoreNamedGeneric(object, name, value); | |
| 5053 | |
| 5054 // Handle a store to a known field. | 5055 // Handle a store to a known field. |
| 5055 LookupResult lookup(isolate()); | 5056 LookupResult lookup(isolate()); |
| 5056 if (ComputeLoadStoreField(type, name, &lookup, true)) { | 5057 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
| 5057 // true = needs smi and map check. | 5058 // true = needs smi and map check. |
| 5058 return BuildStoreNamedField(object, name, value, type, &lookup, true); | 5059 return BuildStoreNamedField(object, name, value, map, &lookup, true); |
| 5059 } | |
| 5060 | |
| 5061 // Handle a known setter directly in the receiver. | |
| 5062 type->LookupDescriptor(NULL, *name, &lookup); | |
| 5063 if (lookup.IsPropertyCallbacks()) { | |
| 5064 Handle<Object> callback(lookup.GetValueFromMap(*type)); | |
| 5065 Handle<JSObject> holder; | |
| 5066 return BuildCallSetter(object, name, value, type, callback, holder); | |
| 5067 } | |
| 5068 | |
| 5069 // Handle a known setter somewhere in the prototype chain. | |
| 5070 LookupInPrototypes(type, name, &lookup); | |
| 5071 if (lookup.IsPropertyCallbacks()) { | |
| 5072 Handle<Object> callback(lookup.GetValue()); | |
| 5073 Handle<JSObject> holder(lookup.holder()); | |
| 5074 return BuildCallSetter(object, name, value, type, callback, holder); | |
| 5075 } | 5060 } |
| 5076 | 5061 |
| 5077 // No luck, do a generic store. | 5062 // No luck, do a generic store. |
| 5078 return BuildStoreNamedGeneric(object, name, value); | 5063 return BuildStoreNamedGeneric(object, name, value); |
| 5079 } | 5064 } |
| 5080 | 5065 |
| 5081 | 5066 |
| 5082 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, | 5067 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
| 5083 HValue* object, | 5068 HValue* object, |
| 5084 SmallMapList* types, | 5069 SmallMapList* types, |
| 5085 Handle<String> name) { | 5070 Handle<String> name) { |
| 5071 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 5086 int count = 0; | 5072 int count = 0; |
| 5087 int previous_field_offset = 0; | 5073 int previous_field_offset = 0; |
| 5088 bool previous_field_is_in_object = false; | 5074 bool previous_field_is_in_object = false; |
| 5089 bool is_monomorphic_field = true; | 5075 bool is_monomorphic_field = true; |
| 5090 Handle<Map> map; | 5076 Handle<Map> map; |
| 5091 LookupResult lookup(isolate()); | 5077 LookupResult lookup(isolate()); |
| 5092 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 5078 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
| 5093 map = types->at(i); | 5079 map = types->at(i); |
| 5094 if (ComputeLoadStoreField(map, name, &lookup, false)) { | 5080 if (ComputeLoadStoreField(map, name, &lookup, false)) { |
| 5095 int index = ComputeLoadStoreFieldIndex(map, name, &lookup); | 5081 int index = ComputeLoadStoreFieldIndex(map, name, &lookup); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 5111 } | 5097 } |
| 5112 ++count; | 5098 ++count; |
| 5113 } | 5099 } |
| 5114 } | 5100 } |
| 5115 | 5101 |
| 5116 // Use monomorphic load if property lookup results in the same field index | 5102 // Use monomorphic load if property lookup results in the same field index |
| 5117 // for all maps. Requires special map check on the set of all handled maps. | 5103 // for all maps. Requires special map check on the set of all handled maps. |
| 5118 HInstruction* instr; | 5104 HInstruction* instr; |
| 5119 if (count == types->length() && is_monomorphic_field) { | 5105 if (count == types->length() && is_monomorphic_field) { |
| 5120 AddInstruction(new(zone()) HCheckMaps(object, types, zone())); | 5106 AddInstruction(new(zone()) HCheckMaps(object, types, zone())); |
| 5121 instr = BuildLoadNamedField(object, expr, map, &lookup, false); | 5107 instr = BuildLoadNamedField(object, map, &lookup, false); |
| 5122 } else { | 5108 } else { |
| 5123 HValue* context = environment()->LookupContext(); | 5109 HValue* context = environment()->LookupContext(); |
| 5124 instr = new(zone()) HLoadNamedFieldPolymorphic(context, | 5110 instr = new(zone()) HLoadNamedFieldPolymorphic(context, |
| 5125 object, | 5111 object, |
| 5126 types, | 5112 types, |
| 5127 name, | 5113 name, |
| 5128 zone()); | 5114 zone()); |
| 5129 } | 5115 } |
| 5130 | 5116 |
| 5131 instr->set_position(expr->position()); | 5117 instr->set_position(expr->position()); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5208 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); | 5194 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
| 5209 } | 5195 } |
| 5210 | 5196 |
| 5211 | 5197 |
| 5212 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 5198 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| 5213 Property* prop = expr->target()->AsProperty(); | 5199 Property* prop = expr->target()->AsProperty(); |
| 5214 ASSERT(prop != NULL); | 5200 ASSERT(prop != NULL); |
| 5215 expr->RecordTypeFeedback(oracle(), zone()); | 5201 expr->RecordTypeFeedback(oracle(), zone()); |
| 5216 CHECK_ALIVE(VisitForValue(prop->obj())); | 5202 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 5217 | 5203 |
| 5218 HValue* value = NULL; | |
| 5219 HInstruction* instr = NULL; | |
| 5220 | |
| 5221 if (prop->key()->IsPropertyName()) { | 5204 if (prop->key()->IsPropertyName()) { |
| 5222 // Named store. | 5205 // Named store. |
| 5223 CHECK_ALIVE(VisitForValue(expr->value())); | 5206 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5224 value = Pop(); | 5207 HValue* value = Pop(); |
| 5225 HValue* object = Pop(); | 5208 HValue* object = Pop(); |
| 5226 | 5209 |
| 5227 Literal* key = prop->key()->AsLiteral(); | 5210 Literal* key = prop->key()->AsLiteral(); |
| 5228 Handle<String> name = Handle<String>::cast(key->handle()); | 5211 Handle<String> name = Handle<String>::cast(key->handle()); |
| 5229 ASSERT(!name.is_null()); | 5212 ASSERT(!name.is_null()); |
| 5230 | 5213 |
| 5214 HInstruction* instr = NULL; |
| 5231 SmallMapList* types = expr->GetReceiverTypes(); | 5215 SmallMapList* types = expr->GetReceiverTypes(); |
| 5232 if (expr->IsMonomorphic()) { | 5216 if (expr->IsMonomorphic()) { |
| 5233 CHECK_ALIVE(instr = BuildStoreNamed(object, | 5217 Handle<Map> type = types->first(); |
| 5234 value, | 5218 Handle<AccessorPair> accessors; |
| 5235 types->first(), | 5219 Handle<JSObject> holder; |
| 5236 prop->key())); | 5220 if (LookupAccessorPair(type, name, &accessors, &holder)) { |
| 5221 Push(object); |
| 5222 Push(value); |
| 5223 Handle<JSFunction> setter(JSFunction::cast(accessors->setter())); |
| 5224 AddCheckConstantFunction(holder, object, type, true); |
| 5225 if (TryInlineSetter(setter, expr->AssignmentId(), prop->ReturnId())) { |
| 5226 return; |
| 5227 } |
| 5228 Drop(2); |
| 5229 AddInstruction(new(zone()) HPushArgument(object)); |
| 5230 AddInstruction(new(zone()) HPushArgument(value)); |
| 5231 instr = new(zone()) HCallConstantFunction(setter, 2); |
| 5232 } else { |
| 5233 CHECK_ALIVE(instr = BuildStoreNamed(object, |
| 5234 name, |
| 5235 value, |
| 5236 type)); |
| 5237 } |
| 5237 | 5238 |
| 5238 } else if (types != NULL && types->length() > 1) { | 5239 } else if (types != NULL && types->length() > 1) { |
| 5239 HandlePolymorphicStoreNamedField(expr, object, value, types, name); | 5240 return HandlePolymorphicStoreNamedField(expr, object, value, types, name); |
| 5240 return; | |
| 5241 | |
| 5242 } else { | 5241 } else { |
| 5243 instr = BuildStoreNamedGeneric(object, name, value); | 5242 instr = BuildStoreNamedGeneric(object, name, value); |
| 5244 } | 5243 } |
| 5245 | 5244 |
| 5245 Push(value); |
| 5246 instr->set_position(expr->position()); |
| 5247 AddInstruction(instr); |
| 5248 if (instr->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); |
| 5249 return ast_context()->ReturnValue(Pop()); |
| 5250 |
| 5246 } else { | 5251 } else { |
| 5247 // Keyed store. | 5252 // Keyed store. |
| 5248 CHECK_ALIVE(VisitForValue(prop->key())); | 5253 CHECK_ALIVE(VisitForValue(prop->key())); |
| 5249 CHECK_ALIVE(VisitForValue(expr->value())); | 5254 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5250 value = Pop(); | 5255 HValue* value = Pop(); |
| 5251 HValue* key = Pop(); | 5256 HValue* key = Pop(); |
| 5252 HValue* object = Pop(); | 5257 HValue* object = Pop(); |
| 5253 bool has_side_effects = false; | 5258 bool has_side_effects = false; |
| 5254 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), | 5259 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), |
| 5255 expr->position(), | 5260 expr->position(), |
| 5256 true, // is_store | 5261 true, // is_store |
| 5257 &has_side_effects); | 5262 &has_side_effects); |
| 5258 Push(value); | 5263 Push(value); |
| 5259 ASSERT(has_side_effects); // Stores always have side effects. | 5264 ASSERT(has_side_effects); // Stores always have side effects. |
| 5260 AddSimulate(expr->AssignmentId()); | 5265 AddSimulate(expr->AssignmentId()); |
| 5261 return ast_context()->ReturnValue(Pop()); | 5266 return ast_context()->ReturnValue(Pop()); |
| 5262 } | 5267 } |
| 5263 Push(value); | |
| 5264 instr->set_position(expr->position()); | |
| 5265 AddInstruction(instr); | |
| 5266 if (instr->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); | |
| 5267 return ast_context()->ReturnValue(Pop()); | |
| 5268 } | 5268 } |
| 5269 | 5269 |
| 5270 | 5270 |
| 5271 // Because not every expression has a position and there is not common | 5271 // Because not every expression has a position and there is not common |
| 5272 // superclass of Assignment and CountOperation, we cannot just pass the | 5272 // superclass of Assignment and CountOperation, we cannot just pass the |
| 5273 // owning expression instead of position and ast_id separately. | 5273 // owning expression instead of position and ast_id separately. |
| 5274 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, | 5274 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, |
| 5275 HValue* value, | 5275 HValue* value, |
| 5276 int position, | 5276 int position, |
| 5277 int ast_id) { | 5277 int ast_id) { |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5384 return Bailout("compound assignment to lookup slot"); | 5384 return Bailout("compound assignment to lookup slot"); |
| 5385 } | 5385 } |
| 5386 return ast_context()->ReturnValue(Pop()); | 5386 return ast_context()->ReturnValue(Pop()); |
| 5387 | 5387 |
| 5388 } else if (prop != NULL) { | 5388 } else if (prop != NULL) { |
| 5389 prop->RecordTypeFeedback(oracle(), zone()); | 5389 prop->RecordTypeFeedback(oracle(), zone()); |
| 5390 | 5390 |
| 5391 if (prop->key()->IsPropertyName()) { | 5391 if (prop->key()->IsPropertyName()) { |
| 5392 // Named property. | 5392 // Named property. |
| 5393 CHECK_ALIVE(VisitForValue(prop->obj())); | 5393 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 5394 HValue* obj = Top(); | 5394 HValue* object = Top(); |
| 5395 | 5395 |
| 5396 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| 5396 Handle<Map> map; | 5397 Handle<Map> map; |
| 5397 HInstruction* load; | 5398 HInstruction* load; |
| 5398 if (prop->IsMonomorphic()) { | 5399 if (prop->IsMonomorphic()) { |
| 5399 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | |
| 5400 map = prop->GetReceiverTypes()->first(); | 5400 map = prop->GetReceiverTypes()->first(); |
| 5401 load = BuildLoadNamed(obj, prop, map, name); | 5401 Handle<AccessorPair> accessors; |
| 5402 Handle<JSObject> holder; |
| 5403 if (LookupAccessorPair(map, name, &accessors, &holder)) { |
| 5404 load = BuildCallGetter(object, map, accessors, holder); |
| 5405 } else { |
| 5406 load = BuildLoadNamed(object, name, prop, map); |
| 5407 } |
| 5402 } else { | 5408 } else { |
| 5403 load = BuildLoadNamedGeneric(obj, prop); | 5409 load = BuildLoadNamedGeneric(object, name, prop); |
| 5404 } | 5410 } |
| 5405 PushAndAdd(load); | 5411 PushAndAdd(load); |
| 5406 if (load->HasObservableSideEffects()) AddSimulate(expr->CompoundLoadId()); | 5412 if (load->HasObservableSideEffects()) AddSimulate(expr->CompoundLoadId()); |
| 5407 | 5413 |
| 5408 CHECK_ALIVE(VisitForValue(expr->value())); | 5414 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5409 HValue* right = Pop(); | 5415 HValue* right = Pop(); |
| 5410 HValue* left = Pop(); | 5416 HValue* left = Pop(); |
| 5411 | 5417 |
| 5412 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5418 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
| 5413 PushAndAdd(instr); | 5419 PushAndAdd(instr); |
| 5414 if (instr->HasObservableSideEffects()) AddSimulate(operation->id()); | 5420 if (instr->HasObservableSideEffects()) AddSimulate(operation->id()); |
| 5415 | 5421 |
| 5416 HInstruction* store; | 5422 HInstruction* store; |
| 5417 CHECK_ALIVE(store = BuildStoreNamed(obj, instr, map, prop->key())); | 5423 if (map.is_null()) { |
| 5424 // If we don't know the monomorphic type, do a generic store. |
| 5425 CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, instr)); |
| 5426 } else { |
| 5427 Handle<AccessorPair> accessors; |
| 5428 Handle<JSObject> holder; |
| 5429 if (LookupAccessorPair(map, name, &accessors, &holder)) { |
| 5430 CHECK_ALIVE(store = BuildCallSetter(object, |
| 5431 instr, |
| 5432 map, |
| 5433 accessors, |
| 5434 holder)); |
| 5435 } else { |
| 5436 CHECK_ALIVE(store = BuildStoreNamed(object, name, instr, map)); |
| 5437 } |
| 5438 } |
| 5418 AddInstruction(store); | 5439 AddInstruction(store); |
| 5419 // Drop the simulated receiver and value. Return the value. | 5440 // Drop the simulated receiver and value. Return the value. |
| 5420 Drop(2); | 5441 Drop(2); |
| 5421 Push(instr); | 5442 Push(instr); |
| 5422 if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); | 5443 if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); |
| 5423 return ast_context()->ReturnValue(Pop()); | 5444 return ast_context()->ReturnValue(Pop()); |
| 5424 | 5445 |
| 5425 } else { | 5446 } else { |
| 5426 // Keyed property. | 5447 // Keyed property. |
| 5427 CHECK_ALIVE(VisitForValue(prop->obj())); | 5448 CHECK_ALIVE(VisitForValue(prop->obj())); |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5608 HThrow* instr = new(zone()) HThrow(context, value); | 5629 HThrow* instr = new(zone()) HThrow(context, value); |
| 5609 instr->set_position(expr->position()); | 5630 instr->set_position(expr->position()); |
| 5610 AddInstruction(instr); | 5631 AddInstruction(instr); |
| 5611 AddSimulate(expr->id()); | 5632 AddSimulate(expr->id()); |
| 5612 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5633 current_block()->FinishExit(new(zone()) HAbnormalExit); |
| 5613 set_current_block(NULL); | 5634 set_current_block(NULL); |
| 5614 } | 5635 } |
| 5615 | 5636 |
| 5616 | 5637 |
| 5617 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, | 5638 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
| 5618 Property* expr, | 5639 Handle<Map> map, |
| 5619 Handle<Map> type, | |
| 5620 LookupResult* lookup, | 5640 LookupResult* lookup, |
| 5621 bool smi_and_map_check) { | 5641 bool smi_and_map_check) { |
| 5622 if (smi_and_map_check) { | 5642 if (smi_and_map_check) { |
| 5623 AddInstruction(new(zone()) HCheckNonSmi(object)); | 5643 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 5624 AddInstruction(HCheckMaps::NewWithTransitions(object, type, zone())); | 5644 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
| 5625 } | 5645 } |
| 5626 | 5646 |
| 5627 int index = lookup->GetLocalFieldIndexFromMap(*type); | 5647 int index = lookup->GetLocalFieldIndexFromMap(*map); |
| 5628 if (index < 0) { | 5648 if (index < 0) { |
| 5629 // Negative property indices are in-object properties, indexed | 5649 // Negative property indices are in-object properties, indexed |
| 5630 // from the end of the fixed part of the object. | 5650 // from the end of the fixed part of the object. |
| 5631 int offset = (index * kPointerSize) + type->instance_size(); | 5651 int offset = (index * kPointerSize) + map->instance_size(); |
| 5632 return new(zone()) HLoadNamedField(object, true, offset); | 5652 return new(zone()) HLoadNamedField(object, true, offset); |
| 5633 } else { | 5653 } else { |
| 5634 // Non-negative property indices are in the properties array. | 5654 // Non-negative property indices are in the properties array. |
| 5635 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; | 5655 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; |
| 5636 return new(zone()) HLoadNamedField(object, false, offset); | 5656 return new(zone()) HLoadNamedField(object, false, offset); |
| 5637 } | 5657 } |
| 5638 } | 5658 } |
| 5639 | 5659 |
| 5640 | 5660 |
| 5641 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj, | 5661 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* object, |
| 5662 Handle<String> name, |
| 5642 Property* expr) { | 5663 Property* expr) { |
| 5643 if (expr->IsUninitialized() && !FLAG_always_opt) { | 5664 if (expr->IsUninitialized() && !FLAG_always_opt) { |
| 5644 AddInstruction(new(zone()) HSoftDeoptimize); | 5665 AddInstruction(new(zone()) HSoftDeoptimize); |
| 5645 current_block()->MarkAsDeoptimizing(); | 5666 current_block()->MarkAsDeoptimizing(); |
| 5646 } | 5667 } |
| 5647 ASSERT(expr->key()->IsPropertyName()); | |
| 5648 Handle<Object> name = expr->key()->AsLiteral()->handle(); | |
| 5649 HValue* context = environment()->LookupContext(); | 5668 HValue* context = environment()->LookupContext(); |
| 5650 return new(zone()) HLoadNamedGeneric(context, obj, name); | 5669 return new(zone()) HLoadNamedGeneric(context, object, name); |
| 5651 } | 5670 } |
| 5652 | 5671 |
| 5653 | 5672 |
| 5654 HInstruction* HGraphBuilder::BuildCallGetter(HValue* obj, | 5673 HInstruction* HGraphBuilder::BuildCallGetter(HValue* object, |
| 5655 Property* expr, | |
| 5656 Handle<Map> map, | 5674 Handle<Map> map, |
| 5657 Handle<Object> callback, | 5675 Handle<AccessorPair> accessors, |
| 5658 Handle<JSObject> holder) { | 5676 Handle<JSObject> holder) { |
| 5659 if (!callback->IsAccessorPair()) return BuildLoadNamedGeneric(obj, expr); | 5677 Handle<JSFunction> function(JSFunction::cast(accessors->getter())); |
| 5660 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter()); | 5678 AddCheckConstantFunction(holder, object, map, true); |
| 5661 Handle<JSFunction> function(Handle<JSFunction>::cast(getter)); | 5679 AddInstruction(new(zone()) HPushArgument(object)); |
| 5662 AddCheckConstantFunction(holder, obj, map, true); | |
| 5663 AddInstruction(new(zone()) HPushArgument(obj)); | |
| 5664 return new(zone()) HCallConstantFunction(function, 1); | 5680 return new(zone()) HCallConstantFunction(function, 1); |
| 5665 } | 5681 } |
| 5666 | 5682 |
| 5667 | 5683 |
| 5668 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj, | 5684 bool HGraphBuilder::LookupAccessorPair(Handle<Map> map, |
| 5685 Handle<String> name, |
| 5686 Handle<AccessorPair>* accessors, |
| 5687 Handle<JSObject>* holder) { |
| 5688 LookupResult lookup(isolate()); |
| 5689 |
| 5690 // Check for a JavaScript accessor directly in the map. |
| 5691 map->LookupDescriptor(NULL, *name, &lookup); |
| 5692 if (lookup.IsPropertyCallbacks()) { |
| 5693 Handle<Object> callback(lookup.GetValueFromMap(*map)); |
| 5694 if (!callback->IsAccessorPair()) return false; |
| 5695 *accessors = Handle<AccessorPair>::cast(callback); |
| 5696 *holder = Handle<JSObject>(); |
| 5697 return true; |
| 5698 } |
| 5699 |
| 5700 // Everything else, e.g. a field, can't be an accessor call. |
| 5701 if (lookup.IsFound()) return false; |
| 5702 |
| 5703 // Check for a JavaScript accessor somewhere in the proto chain. |
| 5704 LookupInPrototypes(map, name, &lookup); |
| 5705 if (lookup.IsPropertyCallbacks()) { |
| 5706 Handle<Object> callback(lookup.GetValue()); |
| 5707 if (!callback->IsAccessorPair()) return false; |
| 5708 *accessors = Handle<AccessorPair>::cast(callback); |
| 5709 *holder = Handle<JSObject>(lookup.holder()); |
| 5710 return true; |
| 5711 } |
| 5712 |
| 5713 // We haven't found a JavaScript accessor anywhere. |
| 5714 return false; |
| 5715 } |
| 5716 |
| 5717 |
| 5718 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* object, |
| 5719 Handle<String> name, |
| 5669 Property* expr, | 5720 Property* expr, |
| 5670 Handle<Map> map, | 5721 Handle<Map> map) { |
| 5671 Handle<String> name) { | |
| 5672 LookupResult lookup(isolate()); | 5722 LookupResult lookup(isolate()); |
| 5673 map->LookupDescriptor(NULL, *name, &lookup); | 5723 map->LookupDescriptor(NULL, *name, &lookup); |
| 5674 if (lookup.IsField()) { | 5724 if (lookup.IsField()) { |
| 5675 return BuildLoadNamedField(obj, | 5725 return BuildLoadNamedField(object, map, &lookup, true); |
| 5676 expr, | 5726 } |
| 5677 map, | 5727 if (lookup.IsConstantFunction()) { |
| 5678 &lookup, | 5728 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 5679 true); | 5729 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
| 5680 } else if (lookup.IsConstantFunction()) { | |
| 5681 AddInstruction(new(zone()) HCheckNonSmi(obj)); | |
| 5682 AddInstruction(HCheckMaps::NewWithTransitions(obj, map, zone())); | |
| 5683 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); | 5730 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); |
| 5684 return new(zone()) HConstant(function, Representation::Tagged()); | 5731 return new(zone()) HConstant(function, Representation::Tagged()); |
| 5685 } else if (lookup.IsPropertyCallbacks()) { | |
| 5686 Handle<Object> callback(lookup.GetValueFromMap(*map)); | |
| 5687 Handle<JSObject> holder; | |
| 5688 return BuildCallGetter(obj, expr, map, callback, holder); | |
| 5689 } else { | |
| 5690 LookupInPrototypes(map, name, &lookup); | |
| 5691 if (lookup.IsPropertyCallbacks()) { | |
| 5692 Handle<Object> callback(lookup.GetValue()); | |
| 5693 Handle<JSObject> holder(lookup.holder()); | |
| 5694 return BuildCallGetter(obj, expr, map, callback, holder); | |
| 5695 } | |
| 5696 return BuildLoadNamedGeneric(obj, expr); | |
| 5697 } | 5732 } |
| 5733 return BuildLoadNamedGeneric(object, name, expr); |
| 5698 } | 5734 } |
| 5699 | 5735 |
| 5700 | 5736 |
| 5701 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 5737 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
| 5702 HValue* key) { | 5738 HValue* key) { |
| 5703 HValue* context = environment()->LookupContext(); | 5739 HValue* context = environment()->LookupContext(); |
| 5704 return new(zone()) HLoadKeyedGeneric(context, object, key); | 5740 return new(zone()) HLoadKeyedGeneric(context, object, key); |
| 5705 } | 5741 } |
| 5706 | 5742 |
| 5707 | 5743 |
| (...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6304 | 6340 |
| 6305 } else if (expr->IsFunctionPrototype()) { | 6341 } else if (expr->IsFunctionPrototype()) { |
| 6306 HValue* function = Pop(); | 6342 HValue* function = Pop(); |
| 6307 AddInstruction(new(zone()) HCheckNonSmi(function)); | 6343 AddInstruction(new(zone()) HCheckNonSmi(function)); |
| 6308 instr = new(zone()) HLoadFunctionPrototype(function); | 6344 instr = new(zone()) HLoadFunctionPrototype(function); |
| 6309 | 6345 |
| 6310 } else if (expr->key()->IsPropertyName()) { | 6346 } else if (expr->key()->IsPropertyName()) { |
| 6311 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 6347 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| 6312 SmallMapList* types = expr->GetReceiverTypes(); | 6348 SmallMapList* types = expr->GetReceiverTypes(); |
| 6313 | 6349 |
| 6314 HValue* obj = Pop(); | |
| 6315 if (expr->IsMonomorphic()) { | 6350 if (expr->IsMonomorphic()) { |
| 6316 instr = BuildLoadNamed(obj, expr, types->first(), name); | 6351 Handle<Map> map = types->first(); |
| 6352 Handle<AccessorPair> accessors; |
| 6353 Handle<JSObject> holder; |
| 6354 if (LookupAccessorPair(map, name, &accessors, &holder)) { |
| 6355 AddCheckConstantFunction(holder, Top(), map, true); |
| 6356 Handle<JSFunction> getter(JSFunction::cast(accessors->getter())); |
| 6357 if (TryInlineGetter(getter, expr->id(), expr->ReturnId())) return; |
| 6358 AddInstruction(new(zone()) HPushArgument(Pop())); |
| 6359 instr = new(zone()) HCallConstantFunction(getter, 1); |
| 6360 } else { |
| 6361 instr = BuildLoadNamed(Pop(), name, expr, map); |
| 6362 } |
| 6317 } else if (types != NULL && types->length() > 1) { | 6363 } else if (types != NULL && types->length() > 1) { |
| 6318 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 6364 return HandlePolymorphicLoadNamedField(expr, Pop(), types, name); |
| 6319 HandlePolymorphicLoadNamedField(expr, obj, types, name); | |
| 6320 return; | |
| 6321 } else { | 6365 } else { |
| 6322 instr = BuildLoadNamedGeneric(obj, expr); | 6366 instr = BuildLoadNamedGeneric(Pop(), name, expr); |
| 6323 } | 6367 } |
| 6324 | 6368 |
| 6325 } else { | 6369 } else { |
| 6326 CHECK_ALIVE(VisitForValue(expr->key())); | 6370 CHECK_ALIVE(VisitForValue(expr->key())); |
| 6327 | 6371 |
| 6328 HValue* key = Pop(); | 6372 HValue* key = Pop(); |
| 6329 HValue* obj = Pop(); | 6373 HValue* object = Pop(); |
| 6330 | 6374 |
| 6331 bool has_side_effects = false; | 6375 bool has_side_effects = false; |
| 6332 HValue* load = HandleKeyedElementAccess( | 6376 HValue* load = HandleKeyedElementAccess( |
| 6333 obj, key, NULL, expr, expr->id(), expr->position(), | 6377 object, key, NULL, expr, expr->id(), expr->position(), |
| 6334 false, // is_store | 6378 false, // is_store |
| 6335 &has_side_effects); | 6379 &has_side_effects); |
| 6336 if (has_side_effects) { | 6380 if (has_side_effects) { |
| 6337 if (ast_context()->IsEffect()) { | 6381 if (ast_context()->IsEffect()) { |
| 6338 AddSimulate(expr->id()); | 6382 AddSimulate(expr->id()); |
| 6339 } else { | 6383 } else { |
| 6340 Push(load); | 6384 Push(load); |
| 6341 AddSimulate(expr->id()); | 6385 AddSimulate(expr->id()); |
| 6342 Drop(1); | 6386 Drop(1); |
| 6343 } | 6387 } |
| (...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6873 return TryInline(CALL_AS_FUNCTION, | 6917 return TryInline(CALL_AS_FUNCTION, |
| 6874 expr->target(), | 6918 expr->target(), |
| 6875 expr->arguments()->length(), | 6919 expr->arguments()->length(), |
| 6876 receiver, | 6920 receiver, |
| 6877 expr->id(), | 6921 expr->id(), |
| 6878 expr->ReturnId(), | 6922 expr->ReturnId(), |
| 6879 CONSTRUCT_CALL_RETURN); | 6923 CONSTRUCT_CALL_RETURN); |
| 6880 } | 6924 } |
| 6881 | 6925 |
| 6882 | 6926 |
| 6927 bool HGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, |
| 6928 int ast_id, |
| 6929 int return_id) { |
| 6930 return TryInline(CALL_AS_METHOD, |
| 6931 getter, |
| 6932 0, |
| 6933 NULL, |
| 6934 ast_id, |
| 6935 return_id, |
| 6936 NORMAL_RETURN); |
| 6937 } |
| 6938 |
| 6939 |
| 6940 bool HGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, |
| 6941 int ast_id, |
| 6942 int return_id) { |
| 6943 return TryInline(CALL_AS_METHOD, |
| 6944 setter, |
| 6945 1, |
| 6946 NULL, |
| 6947 ast_id, |
| 6948 return_id, |
| 6949 NORMAL_RETURN); |
| 6950 } |
| 6951 |
| 6952 |
| 6883 bool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) { | 6953 bool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) { |
| 6884 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 6954 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
| 6885 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 6955 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
| 6886 switch (id) { | 6956 switch (id) { |
| 6887 case kMathRound: | 6957 case kMathRound: |
| 6888 case kMathAbs: | 6958 case kMathAbs: |
| 6889 case kMathSqrt: | 6959 case kMathSqrt: |
| 6890 case kMathLog: | 6960 case kMathLog: |
| 6891 case kMathSin: | 6961 case kMathSin: |
| 6892 case kMathCos: | 6962 case kMathCos: |
| (...skipping 898 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7791 ASSERT(prop != NULL); | 7861 ASSERT(prop != NULL); |
| 7792 prop->RecordTypeFeedback(oracle(), zone()); | 7862 prop->RecordTypeFeedback(oracle(), zone()); |
| 7793 | 7863 |
| 7794 if (prop->key()->IsPropertyName()) { | 7864 if (prop->key()->IsPropertyName()) { |
| 7795 // Named property. | 7865 // Named property. |
| 7796 if (returns_original_input) Push(graph_->GetConstantUndefined()); | 7866 if (returns_original_input) Push(graph_->GetConstantUndefined()); |
| 7797 | 7867 |
| 7798 CHECK_ALIVE(VisitForValue(prop->obj())); | 7868 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 7799 HValue* obj = Top(); | 7869 HValue* obj = Top(); |
| 7800 | 7870 |
| 7871 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| 7801 Handle<Map> map; | 7872 Handle<Map> map; |
| 7802 HInstruction* load; | 7873 HInstruction* load; |
| 7803 if (prop->IsMonomorphic()) { | 7874 if (prop->IsMonomorphic()) { |
| 7804 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | |
| 7805 map = prop->GetReceiverTypes()->first(); | 7875 map = prop->GetReceiverTypes()->first(); |
| 7806 load = BuildLoadNamed(obj, prop, map, name); | 7876 Handle<AccessorPair> accessors; |
| 7877 Handle<JSObject> holder; |
| 7878 if (LookupAccessorPair(map, name, &accessors, &holder)) { |
| 7879 load = BuildCallGetter(obj, map, accessors, holder); |
| 7880 } else { |
| 7881 load = BuildLoadNamed(obj, name, prop, map); |
| 7882 } |
| 7807 } else { | 7883 } else { |
| 7808 load = BuildLoadNamedGeneric(obj, prop); | 7884 load = BuildLoadNamedGeneric(obj, name, prop); |
| 7809 } | 7885 } |
| 7810 PushAndAdd(load); | 7886 PushAndAdd(load); |
| 7811 if (load->HasObservableSideEffects()) AddSimulate(expr->CountId()); | 7887 if (load->HasObservableSideEffects()) AddSimulate(expr->CountId()); |
| 7812 | 7888 |
| 7813 after = BuildIncrement(returns_original_input, expr); | 7889 after = BuildIncrement(returns_original_input, expr); |
| 7814 input = Pop(); | 7890 input = Pop(); |
| 7815 | 7891 |
| 7816 HInstruction* store; | 7892 HInstruction* store; |
| 7817 CHECK_ALIVE(store = BuildStoreNamed(obj, after, map, prop->key())); | 7893 if (map.is_null()) { |
| 7894 // If we don't know the monomorphic type, do a generic store. |
| 7895 CHECK_ALIVE(store = BuildStoreNamedGeneric(obj, name, after)); |
| 7896 } else { |
| 7897 Handle<AccessorPair> accessors; |
| 7898 Handle<JSObject> holder; |
| 7899 if (LookupAccessorPair(map, name, &accessors, &holder)) { |
| 7900 CHECK_ALIVE(store = BuildCallSetter(obj, |
| 7901 after, |
| 7902 map, |
| 7903 accessors, |
| 7904 holder)); |
| 7905 } else { |
| 7906 CHECK_ALIVE(store = BuildStoreNamed(obj, name, after, map)); |
| 7907 } |
| 7908 } |
| 7818 AddInstruction(store); | 7909 AddInstruction(store); |
| 7819 | 7910 |
| 7820 // Overwrite the receiver in the bailout environment with the result | 7911 // Overwrite the receiver in the bailout environment with the result |
| 7821 // of the operation, and the placeholder with the original value if | 7912 // of the operation, and the placeholder with the original value if |
| 7822 // necessary. | 7913 // necessary. |
| 7823 environment()->SetExpressionStackAt(0, after); | 7914 environment()->SetExpressionStackAt(0, after); |
| 7824 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | 7915 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
| 7825 if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); | 7916 if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); |
| 7826 | 7917 |
| 7827 } else { | 7918 } else { |
| (...skipping 1364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9192 Handle<JSFunction> target, | 9283 Handle<JSFunction> target, |
| 9193 int arguments, | 9284 int arguments, |
| 9194 FunctionLiteral* function, | 9285 FunctionLiteral* function, |
| 9195 HConstant* undefined, | 9286 HConstant* undefined, |
| 9196 CallKind call_kind, | 9287 CallKind call_kind, |
| 9197 bool is_construct) const { | 9288 bool is_construct) const { |
| 9198 ASSERT(frame_type() == JS_FUNCTION); | 9289 ASSERT(frame_type() == JS_FUNCTION); |
| 9199 | 9290 |
| 9200 // Outer environment is a copy of this one without the arguments. | 9291 // Outer environment is a copy of this one without the arguments. |
| 9201 int arity = function->scope()->num_parameters(); | 9292 int arity = function->scope()->num_parameters(); |
| 9202 | |
| 9203 HEnvironment* outer = Copy(); | 9293 HEnvironment* outer = Copy(); |
| 9204 outer->Drop(arguments + 1); // Including receiver. | 9294 outer->Drop(arguments + 1); // Including receiver. |
| 9205 outer->ClearHistory(); | 9295 outer->ClearHistory(); |
| 9206 | 9296 |
| 9207 if (is_construct) { | 9297 if (is_construct) { |
| 9208 // Create artificial constructor stub environment. The receiver should | 9298 // Create artificial constructor stub environment. The receiver should |
| 9209 // actually be the constructor function, but we pass the newly allocated | 9299 // actually be the constructor function, but we pass the newly allocated |
| 9210 // object instead, DoComputeConstructStubFrame() relies on that. | 9300 // object instead, DoComputeConstructStubFrame() relies on that. |
| 9211 outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments); | 9301 outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments); |
| 9212 } | 9302 } |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9583 } | 9673 } |
| 9584 } | 9674 } |
| 9585 | 9675 |
| 9586 #ifdef DEBUG | 9676 #ifdef DEBUG |
| 9587 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 9677 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 9588 if (allocator_ != NULL) allocator_->Verify(); | 9678 if (allocator_ != NULL) allocator_->Verify(); |
| 9589 #endif | 9679 #endif |
| 9590 } | 9680 } |
| 9591 | 9681 |
| 9592 } } // namespace v8::internal | 9682 } } // namespace v8::internal |
| OLD | NEW |