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 <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 4454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4465 } | 4465 } |
4466 | 4466 |
4467 int rest_index; | 4467 int rest_index; |
4468 Variable* rest = scope->rest_parameter(&rest_index); | 4468 Variable* rest = scope->rest_parameter(&rest_index); |
4469 if (rest) { | 4469 if (rest) { |
4470 return Bailout(kRestParameter); | 4470 return Bailout(kRestParameter); |
4471 } | 4471 } |
4472 } | 4472 } |
4473 | 4473 |
4474 | 4474 |
4475 Type* HOptimizedGraphBuilder::ToType(Handle<Map> map) { | |
4476 return IC::MapToType<Type>(map, zone()); | |
4477 } | |
4478 | |
4479 | |
4480 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { | 4475 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { |
4481 for (int i = 0; i < statements->length(); i++) { | 4476 for (int i = 0; i < statements->length(); i++) { |
4482 Statement* stmt = statements->at(i); | 4477 Statement* stmt = statements->at(i); |
4483 CHECK_ALIVE(Visit(stmt)); | 4478 CHECK_ALIVE(Visit(stmt)); |
4484 if (stmt->IsJump()) break; | 4479 if (stmt->IsJump()) break; |
4485 } | 4480 } |
4486 } | 4481 } |
4487 | 4482 |
4488 | 4483 |
4489 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) { | 4484 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) { |
(...skipping 948 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5438 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 5433 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
5439 Handle<FixedArray> literals(closure->literals()); | 5434 Handle<FixedArray> literals(closure->literals()); |
5440 HRegExpLiteral* instr = New<HRegExpLiteral>(literals, | 5435 HRegExpLiteral* instr = New<HRegExpLiteral>(literals, |
5441 expr->pattern(), | 5436 expr->pattern(), |
5442 expr->flags(), | 5437 expr->flags(), |
5443 expr->literal_index()); | 5438 expr->literal_index()); |
5444 return ast_context()->ReturnInstruction(instr, expr->id()); | 5439 return ast_context()->ReturnInstruction(instr, expr->id()); |
5445 } | 5440 } |
5446 | 5441 |
5447 | 5442 |
5448 static bool CanInlinePropertyAccess(Type* type) { | 5443 static bool CanInlinePropertyAccess(Handle<Map> map) { |
5449 if (type->Is(Type::NumberOrString())) return true; | 5444 if (map->instance_type() == HEAP_NUMBER_TYPE) return true; |
5450 if (!type->IsClass()) return false; | 5445 if (map->instance_type() < FIRST_NONSTRING_TYPE) return true; |
5451 Handle<Map> map = type->AsClass()->Map(); | |
5452 return map->IsJSObjectMap() && | 5446 return map->IsJSObjectMap() && |
5453 !map->is_dictionary_map() && | 5447 !map->is_dictionary_map() && |
5454 !map->has_named_interceptor(); | 5448 !map->has_named_interceptor(); |
5455 } | 5449 } |
5456 | 5450 |
5457 | 5451 |
5458 // Determines whether the given array or object literal boilerplate satisfies | 5452 // Determines whether the given array or object literal boilerplate satisfies |
5459 // all limits to be considered for fast deep-copying and computes the total | 5453 // all limits to be considered for fast deep-copying and computes the total |
5460 // size of all objects that are part of the graph. | 5454 // size of all objects that are part of the graph. |
5461 static bool IsFastLiteral(Handle<JSObject> boilerplate, | 5455 static bool IsFastLiteral(Handle<JSObject> boilerplate, |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5611 } | 5605 } |
5612 | 5606 |
5613 Handle<Map> map = property->GetReceiverType(); | 5607 Handle<Map> map = property->GetReceiverType(); |
5614 Handle<String> name = key->AsPropertyName(); | 5608 Handle<String> name = key->AsPropertyName(); |
5615 HInstruction* store; | 5609 HInstruction* store; |
5616 if (map.is_null()) { | 5610 if (map.is_null()) { |
5617 // If we don't know the monomorphic type, do a generic store. | 5611 // If we don't know the monomorphic type, do a generic store. |
5618 CHECK_ALIVE(store = BuildNamedGeneric( | 5612 CHECK_ALIVE(store = BuildNamedGeneric( |
5619 STORE, NULL, literal, name, value)); | 5613 STORE, NULL, literal, name, value)); |
5620 } else { | 5614 } else { |
5621 PropertyAccessInfo info(this, STORE, ToType(map), name); | 5615 PropertyAccessInfo info(this, STORE, map, name); |
5622 if (info.CanAccessMonomorphic()) { | 5616 if (info.CanAccessMonomorphic()) { |
5623 HValue* checked_literal = Add<HCheckMaps>(literal, map); | 5617 HValue* checked_literal = Add<HCheckMaps>(literal, map); |
5624 DCHECK(!info.IsAccessorConstant()); | 5618 DCHECK(!info.IsAccessorConstant()); |
5625 store = BuildMonomorphicAccess( | 5619 store = BuildMonomorphicAccess( |
5626 &info, literal, checked_literal, value, | 5620 &info, literal, checked_literal, value, |
5627 BailoutId::None(), BailoutId::None()); | 5621 BailoutId::None(), BailoutId::None()); |
5628 } else { | 5622 } else { |
5629 CHECK_ALIVE(store = BuildNamedGeneric( | 5623 CHECK_ALIVE(store = BuildNamedGeneric( |
5630 STORE, NULL, literal, name, value)); | 5624 STORE, NULL, literal, name, value)); |
5631 } | 5625 } |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5900 Handle<Map> transition(info->transition()); | 5894 Handle<Map> transition(info->transition()); |
5901 DCHECK(!transition->is_deprecated()); | 5895 DCHECK(!transition->is_deprecated()); |
5902 instr->SetTransition(Add<HConstant>(transition)); | 5896 instr->SetTransition(Add<HConstant>(transition)); |
5903 } | 5897 } |
5904 return instr; | 5898 return instr; |
5905 } | 5899 } |
5906 | 5900 |
5907 | 5901 |
5908 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible( | 5902 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible( |
5909 PropertyAccessInfo* info) { | 5903 PropertyAccessInfo* info) { |
5910 if (!CanInlinePropertyAccess(type_)) return false; | 5904 if (!CanInlinePropertyAccess(map_)) return false; |
5911 | 5905 |
5912 // Currently only handle Type::Number as a polymorphic case. | 5906 // Currently only handle Type::Number as a polymorphic case. |
5913 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber | 5907 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber |
5914 // instruction. | 5908 // instruction. |
5915 if (type_->Is(Type::Number())) return false; | 5909 if (IsNumberType()) return false; |
5916 | 5910 |
5917 // Values are only compatible for monomorphic load if they all behave the same | 5911 // Values are only compatible for monomorphic load if they all behave the same |
5918 // regarding value wrappers. | 5912 // regarding value wrappers. |
5919 if (type_->Is(Type::NumberOrString())) { | 5913 if (IsValueWrapped() != info->IsValueWrapped()) return false; |
5920 if (!info->type_->Is(Type::NumberOrString())) return false; | |
5921 } else { | |
5922 if (info->type_->Is(Type::NumberOrString())) return false; | |
5923 } | |
5924 | 5914 |
5925 if (!LookupDescriptor()) return false; | 5915 if (!LookupDescriptor()) return false; |
5926 | 5916 |
5927 if (!IsFound()) { | 5917 if (!IsFound()) { |
5928 return (!info->IsFound() || info->has_holder()) && | 5918 return (!info->IsFound() || info->has_holder()) && |
5929 map()->prototype() == info->map()->prototype(); | 5919 map()->prototype() == info->map()->prototype(); |
5930 } | 5920 } |
5931 | 5921 |
5932 // Mismatch if the other access info found the property in the prototype | 5922 // Mismatch if the other access info found the property in the prototype |
5933 // chain. | 5923 // chain. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5972 } | 5962 } |
5973 } | 5963 } |
5974 } | 5964 } |
5975 info->GeneralizeRepresentation(r); | 5965 info->GeneralizeRepresentation(r); |
5976 info->field_type_ = info->field_type_.Combine(field_type_); | 5966 info->field_type_ = info->field_type_.Combine(field_type_); |
5977 return true; | 5967 return true; |
5978 } | 5968 } |
5979 | 5969 |
5980 | 5970 |
5981 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() { | 5971 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() { |
5982 if (!type_->IsClass()) return true; | 5972 if (!map_->IsJSObjectMap()) return true; |
5983 map()->LookupDescriptor(NULL, *name_, &lookup_); | 5973 map_->LookupDescriptor(NULL, *name_, &lookup_); |
5984 return LoadResult(map()); | 5974 return LoadResult(map_); |
5985 } | 5975 } |
5986 | 5976 |
5987 | 5977 |
5988 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { | 5978 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { |
5989 if (!IsLoad() && IsProperty() && IsReadOnly()) { | 5979 if (!IsLoad() && IsProperty() && IsReadOnly()) { |
5990 return false; | 5980 return false; |
5991 } | 5981 } |
5992 | 5982 |
5993 if (IsData()) { | 5983 if (IsData()) { |
5994 // Construct the object field access. | 5984 // Construct the object field access. |
5995 int index = GetLocalFieldIndexFromMap(map); | 5985 int index = GetLocalFieldIndexFromMap(map); |
5996 access_ = HObjectAccess::ForField(map, index, representation(), name_); | 5986 access_ = HObjectAccess::ForField(map, index, representation(), name_); |
5997 | 5987 |
5998 // Load field map for heap objects. | 5988 // Load field map for heap objects. |
5999 LoadFieldMaps(map); | 5989 LoadFieldMaps(map); |
6000 } else if (IsAccessorConstant()) { | 5990 } else if (IsAccessorConstant()) { |
6001 Handle<Object> accessors = GetAccessorsFromMap(map); | 5991 Handle<Object> accessors = GetAccessorsFromMap(map); |
6002 if (!accessors->IsAccessorPair()) return false; | 5992 if (!accessors->IsAccessorPair()) return false; |
6003 Object* raw_accessor = | 5993 Object* raw_accessor = |
6004 IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter() | 5994 IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter() |
6005 : Handle<AccessorPair>::cast(accessors)->setter(); | 5995 : Handle<AccessorPair>::cast(accessors)->setter(); |
6006 if (!raw_accessor->IsJSFunction()) return false; | 5996 if (!raw_accessor->IsJSFunction()) return false; |
6007 Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor)); | 5997 Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor)); |
6008 if (accessor->shared()->IsApiFunction()) { | 5998 if (accessor->shared()->IsApiFunction()) { |
6009 CallOptimization call_optimization(accessor); | 5999 CallOptimization call_optimization(accessor); |
6010 if (call_optimization.is_simple_api_call()) { | 6000 if (call_optimization.is_simple_api_call()) { |
6011 CallOptimization::HolderLookup holder_lookup; | 6001 CallOptimization::HolderLookup holder_lookup; |
6012 Handle<Map> receiver_map = this->map(); | 6002 api_holder_ = |
6013 api_holder_ = call_optimization.LookupHolderOfExpectedType( | 6003 call_optimization.LookupHolderOfExpectedType(map_, &holder_lookup); |
6014 receiver_map, &holder_lookup); | |
6015 } | 6004 } |
6016 } | 6005 } |
6017 accessor_ = accessor; | 6006 accessor_ = accessor; |
6018 } else if (IsDataConstant()) { | 6007 } else if (IsDataConstant()) { |
6019 constant_ = GetConstantFromMap(map); | 6008 constant_ = GetConstantFromMap(map); |
6020 } | 6009 } |
6021 | 6010 |
6022 return true; | 6011 return true; |
6023 } | 6012 } |
6024 | 6013 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6062 | 6051 |
6063 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { | 6052 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { |
6064 Handle<Map> map = this->map(); | 6053 Handle<Map> map = this->map(); |
6065 | 6054 |
6066 while (map->prototype()->IsJSObject()) { | 6055 while (map->prototype()->IsJSObject()) { |
6067 holder_ = handle(JSObject::cast(map->prototype())); | 6056 holder_ = handle(JSObject::cast(map->prototype())); |
6068 if (holder_->map()->is_deprecated()) { | 6057 if (holder_->map()->is_deprecated()) { |
6069 JSObject::TryMigrateInstance(holder_); | 6058 JSObject::TryMigrateInstance(holder_); |
6070 } | 6059 } |
6071 map = Handle<Map>(holder_->map()); | 6060 map = Handle<Map>(holder_->map()); |
6072 if (!CanInlinePropertyAccess(ToType(map))) { | 6061 if (!CanInlinePropertyAccess(map)) { |
6073 lookup_.NotFound(); | 6062 lookup_.NotFound(); |
6074 return false; | 6063 return false; |
6075 } | 6064 } |
6076 map->LookupDescriptor(*holder_, *name_, &lookup_); | 6065 map->LookupDescriptor(*holder_, *name_, &lookup_); |
6077 if (IsFound()) return LoadResult(map); | 6066 if (IsFound()) return LoadResult(map); |
6078 } | 6067 } |
6079 lookup_.NotFound(); | 6068 lookup_.NotFound(); |
6080 return true; | 6069 return true; |
6081 } | 6070 } |
6082 | 6071 |
6083 | 6072 |
6084 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { | 6073 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { |
6085 if (!CanInlinePropertyAccess(type_)) return false; | 6074 if (!CanInlinePropertyAccess(map_)) return false; |
6086 if (IsJSObjectFieldAccessor()) return IsLoad(); | 6075 if (IsJSObjectFieldAccessor()) return IsLoad(); |
6087 if (this->map()->function_with_prototype() && | 6076 if (map_->function_with_prototype() && !map_->has_non_instance_prototype() && |
6088 !this->map()->has_non_instance_prototype() && | |
6089 name_.is_identical_to(isolate()->factory()->prototype_string())) { | 6077 name_.is_identical_to(isolate()->factory()->prototype_string())) { |
6090 return IsLoad(); | 6078 return IsLoad(); |
6091 } | 6079 } |
6092 if (!LookupDescriptor()) return false; | 6080 if (!LookupDescriptor()) return false; |
6093 if (IsFound()) return IsLoad() || !IsReadOnly(); | 6081 if (IsFound()) return IsLoad() || !IsReadOnly(); |
6094 if (!LookupInPrototypes()) return false; | 6082 if (!LookupInPrototypes()) return false; |
6095 if (IsLoad()) return true; | 6083 if (IsLoad()) return true; |
6096 | 6084 |
6097 if (IsAccessorConstant()) return true; | 6085 if (IsAccessorConstant()) return true; |
6098 Handle<Map> map = this->map(); | 6086 map_->LookupTransition(NULL, *name_, NONE, &lookup_); |
6099 map->LookupTransition(NULL, *name_, NONE, &lookup_); | 6087 if (lookup_.IsTransitionToData() && map_->unused_property_fields() > 0) { |
6100 if (lookup_.IsTransitionToData() && map->unused_property_fields() > 0) { | |
6101 // Construct the object field access. | 6088 // Construct the object field access. |
6102 int descriptor = transition()->LastAdded(); | 6089 int descriptor = transition()->LastAdded(); |
6103 int index = | 6090 int index = |
6104 transition()->instance_descriptors()->GetFieldIndex(descriptor) - | 6091 transition()->instance_descriptors()->GetFieldIndex(descriptor) - |
6105 map->inobject_properties(); | 6092 map_->inobject_properties(); |
6106 PropertyDetails details = | 6093 PropertyDetails details = |
6107 transition()->instance_descriptors()->GetDetails(descriptor); | 6094 transition()->instance_descriptors()->GetDetails(descriptor); |
6108 Representation representation = details.representation(); | 6095 Representation representation = details.representation(); |
6109 access_ = HObjectAccess::ForField(map, index, representation, name_); | 6096 access_ = HObjectAccess::ForField(map_, index, representation, name_); |
6110 | 6097 |
6111 // Load field map for heap objects. | 6098 // Load field map for heap objects. |
6112 LoadFieldMaps(transition()); | 6099 LoadFieldMaps(transition()); |
6113 return true; | 6100 return true; |
6114 } | 6101 } |
6115 return false; | 6102 return false; |
6116 } | 6103 } |
6117 | 6104 |
6118 | 6105 |
6119 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic( | 6106 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic( |
6120 SmallMapList* types) { | 6107 SmallMapList* maps) { |
6121 DCHECK(type_->Is(ToType(types->first()))); | 6108 DCHECK(map_.is_identical_to(maps->first())); |
6122 if (!CanAccessMonomorphic()) return false; | 6109 if (!CanAccessMonomorphic()) return false; |
6123 STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism); | 6110 STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism); |
6124 if (types->length() > kMaxLoadPolymorphism) return false; | 6111 if (maps->length() > kMaxLoadPolymorphism) return false; |
6125 | 6112 |
6126 HObjectAccess access = HObjectAccess::ForMap(); // bogus default | 6113 HObjectAccess access = HObjectAccess::ForMap(); // bogus default |
6127 if (GetJSObjectFieldAccess(&access)) { | 6114 if (GetJSObjectFieldAccess(&access)) { |
6128 for (int i = 1; i < types->length(); ++i) { | 6115 for (int i = 1; i < maps->length(); ++i) { |
6129 PropertyAccessInfo test_info( | 6116 PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_); |
6130 builder_, access_type_, ToType(types->at(i)), name_); | |
6131 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default | 6117 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default |
6132 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false; | 6118 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false; |
6133 if (!access.Equals(test_access)) return false; | 6119 if (!access.Equals(test_access)) return false; |
6134 } | 6120 } |
6135 return true; | 6121 return true; |
6136 } | 6122 } |
6137 | 6123 |
6138 // Currently only handle Type::Number as a polymorphic case. | 6124 // Currently only handle numbers as a polymorphic case. |
6139 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber | 6125 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber |
6140 // instruction. | 6126 // instruction. |
6141 if (type_->Is(Type::Number())) return false; | 6127 if (IsNumberType()) return false; |
6142 | 6128 |
6143 // Multiple maps cannot transition to the same target map. | 6129 // Multiple maps cannot transition to the same target map. |
6144 DCHECK(!IsLoad() || !IsTransition()); | 6130 DCHECK(!IsLoad() || !IsTransition()); |
6145 if (IsTransition() && types->length() > 1) return false; | 6131 if (IsTransition() && maps->length() > 1) return false; |
6146 | 6132 |
6147 for (int i = 1; i < types->length(); ++i) { | 6133 for (int i = 1; i < maps->length(); ++i) { |
6148 PropertyAccessInfo test_info( | 6134 PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_); |
6149 builder_, access_type_, ToType(types->at(i)), name_); | |
6150 if (!test_info.IsCompatible(this)) return false; | 6135 if (!test_info.IsCompatible(this)) return false; |
6151 } | 6136 } |
6152 | 6137 |
6153 return true; | 6138 return true; |
6154 } | 6139 } |
6155 | 6140 |
6156 | 6141 |
6157 Handle<Map> HOptimizedGraphBuilder::PropertyAccessInfo::map() { | 6142 Handle<Map> HOptimizedGraphBuilder::PropertyAccessInfo::map() { |
6158 JSFunction* ctor = IC::GetRootConstructor( | 6143 JSFunction* ctor = IC::GetRootConstructor( |
6159 type_, current_info()->closure()->context()->native_context()); | 6144 *map_, current_info()->closure()->context()->native_context()); |
6160 if (ctor != NULL) return handle(ctor->initial_map()); | 6145 if (ctor != NULL) return handle(ctor->initial_map()); |
6161 return type_->AsClass()->Map(); | 6146 return map_; |
6162 } | 6147 } |
6163 | 6148 |
6164 | 6149 |
6165 static bool NeedsWrappingFor(Type* type, Handle<JSFunction> target) { | 6150 static bool NeedsWrapping(Handle<Map> map, Handle<JSFunction> target) { |
6166 return type->Is(Type::NumberOrString()) && | 6151 return !map->IsJSObjectMap() && |
6167 is_sloppy(target->shared()->language_mode()) && | 6152 is_sloppy(target->shared()->language_mode()) && |
6168 !target->shared()->native(); | 6153 !target->shared()->native(); |
6169 } | 6154 } |
6170 | 6155 |
6171 | 6156 |
| 6157 bool HOptimizedGraphBuilder::PropertyAccessInfo::NeedsWrappingFor( |
| 6158 Handle<JSFunction> target) const { |
| 6159 return NeedsWrapping(map_, target); |
| 6160 } |
| 6161 |
| 6162 |
6172 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess( | 6163 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess( |
6173 PropertyAccessInfo* info, | 6164 PropertyAccessInfo* info, |
6174 HValue* object, | 6165 HValue* object, |
6175 HValue* checked_object, | 6166 HValue* checked_object, |
6176 HValue* value, | 6167 HValue* value, |
6177 BailoutId ast_id, | 6168 BailoutId ast_id, |
6178 BailoutId return_id, | 6169 BailoutId return_id, |
6179 bool can_inline_accessor) { | 6170 bool can_inline_accessor) { |
6180 | 6171 |
6181 HObjectAccess access = HObjectAccess::ForMap(); // bogus default | 6172 HObjectAccess access = HObjectAccess::ForMap(); // bogus default |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6215 } | 6206 } |
6216 | 6207 |
6217 if (info->IsAccessorConstant()) { | 6208 if (info->IsAccessorConstant()) { |
6218 Push(checked_object); | 6209 Push(checked_object); |
6219 int argument_count = 1; | 6210 int argument_count = 1; |
6220 if (!info->IsLoad()) { | 6211 if (!info->IsLoad()) { |
6221 argument_count = 2; | 6212 argument_count = 2; |
6222 Push(value); | 6213 Push(value); |
6223 } | 6214 } |
6224 | 6215 |
6225 if (NeedsWrappingFor(info->type(), info->accessor())) { | 6216 if (info->NeedsWrappingFor(info->accessor())) { |
6226 HValue* function = Add<HConstant>(info->accessor()); | 6217 HValue* function = Add<HConstant>(info->accessor()); |
6227 PushArgumentsFromEnvironment(argument_count); | 6218 PushArgumentsFromEnvironment(argument_count); |
6228 return New<HCallFunction>(function, argument_count, WRAP_AND_CALL); | 6219 return New<HCallFunction>(function, argument_count, WRAP_AND_CALL); |
6229 } else if (FLAG_inline_accessors && can_inline_accessor) { | 6220 } else if (FLAG_inline_accessors && can_inline_accessor) { |
6230 bool success = info->IsLoad() | 6221 bool success = info->IsLoad() |
6231 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) | 6222 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) |
6232 : TryInlineSetter( | 6223 : TryInlineSetter( |
6233 info->accessor(), info->map(), ast_id, return_id, value); | 6224 info->accessor(), info->map(), ast_id, return_id, value); |
6234 if (success || HasStackOverflow()) return NULL; | 6225 if (success || HasStackOverflow()) return NULL; |
6235 } | 6226 } |
6236 | 6227 |
6237 PushArgumentsFromEnvironment(argument_count); | 6228 PushArgumentsFromEnvironment(argument_count); |
6238 return BuildCallConstantFunction(info->accessor(), argument_count); | 6229 return BuildCallConstantFunction(info->accessor(), argument_count); |
6239 } | 6230 } |
6240 | 6231 |
6241 DCHECK(info->IsDataConstant()); | 6232 DCHECK(info->IsDataConstant()); |
6242 if (info->IsLoad()) { | 6233 if (info->IsLoad()) { |
6243 return New<HConstant>(info->constant()); | 6234 return New<HConstant>(info->constant()); |
6244 } else { | 6235 } else { |
6245 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); | 6236 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); |
6246 } | 6237 } |
6247 } | 6238 } |
6248 | 6239 |
6249 | 6240 |
6250 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( | 6241 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( |
6251 PropertyAccessType access_type, | 6242 PropertyAccessType access_type, Expression* expr, BailoutId ast_id, |
6252 Expression* expr, | 6243 BailoutId return_id, HValue* object, HValue* value, SmallMapList* maps, |
6253 BailoutId ast_id, | |
6254 BailoutId return_id, | |
6255 HValue* object, | |
6256 HValue* value, | |
6257 SmallMapList* types, | |
6258 Handle<String> name) { | 6244 Handle<String> name) { |
6259 // Something did not match; must use a polymorphic load. | 6245 // Something did not match; must use a polymorphic load. |
6260 int count = 0; | 6246 int count = 0; |
6261 HBasicBlock* join = NULL; | 6247 HBasicBlock* join = NULL; |
6262 HBasicBlock* number_block = NULL; | 6248 HBasicBlock* number_block = NULL; |
6263 bool handled_string = false; | 6249 bool handled_string = false; |
6264 | 6250 |
6265 bool handle_smi = false; | 6251 bool handle_smi = false; |
6266 STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism); | 6252 STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism); |
6267 int i; | 6253 int i; |
6268 for (i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 6254 for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) { |
6269 PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name); | 6255 PropertyAccessInfo info(this, access_type, maps->at(i), name); |
6270 if (info.type()->Is(Type::String())) { | 6256 if (info.IsStringType()) { |
6271 if (handled_string) continue; | 6257 if (handled_string) continue; |
6272 handled_string = true; | 6258 handled_string = true; |
6273 } | 6259 } |
6274 if (info.CanAccessMonomorphic()) { | 6260 if (info.CanAccessMonomorphic()) { |
6275 count++; | 6261 count++; |
6276 if (info.type()->Is(Type::Number())) { | 6262 if (info.IsNumberType()) { |
6277 handle_smi = true; | 6263 handle_smi = true; |
6278 break; | 6264 break; |
6279 } | 6265 } |
6280 } | 6266 } |
6281 } | 6267 } |
6282 | 6268 |
6283 if (i < types->length()) { | 6269 if (i < maps->length()) { |
6284 count = -1; | 6270 count = -1; |
6285 types->Clear(); | 6271 maps->Clear(); |
6286 } else { | 6272 } else { |
6287 count = 0; | 6273 count = 0; |
6288 } | 6274 } |
6289 HControlInstruction* smi_check = NULL; | 6275 HControlInstruction* smi_check = NULL; |
6290 handled_string = false; | 6276 handled_string = false; |
6291 | 6277 |
6292 for (i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 6278 for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) { |
6293 PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name); | 6279 PropertyAccessInfo info(this, access_type, maps->at(i), name); |
6294 if (info.type()->Is(Type::String())) { | 6280 if (info.IsStringType()) { |
6295 if (handled_string) continue; | 6281 if (handled_string) continue; |
6296 handled_string = true; | 6282 handled_string = true; |
6297 } | 6283 } |
6298 if (!info.CanAccessMonomorphic()) continue; | 6284 if (!info.CanAccessMonomorphic()) continue; |
6299 | 6285 |
6300 if (count == 0) { | 6286 if (count == 0) { |
6301 join = graph()->CreateBasicBlock(); | 6287 join = graph()->CreateBasicBlock(); |
6302 if (handle_smi) { | 6288 if (handle_smi) { |
6303 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); | 6289 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); |
6304 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); | 6290 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); |
6305 number_block = graph()->CreateBasicBlock(); | 6291 number_block = graph()->CreateBasicBlock(); |
6306 smi_check = New<HIsSmiAndBranch>( | 6292 smi_check = New<HIsSmiAndBranch>( |
6307 object, empty_smi_block, not_smi_block); | 6293 object, empty_smi_block, not_smi_block); |
6308 FinishCurrentBlock(smi_check); | 6294 FinishCurrentBlock(smi_check); |
6309 GotoNoSimulate(empty_smi_block, number_block); | 6295 GotoNoSimulate(empty_smi_block, number_block); |
6310 set_current_block(not_smi_block); | 6296 set_current_block(not_smi_block); |
6311 } else { | 6297 } else { |
6312 BuildCheckHeapObject(object); | 6298 BuildCheckHeapObject(object); |
6313 } | 6299 } |
6314 } | 6300 } |
6315 ++count; | 6301 ++count; |
6316 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 6302 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
6317 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 6303 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
6318 HUnaryControlInstruction* compare; | 6304 HUnaryControlInstruction* compare; |
6319 | 6305 |
6320 HValue* dependency; | 6306 HValue* dependency; |
6321 if (info.type()->Is(Type::Number())) { | 6307 if (info.IsNumberType()) { |
6322 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); | 6308 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); |
6323 compare = New<HCompareMap>(object, heap_number_map, if_true, if_false); | 6309 compare = New<HCompareMap>(object, heap_number_map, if_true, if_false); |
6324 dependency = smi_check; | 6310 dependency = smi_check; |
6325 } else if (info.type()->Is(Type::String())) { | 6311 } else if (info.IsStringType()) { |
6326 compare = New<HIsStringAndBranch>(object, if_true, if_false); | 6312 compare = New<HIsStringAndBranch>(object, if_true, if_false); |
6327 dependency = compare; | 6313 dependency = compare; |
6328 } else { | 6314 } else { |
6329 compare = New<HCompareMap>(object, info.map(), if_true, if_false); | 6315 compare = New<HCompareMap>(object, info.map(), if_true, if_false); |
6330 dependency = compare; | 6316 dependency = compare; |
6331 } | 6317 } |
6332 FinishCurrentBlock(compare); | 6318 FinishCurrentBlock(compare); |
6333 | 6319 |
6334 if (info.type()->Is(Type::Number())) { | 6320 if (info.IsNumberType()) { |
6335 GotoNoSimulate(if_true, number_block); | 6321 GotoNoSimulate(if_true, number_block); |
6336 if_true = number_block; | 6322 if_true = number_block; |
6337 } | 6323 } |
6338 | 6324 |
6339 set_current_block(if_true); | 6325 set_current_block(if_true); |
6340 | 6326 |
6341 HInstruction* access = BuildMonomorphicAccess( | 6327 HInstruction* access = BuildMonomorphicAccess( |
6342 &info, object, dependency, value, ast_id, | 6328 &info, object, dependency, value, ast_id, |
6343 return_id, FLAG_polymorphic_inlining); | 6329 return_id, FLAG_polymorphic_inlining); |
6344 | 6330 |
(...skipping 14 matching lines...) Expand all Loading... |
6359 if (!ast_context()->IsEffect()) Push(result); | 6345 if (!ast_context()->IsEffect()) Push(result); |
6360 } | 6346 } |
6361 | 6347 |
6362 if (current_block() != NULL) Goto(join); | 6348 if (current_block() != NULL) Goto(join); |
6363 set_current_block(if_false); | 6349 set_current_block(if_false); |
6364 } | 6350 } |
6365 | 6351 |
6366 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6352 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
6367 // know about and do not want to handle ones we've never seen. Otherwise | 6353 // know about and do not want to handle ones we've never seen. Otherwise |
6368 // use a generic IC. | 6354 // use a generic IC. |
6369 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 6355 if (count == maps->length() && FLAG_deoptimize_uncommon_cases) { |
6370 FinishExitWithHardDeoptimization( | 6356 FinishExitWithHardDeoptimization( |
6371 Deoptimizer::kUnknownMapInPolymorphicAccess); | 6357 Deoptimizer::kUnknownMapInPolymorphicAccess); |
6372 } else { | 6358 } else { |
6373 HInstruction* instr = BuildNamedGeneric(access_type, expr, object, name, | 6359 HInstruction* instr = BuildNamedGeneric(access_type, expr, object, name, |
6374 value); | 6360 value); |
6375 AddInstruction(instr); | 6361 AddInstruction(instr); |
6376 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); | 6362 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); |
6377 | 6363 |
6378 if (join != NULL) { | 6364 if (join != NULL) { |
6379 Goto(join); | 6365 Goto(join); |
(...skipping 12 matching lines...) Expand all Loading... |
6392 } else { | 6378 } else { |
6393 set_current_block(NULL); | 6379 set_current_block(NULL); |
6394 } | 6380 } |
6395 } | 6381 } |
6396 | 6382 |
6397 | 6383 |
6398 static bool ComputeReceiverTypes(Expression* expr, | 6384 static bool ComputeReceiverTypes(Expression* expr, |
6399 HValue* receiver, | 6385 HValue* receiver, |
6400 SmallMapList** t, | 6386 SmallMapList** t, |
6401 Zone* zone) { | 6387 Zone* zone) { |
6402 SmallMapList* types = expr->GetReceiverTypes(); | 6388 SmallMapList* maps = expr->GetReceiverTypes(); |
6403 *t = types; | 6389 *t = maps; |
6404 bool monomorphic = expr->IsMonomorphic(); | 6390 bool monomorphic = expr->IsMonomorphic(); |
6405 if (types != NULL && receiver->HasMonomorphicJSObjectType()) { | 6391 if (maps != NULL && receiver->HasMonomorphicJSObjectType()) { |
6406 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap(); | 6392 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap(); |
6407 types->FilterForPossibleTransitions(root_map); | 6393 maps->FilterForPossibleTransitions(root_map); |
6408 monomorphic = types->length() == 1; | 6394 monomorphic = maps->length() == 1; |
6409 } | 6395 } |
6410 return monomorphic && | 6396 return monomorphic && CanInlinePropertyAccess(maps->first()); |
6411 CanInlinePropertyAccess(IC::MapToType<Type>(types->first(), zone)); | |
6412 } | 6397 } |
6413 | 6398 |
6414 | 6399 |
6415 static bool AreStringTypes(SmallMapList* types) { | 6400 static bool AreStringTypes(SmallMapList* maps) { |
6416 for (int i = 0; i < types->length(); i++) { | 6401 for (int i = 0; i < maps->length(); i++) { |
6417 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; | 6402 if (maps->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; |
6418 } | 6403 } |
6419 return true; | 6404 return true; |
6420 } | 6405 } |
6421 | 6406 |
6422 | 6407 |
6423 void HOptimizedGraphBuilder::BuildStore(Expression* expr, | 6408 void HOptimizedGraphBuilder::BuildStore(Expression* expr, |
6424 Property* prop, | 6409 Property* prop, |
6425 BailoutId ast_id, | 6410 BailoutId ast_id, |
6426 BailoutId return_id, | 6411 BailoutId return_id, |
6427 bool is_uninitialized) { | 6412 bool is_uninitialized) { |
(...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7184 AddInstruction(instr); | 7169 AddInstruction(instr); |
7185 *has_side_effects = instr->HasObservableSideEffects(); | 7170 *has_side_effects = instr->HasObservableSideEffects(); |
7186 } | 7171 } |
7187 return instr; | 7172 return instr; |
7188 } | 7173 } |
7189 } | 7174 } |
7190 | 7175 |
7191 DCHECK(!expr->IsPropertyName()); | 7176 DCHECK(!expr->IsPropertyName()); |
7192 HInstruction* instr = NULL; | 7177 HInstruction* instr = NULL; |
7193 | 7178 |
7194 SmallMapList* types; | 7179 SmallMapList* maps; |
7195 bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone()); | 7180 bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, zone()); |
7196 | 7181 |
7197 bool force_generic = false; | 7182 bool force_generic = false; |
7198 if (expr->GetKeyType() == PROPERTY) { | 7183 if (expr->GetKeyType() == PROPERTY) { |
7199 // Non-Generic accesses assume that elements are being accessed, and will | 7184 // Non-Generic accesses assume that elements are being accessed, and will |
7200 // deopt for non-index keys, which the IC knows will occur. | 7185 // deopt for non-index keys, which the IC knows will occur. |
7201 // TODO(jkummerow): Consider adding proper support for property accesses. | 7186 // TODO(jkummerow): Consider adding proper support for property accesses. |
7202 force_generic = true; | 7187 force_generic = true; |
7203 monomorphic = false; | 7188 monomorphic = false; |
7204 } else if (access_type == STORE && | 7189 } else if (access_type == STORE && |
7205 (monomorphic || (types != NULL && !types->is_empty()))) { | 7190 (monomorphic || (maps != NULL && !maps->is_empty()))) { |
7206 // Stores can't be mono/polymorphic if their prototype chain has dictionary | 7191 // Stores can't be mono/polymorphic if their prototype chain has dictionary |
7207 // elements. However a receiver map that has dictionary elements itself | 7192 // elements. However a receiver map that has dictionary elements itself |
7208 // should be left to normal mono/poly behavior (the other maps may benefit | 7193 // should be left to normal mono/poly behavior (the other maps may benefit |
7209 // from highly optimized stores). | 7194 // from highly optimized stores). |
7210 for (int i = 0; i < types->length(); i++) { | 7195 for (int i = 0; i < maps->length(); i++) { |
7211 Handle<Map> current_map = types->at(i); | 7196 Handle<Map> current_map = maps->at(i); |
7212 if (current_map->DictionaryElementsInPrototypeChainOnly()) { | 7197 if (current_map->DictionaryElementsInPrototypeChainOnly()) { |
7213 force_generic = true; | 7198 force_generic = true; |
7214 monomorphic = false; | 7199 monomorphic = false; |
7215 break; | 7200 break; |
7216 } | 7201 } |
7217 } | 7202 } |
7218 } else if (access_type == LOAD && !monomorphic && | 7203 } else if (access_type == LOAD && !monomorphic && |
7219 (types != NULL && !types->is_empty())) { | 7204 (maps != NULL && !maps->is_empty())) { |
7220 // Polymorphic loads have to go generic if any of the maps are strings. | 7205 // Polymorphic loads have to go generic if any of the maps are strings. |
7221 // If some, but not all of the maps are strings, we should go generic | 7206 // If some, but not all of the maps are strings, we should go generic |
7222 // because polymorphic access wants to key on ElementsKind and isn't | 7207 // because polymorphic access wants to key on ElementsKind and isn't |
7223 // compatible with strings. | 7208 // compatible with strings. |
7224 for (int i = 0; i < types->length(); i++) { | 7209 for (int i = 0; i < maps->length(); i++) { |
7225 Handle<Map> current_map = types->at(i); | 7210 Handle<Map> current_map = maps->at(i); |
7226 if (current_map->IsStringMap()) { | 7211 if (current_map->IsStringMap()) { |
7227 force_generic = true; | 7212 force_generic = true; |
7228 break; | 7213 break; |
7229 } | 7214 } |
7230 } | 7215 } |
7231 } | 7216 } |
7232 | 7217 |
7233 if (monomorphic) { | 7218 if (monomorphic) { |
7234 Handle<Map> map = types->first(); | 7219 Handle<Map> map = maps->first(); |
7235 if (!CanInlineElementAccess(map)) { | 7220 if (!CanInlineElementAccess(map)) { |
7236 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, | 7221 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, |
7237 val)); | 7222 val)); |
7238 } else { | 7223 } else { |
7239 BuildCheckHeapObject(obj); | 7224 BuildCheckHeapObject(obj); |
7240 instr = BuildMonomorphicElementAccess( | 7225 instr = BuildMonomorphicElementAccess( |
7241 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); | 7226 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); |
7242 } | 7227 } |
7243 } else if (!force_generic && (types != NULL && !types->is_empty())) { | 7228 } else if (!force_generic && (maps != NULL && !maps->is_empty())) { |
7244 return HandlePolymorphicElementAccess( | 7229 return HandlePolymorphicElementAccess(expr, obj, key, val, maps, |
7245 expr, obj, key, val, types, access_type, | 7230 access_type, expr->GetStoreMode(), |
7246 expr->GetStoreMode(), has_side_effects); | 7231 has_side_effects); |
7247 } else { | 7232 } else { |
7248 if (access_type == STORE) { | 7233 if (access_type == STORE) { |
7249 if (expr->IsAssignment() && | 7234 if (expr->IsAssignment() && |
7250 expr->AsAssignment()->HasNoTypeInformation()) { | 7235 expr->AsAssignment()->HasNoTypeInformation()) { |
7251 Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedStore, | 7236 Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedStore, |
7252 Deoptimizer::SOFT); | 7237 Deoptimizer::SOFT); |
7253 } | 7238 } |
7254 } else { | 7239 } else { |
7255 if (expr->AsProperty()->HasNoTypeInformation()) { | 7240 if (expr->AsProperty()->HasNoTypeInformation()) { |
7256 Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedLoad, | 7241 Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedLoad, |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7345 | 7330 |
7346 HInstruction* HOptimizedGraphBuilder::BuildNamedAccess( | 7331 HInstruction* HOptimizedGraphBuilder::BuildNamedAccess( |
7347 PropertyAccessType access, | 7332 PropertyAccessType access, |
7348 BailoutId ast_id, | 7333 BailoutId ast_id, |
7349 BailoutId return_id, | 7334 BailoutId return_id, |
7350 Expression* expr, | 7335 Expression* expr, |
7351 HValue* object, | 7336 HValue* object, |
7352 Handle<String> name, | 7337 Handle<String> name, |
7353 HValue* value, | 7338 HValue* value, |
7354 bool is_uninitialized) { | 7339 bool is_uninitialized) { |
7355 SmallMapList* types; | 7340 SmallMapList* maps; |
7356 ComputeReceiverTypes(expr, object, &types, zone()); | 7341 ComputeReceiverTypes(expr, object, &maps, zone()); |
7357 DCHECK(types != NULL); | 7342 DCHECK(maps != NULL); |
7358 | 7343 |
7359 if (types->length() > 0) { | 7344 if (maps->length() > 0) { |
7360 PropertyAccessInfo info(this, access, ToType(types->first()), name); | 7345 PropertyAccessInfo info(this, access, maps->first(), name); |
7361 if (!info.CanAccessAsMonomorphic(types)) { | 7346 if (!info.CanAccessAsMonomorphic(maps)) { |
7362 HandlePolymorphicNamedFieldAccess( | 7347 HandlePolymorphicNamedFieldAccess(access, expr, ast_id, return_id, object, |
7363 access, expr, ast_id, return_id, object, value, types, name); | 7348 value, maps, name); |
7364 return NULL; | 7349 return NULL; |
7365 } | 7350 } |
7366 | 7351 |
7367 HValue* checked_object; | 7352 HValue* checked_object; |
7368 // Type::Number() is only supported by polymorphic load/call handling. | 7353 // Type::Number() is only supported by polymorphic load/call handling. |
7369 DCHECK(!info.type()->Is(Type::Number())); | 7354 DCHECK(!info.IsNumberType()); |
7370 BuildCheckHeapObject(object); | 7355 BuildCheckHeapObject(object); |
7371 if (AreStringTypes(types)) { | 7356 if (AreStringTypes(maps)) { |
7372 checked_object = | 7357 checked_object = |
7373 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); | 7358 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); |
7374 } else { | 7359 } else { |
7375 checked_object = Add<HCheckMaps>(object, types); | 7360 checked_object = Add<HCheckMaps>(object, maps); |
7376 } | 7361 } |
7377 return BuildMonomorphicAccess( | 7362 return BuildMonomorphicAccess( |
7378 &info, object, checked_object, value, ast_id, return_id); | 7363 &info, object, checked_object, value, ast_id, return_id); |
7379 } | 7364 } |
7380 | 7365 |
7381 return BuildNamedGeneric(access, expr, object, name, value, is_uninitialized); | 7366 return BuildNamedGeneric(access, expr, object, name, value, is_uninitialized); |
7382 } | 7367 } |
7383 | 7368 |
7384 | 7369 |
7385 void HOptimizedGraphBuilder::PushLoad(Property* expr, | 7370 void HOptimizedGraphBuilder::PushLoad(Property* expr, |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7555 }; | 7540 }; |
7556 | 7541 |
7557 | 7542 |
7558 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) { | 7543 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) { |
7559 int diff = lhs.ticks() - rhs.ticks(); | 7544 int diff = lhs.ticks() - rhs.ticks(); |
7560 if (diff != 0) return diff > 0; | 7545 if (diff != 0) return diff > 0; |
7561 return lhs.size() < rhs.size(); | 7546 return lhs.size() < rhs.size(); |
7562 } | 7547 } |
7563 | 7548 |
7564 | 7549 |
7565 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( | 7550 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(Call* expr, |
7566 Call* expr, | 7551 HValue* receiver, |
7567 HValue* receiver, | 7552 SmallMapList* maps, |
7568 SmallMapList* types, | 7553 Handle<String> name) { |
7569 Handle<String> name) { | |
7570 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 7554 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
7571 FunctionSorter order[kMaxCallPolymorphism]; | 7555 FunctionSorter order[kMaxCallPolymorphism]; |
7572 | 7556 |
7573 bool handle_smi = false; | 7557 bool handle_smi = false; |
7574 bool handled_string = false; | 7558 bool handled_string = false; |
7575 int ordered_functions = 0; | 7559 int ordered_functions = 0; |
7576 | 7560 |
7577 int i; | 7561 int i; |
7578 for (i = 0; i < types->length() && ordered_functions < kMaxCallPolymorphism; | 7562 for (i = 0; i < maps->length() && ordered_functions < kMaxCallPolymorphism; |
7579 ++i) { | 7563 ++i) { |
7580 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name); | 7564 PropertyAccessInfo info(this, LOAD, maps->at(i), name); |
7581 if (info.CanAccessMonomorphic() && info.IsDataConstant() && | 7565 if (info.CanAccessMonomorphic() && info.IsDataConstant() && |
7582 info.constant()->IsJSFunction()) { | 7566 info.constant()->IsJSFunction()) { |
7583 if (info.type()->Is(Type::String())) { | 7567 if (info.IsStringType()) { |
7584 if (handled_string) continue; | 7568 if (handled_string) continue; |
7585 handled_string = true; | 7569 handled_string = true; |
7586 } | 7570 } |
7587 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); | 7571 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); |
7588 if (info.type()->Is(Type::Number())) { | 7572 if (info.IsNumberType()) { |
7589 handle_smi = true; | 7573 handle_smi = true; |
7590 } | 7574 } |
7591 expr->set_target(target); | 7575 expr->set_target(target); |
7592 order[ordered_functions++] = FunctionSorter( | 7576 order[ordered_functions++] = FunctionSorter( |
7593 i, target->shared()->profiler_ticks(), InliningAstSize(target)); | 7577 i, target->shared()->profiler_ticks(), InliningAstSize(target)); |
7594 } | 7578 } |
7595 } | 7579 } |
7596 | 7580 |
7597 std::sort(order, order + ordered_functions); | 7581 std::sort(order, order + ordered_functions); |
7598 | 7582 |
7599 if (i < types->length()) { | 7583 if (i < maps->length()) { |
7600 types->Clear(); | 7584 maps->Clear(); |
7601 ordered_functions = -1; | 7585 ordered_functions = -1; |
7602 } | 7586 } |
7603 | 7587 |
7604 HBasicBlock* number_block = NULL; | 7588 HBasicBlock* number_block = NULL; |
7605 HBasicBlock* join = NULL; | 7589 HBasicBlock* join = NULL; |
7606 handled_string = false; | 7590 handled_string = false; |
7607 int count = 0; | 7591 int count = 0; |
7608 | 7592 |
7609 for (int fn = 0; fn < ordered_functions; ++fn) { | 7593 for (int fn = 0; fn < ordered_functions; ++fn) { |
7610 int i = order[fn].index(); | 7594 int i = order[fn].index(); |
7611 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name); | 7595 PropertyAccessInfo info(this, LOAD, maps->at(i), name); |
7612 if (info.type()->Is(Type::String())) { | 7596 if (info.IsStringType()) { |
7613 if (handled_string) continue; | 7597 if (handled_string) continue; |
7614 handled_string = true; | 7598 handled_string = true; |
7615 } | 7599 } |
7616 // Reloads the target. | 7600 // Reloads the target. |
7617 info.CanAccessMonomorphic(); | 7601 info.CanAccessMonomorphic(); |
7618 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); | 7602 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); |
7619 | 7603 |
7620 expr->set_target(target); | 7604 expr->set_target(target); |
7621 if (count == 0) { | 7605 if (count == 0) { |
7622 // Only needed once. | 7606 // Only needed once. |
7623 join = graph()->CreateBasicBlock(); | 7607 join = graph()->CreateBasicBlock(); |
7624 if (handle_smi) { | 7608 if (handle_smi) { |
7625 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); | 7609 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); |
7626 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); | 7610 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); |
7627 number_block = graph()->CreateBasicBlock(); | 7611 number_block = graph()->CreateBasicBlock(); |
7628 FinishCurrentBlock(New<HIsSmiAndBranch>( | 7612 FinishCurrentBlock(New<HIsSmiAndBranch>( |
7629 receiver, empty_smi_block, not_smi_block)); | 7613 receiver, empty_smi_block, not_smi_block)); |
7630 GotoNoSimulate(empty_smi_block, number_block); | 7614 GotoNoSimulate(empty_smi_block, number_block); |
7631 set_current_block(not_smi_block); | 7615 set_current_block(not_smi_block); |
7632 } else { | 7616 } else { |
7633 BuildCheckHeapObject(receiver); | 7617 BuildCheckHeapObject(receiver); |
7634 } | 7618 } |
7635 } | 7619 } |
7636 ++count; | 7620 ++count; |
7637 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 7621 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
7638 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 7622 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
7639 HUnaryControlInstruction* compare; | 7623 HUnaryControlInstruction* compare; |
7640 | 7624 |
7641 Handle<Map> map = info.map(); | 7625 Handle<Map> map = info.map(); |
7642 if (info.type()->Is(Type::Number())) { | 7626 if (info.IsNumberType()) { |
7643 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); | 7627 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); |
7644 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); | 7628 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); |
7645 } else if (info.type()->Is(Type::String())) { | 7629 } else if (info.IsStringType()) { |
7646 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); | 7630 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); |
7647 } else { | 7631 } else { |
7648 compare = New<HCompareMap>(receiver, map, if_true, if_false); | 7632 compare = New<HCompareMap>(receiver, map, if_true, if_false); |
7649 } | 7633 } |
7650 FinishCurrentBlock(compare); | 7634 FinishCurrentBlock(compare); |
7651 | 7635 |
7652 if (info.type()->Is(Type::Number())) { | 7636 if (info.IsNumberType()) { |
7653 GotoNoSimulate(if_true, number_block); | 7637 GotoNoSimulate(if_true, number_block); |
7654 if_true = number_block; | 7638 if_true = number_block; |
7655 } | 7639 } |
7656 | 7640 |
7657 set_current_block(if_true); | 7641 set_current_block(if_true); |
7658 | 7642 |
7659 AddCheckPrototypeMaps(info.holder(), map); | 7643 AddCheckPrototypeMaps(info.holder(), map); |
7660 | 7644 |
7661 HValue* function = Add<HConstant>(expr->target()); | 7645 HValue* function = Add<HConstant>(expr->target()); |
7662 environment()->SetExpressionStackAt(0, function); | 7646 environment()->SetExpressionStackAt(0, function); |
7663 Push(receiver); | 7647 Push(receiver); |
7664 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7648 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
7665 bool needs_wrapping = NeedsWrappingFor(info.type(), target); | 7649 bool needs_wrapping = info.NeedsWrappingFor(target); |
7666 bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping; | 7650 bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping; |
7667 if (FLAG_trace_inlining && try_inline) { | 7651 if (FLAG_trace_inlining && try_inline) { |
7668 Handle<JSFunction> caller = current_info()->closure(); | 7652 Handle<JSFunction> caller = current_info()->closure(); |
7669 SmartArrayPointer<char> caller_name = | 7653 SmartArrayPointer<char> caller_name = |
7670 caller->shared()->DebugName()->ToCString(); | 7654 caller->shared()->DebugName()->ToCString(); |
7671 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 7655 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
7672 name->ToCString().get(), | 7656 name->ToCString().get(), |
7673 caller_name.get()); | 7657 caller_name.get()); |
7674 } | 7658 } |
7675 if (try_inline && TryInlineCall(expr)) { | 7659 if (try_inline && TryInlineCall(expr)) { |
(...skipping 15 matching lines...) Expand all Loading... |
7691 if (!ast_context()->IsEffect()) Push(call); | 7675 if (!ast_context()->IsEffect()) Push(call); |
7692 } | 7676 } |
7693 | 7677 |
7694 if (current_block() != NULL) Goto(join); | 7678 if (current_block() != NULL) Goto(join); |
7695 set_current_block(if_false); | 7679 set_current_block(if_false); |
7696 } | 7680 } |
7697 | 7681 |
7698 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 7682 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
7699 // know about and do not want to handle ones we've never seen. Otherwise | 7683 // know about and do not want to handle ones we've never seen. Otherwise |
7700 // use a generic IC. | 7684 // use a generic IC. |
7701 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 7685 if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) { |
7702 FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall); | 7686 FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall); |
7703 } else { | 7687 } else { |
7704 Property* prop = expr->expression()->AsProperty(); | 7688 Property* prop = expr->expression()->AsProperty(); |
7705 HInstruction* function = BuildNamedGeneric( | 7689 HInstruction* function = BuildNamedGeneric( |
7706 LOAD, prop, receiver, name, NULL, prop->IsUninitialized()); | 7690 LOAD, prop, receiver, name, NULL, prop->IsUninitialized()); |
7707 AddInstruction(function); | 7691 AddInstruction(function); |
7708 Push(function); | 7692 Push(function); |
7709 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7693 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
7710 | 7694 |
7711 environment()->SetExpressionStackAt(1, function); | 7695 environment()->SetExpressionStackAt(1, function); |
(...skipping 1416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9128 DCHECK(current_block()->HasPredecessor()); | 9112 DCHECK(current_block()->HasPredecessor()); |
9129 Expression* callee = expr->expression(); | 9113 Expression* callee = expr->expression(); |
9130 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 9114 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
9131 HInstruction* call = NULL; | 9115 HInstruction* call = NULL; |
9132 | 9116 |
9133 Property* prop = callee->AsProperty(); | 9117 Property* prop = callee->AsProperty(); |
9134 if (prop != NULL) { | 9118 if (prop != NULL) { |
9135 CHECK_ALIVE(VisitForValue(prop->obj())); | 9119 CHECK_ALIVE(VisitForValue(prop->obj())); |
9136 HValue* receiver = Top(); | 9120 HValue* receiver = Top(); |
9137 | 9121 |
9138 SmallMapList* types; | 9122 SmallMapList* maps; |
9139 ComputeReceiverTypes(expr, receiver, &types, zone()); | 9123 ComputeReceiverTypes(expr, receiver, &maps, zone()); |
9140 | 9124 |
9141 if (prop->key()->IsPropertyName() && types->length() > 0) { | 9125 if (prop->key()->IsPropertyName() && maps->length() > 0) { |
9142 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 9126 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
9143 PropertyAccessInfo info(this, LOAD, ToType(types->first()), name); | 9127 PropertyAccessInfo info(this, LOAD, maps->first(), name); |
9144 if (!info.CanAccessAsMonomorphic(types)) { | 9128 if (!info.CanAccessAsMonomorphic(maps)) { |
9145 HandlePolymorphicCallNamed(expr, receiver, types, name); | 9129 HandlePolymorphicCallNamed(expr, receiver, maps, name); |
9146 return; | 9130 return; |
9147 } | 9131 } |
9148 } | 9132 } |
9149 | 9133 |
9150 HValue* key = NULL; | 9134 HValue* key = NULL; |
9151 if (!prop->key()->IsPropertyName()) { | 9135 if (!prop->key()->IsPropertyName()) { |
9152 CHECK_ALIVE(VisitForValue(prop->key())); | 9136 CHECK_ALIVE(VisitForValue(prop->key())); |
9153 key = Pop(); | 9137 key = Pop(); |
9154 } | 9138 } |
9155 | 9139 |
9156 CHECK_ALIVE(PushLoad(prop, receiver, key)); | 9140 CHECK_ALIVE(PushLoad(prop, receiver, key)); |
9157 HValue* function = Pop(); | 9141 HValue* function = Pop(); |
9158 | 9142 |
9159 if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); | 9143 if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); |
9160 | 9144 |
9161 if (function->IsConstant() && | 9145 if (function->IsConstant() && |
9162 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { | 9146 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { |
9163 // Push the function under the receiver. | 9147 // Push the function under the receiver. |
9164 environment()->SetExpressionStackAt(0, function); | 9148 environment()->SetExpressionStackAt(0, function); |
9165 Push(receiver); | 9149 Push(receiver); |
9166 | 9150 |
9167 Handle<JSFunction> known_function = Handle<JSFunction>::cast( | 9151 Handle<JSFunction> known_function = Handle<JSFunction>::cast( |
9168 HConstant::cast(function)->handle(isolate())); | 9152 HConstant::cast(function)->handle(isolate())); |
9169 expr->set_target(known_function); | 9153 expr->set_target(known_function); |
9170 | 9154 |
9171 if (TryIndirectCall(expr)) return; | 9155 if (TryIndirectCall(expr)) return; |
9172 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 9156 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
9173 | 9157 |
9174 Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>(); | 9158 Handle<Map> map = maps->length() == 1 ? maps->first() : Handle<Map>(); |
9175 if (TryInlineBuiltinMethodCall(expr, known_function, map, | 9159 if (TryInlineBuiltinMethodCall(expr, known_function, map, |
9176 expr->arguments()->length())) { | 9160 expr->arguments()->length())) { |
9177 if (FLAG_trace_inlining) { | 9161 if (FLAG_trace_inlining) { |
9178 PrintF("Inlining builtin "); | 9162 PrintF("Inlining builtin "); |
9179 known_function->ShortPrint(); | 9163 known_function->ShortPrint(); |
9180 PrintF("\n"); | 9164 PrintF("\n"); |
9181 } | 9165 } |
9182 return; | 9166 return; |
9183 } | 9167 } |
9184 if (TryInlineApiMethodCall(expr, receiver, types)) return; | 9168 if (TryInlineApiMethodCall(expr, receiver, maps)) return; |
9185 | 9169 |
9186 // Wrap the receiver if necessary. | 9170 // Wrap the receiver if necessary. |
9187 if (NeedsWrappingFor(ToType(types->first()), known_function)) { | 9171 if (NeedsWrapping(maps->first(), known_function)) { |
9188 // Since HWrapReceiver currently cannot actually wrap numbers and | 9172 // Since HWrapReceiver currently cannot actually wrap numbers and |
9189 // strings, use the regular CallFunctionStub for method calls to wrap | 9173 // strings, use the regular CallFunctionStub for method calls to wrap |
9190 // the receiver. | 9174 // the receiver. |
9191 // TODO(verwaest): Support creation of value wrappers directly in | 9175 // TODO(verwaest): Support creation of value wrappers directly in |
9192 // HWrapReceiver. | 9176 // HWrapReceiver. |
9193 call = New<HCallFunction>( | 9177 call = New<HCallFunction>( |
9194 function, argument_count, WRAP_AND_CALL); | 9178 function, argument_count, WRAP_AND_CALL); |
9195 } else if (TryInlineCall(expr)) { | 9179 } else if (TryInlineCall(expr)) { |
9196 return; | 9180 return; |
9197 } else { | 9181 } else { |
(...skipping 4245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13443 if (ShouldProduceTraceOutput()) { | 13427 if (ShouldProduceTraceOutput()) { |
13444 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13428 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13445 } | 13429 } |
13446 | 13430 |
13447 #ifdef DEBUG | 13431 #ifdef DEBUG |
13448 graph_->Verify(false); // No full verify. | 13432 graph_->Verify(false); // No full verify. |
13449 #endif | 13433 #endif |
13450 } | 13434 } |
13451 | 13435 |
13452 } } // namespace v8::internal | 13436 } } // namespace v8::internal |
OLD | NEW |