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<String> name = | |
4768 Handle<String>::cast(property->key()->handle()); | |
Michael Starzinger
2012/07/26 08:36:29
Consider using property->key()->AsPropertyName() h
Sven Panne
2012/07/26 08:50:09
Good point, it seems that I start getting lost in
| |
4767 HInstruction* store; | 4769 HInstruction* store; |
4768 CHECK_ALIVE(store = BuildStoreNamed(literal, | 4770 CHECK_ALIVE(store = BuildStoreNamed(literal, |
4771 name, | |
4769 value, | 4772 value, |
4770 property->GetReceiverType(), | 4773 property->GetReceiverType())); |
4771 property->key())); | |
4772 AddInstruction(store); | 4774 AddInstruction(store); |
4773 if (store->HasObservableSideEffects()) AddSimulate(key->id()); | 4775 if (store->HasObservableSideEffects()) AddSimulate(key->id()); |
4774 } else { | 4776 } else { |
4775 CHECK_ALIVE(VisitForEffect(value)); | 4777 CHECK_ALIVE(VisitForEffect(value)); |
4776 } | 4778 } |
4777 break; | 4779 break; |
4778 } | 4780 } |
4779 // Fall through. | 4781 // Fall through. |
4780 case ObjectLiteral::Property::PROTOTYPE: | 4782 case ObjectLiteral::Property::PROTOTYPE: |
4781 case ObjectLiteral::Property::SETTER: | 4783 case ObjectLiteral::Property::SETTER: |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4932 } else { | 4934 } else { |
4933 Map* transition = lookup->GetTransitionMapFromMap(*type); | 4935 Map* transition = lookup->GetTransitionMapFromMap(*type); |
4934 return transition->PropertyIndexFor(*name) - type->inobject_properties(); | 4936 return transition->PropertyIndexFor(*name) - type->inobject_properties(); |
4935 } | 4937 } |
4936 } | 4938 } |
4937 | 4939 |
4938 | 4940 |
4939 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, | 4941 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, |
4940 Handle<String> name, | 4942 Handle<String> name, |
4941 HValue* value, | 4943 HValue* value, |
4942 Handle<Map> type, | 4944 Handle<Map> map, |
4943 LookupResult* lookup, | 4945 LookupResult* lookup, |
4944 bool smi_and_map_check) { | 4946 bool smi_and_map_check) { |
4945 ASSERT(lookup->IsFound()); | 4947 ASSERT(lookup->IsFound()); |
4946 if (smi_and_map_check) { | 4948 if (smi_and_map_check) { |
4947 AddInstruction(new(zone()) HCheckNonSmi(object)); | 4949 AddInstruction(new(zone()) HCheckNonSmi(object)); |
4948 AddInstruction(HCheckMaps::NewWithTransitions(object, type, zone())); | 4950 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
4949 } | 4951 } |
4950 | 4952 |
4951 // If the property does not exist yet, we have to check that it wasn't made | 4953 // 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 | 4954 // readonly or turned into a setter by some meanwhile modifications on the |
4953 // prototype chain. | 4955 // prototype chain. |
4954 if (!lookup->IsProperty() && type->prototype()->IsJSReceiver()) { | 4956 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { |
4955 Object* proto = type->prototype(); | 4957 Object* proto = map->prototype(); |
4956 // First check that the prototype chain isn't affected already. | 4958 // First check that the prototype chain isn't affected already. |
4957 LookupResult proto_result(isolate()); | 4959 LookupResult proto_result(isolate()); |
4958 proto->Lookup(*name, &proto_result); | 4960 proto->Lookup(*name, &proto_result); |
4959 if (proto_result.IsProperty()) { | 4961 if (proto_result.IsProperty()) { |
4960 // If the inherited property could induce readonly-ness, bail out. | 4962 // If the inherited property could induce readonly-ness, bail out. |
4961 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) { | 4963 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) { |
4962 Bailout("improper object on prototype chain for store"); | 4964 Bailout("improper object on prototype chain for store"); |
4963 return NULL; | 4965 return NULL; |
4964 } | 4966 } |
4965 // We only need to check up to the preexisting property. | 4967 // We only need to check up to the preexisting property. |
4966 proto = proto_result.holder(); | 4968 proto = proto_result.holder(); |
4967 } else { | 4969 } else { |
4968 // Otherwise, find the top prototype. | 4970 // Otherwise, find the top prototype. |
4969 while (proto->GetPrototype()->IsJSObject()) proto = proto->GetPrototype(); | 4971 while (proto->GetPrototype()->IsJSObject()) proto = proto->GetPrototype(); |
4970 ASSERT(proto->GetPrototype()->IsNull()); | 4972 ASSERT(proto->GetPrototype()->IsNull()); |
4971 } | 4973 } |
4972 ASSERT(proto->IsJSObject()); | 4974 ASSERT(proto->IsJSObject()); |
4973 AddInstruction(new(zone()) HCheckPrototypeMaps( | 4975 AddInstruction(new(zone()) HCheckPrototypeMaps( |
4974 Handle<JSObject>(JSObject::cast(type->prototype())), | 4976 Handle<JSObject>(JSObject::cast(map->prototype())), |
4975 Handle<JSObject>(JSObject::cast(proto)))); | 4977 Handle<JSObject>(JSObject::cast(proto)))); |
4976 } | 4978 } |
4977 | 4979 |
4978 int index = ComputeLoadStoreFieldIndex(type, name, lookup); | 4980 int index = ComputeLoadStoreFieldIndex(map, name, lookup); |
4979 bool is_in_object = index < 0; | 4981 bool is_in_object = index < 0; |
4980 int offset = index * kPointerSize; | 4982 int offset = index * kPointerSize; |
4981 if (index < 0) { | 4983 if (index < 0) { |
4982 // Negative property indices are in-object properties, indexed | 4984 // Negative property indices are in-object properties, indexed |
4983 // from the end of the fixed part of the object. | 4985 // from the end of the fixed part of the object. |
4984 offset += type->instance_size(); | 4986 offset += map->instance_size(); |
4985 } else { | 4987 } else { |
4986 offset += FixedArray::kHeaderSize; | 4988 offset += FixedArray::kHeaderSize; |
4987 } | 4989 } |
4988 HStoreNamedField* instr = | 4990 HStoreNamedField* instr = |
4989 new(zone()) HStoreNamedField(object, name, value, is_in_object, offset); | 4991 new(zone()) HStoreNamedField(object, name, value, is_in_object, offset); |
4990 if (lookup->IsTransitionToField(*type)) { | 4992 if (lookup->IsTransitionToField(*map)) { |
4991 Handle<Map> transition(lookup->GetTransitionMapFromMap(*type)); | 4993 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
4992 instr->set_transition(transition); | 4994 instr->set_transition(transition); |
4993 // TODO(fschneider): Record the new map type of the object in the IR to | 4995 // TODO(fschneider): Record the new map type of the object in the IR to |
4994 // enable elimination of redundant checks after the transition store. | 4996 // enable elimination of redundant checks after the transition store. |
4995 instr->SetGVNFlag(kChangesMaps); | 4997 instr->SetGVNFlag(kChangesMaps); |
4996 } | 4998 } |
4997 return instr; | 4999 return instr; |
4998 } | 5000 } |
4999 | 5001 |
5000 | 5002 |
5001 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, | 5003 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, |
(...skipping 16 matching lines...) Expand all Loading... | |
5018 Handle<JSObject> holder(JSObject::cast(map->prototype())); | 5020 Handle<JSObject> holder(JSObject::cast(map->prototype())); |
5019 if (!holder->HasFastProperties()) break; | 5021 if (!holder->HasFastProperties()) break; |
5020 map = Handle<Map>(holder->map()); | 5022 map = Handle<Map>(holder->map()); |
5021 map->LookupDescriptor(*holder, *name, lookup); | 5023 map->LookupDescriptor(*holder, *name, lookup); |
5022 if (lookup->IsFound()) return; | 5024 if (lookup->IsFound()) return; |
5023 } | 5025 } |
5024 lookup->NotFound(); | 5026 lookup->NotFound(); |
5025 } | 5027 } |
5026 | 5028 |
5027 | 5029 |
5028 HInstruction* HGraphBuilder::BuildCallSetter(HValue* obj, | 5030 HInstruction* HGraphBuilder::BuildCallSetter(HValue* object, |
5029 Handle<String> name, | |
5030 HValue* value, | 5031 HValue* value, |
5031 Handle<Map> map, | 5032 Handle<Map> map, |
5032 Handle<Object> callback, | 5033 Handle<AccessorPair> accessors, |
5033 Handle<JSObject> holder) { | 5034 Handle<JSObject> holder) { |
5034 if (!callback->IsAccessorPair()) { | 5035 Handle<JSFunction> setter(JSFunction::cast(accessors->setter())); |
5035 return BuildStoreNamedGeneric(obj, name, value); | 5036 AddCheckConstantFunction(holder, object, map, true); |
5036 } | 5037 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)); | 5038 AddInstruction(new(zone()) HPushArgument(value)); |
5042 return new(zone()) HCallConstantFunction(function, 2); | 5039 return new(zone()) HCallConstantFunction(setter, 2); |
5043 } | 5040 } |
5044 | 5041 |
5045 | 5042 |
5046 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, | 5043 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, |
5044 Handle<String> name, | |
5047 HValue* value, | 5045 HValue* value, |
5048 Handle<Map> type, | 5046 Handle<Map> map) { |
5049 Expression* key) { | |
5050 // If we don't know the monomorphic type, do a generic store. | 5047 // If we don't know the monomorphic type, do a generic store. |
5051 Handle<String> name = Handle<String>::cast(key->AsLiteral()->handle()); | 5048 if (map.is_null()) return BuildStoreNamedGeneric(object, name, value); |
5052 if (type.is_null()) return BuildStoreNamedGeneric(object, name, value); | |
5053 | 5049 |
5054 // Handle a store to a known field. | 5050 // Handle a store to a known field. |
5055 LookupResult lookup(isolate()); | 5051 LookupResult lookup(isolate()); |
5056 if (ComputeLoadStoreField(type, name, &lookup, true)) { | 5052 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
5057 // true = needs smi and map check. | 5053 // true = needs smi and map check. |
5058 return BuildStoreNamedField(object, name, value, type, &lookup, true); | 5054 return BuildStoreNamedField(object, name, value, map, &lookup, true); |
5059 } | 5055 } |
5060 | 5056 |
5061 // Handle a known setter directly in the receiver. | 5057 // Handle a known setter directly in the receiver. |
5062 type->LookupDescriptor(NULL, *name, &lookup); | 5058 map->LookupDescriptor(NULL, *name, &lookup); |
5063 if (lookup.IsPropertyCallbacks()) { | 5059 if (lookup.IsPropertyCallbacks()) { |
5064 Handle<Object> callback(lookup.GetValueFromMap(*type)); | 5060 Handle<Object> callback(lookup.GetValueFromMap(*map)); |
5065 Handle<JSObject> holder; | 5061 Handle<JSObject> holder; |
5066 return BuildCallSetter(object, name, value, type, callback, holder); | 5062 if (!callback->IsAccessorPair()) { |
5063 return BuildStoreNamedGeneric(object, name, value); | |
5064 } | |
5065 Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(callback); | |
5066 return BuildCallSetter(object, value, map, accessors, holder); | |
5067 } | 5067 } |
5068 | 5068 |
5069 // Handle a known setter somewhere in the prototype chain. | 5069 // Handle a known setter somewhere in the prototype chain. |
5070 LookupInPrototypes(type, name, &lookup); | 5070 LookupInPrototypes(map, name, &lookup); |
5071 if (lookup.IsPropertyCallbacks()) { | 5071 if (lookup.IsPropertyCallbacks()) { |
5072 Handle<Object> callback(lookup.GetValue()); | 5072 Handle<Object> callback(lookup.GetValue()); |
5073 Handle<JSObject> holder(lookup.holder()); | 5073 Handle<JSObject> holder(lookup.holder()); |
5074 return BuildCallSetter(object, name, value, type, callback, holder); | 5074 if (!callback->IsAccessorPair()) { |
5075 return BuildStoreNamedGeneric(object, name, value); | |
5076 } | |
5077 Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(callback); | |
5078 return BuildCallSetter(object, value, map, accessors, holder); | |
5075 } | 5079 } |
5076 | 5080 |
5077 // No luck, do a generic store. | 5081 // No luck, do a generic store. |
5078 return BuildStoreNamedGeneric(object, name, value); | 5082 return BuildStoreNamedGeneric(object, name, value); |
5079 } | 5083 } |
5080 | 5084 |
5081 | 5085 |
5082 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, | 5086 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
5083 HValue* object, | 5087 HValue* object, |
5084 SmallMapList* types, | 5088 SmallMapList* types, |
(...skipping 26 matching lines...) Expand all Loading... | |
5111 } | 5115 } |
5112 ++count; | 5116 ++count; |
5113 } | 5117 } |
5114 } | 5118 } |
5115 | 5119 |
5116 // Use monomorphic load if property lookup results in the same field index | 5120 // 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. | 5121 // for all maps. Requires special map check on the set of all handled maps. |
5118 HInstruction* instr; | 5122 HInstruction* instr; |
5119 if (count == types->length() && is_monomorphic_field) { | 5123 if (count == types->length() && is_monomorphic_field) { |
5120 AddInstruction(new(zone()) HCheckMaps(object, types, zone())); | 5124 AddInstruction(new(zone()) HCheckMaps(object, types, zone())); |
5121 instr = BuildLoadNamedField(object, expr, map, &lookup, false); | 5125 instr = BuildLoadNamedField(object, map, &lookup, false); |
5122 } else { | 5126 } else { |
5123 HValue* context = environment()->LookupContext(); | 5127 HValue* context = environment()->LookupContext(); |
5124 instr = new(zone()) HLoadNamedFieldPolymorphic(context, | 5128 instr = new(zone()) HLoadNamedFieldPolymorphic(context, |
5125 object, | 5129 object, |
5126 types, | 5130 types, |
5127 name, | 5131 name, |
5128 zone()); | 5132 zone()); |
5129 } | 5133 } |
5130 | 5134 |
5131 instr->set_position(expr->position()); | 5135 instr->set_position(expr->position()); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5224 value = Pop(); | 5228 value = Pop(); |
5225 HValue* object = Pop(); | 5229 HValue* object = Pop(); |
5226 | 5230 |
5227 Literal* key = prop->key()->AsLiteral(); | 5231 Literal* key = prop->key()->AsLiteral(); |
5228 Handle<String> name = Handle<String>::cast(key->handle()); | 5232 Handle<String> name = Handle<String>::cast(key->handle()); |
5229 ASSERT(!name.is_null()); | 5233 ASSERT(!name.is_null()); |
5230 | 5234 |
5231 SmallMapList* types = expr->GetReceiverTypes(); | 5235 SmallMapList* types = expr->GetReceiverTypes(); |
5232 if (expr->IsMonomorphic()) { | 5236 if (expr->IsMonomorphic()) { |
5233 CHECK_ALIVE(instr = BuildStoreNamed(object, | 5237 CHECK_ALIVE(instr = BuildStoreNamed(object, |
5238 name, | |
5234 value, | 5239 value, |
5235 types->first(), | 5240 types->first())); |
5236 prop->key())); | |
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 load = BuildLoadNamed(object, name, prop, map); |
5402 } else { | 5406 } else { |
5403 load = BuildLoadNamedGeneric(obj, prop); | 5407 load = BuildLoadNamedGeneric(object, name, prop); |
5404 } | 5408 } |
5405 PushAndAdd(load); | 5409 PushAndAdd(load); |
5406 if (load->HasObservableSideEffects()) AddSimulate(expr->CompoundLoadId()); | 5410 if (load->HasObservableSideEffects()) AddSimulate(expr->CompoundLoadId()); |
5407 | 5411 |
5408 CHECK_ALIVE(VisitForValue(expr->value())); | 5412 CHECK_ALIVE(VisitForValue(expr->value())); |
5409 HValue* right = Pop(); | 5413 HValue* right = Pop(); |
5410 HValue* left = Pop(); | 5414 HValue* left = Pop(); |
5411 | 5415 |
5412 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5416 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
5413 PushAndAdd(instr); | 5417 PushAndAdd(instr); |
5414 if (instr->HasObservableSideEffects()) AddSimulate(operation->id()); | 5418 if (instr->HasObservableSideEffects()) AddSimulate(operation->id()); |
5415 | 5419 |
5416 HInstruction* store; | 5420 HInstruction* store; |
5417 CHECK_ALIVE(store = BuildStoreNamed(obj, instr, map, prop->key())); | 5421 CHECK_ALIVE(store = BuildStoreNamed(object, name, instr, map)); |
5418 AddInstruction(store); | 5422 AddInstruction(store); |
5419 // Drop the simulated receiver and value. Return the value. | 5423 // Drop the simulated receiver and value. Return the value. |
5420 Drop(2); | 5424 Drop(2); |
5421 Push(instr); | 5425 Push(instr); |
5422 if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); | 5426 if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); |
5423 return ast_context()->ReturnValue(Pop()); | 5427 return ast_context()->ReturnValue(Pop()); |
5424 | 5428 |
5425 } else { | 5429 } else { |
5426 // Keyed property. | 5430 // Keyed property. |
5427 CHECK_ALIVE(VisitForValue(prop->obj())); | 5431 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); | 5612 HThrow* instr = new(zone()) HThrow(context, value); |
5609 instr->set_position(expr->position()); | 5613 instr->set_position(expr->position()); |
5610 AddInstruction(instr); | 5614 AddInstruction(instr); |
5611 AddSimulate(expr->id()); | 5615 AddSimulate(expr->id()); |
5612 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5616 current_block()->FinishExit(new(zone()) HAbnormalExit); |
5613 set_current_block(NULL); | 5617 set_current_block(NULL); |
5614 } | 5618 } |
5615 | 5619 |
5616 | 5620 |
5617 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, | 5621 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
5618 Property* expr, | 5622 Handle<Map> map, |
5619 Handle<Map> type, | |
5620 LookupResult* lookup, | 5623 LookupResult* lookup, |
5621 bool smi_and_map_check) { | 5624 bool smi_and_map_check) { |
5622 if (smi_and_map_check) { | 5625 if (smi_and_map_check) { |
5623 AddInstruction(new(zone()) HCheckNonSmi(object)); | 5626 AddInstruction(new(zone()) HCheckNonSmi(object)); |
5624 AddInstruction(HCheckMaps::NewWithTransitions(object, type, zone())); | 5627 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
5625 } | 5628 } |
5626 | 5629 |
5627 int index = lookup->GetLocalFieldIndexFromMap(*type); | 5630 int index = lookup->GetLocalFieldIndexFromMap(*map); |
5628 if (index < 0) { | 5631 if (index < 0) { |
5629 // Negative property indices are in-object properties, indexed | 5632 // Negative property indices are in-object properties, indexed |
5630 // from the end of the fixed part of the object. | 5633 // from the end of the fixed part of the object. |
5631 int offset = (index * kPointerSize) + type->instance_size(); | 5634 int offset = (index * kPointerSize) + map->instance_size(); |
5632 return new(zone()) HLoadNamedField(object, true, offset); | 5635 return new(zone()) HLoadNamedField(object, true, offset); |
5633 } else { | 5636 } else { |
5634 // Non-negative property indices are in the properties array. | 5637 // Non-negative property indices are in the properties array. |
5635 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; | 5638 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; |
5636 return new(zone()) HLoadNamedField(object, false, offset); | 5639 return new(zone()) HLoadNamedField(object, false, offset); |
5637 } | 5640 } |
5638 } | 5641 } |
5639 | 5642 |
5640 | 5643 |
5641 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj, | 5644 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj, |
5645 Handle<String> name, | |
5642 Property* expr) { | 5646 Property* expr) { |
5643 if (expr->IsUninitialized() && !FLAG_always_opt) { | 5647 if (expr->IsUninitialized() && !FLAG_always_opt) { |
5644 AddInstruction(new(zone()) HSoftDeoptimize); | 5648 AddInstruction(new(zone()) HSoftDeoptimize); |
5645 current_block()->MarkAsDeoptimizing(); | 5649 current_block()->MarkAsDeoptimizing(); |
5646 } | 5650 } |
5647 ASSERT(expr->key()->IsPropertyName()); | |
5648 Handle<Object> name = expr->key()->AsLiteral()->handle(); | |
5649 HValue* context = environment()->LookupContext(); | 5651 HValue* context = environment()->LookupContext(); |
5650 return new(zone()) HLoadNamedGeneric(context, obj, name); | 5652 return new(zone()) HLoadNamedGeneric(context, obj, name); |
5651 } | 5653 } |
5652 | 5654 |
5653 | 5655 |
5654 HInstruction* HGraphBuilder::BuildCallGetter(HValue* obj, | 5656 HInstruction* HGraphBuilder::BuildCallGetter(HValue* object, |
5655 Property* expr, | |
5656 Handle<Map> map, | 5657 Handle<Map> map, |
5657 Handle<Object> callback, | 5658 Handle<AccessorPair> accessors, |
5658 Handle<JSObject> holder) { | 5659 Handle<JSObject> holder) { |
5659 if (!callback->IsAccessorPair()) return BuildLoadNamedGeneric(obj, expr); | 5660 Handle<JSFunction> getter(JSFunction::cast(accessors->getter())); |
5660 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter()); | 5661 AddCheckConstantFunction(holder, object, map, true); |
5661 Handle<JSFunction> function(Handle<JSFunction>::cast(getter)); | 5662 AddInstruction(new(zone()) HPushArgument(object)); |
5662 AddCheckConstantFunction(holder, obj, map, true); | 5663 return new(zone()) HCallConstantFunction(getter, 1); |
5663 AddInstruction(new(zone()) HPushArgument(obj)); | |
5664 return new(zone()) HCallConstantFunction(function, 1); | |
5665 } | 5664 } |
5666 | 5665 |
5667 | 5666 |
5668 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj, | 5667 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* object, |
5668 Handle<String> name, | |
5669 Property* expr, | 5669 Property* expr, |
5670 Handle<Map> map, | 5670 Handle<Map> map) { |
5671 Handle<String> name) { | |
5672 LookupResult lookup(isolate()); | 5671 LookupResult lookup(isolate()); |
5673 map->LookupDescriptor(NULL, *name, &lookup); | 5672 map->LookupDescriptor(NULL, *name, &lookup); |
5674 if (lookup.IsField()) { | 5673 if (lookup.IsField()) { |
5675 return BuildLoadNamedField(obj, | 5674 return BuildLoadNamedField(object, map, &lookup, true); |
5676 expr, | |
5677 map, | |
5678 &lookup, | |
5679 true); | |
5680 } else if (lookup.IsConstantFunction()) { | 5675 } else if (lookup.IsConstantFunction()) { |
5681 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 5676 AddInstruction(new(zone()) HCheckNonSmi(object)); |
5682 AddInstruction(HCheckMaps::NewWithTransitions(obj, map, zone())); | 5677 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
5683 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); | 5678 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); |
5684 return new(zone()) HConstant(function, Representation::Tagged()); | 5679 return new(zone()) HConstant(function, Representation::Tagged()); |
5685 } else if (lookup.IsPropertyCallbacks()) { | 5680 } else if (lookup.IsPropertyCallbacks()) { |
5686 Handle<Object> callback(lookup.GetValueFromMap(*map)); | 5681 Handle<Object> callback(lookup.GetValueFromMap(*map)); |
5687 Handle<JSObject> holder; | 5682 Handle<JSObject> holder; |
5688 return BuildCallGetter(obj, expr, map, callback, holder); | 5683 if (!callback->IsAccessorPair()) { |
5684 return BuildLoadNamedGeneric(object, name, expr); | |
5685 } | |
5686 Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(callback); | |
5687 return BuildCallGetter(object, map, accessors, holder); | |
5689 } else { | 5688 } else { |
5690 LookupInPrototypes(map, name, &lookup); | 5689 LookupInPrototypes(map, name, &lookup); |
5691 if (lookup.IsPropertyCallbacks()) { | 5690 if (lookup.IsPropertyCallbacks()) { |
5692 Handle<Object> callback(lookup.GetValue()); | 5691 Handle<Object> callback(lookup.GetValue()); |
5693 Handle<JSObject> holder(lookup.holder()); | 5692 Handle<JSObject> holder(lookup.holder()); |
5694 return BuildCallGetter(obj, expr, map, callback, holder); | 5693 if (!callback->IsAccessorPair()) { |
5694 return BuildLoadNamedGeneric(object, name, expr); | |
5695 } | |
5696 Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(callback); | |
5697 return BuildCallGetter(object, map, accessors, holder); | |
5695 } | 5698 } |
5696 return BuildLoadNamedGeneric(obj, expr); | 5699 return BuildLoadNamedGeneric(object, name, expr); |
5697 } | 5700 } |
5698 } | 5701 } |
5699 | 5702 |
5700 | 5703 |
5701 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 5704 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
5702 HValue* key) { | 5705 HValue* key) { |
5703 HValue* context = environment()->LookupContext(); | 5706 HValue* context = environment()->LookupContext(); |
5704 return new(zone()) HLoadKeyedGeneric(context, object, key); | 5707 return new(zone()) HLoadKeyedGeneric(context, object, key); |
5705 } | 5708 } |
5706 | 5709 |
(...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6306 HValue* function = Pop(); | 6309 HValue* function = Pop(); |
6307 AddInstruction(new(zone()) HCheckNonSmi(function)); | 6310 AddInstruction(new(zone()) HCheckNonSmi(function)); |
6308 instr = new(zone()) HLoadFunctionPrototype(function); | 6311 instr = new(zone()) HLoadFunctionPrototype(function); |
6309 | 6312 |
6310 } else if (expr->key()->IsPropertyName()) { | 6313 } else if (expr->key()->IsPropertyName()) { |
6311 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 6314 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
6312 SmallMapList* types = expr->GetReceiverTypes(); | 6315 SmallMapList* types = expr->GetReceiverTypes(); |
6313 | 6316 |
6314 HValue* obj = Pop(); | 6317 HValue* obj = Pop(); |
6315 if (expr->IsMonomorphic()) { | 6318 if (expr->IsMonomorphic()) { |
6316 instr = BuildLoadNamed(obj, expr, types->first(), name); | 6319 instr = BuildLoadNamed(obj, name, expr, types->first()); |
6317 } else if (types != NULL && types->length() > 1) { | 6320 } else if (types != NULL && types->length() > 1) { |
6318 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 6321 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
6319 HandlePolymorphicLoadNamedField(expr, obj, types, name); | 6322 HandlePolymorphicLoadNamedField(expr, obj, types, name); |
6320 return; | 6323 return; |
6321 } else { | 6324 } else { |
6322 instr = BuildLoadNamedGeneric(obj, expr); | 6325 instr = BuildLoadNamedGeneric(obj, name, expr); |
6323 } | 6326 } |
6324 | 6327 |
6325 } else { | 6328 } else { |
6326 CHECK_ALIVE(VisitForValue(expr->key())); | 6329 CHECK_ALIVE(VisitForValue(expr->key())); |
6327 | 6330 |
6328 HValue* key = Pop(); | 6331 HValue* key = Pop(); |
6329 HValue* obj = Pop(); | 6332 HValue* obj = Pop(); |
6330 | 6333 |
6331 bool has_side_effects = false; | 6334 bool has_side_effects = false; |
6332 HValue* load = HandleKeyedElementAccess( | 6335 HValue* load = HandleKeyedElementAccess( |
(...skipping 1458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7791 ASSERT(prop != NULL); | 7794 ASSERT(prop != NULL); |
7792 prop->RecordTypeFeedback(oracle(), zone()); | 7795 prop->RecordTypeFeedback(oracle(), zone()); |
7793 | 7796 |
7794 if (prop->key()->IsPropertyName()) { | 7797 if (prop->key()->IsPropertyName()) { |
7795 // Named property. | 7798 // Named property. |
7796 if (returns_original_input) Push(graph_->GetConstantUndefined()); | 7799 if (returns_original_input) Push(graph_->GetConstantUndefined()); |
7797 | 7800 |
7798 CHECK_ALIVE(VisitForValue(prop->obj())); | 7801 CHECK_ALIVE(VisitForValue(prop->obj())); |
7799 HValue* obj = Top(); | 7802 HValue* obj = Top(); |
7800 | 7803 |
7804 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | |
7801 Handle<Map> map; | 7805 Handle<Map> map; |
7802 HInstruction* load; | 7806 HInstruction* load; |
7803 if (prop->IsMonomorphic()) { | 7807 if (prop->IsMonomorphic()) { |
7804 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | |
7805 map = prop->GetReceiverTypes()->first(); | 7808 map = prop->GetReceiverTypes()->first(); |
7806 load = BuildLoadNamed(obj, prop, map, name); | 7809 load = BuildLoadNamed(obj, name, prop, map); |
7807 } else { | 7810 } else { |
7808 load = BuildLoadNamedGeneric(obj, prop); | 7811 load = BuildLoadNamedGeneric(obj, name, prop); |
7809 } | 7812 } |
7810 PushAndAdd(load); | 7813 PushAndAdd(load); |
7811 if (load->HasObservableSideEffects()) AddSimulate(expr->CountId()); | 7814 if (load->HasObservableSideEffects()) AddSimulate(expr->CountId()); |
7812 | 7815 |
7813 after = BuildIncrement(returns_original_input, expr); | 7816 after = BuildIncrement(returns_original_input, expr); |
7814 input = Pop(); | 7817 input = Pop(); |
7815 | 7818 |
7816 HInstruction* store; | 7819 HInstruction* store; |
7817 CHECK_ALIVE(store = BuildStoreNamed(obj, after, map, prop->key())); | 7820 CHECK_ALIVE(store = BuildStoreNamed(obj, name, after, map)); |
7818 AddInstruction(store); | 7821 AddInstruction(store); |
7819 | 7822 |
7820 // Overwrite the receiver in the bailout environment with the result | 7823 // Overwrite the receiver in the bailout environment with the result |
7821 // of the operation, and the placeholder with the original value if | 7824 // of the operation, and the placeholder with the original value if |
7822 // necessary. | 7825 // necessary. |
7823 environment()->SetExpressionStackAt(0, after); | 7826 environment()->SetExpressionStackAt(0, after); |
7824 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | 7827 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
7825 if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); | 7828 if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); |
7826 | 7829 |
7827 } else { | 7830 } else { |
(...skipping 1755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9583 } | 9586 } |
9584 } | 9587 } |
9585 | 9588 |
9586 #ifdef DEBUG | 9589 #ifdef DEBUG |
9587 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 9590 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
9588 if (allocator_ != NULL) allocator_->Verify(); | 9591 if (allocator_ != NULL) allocator_->Verify(); |
9589 #endif | 9592 #endif |
9590 } | 9593 } |
9591 | 9594 |
9592 } } // namespace v8::internal | 9595 } } // namespace v8::internal |
OLD | NEW |