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 |