Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: src/hydrogen.cc

Issue 10801013: Preparatory refactoring-only steps for inlining accessors. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698