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 4928 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4939 } | 4939 } |
4940 return ast_context()->ReturnValue(Pop()); | 4940 return ast_context()->ReturnValue(Pop()); |
4941 } | 4941 } |
4942 | 4942 |
4943 | 4943 |
4944 // Sets the lookup result and returns true if the load/store can be inlined. | 4944 // Sets the lookup result and returns true if the load/store can be inlined. |
4945 static bool ComputeLoadStoreField(Handle<Map> type, | 4945 static bool ComputeLoadStoreField(Handle<Map> type, |
4946 Handle<String> name, | 4946 Handle<String> name, |
4947 LookupResult* lookup, | 4947 LookupResult* lookup, |
4948 bool is_store) { | 4948 bool is_store) { |
4949 type->LookupTransitionOrDescriptor(NULL, *name, lookup); | 4949 // If we directly find a field, the access can be inlined. |
| 4950 type->LookupDescriptor(NULL, *name, lookup); |
4950 if (lookup->IsField()) return true; | 4951 if (lookup->IsField()) return true; |
4951 return is_store && | 4952 |
4952 lookup->IsTransitionToField(*type) && | 4953 // For a load, we are out of luck if there is no such field. |
4953 (type->unused_property_fields() > 0); | 4954 if (!is_store) return false; |
| 4955 |
| 4956 // 2nd chance: A store into a non-existent field can still be inlined if we |
| 4957 // have a matching transition and some room left in the object. |
| 4958 type->LookupTransition(NULL, *name, lookup); |
| 4959 return lookup->IsTransitionToField(*type) && |
| 4960 (type->unused_property_fields() > 0); |
4954 } | 4961 } |
4955 | 4962 |
4956 | 4963 |
4957 static int ComputeLoadStoreFieldIndex(Handle<Map> type, | 4964 static int ComputeLoadStoreFieldIndex(Handle<Map> type, |
4958 Handle<String> name, | 4965 Handle<String> name, |
4959 LookupResult* lookup) { | 4966 LookupResult* lookup) { |
4960 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type)); | 4967 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type)); |
4961 if (lookup->IsField()) { | 4968 if (lookup->IsField()) { |
4962 return lookup->GetLocalFieldIndexFromMap(*type); | 4969 return lookup->GetLocalFieldIndexFromMap(*type); |
4963 } else { | 4970 } else { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5035 HValue* context = environment()->LookupContext(); | 5042 HValue* context = environment()->LookupContext(); |
5036 return new(zone()) HStoreNamedGeneric( | 5043 return new(zone()) HStoreNamedGeneric( |
5037 context, | 5044 context, |
5038 object, | 5045 object, |
5039 name, | 5046 name, |
5040 value, | 5047 value, |
5041 function_strict_mode_flag()); | 5048 function_strict_mode_flag()); |
5042 } | 5049 } |
5043 | 5050 |
5044 | 5051 |
| 5052 static void LookupInPrototypes(Handle<Map> map, |
| 5053 Handle<String> name, |
| 5054 LookupResult* lookup) { |
| 5055 while (map->prototype()->IsJSObject()) { |
| 5056 Handle<JSObject> holder(JSObject::cast(map->prototype())); |
| 5057 if (!holder->HasFastProperties()) break; |
| 5058 map = Handle<Map>(holder->map()); |
| 5059 map->LookupDescriptor(*holder, *name, lookup); |
| 5060 if (lookup->IsFound()) return; |
| 5061 } |
| 5062 lookup->NotFound(); |
| 5063 } |
| 5064 |
| 5065 |
| 5066 HInstruction* HGraphBuilder::BuildCallSetter(HValue* obj, |
| 5067 Handle<String> name, |
| 5068 HValue* value, |
| 5069 Handle<Map> map, |
| 5070 Handle<Object> callback, |
| 5071 Handle<JSObject> holder) { |
| 5072 if (!callback->IsAccessorPair()) { |
| 5073 return BuildStoreNamedGeneric(obj, name, value); |
| 5074 } |
| 5075 Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter()); |
| 5076 Handle<JSFunction> function(Handle<JSFunction>::cast(setter)); |
| 5077 AddCheckConstantFunction(holder, obj, map, true); |
| 5078 AddInstruction(new(zone()) HPushArgument(obj)); |
| 5079 AddInstruction(new(zone()) HPushArgument(value)); |
| 5080 return new(zone()) HCallConstantFunction(function, 2); |
| 5081 } |
| 5082 |
| 5083 |
5045 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, | 5084 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, |
5046 HValue* value, | 5085 HValue* value, |
5047 Handle<Map> type, | 5086 Handle<Map> type, |
5048 Expression* key) { | 5087 Expression* key) { |
| 5088 // If we don't know the monomorphic type, do a generic store. |
5049 Handle<String> name = Handle<String>::cast(key->AsLiteral()->handle()); | 5089 Handle<String> name = Handle<String>::cast(key->AsLiteral()->handle()); |
5050 ASSERT(!name.is_null()); | 5090 if (type.is_null()) return BuildStoreNamedGeneric(object, name, value); |
5051 | 5091 |
| 5092 // Handle a store to a known field. |
5052 LookupResult lookup(isolate()); | 5093 LookupResult lookup(isolate()); |
5053 bool is_monomorphic = !type.is_null() && | 5094 if (ComputeLoadStoreField(type, name, &lookup, true)) { |
5054 ComputeLoadStoreField(type, name, &lookup, true); | 5095 // true = needs smi and map check. |
| 5096 return BuildStoreNamedField(object, name, value, type, &lookup, true); |
| 5097 } |
5055 | 5098 |
5056 return is_monomorphic | 5099 // Handle a known setter directly in the receiver. |
5057 ? BuildStoreNamedField(object, name, value, type, &lookup, | 5100 type->LookupDescriptor(NULL, *name, &lookup); |
5058 true) // Needs smi and map check. | 5101 if (lookup.IsPropertyCallbacks()) { |
5059 : BuildStoreNamedGeneric(object, name, value); | 5102 Handle<Object> callback(lookup.GetValueFromMap(*type)); |
| 5103 Handle<JSObject> holder; |
| 5104 return BuildCallSetter(object, name, value, type, callback, holder); |
| 5105 } |
| 5106 |
| 5107 // Handle a known setter somewhere in the prototype chain. |
| 5108 LookupInPrototypes(type, name, &lookup); |
| 5109 if (lookup.IsPropertyCallbacks()) { |
| 5110 Handle<Object> callback(lookup.GetValue()); |
| 5111 Handle<JSObject> holder(lookup.holder()); |
| 5112 return BuildCallSetter(object, name, value, type, callback, holder); |
| 5113 } |
| 5114 |
| 5115 // No luck, do a generic store. |
| 5116 return BuildStoreNamedGeneric(object, name, value); |
5060 } | 5117 } |
5061 | 5118 |
5062 | 5119 |
5063 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, | 5120 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
5064 HValue* object, | 5121 HValue* object, |
5065 SmallMapList* types, | 5122 SmallMapList* types, |
5066 Handle<String> name) { | 5123 Handle<String> name) { |
5067 int count = 0; | 5124 int count = 0; |
5068 int previous_field_offset = 0; | 5125 int previous_field_offset = 0; |
5069 bool previous_field_is_in_object = false; | 5126 bool previous_field_is_in_object = false; |
(...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5625 AddInstruction(new(zone()) HSoftDeoptimize); | 5682 AddInstruction(new(zone()) HSoftDeoptimize); |
5626 current_block()->MarkAsDeoptimizing(); | 5683 current_block()->MarkAsDeoptimizing(); |
5627 } | 5684 } |
5628 ASSERT(expr->key()->IsPropertyName()); | 5685 ASSERT(expr->key()->IsPropertyName()); |
5629 Handle<Object> name = expr->key()->AsLiteral()->handle(); | 5686 Handle<Object> name = expr->key()->AsLiteral()->handle(); |
5630 HValue* context = environment()->LookupContext(); | 5687 HValue* context = environment()->LookupContext(); |
5631 return new(zone()) HLoadNamedGeneric(context, obj, name); | 5688 return new(zone()) HLoadNamedGeneric(context, obj, name); |
5632 } | 5689 } |
5633 | 5690 |
5634 | 5691 |
5635 static void LookupInPrototypes(Handle<Map> map, | |
5636 Handle<String> name, | |
5637 LookupResult* lookup) { | |
5638 while (map->prototype()->IsJSObject()) { | |
5639 Handle<JSObject> holder(JSObject::cast(map->prototype())); | |
5640 if (!holder->HasFastProperties()) break; | |
5641 map = Handle<Map>(holder->map()); | |
5642 map->LookupDescriptor(*holder, *name, lookup); | |
5643 if (lookup->IsFound()) return; | |
5644 } | |
5645 lookup->NotFound(); | |
5646 } | |
5647 | |
5648 | |
5649 HInstruction* HGraphBuilder::BuildCallGetter(HValue* obj, | 5692 HInstruction* HGraphBuilder::BuildCallGetter(HValue* obj, |
5650 Property* expr, | 5693 Property* expr, |
5651 Handle<Map> map, | 5694 Handle<Map> map, |
5652 Handle<Object> callback, | 5695 Handle<Object> callback, |
5653 Handle<JSObject> holder) { | 5696 Handle<JSObject> holder) { |
5654 if (!callback->IsAccessorPair()) return BuildLoadNamedGeneric(obj, expr); | 5697 if (!callback->IsAccessorPair()) return BuildLoadNamedGeneric(obj, expr); |
5655 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter()); | 5698 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter()); |
5656 Handle<JSFunction> function(Handle<JSFunction>::cast(getter)); | 5699 Handle<JSFunction> function(Handle<JSFunction>::cast(getter)); |
5657 AddCheckConstantFunction(holder, obj, map, true); | 5700 AddCheckConstantFunction(holder, obj, map, true); |
5658 AddInstruction(new(zone()) HPushArgument(obj)); | 5701 AddInstruction(new(zone()) HPushArgument(obj)); |
(...skipping 3908 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9567 } | 9610 } |
9568 } | 9611 } |
9569 | 9612 |
9570 #ifdef DEBUG | 9613 #ifdef DEBUG |
9571 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 9614 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
9572 if (allocator_ != NULL) allocator_->Verify(); | 9615 if (allocator_ != NULL) allocator_->Verify(); |
9573 #endif | 9616 #endif |
9574 } | 9617 } |
9575 | 9618 |
9576 } } // namespace v8::internal | 9619 } } // namespace v8::internal |
OLD | NEW |