Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(300)

Side by Side Diff: src/hydrogen.cc

Issue 935603002: Stop using HeapType in IC and Crankshaft (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/hydrogen.h ('k') | src/ic/arm/handler-compiler-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/ic/arm/handler-compiler-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698