| 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 |