Chromium Code Reviews| 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 Handle<AccessorPair> accessors; | |
| 4776 Handle<JSObject> holder; | |
| 4777 if (IsAccessorCall(map, name, &accessors, &holder)) { | |
| 4778 CHECK_ALIVE(store = BuildCallSetter(literal, | |
|
Michael Starzinger
2012/07/19 13:28:13
For object literals we should never get an accesso
Sven Panne
2012/07/23 12:25:01
Done.
| |
| 4779 value, | |
| 4780 map, | |
| 4781 accessors, | |
| 4782 holder)); | |
| 4783 } else { | |
| 4784 CHECK_ALIVE(store = BuildStoreNamed(literal, | |
| 4785 name, | |
| 4786 value, | |
| 4787 map)); | |
| 4788 } | |
| 4789 } | |
| 4772 AddInstruction(store); | 4790 AddInstruction(store); |
| 4773 if (store->HasObservableSideEffects()) AddSimulate(key->id()); | 4791 if (store->HasObservableSideEffects()) AddSimulate(key->id()); |
| 4774 } else { | 4792 } else { |
| 4775 CHECK_ALIVE(VisitForEffect(value)); | 4793 CHECK_ALIVE(VisitForEffect(value)); |
| 4776 } | 4794 } |
| 4777 break; | 4795 break; |
| 4778 } | 4796 } |
| 4779 // Fall through. | 4797 // Fall through. |
| 4780 case ObjectLiteral::Property::PROTOTYPE: | 4798 case ObjectLiteral::Property::PROTOTYPE: |
| 4781 case ObjectLiteral::Property::SETTER: | 4799 case ObjectLiteral::Property::SETTER: |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4932 } else { | 4950 } else { |
| 4933 Map* transition = lookup->GetTransitionMapFromMap(*type); | 4951 Map* transition = lookup->GetTransitionMapFromMap(*type); |
| 4934 return transition->PropertyIndexFor(*name) - type->inobject_properties(); | 4952 return transition->PropertyIndexFor(*name) - type->inobject_properties(); |
| 4935 } | 4953 } |
| 4936 } | 4954 } |
| 4937 | 4955 |
| 4938 | 4956 |
| 4939 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, | 4957 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, |
| 4940 Handle<String> name, | 4958 Handle<String> name, |
| 4941 HValue* value, | 4959 HValue* value, |
| 4942 Handle<Map> type, | 4960 Handle<Map> map, |
| 4943 LookupResult* lookup, | 4961 LookupResult* lookup, |
| 4944 bool smi_and_map_check) { | 4962 bool smi_and_map_check) { |
| 4945 ASSERT(lookup->IsFound()); | 4963 ASSERT(lookup->IsFound()); |
| 4946 if (smi_and_map_check) { | 4964 if (smi_and_map_check) { |
| 4947 AddInstruction(new(zone()) HCheckNonSmi(object)); | 4965 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 4948 AddInstruction(HCheckMaps::NewWithTransitions(object, type, zone())); | 4966 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
| 4949 } | 4967 } |
| 4950 | 4968 |
| 4951 // If the property does not exist yet, we have to check that it wasn't made | 4969 // 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 | 4970 // readonly or turned into a setter by some meanwhile modifications on the |
| 4953 // prototype chain. | 4971 // prototype chain. |
| 4954 if (!lookup->IsProperty() && type->prototype()->IsJSReceiver()) { | 4972 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { |
| 4955 Object* proto = type->prototype(); | 4973 Object* proto = map->prototype(); |
| 4956 // First check that the prototype chain isn't affected already. | 4974 // First check that the prototype chain isn't affected already. |
| 4957 LookupResult proto_result(isolate()); | 4975 LookupResult proto_result(isolate()); |
| 4958 proto->Lookup(*name, &proto_result); | 4976 proto->Lookup(*name, &proto_result); |
| 4959 if (proto_result.IsProperty()) { | 4977 if (proto_result.IsProperty()) { |
| 4960 // If the inherited property could induce readonly-ness, bail out. | 4978 // If the inherited property could induce readonly-ness, bail out. |
| 4961 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) { | 4979 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) { |
| 4962 Bailout("improper object on prototype chain for store"); | 4980 Bailout("improper object on prototype chain for store"); |
| 4963 return NULL; | 4981 return NULL; |
| 4964 } | 4982 } |
| 4965 // We only need to check up to the preexisting property. | 4983 // We only need to check up to the preexisting property. |
| 4966 proto = proto_result.holder(); | 4984 proto = proto_result.holder(); |
| 4967 } else { | 4985 } else { |
| 4968 // Otherwise, find the top prototype. | 4986 // Otherwise, find the top prototype. |
| 4969 while (proto->GetPrototype()->IsJSObject()) proto = proto->GetPrototype(); | 4987 while (proto->GetPrototype()->IsJSObject()) proto = proto->GetPrototype(); |
| 4970 ASSERT(proto->GetPrototype()->IsNull()); | 4988 ASSERT(proto->GetPrototype()->IsNull()); |
| 4971 } | 4989 } |
| 4972 ASSERT(proto->IsJSObject()); | 4990 ASSERT(proto->IsJSObject()); |
| 4973 AddInstruction(new(zone()) HCheckPrototypeMaps( | 4991 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 4974 Handle<JSObject>(JSObject::cast(type->prototype())), | 4992 Handle<JSObject>(JSObject::cast(map->prototype())), |
| 4975 Handle<JSObject>(JSObject::cast(proto)))); | 4993 Handle<JSObject>(JSObject::cast(proto)))); |
| 4976 } | 4994 } |
| 4977 | 4995 |
| 4978 int index = ComputeLoadStoreFieldIndex(type, name, lookup); | 4996 int index = ComputeLoadStoreFieldIndex(map, name, lookup); |
| 4979 bool is_in_object = index < 0; | 4997 bool is_in_object = index < 0; |
| 4980 int offset = index * kPointerSize; | 4998 int offset = index * kPointerSize; |
| 4981 if (index < 0) { | 4999 if (index < 0) { |
| 4982 // Negative property indices are in-object properties, indexed | 5000 // Negative property indices are in-object properties, indexed |
| 4983 // from the end of the fixed part of the object. | 5001 // from the end of the fixed part of the object. |
| 4984 offset += type->instance_size(); | 5002 offset += map->instance_size(); |
| 4985 } else { | 5003 } else { |
| 4986 offset += FixedArray::kHeaderSize; | 5004 offset += FixedArray::kHeaderSize; |
| 4987 } | 5005 } |
| 4988 HStoreNamedField* instr = | 5006 HStoreNamedField* instr = |
| 4989 new(zone()) HStoreNamedField(object, name, value, is_in_object, offset); | 5007 new(zone()) HStoreNamedField(object, name, value, is_in_object, offset); |
| 4990 if (lookup->IsTransitionToField(*type)) { | 5008 if (lookup->IsTransitionToField(*map)) { |
| 4991 Handle<Map> transition(lookup->GetTransitionMapFromMap(*type)); | 5009 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
| 4992 instr->set_transition(transition); | 5010 instr->set_transition(transition); |
| 4993 // TODO(fschneider): Record the new map type of the object in the IR to | 5011 // TODO(fschneider): Record the new map type of the object in the IR to |
| 4994 // enable elimination of redundant checks after the transition store. | 5012 // enable elimination of redundant checks after the transition store. |
| 4995 instr->SetGVNFlag(kChangesMaps); | 5013 instr->SetGVNFlag(kChangesMaps); |
| 4996 } | 5014 } |
| 4997 return instr; | 5015 return instr; |
| 4998 } | 5016 } |
| 4999 | 5017 |
| 5000 | 5018 |
| 5001 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, | 5019 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 5018 Handle<JSObject> holder(JSObject::cast(map->prototype())); | 5036 Handle<JSObject> holder(JSObject::cast(map->prototype())); |
| 5019 if (!holder->HasFastProperties()) break; | 5037 if (!holder->HasFastProperties()) break; |
| 5020 map = Handle<Map>(holder->map()); | 5038 map = Handle<Map>(holder->map()); |
| 5021 map->LookupDescriptor(*holder, *name, lookup); | 5039 map->LookupDescriptor(*holder, *name, lookup); |
| 5022 if (lookup->IsFound()) return; | 5040 if (lookup->IsFound()) return; |
| 5023 } | 5041 } |
| 5024 lookup->NotFound(); | 5042 lookup->NotFound(); |
| 5025 } | 5043 } |
| 5026 | 5044 |
| 5027 | 5045 |
| 5028 HInstruction* HGraphBuilder::BuildCallSetter(HValue* obj, | 5046 HInstruction* HGraphBuilder::BuildCallSetter(HValue* object, |
| 5029 Handle<String> name, | |
| 5030 HValue* value, | 5047 HValue* value, |
| 5031 Handle<Map> map, | 5048 Handle<Map> map, |
| 5032 Handle<Object> callback, | 5049 Handle<AccessorPair> accessors, |
| 5033 Handle<JSObject> holder) { | 5050 Handle<JSObject> holder) { |
| 5034 if (!callback->IsAccessorPair()) { | 5051 Handle<JSFunction> function(JSFunction::cast(accessors->setter())); |
| 5035 return BuildStoreNamedGeneric(obj, name, value); | 5052 AddCheckConstantFunction(holder, object, map, true); |
| 5036 } | 5053 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)); | 5054 AddInstruction(new(zone()) HPushArgument(value)); |
| 5042 return new(zone()) HCallConstantFunction(function, 2); | 5055 return new(zone()) HCallConstantFunction(function, 2); |
| 5043 } | 5056 } |
| 5044 | 5057 |
| 5045 | 5058 |
| 5046 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, | 5059 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, |
| 5060 Handle<String> name, | |
| 5047 HValue* value, | 5061 HValue* value, |
| 5048 Handle<Map> type, | 5062 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. | 5063 // Handle a store to a known field. |
| 5055 LookupResult lookup(isolate()); | 5064 LookupResult lookup(isolate()); |
| 5056 if (ComputeLoadStoreField(type, name, &lookup, true)) { | 5065 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
| 5057 // true = needs smi and map check. | 5066 // true = needs smi and map check. |
| 5058 return BuildStoreNamedField(object, name, value, type, &lookup, true); | 5067 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 } | 5068 } |
| 5076 | 5069 |
| 5077 // No luck, do a generic store. | 5070 // No luck, do a generic store. |
| 5078 return BuildStoreNamedGeneric(object, name, value); | 5071 return BuildStoreNamedGeneric(object, name, value); |
| 5079 } | 5072 } |
| 5080 | 5073 |
| 5081 | 5074 |
| 5082 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, | 5075 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
| 5083 HValue* object, | 5076 HValue* object, |
| 5084 SmallMapList* types, | 5077 SmallMapList* types, |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 5111 } | 5104 } |
| 5112 ++count; | 5105 ++count; |
| 5113 } | 5106 } |
| 5114 } | 5107 } |
| 5115 | 5108 |
| 5116 // Use monomorphic load if property lookup results in the same field index | 5109 // 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. | 5110 // for all maps. Requires special map check on the set of all handled maps. |
| 5118 HInstruction* instr; | 5111 HInstruction* instr; |
| 5119 if (count == types->length() && is_monomorphic_field) { | 5112 if (count == types->length() && is_monomorphic_field) { |
| 5120 AddInstruction(new(zone()) HCheckMaps(object, types, zone())); | 5113 AddInstruction(new(zone()) HCheckMaps(object, types, zone())); |
| 5121 instr = BuildLoadNamedField(object, expr, map, &lookup, false); | 5114 instr = BuildLoadNamedField(object, map, &lookup, false); |
| 5122 } else { | 5115 } else { |
| 5123 HValue* context = environment()->LookupContext(); | 5116 HValue* context = environment()->LookupContext(); |
| 5124 instr = new(zone()) HLoadNamedFieldPolymorphic(context, | 5117 instr = new(zone()) HLoadNamedFieldPolymorphic(context, |
| 5125 object, | 5118 object, |
| 5126 types, | 5119 types, |
| 5127 name, | 5120 name, |
| 5128 zone()); | 5121 zone()); |
| 5129 } | 5122 } |
| 5130 | 5123 |
| 5131 instr->set_position(expr->position()); | 5124 instr->set_position(expr->position()); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5223 CHECK_ALIVE(VisitForValue(expr->value())); | 5216 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5224 value = Pop(); | 5217 value = Pop(); |
| 5225 HValue* object = Pop(); | 5218 HValue* object = Pop(); |
| 5226 | 5219 |
| 5227 Literal* key = prop->key()->AsLiteral(); | 5220 Literal* key = prop->key()->AsLiteral(); |
| 5228 Handle<String> name = Handle<String>::cast(key->handle()); | 5221 Handle<String> name = Handle<String>::cast(key->handle()); |
| 5229 ASSERT(!name.is_null()); | 5222 ASSERT(!name.is_null()); |
| 5230 | 5223 |
| 5231 SmallMapList* types = expr->GetReceiverTypes(); | 5224 SmallMapList* types = expr->GetReceiverTypes(); |
| 5232 if (expr->IsMonomorphic()) { | 5225 if (expr->IsMonomorphic()) { |
| 5233 CHECK_ALIVE(instr = BuildStoreNamed(object, | 5226 Handle<Map> type = types->first(); |
| 5234 value, | 5227 Handle<AccessorPair> accessors; |
| 5235 types->first(), | 5228 Handle<JSObject> holder; |
| 5236 prop->key())); | 5229 if (IsAccessorCall(type, name, &accessors, &holder)) { |
| 5230 CHECK_ALIVE(instr = BuildCallSetter(object, | |
| 5231 value, | |
| 5232 type, | |
| 5233 accessors, | |
| 5234 holder)); | |
| 5235 } else { | |
| 5236 CHECK_ALIVE(instr = BuildStoreNamed(object, | |
| 5237 name, | |
| 5238 value, | |
| 5239 type)); | |
| 5240 } | |
| 5237 | 5241 |
| 5238 } else if (types != NULL && types->length() > 1) { | 5242 } else if (types != NULL && types->length() > 1) { |
| 5239 HandlePolymorphicStoreNamedField(expr, object, value, types, name); | 5243 HandlePolymorphicStoreNamedField(expr, object, value, types, name); |
| 5240 return; | 5244 return; |
| 5241 | 5245 |
| 5242 } else { | 5246 } else { |
| 5243 instr = BuildStoreNamedGeneric(object, name, value); | 5247 instr = BuildStoreNamedGeneric(object, name, value); |
| 5244 } | 5248 } |
| 5245 | 5249 |
| 5246 } else { | 5250 } else { |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5384 return Bailout("compound assignment to lookup slot"); | 5388 return Bailout("compound assignment to lookup slot"); |
| 5385 } | 5389 } |
| 5386 return ast_context()->ReturnValue(Pop()); | 5390 return ast_context()->ReturnValue(Pop()); |
| 5387 | 5391 |
| 5388 } else if (prop != NULL) { | 5392 } else if (prop != NULL) { |
| 5389 prop->RecordTypeFeedback(oracle(), zone()); | 5393 prop->RecordTypeFeedback(oracle(), zone()); |
| 5390 | 5394 |
| 5391 if (prop->key()->IsPropertyName()) { | 5395 if (prop->key()->IsPropertyName()) { |
| 5392 // Named property. | 5396 // Named property. |
| 5393 CHECK_ALIVE(VisitForValue(prop->obj())); | 5397 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 5394 HValue* obj = Top(); | 5398 HValue* object = Top(); |
| 5395 | 5399 |
| 5400 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | |
| 5396 Handle<Map> map; | 5401 Handle<Map> map; |
| 5397 HInstruction* load; | 5402 HInstruction* load; |
| 5398 if (prop->IsMonomorphic()) { | 5403 if (prop->IsMonomorphic()) { |
| 5399 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | |
| 5400 map = prop->GetReceiverTypes()->first(); | 5404 map = prop->GetReceiverTypes()->first(); |
| 5401 load = BuildLoadNamed(obj, prop, map, name); | 5405 Handle<AccessorPair> accessors; |
| 5406 Handle<JSObject> holder; | |
| 5407 if (IsAccessorCall(map, name, &accessors, &holder)) { | |
| 5408 load = BuildCallGetter(object, map, accessors, holder); | |
| 5409 } else { | |
| 5410 load = BuildLoadNamed(object, name, prop, map); | |
| 5411 } | |
|
Michael Starzinger
2012/07/19 13:28:13
This part cannot yet be inlined with out current m
| |
| 5402 } else { | 5412 } else { |
| 5403 load = BuildLoadNamedGeneric(obj, prop); | 5413 load = BuildLoadNamedGeneric(object, name, prop); |
| 5404 } | 5414 } |
| 5405 PushAndAdd(load); | 5415 PushAndAdd(load); |
| 5406 if (load->HasObservableSideEffects()) AddSimulate(expr->CompoundLoadId()); | 5416 if (load->HasObservableSideEffects()) AddSimulate(expr->CompoundLoadId()); |
| 5407 | 5417 |
| 5408 CHECK_ALIVE(VisitForValue(expr->value())); | 5418 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5409 HValue* right = Pop(); | 5419 HValue* right = Pop(); |
| 5410 HValue* left = Pop(); | 5420 HValue* left = Pop(); |
| 5411 | 5421 |
| 5412 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5422 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
| 5413 PushAndAdd(instr); | 5423 PushAndAdd(instr); |
| 5414 if (instr->HasObservableSideEffects()) AddSimulate(operation->id()); | 5424 if (instr->HasObservableSideEffects()) AddSimulate(operation->id()); |
| 5415 | 5425 |
| 5416 HInstruction* store; | 5426 HInstruction* store; |
| 5417 CHECK_ALIVE(store = BuildStoreNamed(obj, instr, map, prop->key())); | 5427 if (map.is_null()) { |
| 5428 // If we don't know the monomorphic type, do a generic store. | |
| 5429 CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, instr)); | |
| 5430 } else { | |
| 5431 Handle<AccessorPair> accessors; | |
| 5432 Handle<JSObject> holder; | |
| 5433 if (IsAccessorCall(map, name, &accessors, &holder)) { | |
| 5434 CHECK_ALIVE(store = BuildCallSetter(object, | |
| 5435 instr, | |
| 5436 map, | |
| 5437 accessors, | |
| 5438 holder)); | |
| 5439 } else { | |
| 5440 CHECK_ALIVE(store = BuildStoreNamed(object, name, instr, map)); | |
| 5441 } | |
| 5442 } | |
| 5418 AddInstruction(store); | 5443 AddInstruction(store); |
| 5419 // Drop the simulated receiver and value. Return the value. | 5444 // Drop the simulated receiver and value. Return the value. |
| 5420 Drop(2); | 5445 Drop(2); |
| 5421 Push(instr); | 5446 Push(instr); |
| 5422 if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); | 5447 if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); |
| 5423 return ast_context()->ReturnValue(Pop()); | 5448 return ast_context()->ReturnValue(Pop()); |
| 5424 | 5449 |
| 5425 } else { | 5450 } else { |
| 5426 // Keyed property. | 5451 // Keyed property. |
| 5427 CHECK_ALIVE(VisitForValue(prop->obj())); | 5452 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); | 5633 HThrow* instr = new(zone()) HThrow(context, value); |
| 5609 instr->set_position(expr->position()); | 5634 instr->set_position(expr->position()); |
| 5610 AddInstruction(instr); | 5635 AddInstruction(instr); |
| 5611 AddSimulate(expr->id()); | 5636 AddSimulate(expr->id()); |
| 5612 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5637 current_block()->FinishExit(new(zone()) HAbnormalExit); |
| 5613 set_current_block(NULL); | 5638 set_current_block(NULL); |
| 5614 } | 5639 } |
| 5615 | 5640 |
| 5616 | 5641 |
| 5617 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, | 5642 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
| 5618 Property* expr, | 5643 Handle<Map> map, |
| 5619 Handle<Map> type, | |
| 5620 LookupResult* lookup, | 5644 LookupResult* lookup, |
| 5621 bool smi_and_map_check) { | 5645 bool smi_and_map_check) { |
| 5622 if (smi_and_map_check) { | 5646 if (smi_and_map_check) { |
| 5623 AddInstruction(new(zone()) HCheckNonSmi(object)); | 5647 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 5624 AddInstruction(HCheckMaps::NewWithTransitions(object, type, zone())); | 5648 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
| 5625 } | 5649 } |
| 5626 | 5650 |
| 5627 int index = lookup->GetLocalFieldIndexFromMap(*type); | 5651 int index = lookup->GetLocalFieldIndexFromMap(*map); |
| 5628 if (index < 0) { | 5652 if (index < 0) { |
| 5629 // Negative property indices are in-object properties, indexed | 5653 // Negative property indices are in-object properties, indexed |
| 5630 // from the end of the fixed part of the object. | 5654 // from the end of the fixed part of the object. |
| 5631 int offset = (index * kPointerSize) + type->instance_size(); | 5655 int offset = (index * kPointerSize) + map->instance_size(); |
| 5632 return new(zone()) HLoadNamedField(object, true, offset); | 5656 return new(zone()) HLoadNamedField(object, true, offset); |
| 5633 } else { | 5657 } else { |
| 5634 // Non-negative property indices are in the properties array. | 5658 // Non-negative property indices are in the properties array. |
| 5635 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; | 5659 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; |
| 5636 return new(zone()) HLoadNamedField(object, false, offset); | 5660 return new(zone()) HLoadNamedField(object, false, offset); |
| 5637 } | 5661 } |
| 5638 } | 5662 } |
| 5639 | 5663 |
| 5640 | 5664 |
| 5641 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj, | 5665 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* object, |
| 5666 Handle<String> name, | |
| 5642 Property* expr) { | 5667 Property* expr) { |
| 5643 if (expr->IsUninitialized() && !FLAG_always_opt) { | 5668 if (expr->IsUninitialized() && !FLAG_always_opt) { |
| 5644 AddInstruction(new(zone()) HSoftDeoptimize); | 5669 AddInstruction(new(zone()) HSoftDeoptimize); |
| 5645 current_block()->MarkAsDeoptimizing(); | 5670 current_block()->MarkAsDeoptimizing(); |
| 5646 } | 5671 } |
| 5647 ASSERT(expr->key()->IsPropertyName()); | |
| 5648 Handle<Object> name = expr->key()->AsLiteral()->handle(); | |
| 5649 HValue* context = environment()->LookupContext(); | 5672 HValue* context = environment()->LookupContext(); |
| 5650 return new(zone()) HLoadNamedGeneric(context, obj, name); | 5673 return new(zone()) HLoadNamedGeneric(context, object, name); |
| 5651 } | 5674 } |
| 5652 | 5675 |
| 5653 | 5676 |
| 5654 HInstruction* HGraphBuilder::BuildCallGetter(HValue* obj, | 5677 HInstruction* HGraphBuilder::BuildCallGetter(HValue* object, |
| 5655 Property* expr, | |
| 5656 Handle<Map> map, | 5678 Handle<Map> map, |
| 5657 Handle<Object> callback, | 5679 Handle<AccessorPair> accessors, |
| 5658 Handle<JSObject> holder) { | 5680 Handle<JSObject> holder) { |
| 5659 if (!callback->IsAccessorPair()) return BuildLoadNamedGeneric(obj, expr); | 5681 Handle<JSFunction> function(JSFunction::cast(accessors->getter())); |
| 5660 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter()); | 5682 AddCheckConstantFunction(holder, object, map, true); |
| 5661 Handle<JSFunction> function(Handle<JSFunction>::cast(getter)); | 5683 AddInstruction(new(zone()) HPushArgument(object)); |
| 5662 AddCheckConstantFunction(holder, obj, map, true); | |
| 5663 AddInstruction(new(zone()) HPushArgument(obj)); | |
| 5664 return new(zone()) HCallConstantFunction(function, 1); | 5684 return new(zone()) HCallConstantFunction(function, 1); |
| 5665 } | 5685 } |
| 5666 | 5686 |
| 5667 | 5687 |
| 5668 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj, | 5688 bool HGraphBuilder::IsAccessorCall(Handle<Map> map, |
|
Michael Starzinger
2012/07/19 13:28:13
The name of this method is misleading, because it
Sven Panne
2012/07/23 12:25:01
Done.
| |
| 5689 Handle<String> name, | |
| 5690 Handle<AccessorPair>* accessors, | |
| 5691 Handle<JSObject>* holder) { | |
| 5692 LookupResult lookup(isolate()); | |
| 5693 | |
| 5694 // Check for a JavaScript accessor directly in the map. | |
| 5695 map->LookupDescriptor(NULL, *name, &lookup); | |
| 5696 if (lookup.IsPropertyCallbacks()) { | |
| 5697 Handle<Object> callback(lookup.GetValueFromMap(*map)); | |
| 5698 if (!callback->IsAccessorPair()) return false; | |
| 5699 *accessors = Handle<AccessorPair>::cast(callback); | |
| 5700 *holder = Handle<JSObject>(); | |
| 5701 return true; | |
| 5702 } | |
| 5703 | |
| 5704 // Everything else, e.g. a field, can't be an accessor call. | |
| 5705 if (lookup.IsFound()) return false; | |
| 5706 | |
| 5707 // Check for a JavaScript accessor somewhere in the proto chain. | |
| 5708 LookupInPrototypes(map, name, &lookup); | |
| 5709 if (lookup.IsPropertyCallbacks()) { | |
| 5710 Handle<Object> callback(lookup.GetValue()); | |
| 5711 if (!callback->IsAccessorPair()) return false; | |
| 5712 *accessors = Handle<AccessorPair>::cast(callback); | |
| 5713 *holder = Handle<JSObject>(lookup.holder()); | |
| 5714 return true; | |
| 5715 } | |
| 5716 | |
| 5717 // We haven't found a JavaScript accessor anywhere. | |
| 5718 return false; | |
| 5719 } | |
| 5720 | |
| 5721 | |
| 5722 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* object, | |
| 5723 Handle<String> name, | |
| 5669 Property* expr, | 5724 Property* expr, |
| 5670 Handle<Map> map, | 5725 Handle<Map> map) { |
| 5671 Handle<String> name) { | |
| 5672 LookupResult lookup(isolate()); | 5726 LookupResult lookup(isolate()); |
| 5673 map->LookupDescriptor(NULL, *name, &lookup); | 5727 map->LookupDescriptor(NULL, *name, &lookup); |
| 5674 if (lookup.IsField()) { | 5728 if (lookup.IsField()) { |
| 5675 return BuildLoadNamedField(obj, | 5729 return BuildLoadNamedField(object, map, &lookup, true); |
| 5676 expr, | 5730 } |
| 5677 map, | 5731 if (lookup.IsConstantFunction()) { |
| 5678 &lookup, | 5732 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 5679 true); | 5733 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)); | 5734 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); |
| 5684 return new(zone()) HConstant(function, Representation::Tagged()); | 5735 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 } | 5736 } |
| 5737 return BuildLoadNamedGeneric(object, name, expr); | |
| 5698 } | 5738 } |
| 5699 | 5739 |
| 5700 | 5740 |
| 5701 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 5741 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
| 5702 HValue* key) { | 5742 HValue* key) { |
| 5703 HValue* context = environment()->LookupContext(); | 5743 HValue* context = environment()->LookupContext(); |
| 5704 return new(zone()) HLoadKeyedGeneric(context, object, key); | 5744 return new(zone()) HLoadKeyedGeneric(context, object, key); |
| 5705 } | 5745 } |
| 5706 | 5746 |
| 5707 | 5747 |
| (...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6294 | 6334 |
| 6295 } else if (expr->IsFunctionPrototype()) { | 6335 } else if (expr->IsFunctionPrototype()) { |
| 6296 HValue* function = Pop(); | 6336 HValue* function = Pop(); |
| 6297 AddInstruction(new(zone()) HCheckNonSmi(function)); | 6337 AddInstruction(new(zone()) HCheckNonSmi(function)); |
| 6298 instr = new(zone()) HLoadFunctionPrototype(function); | 6338 instr = new(zone()) HLoadFunctionPrototype(function); |
| 6299 | 6339 |
| 6300 } else if (expr->key()->IsPropertyName()) { | 6340 } else if (expr->key()->IsPropertyName()) { |
| 6301 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 6341 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| 6302 SmallMapList* types = expr->GetReceiverTypes(); | 6342 SmallMapList* types = expr->GetReceiverTypes(); |
| 6303 | 6343 |
| 6304 HValue* obj = Pop(); | 6344 HValue* object = Pop(); |
| 6305 if (expr->IsMonomorphic()) { | 6345 if (expr->IsMonomorphic()) { |
| 6306 instr = BuildLoadNamed(obj, expr, types->first(), name); | 6346 Handle<Map> map = types->first(); |
| 6347 Handle<AccessorPair> accessors; | |
| 6348 Handle<JSObject> holder; | |
| 6349 if (IsAccessorCall(map, name, &accessors, &holder)) { | |
| 6350 instr = BuildCallGetter(object, map, accessors, holder); | |
| 6351 } else { | |
| 6352 instr = BuildLoadNamed(object, name, expr, map); | |
| 6353 } | |
| 6307 } else if (types != NULL && types->length() > 1) { | 6354 } else if (types != NULL && types->length() > 1) { |
| 6308 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 6355 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 6309 HandlePolymorphicLoadNamedField(expr, obj, types, name); | 6356 HandlePolymorphicLoadNamedField(expr, object, types, name); |
| 6310 return; | 6357 return; |
| 6311 } else { | 6358 } else { |
| 6312 instr = BuildLoadNamedGeneric(obj, expr); | 6359 instr = BuildLoadNamedGeneric(object, name, expr); |
| 6313 } | 6360 } |
| 6314 | 6361 |
| 6315 } else { | 6362 } else { |
| 6316 CHECK_ALIVE(VisitForValue(expr->key())); | 6363 CHECK_ALIVE(VisitForValue(expr->key())); |
| 6317 | 6364 |
| 6318 HValue* key = Pop(); | 6365 HValue* key = Pop(); |
| 6319 HValue* obj = Pop(); | 6366 HValue* object = Pop(); |
| 6320 | 6367 |
| 6321 bool has_side_effects = false; | 6368 bool has_side_effects = false; |
| 6322 HValue* load = HandleKeyedElementAccess( | 6369 HValue* load = HandleKeyedElementAccess( |
| 6323 obj, key, NULL, expr, expr->id(), expr->position(), | 6370 object, key, NULL, expr, expr->id(), expr->position(), |
| 6324 false, // is_store | 6371 false, // is_store |
| 6325 &has_side_effects); | 6372 &has_side_effects); |
| 6326 if (has_side_effects) { | 6373 if (has_side_effects) { |
| 6327 if (ast_context()->IsEffect()) { | 6374 if (ast_context()->IsEffect()) { |
| 6328 AddSimulate(expr->id()); | 6375 AddSimulate(expr->id()); |
| 6329 } else { | 6376 } else { |
| 6330 Push(load); | 6377 Push(load); |
| 6331 AddSimulate(expr->id()); | 6378 AddSimulate(expr->id()); |
| 6332 Drop(1); | 6379 Drop(1); |
| 6333 } | 6380 } |
| (...skipping 1447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7781 ASSERT(prop != NULL); | 7828 ASSERT(prop != NULL); |
| 7782 prop->RecordTypeFeedback(oracle(), zone()); | 7829 prop->RecordTypeFeedback(oracle(), zone()); |
| 7783 | 7830 |
| 7784 if (prop->key()->IsPropertyName()) { | 7831 if (prop->key()->IsPropertyName()) { |
| 7785 // Named property. | 7832 // Named property. |
| 7786 if (returns_original_input) Push(graph_->GetConstantUndefined()); | 7833 if (returns_original_input) Push(graph_->GetConstantUndefined()); |
| 7787 | 7834 |
| 7788 CHECK_ALIVE(VisitForValue(prop->obj())); | 7835 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 7789 HValue* obj = Top(); | 7836 HValue* obj = Top(); |
| 7790 | 7837 |
| 7838 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | |
| 7791 Handle<Map> map; | 7839 Handle<Map> map; |
| 7792 HInstruction* load; | 7840 HInstruction* load; |
| 7793 if (prop->IsMonomorphic()) { | 7841 if (prop->IsMonomorphic()) { |
| 7794 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | |
| 7795 map = prop->GetReceiverTypes()->first(); | 7842 map = prop->GetReceiverTypes()->first(); |
| 7796 load = BuildLoadNamed(obj, prop, map, name); | 7843 Handle<AccessorPair> accessors; |
| 7844 Handle<JSObject> holder; | |
| 7845 if (IsAccessorCall(map, name, &accessors, &holder)) { | |
| 7846 load = BuildCallGetter(obj, map, accessors, holder); | |
| 7847 } else { | |
| 7848 load = BuildLoadNamed(obj, name, prop, map); | |
| 7849 } | |
|
Michael Starzinger
2012/07/19 13:28:13
Same comment as for HandleCompoundAssignment() app
| |
| 7797 } else { | 7850 } else { |
| 7798 load = BuildLoadNamedGeneric(obj, prop); | 7851 load = BuildLoadNamedGeneric(obj, name, prop); |
| 7799 } | 7852 } |
| 7800 PushAndAdd(load); | 7853 PushAndAdd(load); |
| 7801 if (load->HasObservableSideEffects()) AddSimulate(expr->CountId()); | 7854 if (load->HasObservableSideEffects()) AddSimulate(expr->CountId()); |
| 7802 | 7855 |
| 7803 after = BuildIncrement(returns_original_input, expr); | 7856 after = BuildIncrement(returns_original_input, expr); |
| 7804 input = Pop(); | 7857 input = Pop(); |
| 7805 | 7858 |
| 7806 HInstruction* store; | 7859 HInstruction* store; |
| 7807 CHECK_ALIVE(store = BuildStoreNamed(obj, after, map, prop->key())); | 7860 if (map.is_null()) { |
| 7861 // If we don't know the monomorphic type, do a generic store. | |
| 7862 CHECK_ALIVE(store = BuildStoreNamedGeneric(obj, name, after)); | |
| 7863 } else { | |
| 7864 Handle<AccessorPair> accessors; | |
| 7865 Handle<JSObject> holder; | |
| 7866 if (IsAccessorCall(map, name, &accessors, &holder)) { | |
| 7867 CHECK_ALIVE(store = BuildCallSetter(obj, | |
| 7868 after, | |
| 7869 map, | |
| 7870 accessors, | |
| 7871 holder)); | |
| 7872 } else { | |
| 7873 CHECK_ALIVE(store = BuildStoreNamed(obj, name, after, map)); | |
| 7874 } | |
| 7875 } | |
| 7808 AddInstruction(store); | 7876 AddInstruction(store); |
| 7809 | 7877 |
| 7810 // Overwrite the receiver in the bailout environment with the result | 7878 // Overwrite the receiver in the bailout environment with the result |
| 7811 // of the operation, and the placeholder with the original value if | 7879 // of the operation, and the placeholder with the original value if |
| 7812 // necessary. | 7880 // necessary. |
| 7813 environment()->SetExpressionStackAt(0, after); | 7881 environment()->SetExpressionStackAt(0, after); |
| 7814 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | 7882 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
| 7815 if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); | 7883 if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); |
| 7816 | 7884 |
| 7817 } else { | 7885 } else { |
| (...skipping 1755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9573 } | 9641 } |
| 9574 } | 9642 } |
| 9575 | 9643 |
| 9576 #ifdef DEBUG | 9644 #ifdef DEBUG |
| 9577 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 9645 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 9578 if (allocator_ != NULL) allocator_->Verify(); | 9646 if (allocator_ != NULL) allocator_->Verify(); |
| 9579 #endif | 9647 #endif |
| 9580 } | 9648 } |
| 9581 | 9649 |
| 9582 } } // namespace v8::internal | 9650 } } // namespace v8::internal |
| OLD | NEW |