| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/hydrogen.h" | 5 #include "src/hydrogen.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "src/v8.h" | 9 #include "src/v8.h" |
| 10 | 10 |
| (...skipping 5584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5595 Handle<String> name = property->key()->AsPropertyName(); | 5595 Handle<String> name = property->key()->AsPropertyName(); |
| 5596 HInstruction* store; | 5596 HInstruction* store; |
| 5597 if (map.is_null()) { | 5597 if (map.is_null()) { |
| 5598 // If we don't know the monomorphic type, do a generic store. | 5598 // If we don't know the monomorphic type, do a generic store. |
| 5599 CHECK_ALIVE(store = BuildNamedGeneric( | 5599 CHECK_ALIVE(store = BuildNamedGeneric( |
| 5600 STORE, NULL, literal, name, value)); | 5600 STORE, NULL, literal, name, value)); |
| 5601 } else { | 5601 } else { |
| 5602 PropertyAccessInfo info(this, STORE, ToType(map), name); | 5602 PropertyAccessInfo info(this, STORE, ToType(map), name); |
| 5603 if (info.CanAccessMonomorphic()) { | 5603 if (info.CanAccessMonomorphic()) { |
| 5604 HValue* checked_literal = Add<HCheckMaps>(literal, map); | 5604 HValue* checked_literal = Add<HCheckMaps>(literal, map); |
| 5605 DCHECK(!info.lookup()->IsPropertyCallbacks()); | 5605 DCHECK(!info.IsAccessor()); |
| 5606 store = BuildMonomorphicAccess( | 5606 store = BuildMonomorphicAccess( |
| 5607 &info, literal, checked_literal, value, | 5607 &info, literal, checked_literal, value, |
| 5608 BailoutId::None(), BailoutId::None()); | 5608 BailoutId::None(), BailoutId::None()); |
| 5609 } else { | 5609 } else { |
| 5610 CHECK_ALIVE(store = BuildNamedGeneric( | 5610 CHECK_ALIVE(store = BuildNamedGeneric( |
| 5611 STORE, NULL, literal, name, value)); | 5611 STORE, NULL, literal, name, value)); |
| 5612 } | 5612 } |
| 5613 } | 5613 } |
| 5614 AddInstruction(store); | 5614 AddInstruction(store); |
| 5615 if (store->HasObservableSideEffects()) { | 5615 if (store->HasObservableSideEffects()) { |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5782 Handle<Map> map) { | 5782 Handle<Map> map) { |
| 5783 BuildCheckHeapObject(object); | 5783 BuildCheckHeapObject(object); |
| 5784 return Add<HCheckMaps>(object, map); | 5784 return Add<HCheckMaps>(object, map); |
| 5785 } | 5785 } |
| 5786 | 5786 |
| 5787 | 5787 |
| 5788 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField( | 5788 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField( |
| 5789 PropertyAccessInfo* info, | 5789 PropertyAccessInfo* info, |
| 5790 HValue* checked_object) { | 5790 HValue* checked_object) { |
| 5791 // See if this is a load for an immutable property | 5791 // See if this is a load for an immutable property |
| 5792 if (checked_object->ActualValue()->IsConstant() && | 5792 if (checked_object->ActualValue()->IsConstant() && info->IsCacheable() && |
| 5793 info->lookup()->IsCacheable() && | 5793 info->IsReadOnly() && !info->IsConfigurable()) { |
| 5794 info->lookup()->IsReadOnly() && info->lookup()->IsDontDelete()) { | |
| 5795 Handle<Object> object( | 5794 Handle<Object> object( |
| 5796 HConstant::cast(checked_object->ActualValue())->handle(isolate())); | 5795 HConstant::cast(checked_object->ActualValue())->handle(isolate())); |
| 5797 | 5796 |
| 5798 if (object->IsJSObject()) { | 5797 if (object->IsJSObject()) { |
| 5799 LookupIterator it(object, info->name(), LookupIterator::CHECK_PROPERTY); | 5798 LookupIterator it(object, info->name(), LookupIterator::CHECK_PROPERTY); |
| 5800 Handle<Object> value = JSObject::GetDataProperty(&it); | 5799 Handle<Object> value = JSObject::GetDataProperty(&it); |
| 5801 CHECK(it.IsFound()); | 5800 CHECK(it.IsFound()); |
| 5802 return New<HConstant>(value); | 5801 return New<HConstant>(value); |
| 5803 } | 5802 } |
| 5804 } | 5803 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 5824 } | 5823 } |
| 5825 return New<HLoadNamedField>( | 5824 return New<HLoadNamedField>( |
| 5826 checked_object, checked_object, access, maps, info->field_type()); | 5825 checked_object, checked_object, access, maps, info->field_type()); |
| 5827 } | 5826 } |
| 5828 | 5827 |
| 5829 | 5828 |
| 5830 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( | 5829 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( |
| 5831 PropertyAccessInfo* info, | 5830 PropertyAccessInfo* info, |
| 5832 HValue* checked_object, | 5831 HValue* checked_object, |
| 5833 HValue* value) { | 5832 HValue* value) { |
| 5834 bool transition_to_field = info->lookup()->IsTransition(); | 5833 bool transition_to_field = info->IsTransition(); |
| 5835 // TODO(verwaest): Move this logic into PropertyAccessInfo. | 5834 // TODO(verwaest): Move this logic into PropertyAccessInfo. |
| 5836 HObjectAccess field_access = info->access(); | 5835 HObjectAccess field_access = info->access(); |
| 5837 | 5836 |
| 5838 HStoreNamedField *instr; | 5837 HStoreNamedField *instr; |
| 5839 if (field_access.representation().IsDouble()) { | 5838 if (field_access.representation().IsDouble()) { |
| 5840 HObjectAccess heap_number_access = | 5839 HObjectAccess heap_number_access = |
| 5841 field_access.WithRepresentation(Representation::Tagged()); | 5840 field_access.WithRepresentation(Representation::Tagged()); |
| 5842 if (transition_to_field) { | 5841 if (transition_to_field) { |
| 5843 // The store requires a mutable HeapNumber to be allocated. | 5842 // The store requires a mutable HeapNumber to be allocated. |
| 5844 NoObservableSideEffectsScope no_side_effects(this); | 5843 NoObservableSideEffectsScope no_side_effects(this); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5901 // Values are only compatible for monomorphic load if they all behave the same | 5900 // Values are only compatible for monomorphic load if they all behave the same |
| 5902 // regarding value wrappers. | 5901 // regarding value wrappers. |
| 5903 if (type_->Is(Type::NumberOrString())) { | 5902 if (type_->Is(Type::NumberOrString())) { |
| 5904 if (!info->type_->Is(Type::NumberOrString())) return false; | 5903 if (!info->type_->Is(Type::NumberOrString())) return false; |
| 5905 } else { | 5904 } else { |
| 5906 if (info->type_->Is(Type::NumberOrString())) return false; | 5905 if (info->type_->Is(Type::NumberOrString())) return false; |
| 5907 } | 5906 } |
| 5908 | 5907 |
| 5909 if (!LookupDescriptor()) return false; | 5908 if (!LookupDescriptor()) return false; |
| 5910 | 5909 |
| 5911 if (!lookup_.IsFound()) { | 5910 if (!IsFound()) { |
| 5912 return (!info->lookup_.IsFound() || info->has_holder()) && | 5911 return (!info->IsFound() || info->has_holder()) && |
| 5913 map()->prototype() == info->map()->prototype(); | 5912 map()->prototype() == info->map()->prototype(); |
| 5914 } | 5913 } |
| 5915 | 5914 |
| 5916 // Mismatch if the other access info found the property in the prototype | 5915 // Mismatch if the other access info found the property in the prototype |
| 5917 // chain. | 5916 // chain. |
| 5918 if (info->has_holder()) return false; | 5917 if (info->has_holder()) return false; |
| 5919 | 5918 |
| 5920 if (lookup_.IsPropertyCallbacks()) { | 5919 if (IsAccessor()) { |
| 5921 return accessor_.is_identical_to(info->accessor_) && | 5920 return accessor_.is_identical_to(info->accessor_) && |
| 5922 api_holder_.is_identical_to(info->api_holder_); | 5921 api_holder_.is_identical_to(info->api_holder_); |
| 5923 } | 5922 } |
| 5924 | 5923 |
| 5925 if (lookup_.IsConstant()) { | 5924 if (IsConstant()) { |
| 5926 return constant_.is_identical_to(info->constant_); | 5925 return constant_.is_identical_to(info->constant_); |
| 5927 } | 5926 } |
| 5928 | 5927 |
| 5929 DCHECK(lookup_.IsField()); | 5928 DCHECK(IsField()); |
| 5930 if (!info->lookup_.IsField()) return false; | 5929 if (!info->IsField()) return false; |
| 5931 | 5930 |
| 5932 Representation r = access_.representation(); | 5931 Representation r = access_.representation(); |
| 5933 if (IsLoad()) { | 5932 if (IsLoad()) { |
| 5934 if (!info->access_.representation().IsCompatibleForLoad(r)) return false; | 5933 if (!info->access_.representation().IsCompatibleForLoad(r)) return false; |
| 5935 } else { | 5934 } else { |
| 5936 if (!info->access_.representation().IsCompatibleForStore(r)) return false; | 5935 if (!info->access_.representation().IsCompatibleForStore(r)) return false; |
| 5937 } | 5936 } |
| 5938 if (info->access_.offset() != access_.offset()) return false; | 5937 if (info->access_.offset() != access_.offset()) return false; |
| 5939 if (info->access_.IsInobject() != access_.IsInobject()) return false; | 5938 if (info->access_.IsInobject() != access_.IsInobject()) return false; |
| 5940 if (IsLoad()) { | 5939 if (IsLoad()) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 5963 | 5962 |
| 5964 | 5963 |
| 5965 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() { | 5964 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() { |
| 5966 if (!type_->IsClass()) return true; | 5965 if (!type_->IsClass()) return true; |
| 5967 map()->LookupDescriptor(NULL, *name_, &lookup_); | 5966 map()->LookupDescriptor(NULL, *name_, &lookup_); |
| 5968 return LoadResult(map()); | 5967 return LoadResult(map()); |
| 5969 } | 5968 } |
| 5970 | 5969 |
| 5971 | 5970 |
| 5972 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { | 5971 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { |
| 5973 if (!IsLoad() && lookup_.IsProperty() && | 5972 if (!IsLoad() && IsProperty() && (IsReadOnly() || !IsCacheable())) { |
| 5974 (lookup_.IsReadOnly() || !lookup_.IsCacheable())) { | |
| 5975 return false; | 5973 return false; |
| 5976 } | 5974 } |
| 5977 | 5975 |
| 5978 if (lookup_.IsField()) { | 5976 if (IsField()) { |
| 5979 // Construct the object field access. | 5977 // Construct the object field access. |
| 5980 int index = lookup_.GetLocalFieldIndexFromMap(*map); | 5978 int index = GetLocalFieldIndexFromMap(map); |
| 5981 Representation representation = lookup_.representation(); | 5979 access_ = HObjectAccess::ForField(map, index, representation(), name_); |
| 5982 access_ = HObjectAccess::ForField(map, index, representation, name_); | |
| 5983 | 5980 |
| 5984 // Load field map for heap objects. | 5981 // Load field map for heap objects. |
| 5985 LoadFieldMaps(map); | 5982 LoadFieldMaps(map); |
| 5986 } else if (lookup_.IsPropertyCallbacks()) { | 5983 } else if (IsAccessor()) { |
| 5987 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate()); | 5984 Handle<Object> accessors = GetAccessorsFromMap(map); |
| 5988 if (!callback->IsAccessorPair()) return false; | 5985 if (!accessors->IsAccessorPair()) return false; |
| 5989 Object* raw_accessor = IsLoad() | 5986 Object* raw_accessor = |
| 5990 ? Handle<AccessorPair>::cast(callback)->getter() | 5987 IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter() |
| 5991 : Handle<AccessorPair>::cast(callback)->setter(); | 5988 : Handle<AccessorPair>::cast(accessors)->setter(); |
| 5992 if (!raw_accessor->IsJSFunction()) return false; | 5989 if (!raw_accessor->IsJSFunction()) return false; |
| 5993 Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor)); | 5990 Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor)); |
| 5994 if (accessor->shared()->IsApiFunction()) { | 5991 if (accessor->shared()->IsApiFunction()) { |
| 5995 CallOptimization call_optimization(accessor); | 5992 CallOptimization call_optimization(accessor); |
| 5996 if (call_optimization.is_simple_api_call()) { | 5993 if (call_optimization.is_simple_api_call()) { |
| 5997 CallOptimization::HolderLookup holder_lookup; | 5994 CallOptimization::HolderLookup holder_lookup; |
| 5998 Handle<Map> receiver_map = this->map(); | 5995 Handle<Map> receiver_map = this->map(); |
| 5999 api_holder_ = call_optimization.LookupHolderOfExpectedType( | 5996 api_holder_ = call_optimization.LookupHolderOfExpectedType( |
| 6000 receiver_map, &holder_lookup); | 5997 receiver_map, &holder_lookup); |
| 6001 } | 5998 } |
| 6002 } | 5999 } |
| 6003 accessor_ = accessor; | 6000 accessor_ = accessor; |
| 6004 } else if (lookup_.IsConstant()) { | 6001 } else if (IsConstant()) { |
| 6005 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate()); | 6002 constant_ = GetConstantFromMap(map); |
| 6006 } | 6003 } |
| 6007 | 6004 |
| 6008 return true; | 6005 return true; |
| 6009 } | 6006 } |
| 6010 | 6007 |
| 6011 | 6008 |
| 6012 void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps( | 6009 void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps( |
| 6013 Handle<Map> map) { | 6010 Handle<Map> map) { |
| 6014 // Clear any previously collected field maps/type. | 6011 // Clear any previously collected field maps/type. |
| 6015 field_maps_.Clear(); | 6012 field_maps_.Clear(); |
| 6016 field_type_ = HType::Tagged(); | 6013 field_type_ = HType::Tagged(); |
| 6017 | 6014 |
| 6018 // Figure out the field type from the accessor map. | 6015 // Figure out the field type from the accessor map. |
| 6019 Handle<HeapType> field_type(lookup_.GetFieldTypeFromMap(*map), isolate()); | 6016 Handle<HeapType> field_type = GetFieldTypeFromMap(map); |
| 6020 | 6017 |
| 6021 // Collect the (stable) maps from the field type. | 6018 // Collect the (stable) maps from the field type. |
| 6022 int num_field_maps = field_type->NumClasses(); | 6019 int num_field_maps = field_type->NumClasses(); |
| 6023 if (num_field_maps == 0) return; | 6020 if (num_field_maps == 0) return; |
| 6024 DCHECK(access_.representation().IsHeapObject()); | 6021 DCHECK(access_.representation().IsHeapObject()); |
| 6025 field_maps_.Reserve(num_field_maps, zone()); | 6022 field_maps_.Reserve(num_field_maps, zone()); |
| 6026 HeapType::Iterator<Map> it = field_type->Classes(); | 6023 HeapType::Iterator<Map> it = field_type->Classes(); |
| 6027 while (!it.Done()) { | 6024 while (!it.Done()) { |
| 6028 Handle<Map> field_map = it.Current(); | 6025 Handle<Map> field_map = it.Current(); |
| 6029 if (!field_map->is_stable()) { | 6026 if (!field_map->is_stable()) { |
| 6030 field_maps_.Clear(); | 6027 field_maps_.Clear(); |
| 6031 return; | 6028 return; |
| 6032 } | 6029 } |
| 6033 field_maps_.Add(field_map, zone()); | 6030 field_maps_.Add(field_map, zone()); |
| 6034 it.Advance(); | 6031 it.Advance(); |
| 6035 } | 6032 } |
| 6036 field_maps_.Sort(); | 6033 field_maps_.Sort(); |
| 6037 DCHECK_EQ(num_field_maps, field_maps_.length()); | 6034 DCHECK_EQ(num_field_maps, field_maps_.length()); |
| 6038 | 6035 |
| 6039 // Determine field HType from field HeapType. | 6036 // Determine field HType from field HeapType. |
| 6040 field_type_ = HType::FromType<HeapType>(field_type); | 6037 field_type_ = HType::FromType<HeapType>(field_type); |
| 6041 DCHECK(field_type_.IsHeapObject()); | 6038 DCHECK(field_type_.IsHeapObject()); |
| 6042 | 6039 |
| 6043 // Add dependency on the map that introduced the field. | 6040 // Add dependency on the map that introduced the field. |
| 6044 Map::AddDependentCompilationInfo( | 6041 Map::AddDependentCompilationInfo(GetFieldOwnerFromMap(map), |
| 6045 handle(lookup_.GetFieldOwnerFromMap(*map), isolate()), | 6042 DependentCode::kFieldTypeGroup, top_info()); |
| 6046 DependentCode::kFieldTypeGroup, top_info()); | |
| 6047 } | 6043 } |
| 6048 | 6044 |
| 6049 | 6045 |
| 6050 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { | 6046 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { |
| 6051 Handle<Map> map = this->map(); | 6047 Handle<Map> map = this->map(); |
| 6052 | 6048 |
| 6053 while (map->prototype()->IsJSObject()) { | 6049 while (map->prototype()->IsJSObject()) { |
| 6054 holder_ = handle(JSObject::cast(map->prototype())); | 6050 holder_ = handle(JSObject::cast(map->prototype())); |
| 6055 if (holder_->map()->is_deprecated()) { | 6051 if (holder_->map()->is_deprecated()) { |
| 6056 JSObject::TryMigrateInstance(holder_); | 6052 JSObject::TryMigrateInstance(holder_); |
| 6057 } | 6053 } |
| 6058 map = Handle<Map>(holder_->map()); | 6054 map = Handle<Map>(holder_->map()); |
| 6059 if (!CanInlinePropertyAccess(ToType(map))) { | 6055 if (!CanInlinePropertyAccess(ToType(map))) { |
| 6060 lookup_.NotFound(); | 6056 lookup_.NotFound(); |
| 6061 return false; | 6057 return false; |
| 6062 } | 6058 } |
| 6063 map->LookupDescriptor(*holder_, *name_, &lookup_); | 6059 map->LookupDescriptor(*holder_, *name_, &lookup_); |
| 6064 if (lookup_.IsFound()) return LoadResult(map); | 6060 if (IsFound()) return LoadResult(map); |
| 6065 } | 6061 } |
| 6066 lookup_.NotFound(); | 6062 lookup_.NotFound(); |
| 6067 return true; | 6063 return true; |
| 6068 } | 6064 } |
| 6069 | 6065 |
| 6070 | 6066 |
| 6071 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { | 6067 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { |
| 6072 if (!CanInlinePropertyAccess(type_)) return false; | 6068 if (!CanInlinePropertyAccess(type_)) return false; |
| 6073 if (IsJSObjectFieldAccessor()) return IsLoad(); | 6069 if (IsJSObjectFieldAccessor()) return IsLoad(); |
| 6074 if (this->map()->function_with_prototype() && | 6070 if (this->map()->function_with_prototype() && |
| 6075 !this->map()->has_non_instance_prototype() && | 6071 !this->map()->has_non_instance_prototype() && |
| 6076 name_.is_identical_to(isolate()->factory()->prototype_string())) { | 6072 name_.is_identical_to(isolate()->factory()->prototype_string())) { |
| 6077 return IsLoad(); | 6073 return IsLoad(); |
| 6078 } | 6074 } |
| 6079 if (!LookupDescriptor()) return false; | 6075 if (!LookupDescriptor()) return false; |
| 6080 if (lookup_.IsFound()) { | 6076 if (IsFound()) { |
| 6081 if (IsLoad()) return true; | 6077 if (IsLoad()) return true; |
| 6082 return !lookup_.IsReadOnly() && lookup_.IsCacheable(); | 6078 return !IsReadOnly() && IsCacheable(); |
| 6083 } | 6079 } |
| 6084 if (!LookupInPrototypes()) return false; | 6080 if (!LookupInPrototypes()) return false; |
| 6085 if (IsLoad()) return true; | 6081 if (IsLoad()) return true; |
| 6086 | 6082 |
| 6087 if (lookup_.IsPropertyCallbacks()) return true; | 6083 if (IsAccessor()) return true; |
| 6088 Handle<Map> map = this->map(); | 6084 Handle<Map> map = this->map(); |
| 6089 map->LookupTransition(NULL, *name_, &lookup_); | 6085 map->LookupTransition(NULL, *name_, &lookup_); |
| 6090 if (lookup_.IsTransitionToField() && map->unused_property_fields() > 0) { | 6086 if (lookup_.IsTransitionToField() && map->unused_property_fields() > 0) { |
| 6091 // Construct the object field access. | 6087 // Construct the object field access. |
| 6092 int descriptor = transition()->LastAdded(); | 6088 int descriptor = transition()->LastAdded(); |
| 6093 int index = | 6089 int index = |
| 6094 transition()->instance_descriptors()->GetFieldIndex(descriptor) - | 6090 transition()->instance_descriptors()->GetFieldIndex(descriptor) - |
| 6095 map->inobject_properties(); | 6091 map->inobject_properties(); |
| 6096 PropertyDetails details = | 6092 PropertyDetails details = |
| 6097 transition()->instance_descriptors()->GetDetails(descriptor); | 6093 transition()->instance_descriptors()->GetDetails(descriptor); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 6124 } | 6120 } |
| 6125 return true; | 6121 return true; |
| 6126 } | 6122 } |
| 6127 | 6123 |
| 6128 // Currently only handle Type::Number as a polymorphic case. | 6124 // Currently only handle Type::Number as a polymorphic case. |
| 6129 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber | 6125 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber |
| 6130 // instruction. | 6126 // instruction. |
| 6131 if (type_->Is(Type::Number())) return false; | 6127 if (type_->Is(Type::Number())) return false; |
| 6132 | 6128 |
| 6133 // Multiple maps cannot transition to the same target map. | 6129 // Multiple maps cannot transition to the same target map. |
| 6134 DCHECK(!IsLoad() || !lookup_.IsTransition()); | 6130 DCHECK(!IsLoad() || !IsTransition()); |
| 6135 if (lookup_.IsTransition() && types->length() > 1) return false; | 6131 if (IsTransition() && types->length() > 1) return false; |
| 6136 | 6132 |
| 6137 for (int i = 1; i < types->length(); ++i) { | 6133 for (int i = 1; i < types->length(); ++i) { |
| 6138 PropertyAccessInfo test_info( | 6134 PropertyAccessInfo test_info( |
| 6139 builder_, access_type_, ToType(types->at(i)), name_); | 6135 builder_, access_type_, ToType(types->at(i)), name_); |
| 6140 if (!test_info.IsCompatible(this)) return false; | 6136 if (!test_info.IsCompatible(this)) return false; |
| 6141 } | 6137 } |
| 6142 | 6138 |
| 6143 return true; | 6139 return true; |
| 6144 } | 6140 } |
| 6145 | 6141 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6179 DCHECK(!info->map()->has_non_instance_prototype()); | 6175 DCHECK(!info->map()->has_non_instance_prototype()); |
| 6180 return New<HLoadFunctionPrototype>(checked_object); | 6176 return New<HLoadFunctionPrototype>(checked_object); |
| 6181 } | 6177 } |
| 6182 | 6178 |
| 6183 HValue* checked_holder = checked_object; | 6179 HValue* checked_holder = checked_object; |
| 6184 if (info->has_holder()) { | 6180 if (info->has_holder()) { |
| 6185 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); | 6181 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); |
| 6186 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); | 6182 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); |
| 6187 } | 6183 } |
| 6188 | 6184 |
| 6189 if (!info->lookup()->IsFound()) { | 6185 if (!info->IsFound()) { |
| 6190 DCHECK(info->IsLoad()); | 6186 DCHECK(info->IsLoad()); |
| 6191 return graph()->GetConstantUndefined(); | 6187 return graph()->GetConstantUndefined(); |
| 6192 } | 6188 } |
| 6193 | 6189 |
| 6194 if (info->lookup()->IsField()) { | 6190 if (info->IsField()) { |
| 6195 if (info->IsLoad()) { | 6191 if (info->IsLoad()) { |
| 6196 return BuildLoadNamedField(info, checked_holder); | 6192 return BuildLoadNamedField(info, checked_holder); |
| 6197 } else { | 6193 } else { |
| 6198 return BuildStoreNamedField(info, checked_object, value); | 6194 return BuildStoreNamedField(info, checked_object, value); |
| 6199 } | 6195 } |
| 6200 } | 6196 } |
| 6201 | 6197 |
| 6202 if (info->lookup()->IsTransition()) { | 6198 if (info->IsTransition()) { |
| 6203 DCHECK(!info->IsLoad()); | 6199 DCHECK(!info->IsLoad()); |
| 6204 return BuildStoreNamedField(info, checked_object, value); | 6200 return BuildStoreNamedField(info, checked_object, value); |
| 6205 } | 6201 } |
| 6206 | 6202 |
| 6207 if (info->lookup()->IsPropertyCallbacks()) { | 6203 if (info->IsAccessor()) { |
| 6208 Push(checked_object); | 6204 Push(checked_object); |
| 6209 int argument_count = 1; | 6205 int argument_count = 1; |
| 6210 if (!info->IsLoad()) { | 6206 if (!info->IsLoad()) { |
| 6211 argument_count = 2; | 6207 argument_count = 2; |
| 6212 Push(value); | 6208 Push(value); |
| 6213 } | 6209 } |
| 6214 | 6210 |
| 6215 if (NeedsWrappingFor(info->type(), info->accessor())) { | 6211 if (NeedsWrappingFor(info->type(), info->accessor())) { |
| 6216 HValue* function = Add<HConstant>(info->accessor()); | 6212 HValue* function = Add<HConstant>(info->accessor()); |
| 6217 PushArgumentsFromEnvironment(argument_count); | 6213 PushArgumentsFromEnvironment(argument_count); |
| 6218 return New<HCallFunction>(function, argument_count, WRAP_AND_CALL); | 6214 return New<HCallFunction>(function, argument_count, WRAP_AND_CALL); |
| 6219 } else if (FLAG_inline_accessors && can_inline_accessor) { | 6215 } else if (FLAG_inline_accessors && can_inline_accessor) { |
| 6220 bool success = info->IsLoad() | 6216 bool success = info->IsLoad() |
| 6221 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) | 6217 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) |
| 6222 : TryInlineSetter( | 6218 : TryInlineSetter( |
| 6223 info->accessor(), info->map(), ast_id, return_id, value); | 6219 info->accessor(), info->map(), ast_id, return_id, value); |
| 6224 if (success || HasStackOverflow()) return NULL; | 6220 if (success || HasStackOverflow()) return NULL; |
| 6225 } | 6221 } |
| 6226 | 6222 |
| 6227 PushArgumentsFromEnvironment(argument_count); | 6223 PushArgumentsFromEnvironment(argument_count); |
| 6228 return BuildCallConstantFunction(info->accessor(), argument_count); | 6224 return BuildCallConstantFunction(info->accessor(), argument_count); |
| 6229 } | 6225 } |
| 6230 | 6226 |
| 6231 DCHECK(info->lookup()->IsConstant()); | 6227 DCHECK(info->IsConstant()); |
| 6232 if (info->IsLoad()) { | 6228 if (info->IsLoad()) { |
| 6233 return New<HConstant>(info->constant()); | 6229 return New<HConstant>(info->constant()); |
| 6234 } else { | 6230 } else { |
| 6235 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); | 6231 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); |
| 6236 } | 6232 } |
| 6237 } | 6233 } |
| 6238 | 6234 |
| 6239 | 6235 |
| 6240 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( | 6236 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( |
| 6241 PropertyAccessType access_type, | 6237 PropertyAccessType access_type, |
| (...skipping 1235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7477 FunctionSorter order[kMaxCallPolymorphism]; | 7473 FunctionSorter order[kMaxCallPolymorphism]; |
| 7478 | 7474 |
| 7479 bool handle_smi = false; | 7475 bool handle_smi = false; |
| 7480 bool handled_string = false; | 7476 bool handled_string = false; |
| 7481 int ordered_functions = 0; | 7477 int ordered_functions = 0; |
| 7482 | 7478 |
| 7483 for (int i = 0; | 7479 for (int i = 0; |
| 7484 i < types->length() && ordered_functions < kMaxCallPolymorphism; | 7480 i < types->length() && ordered_functions < kMaxCallPolymorphism; |
| 7485 ++i) { | 7481 ++i) { |
| 7486 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name); | 7482 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name); |
| 7487 if (info.CanAccessMonomorphic() && | 7483 if (info.CanAccessMonomorphic() && info.IsConstant() && |
| 7488 info.lookup()->IsConstant() && | |
| 7489 info.constant()->IsJSFunction()) { | 7484 info.constant()->IsJSFunction()) { |
| 7490 if (info.type()->Is(Type::String())) { | 7485 if (info.type()->Is(Type::String())) { |
| 7491 if (handled_string) continue; | 7486 if (handled_string) continue; |
| 7492 handled_string = true; | 7487 handled_string = true; |
| 7493 } | 7488 } |
| 7494 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); | 7489 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); |
| 7495 if (info.type()->Is(Type::Number())) { | 7490 if (info.type()->Is(Type::Number())) { |
| 7496 handle_smi = true; | 7491 handle_smi = true; |
| 7497 } | 7492 } |
| 7498 expr->set_target(target); | 7493 expr->set_target(target); |
| (...skipping 4996 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12495 if (ShouldProduceTraceOutput()) { | 12490 if (ShouldProduceTraceOutput()) { |
| 12496 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 12491 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 12497 } | 12492 } |
| 12498 | 12493 |
| 12499 #ifdef DEBUG | 12494 #ifdef DEBUG |
| 12500 graph_->Verify(false); // No full verify. | 12495 graph_->Verify(false); // No full verify. |
| 12501 #endif | 12496 #endif |
| 12502 } | 12497 } |
| 12503 | 12498 |
| 12504 } } // namespace v8::internal | 12499 } } // namespace v8::internal |
| OLD | NEW |