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

Side by Side Diff: src/hydrogen.cc

Issue 153933002: Use PropertyAccessInfo to compute stores in crankshaft. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebase and fixes Created 6 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 | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.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 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 4910 matching lines...) Expand 10 before | Expand all | Expand 10 after
4921 static bool CanInlinePropertyAccess(Type* type) { 4921 static bool CanInlinePropertyAccess(Type* type) {
4922 if (type->Is(Type::NumberOrString())) return true; 4922 if (type->Is(Type::NumberOrString())) return true;
4923 if (!type->IsClass()) return false; 4923 if (!type->IsClass()) return false;
4924 Handle<Map> map = type->AsClass(); 4924 Handle<Map> map = type->AsClass();
4925 return map->IsJSObjectMap() && 4925 return map->IsJSObjectMap() &&
4926 !map->is_dictionary_map() && 4926 !map->is_dictionary_map() &&
4927 !map->has_named_interceptor(); 4927 !map->has_named_interceptor();
4928 } 4928 }
4929 4929
4930 4930
4931 static void LookupInPrototypes(Handle<Map> map,
4932 Handle<String> name,
4933 LookupResult* lookup,
4934 Zone* zone) {
4935 while (map->prototype()->IsJSObject()) {
4936 Handle<JSObject> holder(JSObject::cast(map->prototype()));
4937 map = handle(holder->map());
4938 if (!CanInlinePropertyAccess(IC::MapToType<Type>(map, zone))) break;
4939 map->LookupDescriptor(*holder, *name, lookup);
4940 if (lookup->IsFound()) return;
4941 }
4942 lookup->NotFound();
4943 }
4944
4945
4946 // Tries to find a JavaScript accessor of the given name in the prototype chain
4947 // starting at the given map. Return true iff there is one, including the
4948 // corresponding AccessorPair plus its holder (which could be null when the
4949 // accessor is found directly in the given map).
4950 static bool LookupAccessorPair(Handle<Map> map,
4951 Handle<String> name,
4952 Handle<AccessorPair>* accessors,
4953 Handle<JSObject>* holder,
4954 Zone* zone) {
4955 Isolate* isolate = map->GetIsolate();
4956 LookupResult lookup(isolate);
4957
4958 // Check for a JavaScript accessor directly in the map.
4959 map->LookupDescriptor(NULL, *name, &lookup);
4960 if (lookup.IsPropertyCallbacks()) {
4961 Handle<Object> callback(lookup.GetValueFromMap(*map), isolate);
4962 if (!callback->IsAccessorPair()) return false;
4963 *accessors = Handle<AccessorPair>::cast(callback);
4964 *holder = Handle<JSObject>();
4965 return true;
4966 }
4967
4968 // Everything else, e.g. a field, can't be an accessor call.
4969 if (lookup.IsFound()) return false;
4970
4971 // Check for a JavaScript accessor somewhere in the proto chain.
4972 LookupInPrototypes(map, name, &lookup, zone);
4973 if (lookup.IsPropertyCallbacks()) {
4974 Handle<Object> callback(lookup.GetValue(), isolate);
4975 if (!callback->IsAccessorPair()) return false;
4976 *accessors = Handle<AccessorPair>::cast(callback);
4977 *holder = Handle<JSObject>(lookup.holder());
4978 return true;
4979 }
4980
4981 // We haven't found a JavaScript accessor anywhere.
4982 return false;
4983 }
4984
4985
4986 static bool LookupSetter(Handle<Map> map,
4987 Handle<String> name,
4988 Handle<JSFunction>* setter,
4989 Handle<JSObject>* holder,
4990 Zone* zone) {
4991 Handle<AccessorPair> accessors;
4992 if (LookupAccessorPair(map, name, &accessors, holder, zone) &&
4993 accessors->setter()->IsJSFunction()) {
4994 Handle<JSFunction> func(JSFunction::cast(accessors->setter()));
4995 CallOptimization call_optimization(func);
4996 // TODO(dcarney): temporary hack unless crankshaft can handle api calls.
4997 if (call_optimization.is_simple_api_call()) return false;
4998 *setter = func;
4999 return true;
5000 }
5001 return false;
5002 }
5003
5004
5005 // Determines whether the given array or object literal boilerplate satisfies 4931 // Determines whether the given array or object literal boilerplate satisfies
5006 // all limits to be considered for fast deep-copying and computes the total 4932 // all limits to be considered for fast deep-copying and computes the total
5007 // size of all objects that are part of the graph. 4933 // size of all objects that are part of the graph.
5008 static bool IsFastLiteral(Handle<JSObject> boilerplate, 4934 static bool IsFastLiteral(Handle<JSObject> boilerplate,
5009 int max_depth, 4935 int max_depth,
5010 int* max_properties) { 4936 int* max_properties) {
5011 if (boilerplate->map()->is_deprecated()) { 4937 if (boilerplate->map()->is_deprecated()) {
5012 Handle<Object> result = JSObject::TryMigrateInstance(boilerplate); 4938 Handle<Object> result = JSObject::TryMigrateInstance(boilerplate);
5013 if (result.is_null()) return false; 4939 if (result.is_null()) return false;
5014 } 4940 }
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
5140 if (property->emit_store()) { 5066 if (property->emit_store()) {
5141 CHECK_ALIVE(VisitForValue(value)); 5067 CHECK_ALIVE(VisitForValue(value));
5142 HValue* value = Pop(); 5068 HValue* value = Pop();
5143 Handle<Map> map = property->GetReceiverType(); 5069 Handle<Map> map = property->GetReceiverType();
5144 Handle<String> name = property->key()->AsPropertyName(); 5070 Handle<String> name = property->key()->AsPropertyName();
5145 HInstruction* store; 5071 HInstruction* store;
5146 if (map.is_null()) { 5072 if (map.is_null()) {
5147 // If we don't know the monomorphic type, do a generic store. 5073 // If we don't know the monomorphic type, do a generic store.
5148 CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value)); 5074 CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value));
5149 } else { 5075 } else {
5150 #if DEBUG 5076 PropertyAccessInfo info(this, STORE, ToType(map), name);
5151 Handle<JSFunction> setter; 5077 if (info.CanAccessMonomorphic()) {
5152 Handle<JSObject> holder; 5078 HValue* checked_literal = BuildCheckMap(literal, map);
5153 ASSERT(!LookupSetter(map, name, &setter, &holder, zone())); 5079 ASSERT(!info.lookup()->IsPropertyCallbacks());
5154 #endif 5080 store = BuildStoreMonomorphic(
5155 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, 5081 &info, checked_literal, value,
5156 name, 5082 BailoutId::None(), BailoutId::None());
5157 value, 5083 } else {
5158 map)); 5084 CHECK_ALIVE(
5085 store = BuildStoreNamedGeneric(literal, name, value));
5086 }
5159 } 5087 }
5160 AddInstruction(store); 5088 AddInstruction(store);
5161 if (store->HasObservableSideEffects()) { 5089 if (store->HasObservableSideEffects()) {
5162 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); 5090 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
5163 } 5091 }
5164 } else { 5092 } else {
5165 CHECK_ALIVE(VisitForEffect(value)); 5093 CHECK_ALIVE(VisitForEffect(value));
5166 } 5094 }
5167 break; 5095 break;
5168 } 5096 }
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
5324 5252
5325 5253
5326 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object, 5254 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
5327 Handle<Map> map) { 5255 Handle<Map> map) {
5328 BuildCheckHeapObject(object); 5256 BuildCheckHeapObject(object);
5329 return Add<HCheckMaps>(object, map, top_info()); 5257 return Add<HCheckMaps>(object, map, top_info());
5330 } 5258 }
5331 5259
5332 5260
5333 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( 5261 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
5262 PropertyAccessInfo* info,
5334 HValue* checked_object, 5263 HValue* checked_object,
5335 Handle<String> name, 5264 HValue* value) {
5336 HValue* value, 5265 bool transition_to_field = info->lookup()->IsTransition();
5337 Handle<Map> map, 5266 // TODO(verwaest): Move this logic into PropertyAccessInfo.
5338 LookupResult* lookup) { 5267 HObjectAccess field_access = HObjectAccess::ForField(
5339 ASSERT(lookup->IsFound()); 5268 info->map(), info->lookup(), info->name());
5340 // If the property does not exist yet, we have to check that it wasn't made
5341 // readonly or turned into a setter by some meanwhile modifications on the
5342 // prototype chain.
5343 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) {
5344 Object* proto = map->prototype();
5345 // First check that the prototype chain isn't affected already.
5346 LookupResult proto_result(isolate());
5347 proto->Lookup(*name, &proto_result);
5348 if (proto_result.IsProperty()) {
5349 // If the inherited property could induce readonly-ness, bail out.
5350 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) {
5351 Bailout(kImproperObjectOnPrototypeChainForStore);
5352 return NULL;
5353 }
5354 // We only need to check up to the preexisting property.
5355 proto = proto_result.holder();
5356 } else {
5357 // Otherwise, find the top prototype.
5358 while (proto->GetPrototype(isolate())->IsJSObject()) {
5359 proto = proto->GetPrototype(isolate());
5360 }
5361 ASSERT(proto->GetPrototype(isolate())->IsNull());
5362 }
5363 ASSERT(proto->IsJSObject());
5364 BuildCheckPrototypeMaps(
5365 Handle<JSObject>(JSObject::cast(map->prototype())),
5366 Handle<JSObject>(JSObject::cast(proto)));
5367 }
5368
5369 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name);
5370 bool transition_to_field = lookup->IsTransitionToField(*map);
5371 5269
5372 HStoreNamedField *instr; 5270 HStoreNamedField *instr;
5373 if (FLAG_track_double_fields && field_access.representation().IsDouble()) { 5271 if (FLAG_track_double_fields && field_access.representation().IsDouble()) {
5374 HObjectAccess heap_number_access = 5272 HObjectAccess heap_number_access =
5375 field_access.WithRepresentation(Representation::Tagged()); 5273 field_access.WithRepresentation(Representation::Tagged());
5376 if (transition_to_field) { 5274 if (transition_to_field) {
5377 // The store requires a mutable HeapNumber to be allocated. 5275 // The store requires a mutable HeapNumber to be allocated.
5378 NoObservableSideEffectsScope no_side_effects(this); 5276 NoObservableSideEffectsScope no_side_effects(this);
5379 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); 5277 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
5380 5278
(...skipping 20 matching lines...) Expand all
5401 value, STORE_TO_INITIALIZED_ENTRY); 5299 value, STORE_TO_INITIALIZED_ENTRY);
5402 } 5300 }
5403 } else { 5301 } else {
5404 // This is a normal store. 5302 // This is a normal store.
5405 instr = New<HStoreNamedField>( 5303 instr = New<HStoreNamedField>(
5406 checked_object->ActualValue(), field_access, value, 5304 checked_object->ActualValue(), field_access, value,
5407 transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY); 5305 transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY);
5408 } 5306 }
5409 5307
5410 if (transition_to_field) { 5308 if (transition_to_field) {
5411 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); 5309 HConstant* transition_constant = Add<HConstant>(info->transition());
5412 HConstant* transition_constant = Add<HConstant>(transition);
5413 instr->SetTransition(transition_constant, top_info()); 5310 instr->SetTransition(transition_constant, top_info());
5414 // TODO(fschneider): Record the new map type of the object in the IR to
5415 // enable elimination of redundant checks after the transition store.
5416 instr->SetGVNFlag(kChangesMaps); 5311 instr->SetGVNFlag(kChangesMaps);
5417 } 5312 }
5418 return instr; 5313 return instr;
5419 } 5314 }
5420 5315
5421 5316
5422 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( 5317 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric(
5423 HValue* object, 5318 HValue* object,
5424 Handle<String> name, 5319 Handle<String> name,
5425 HValue* value) { 5320 HValue* value,
5321 bool is_uninitialized) {
5322 if (is_uninitialized) {
5323 Add<HDeoptimize>("Insufficient type feedback for property assignment",
5324 Deoptimizer::SOFT);
5325 }
5326
5426 return New<HStoreNamedGeneric>( 5327 return New<HStoreNamedGeneric>(
5427 object, 5328 object,
5428 name, 5329 name,
5429 value, 5330 value,
5430 function_strict_mode_flag()); 5331 function_strict_mode_flag());
5431 } 5332 }
5432 5333
5433 5334
5434 // Sets the lookup result and returns true if the load/store can be inlined. 5335 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
5435 static bool ComputeStoreField(Type* type,
5436 Handle<String> name,
5437 LookupResult* lookup,
5438 bool lookup_transition = true) {
5439 if (!CanInlinePropertyAccess(type) || !type->IsClass()) {
5440 lookup->NotFound();
5441 return false;
5442 }
5443 Handle<Map> map = type->AsClass();
5444 ASSERT(!map->is_observed());
5445 // If we directly find a field, the access can be inlined.
5446 map->LookupDescriptor(NULL, *name, lookup);
5447 if (lookup->IsField()) return true;
5448
5449 if (!lookup_transition) return false;
5450
5451 map->LookupTransition(NULL, *name, lookup);
5452 return lookup->IsTransitionToField(*map) && map->unused_property_fields() > 0;
5453 }
5454
5455
5456 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic(
5457 HValue* object,
5458 Handle<String> name,
5459 HValue* value,
5460 Handle<Map> map) {
5461 // Handle a store to a known field.
5462 LookupResult lookup(isolate());
5463 if (ComputeStoreField(ToType(map), name, &lookup)) {
5464 HCheckMaps* checked_object = AddCheckMap(object, map);
5465 return BuildStoreNamedField(checked_object, name, value, map, &lookup);
5466 }
5467
5468 // No luck, do a generic store.
5469 return BuildStoreNamedGeneric(object, name, value);
5470 }
5471
5472
5473 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatibleForLoad(
5474 PropertyAccessInfo* info) { 5336 PropertyAccessInfo* info) {
5475 if (!CanInlinePropertyAccess(type_)) return false; 5337 if (!CanInlinePropertyAccess(type_)) return false;
5476 5338
5477 // Currently only handle Type::Number as a polymorphic case. 5339 // Currently only handle Type::Number as a polymorphic case.
5478 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber 5340 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
5479 // instruction. 5341 // instruction.
5480 if (type_->Is(Type::Number())) return false; 5342 if (type_->Is(Type::Number())) return false;
5481 5343
5482 // Values are only compatible for monomorphic load if they all behave the same 5344 // Values are only compatible for monomorphic load if they all behave the same
5483 // regarding value wrappers. 5345 // regarding value wrappers.
(...skipping 19 matching lines...) Expand all
5503 } 5365 }
5504 5366
5505 if (lookup_.IsConstant()) { 5367 if (lookup_.IsConstant()) {
5506 return constant_.is_identical_to(info->constant_); 5368 return constant_.is_identical_to(info->constant_);
5507 } 5369 }
5508 5370
5509 ASSERT(lookup_.IsField()); 5371 ASSERT(lookup_.IsField());
5510 if (!info->lookup_.IsField()) return false; 5372 if (!info->lookup_.IsField()) return false;
5511 5373
5512 Representation r = access_.representation(); 5374 Representation r = access_.representation();
5513 if (!info->access_.representation().IsCompatibleForLoad(r)) return false; 5375 if (IsLoad()) {
5376 if (!info->access_.representation().IsCompatibleForLoad(r)) return false;
5377 } else {
5378 if (!info->access_.representation().IsCompatibleForStore(r)) return false;
5379 }
5514 if (info->access_.offset() != access_.offset()) return false; 5380 if (info->access_.offset() != access_.offset()) return false;
5515 if (info->access_.IsInobject() != access_.IsInobject()) return false; 5381 if (info->access_.IsInobject() != access_.IsInobject()) return false;
5516 info->GeneralizeRepresentation(r); 5382 info->GeneralizeRepresentation(r);
5517 return true; 5383 return true;
5518 } 5384 }
5519 5385
5520 5386
5521 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() { 5387 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
5522 if (!type_->IsClass()) return true; 5388 if (!type_->IsClass()) return true;
5523 map()->LookupDescriptor(NULL, *name_, &lookup_); 5389 map()->LookupDescriptor(NULL, *name_, &lookup_);
5524 return LoadResult(map()); 5390 return LoadResult(map());
5525 } 5391 }
5526 5392
5527 5393
5528 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { 5394 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
5395 if (!IsLoad() && lookup_.IsProperty() &&
5396 (lookup_.IsReadOnly() || !lookup_.IsCacheable())) {
5397 return false;
5398 }
5399
5529 if (lookup_.IsField()) { 5400 if (lookup_.IsField()) {
5530 access_ = HObjectAccess::ForField(map, &lookup_, name_); 5401 access_ = HObjectAccess::ForField(map, &lookup_, name_);
5531 } else if (lookup_.IsPropertyCallbacks()) { 5402 } else if (lookup_.IsPropertyCallbacks()) {
5532 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate()); 5403 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate());
5533 if (!callback->IsAccessorPair()) return false; 5404 if (!callback->IsAccessorPair()) return false;
5534 Object* getter = Handle<AccessorPair>::cast(callback)->getter(); 5405 Object* raw_accessor = IsLoad()
5535 if (!getter->IsJSFunction()) return false; 5406 ? Handle<AccessorPair>::cast(callback)->getter()
5536 Handle<JSFunction> accessor = handle(JSFunction::cast(getter)); 5407 : Handle<AccessorPair>::cast(callback)->setter();
5408 if (!raw_accessor->IsJSFunction()) return false;
5409 Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor));
5537 CallOptimization call_optimization(accessor); 5410 CallOptimization call_optimization(accessor);
5538 // TODO(dcarney): temporary hack unless crankshaft can handle api calls. 5411 // TODO(dcarney): temporary hack unless crankshaft can handle api calls.
5539 if (call_optimization.is_simple_api_call()) return false; 5412 if (call_optimization.is_simple_api_call()) return false;
5540 accessor_ = accessor; 5413 accessor_ = accessor;
5541 } else if (lookup_.IsConstant()) { 5414 } else if (lookup_.IsConstant()) {
5542 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate()); 5415 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate());
5543 } 5416 }
5544 5417
5545 return true; 5418 return true;
5546 } 5419 }
(...skipping 13 matching lines...) Expand all
5560 return false; 5433 return false;
5561 } 5434 }
5562 map->LookupDescriptor(*holder_, *name_, &lookup_); 5435 map->LookupDescriptor(*holder_, *name_, &lookup_);
5563 if (lookup_.IsFound()) return LoadResult(map); 5436 if (lookup_.IsFound()) return LoadResult(map);
5564 } 5437 }
5565 lookup_.NotFound(); 5438 lookup_.NotFound();
5566 return true; 5439 return true;
5567 } 5440 }
5568 5441
5569 5442
5570 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadMonomorphic() { 5443 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
5571 if (!CanInlinePropertyAccess(type_)) return false; 5444 if (!CanInlinePropertyAccess(type_)) return false;
5572 if (IsJSObjectFieldAccessor()) return true; 5445 if (IsJSObjectFieldAccessor()) {
5446 // We should never have gathered typefeedback for JSObjectFieldAccessor
5447 // stores.
5448 ASSERT(IsLoad());
5449 return true;
5450 }
5573 if (!LookupDescriptor()) return false; 5451 if (!LookupDescriptor()) return false;
5574 if (lookup_.IsFound()) return true; 5452 if (lookup_.IsFound()) {
5575 return LookupInPrototypes(); 5453 if (IsLoad()) return true;
5454 return !lookup_.IsReadOnly() && lookup_.IsCacheable();
5455 }
5456 if (!LookupInPrototypes()) return false;
5457 if (IsLoad()) return true;
5458
5459 if (lookup_.IsPropertyCallbacks()) return true;
5460 Handle<Map> map = this->map();
5461 map->LookupTransition(NULL, *name_, &lookup_);
5462 if (lookup_.IsTransitionToField(*map) && map->unused_property_fields() > 0) {
5463 transition_ = handle(lookup_.GetTransitionMapFromMap(*map));
5464 return true;
5465 }
5466 return false;
5576 } 5467 }
5577 5468
5578 5469
5579 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadAsMonomorphic( 5470 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
5580 SmallMapList* types) { 5471 SmallMapList* types) {
5581 ASSERT(type_->Is(ToType(types->first()))); 5472 ASSERT(type_->Is(ToType(types->first())));
5582 if (!CanLoadMonomorphic()) return false; 5473 if (!CanAccessMonomorphic()) return false;
5474 STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
5583 if (types->length() > kMaxLoadPolymorphism) return false; 5475 if (types->length() > kMaxLoadPolymorphism) return false;
5584 5476
5585 if (IsArrayLength()) { 5477 if (IsArrayLength()) {
5586 bool is_fast = IsFastElementsKind(map()->elements_kind()); 5478 bool is_fast = IsFastElementsKind(map()->elements_kind());
5587 for (int i = 1; i < types->length(); ++i) { 5479 for (int i = 1; i < types->length(); ++i) {
5588 Handle<Map> test_map = types->at(i); 5480 Handle<Map> test_map = types->at(i);
5589 if (test_map->instance_type() != JS_ARRAY_TYPE) return false; 5481 if (test_map->instance_type() != JS_ARRAY_TYPE) return false;
5590 if (IsFastElementsKind(test_map->elements_kind()) != is_fast) { 5482 if (IsFastElementsKind(test_map->elements_kind()) != is_fast) {
5591 return false; 5483 return false;
5592 } 5484 }
5593 } 5485 }
5594 return true; 5486 return true;
5595 } 5487 }
5596 5488
5597 HObjectAccess access = HObjectAccess::ForMap(); // bogus default 5489 HObjectAccess access = HObjectAccess::ForMap(); // bogus default
5598 if (GetJSObjectFieldAccess(&access)) { 5490 if (GetJSObjectFieldAccess(&access)) {
5599 for (int i = 1; i < types->length(); ++i) { 5491 for (int i = 1; i < types->length(); ++i) {
5600 PropertyAccessInfo test_info(builder_, ToType(types->at(i)), name_); 5492 PropertyAccessInfo test_info(
5493 builder_, access_type_, ToType(types->at(i)), name_);
5601 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default 5494 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default
5602 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false; 5495 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false;
5603 if (!access.Equals(test_access)) return false; 5496 if (!access.Equals(test_access)) return false;
5604 } 5497 }
5605 return true; 5498 return true;
5606 } 5499 }
5607 5500
5608 // Currently only handle Type::Number as a polymorphic case. 5501 // Currently only handle Type::Number as a polymorphic case.
5609 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber 5502 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
5610 // instruction. 5503 // instruction.
5611 if (type_->Is(Type::Number())) return false; 5504 if (type_->Is(Type::Number())) return false;
5612 5505
5506 // Multiple maps cannot transition to the same target map.
5507 ASSERT(!IsLoad() || !lookup_.IsTransition());
5508 if (lookup_.IsTransition() && types->length() > 1) return false;
5509
5613 for (int i = 1; i < types->length(); ++i) { 5510 for (int i = 1; i < types->length(); ++i) {
5614 PropertyAccessInfo test_info(builder_, ToType(types->at(i)), name_); 5511 PropertyAccessInfo test_info(
5615 if (!test_info.IsCompatibleForLoad(this)) return false; 5512 builder_, access_type_, ToType(types->at(i)), name_);
5513 if (!test_info.IsCompatible(this)) return false;
5616 } 5514 }
5617 5515
5618 return true; 5516 return true;
5619 } 5517 }
5620 5518
5621 5519
5622 static bool NeedsWrappingFor(Type* type, Handle<JSFunction> target) { 5520 static bool NeedsWrappingFor(Type* type, Handle<JSFunction> target) {
5623 return type->Is(Type::NumberOrString()) && 5521 return type->Is(Type::NumberOrString()) &&
5624 target->shared()->is_classic_mode() && 5522 target->shared()->is_classic_mode() &&
5625 !target->shared()->native(); 5523 !target->shared()->native();
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
5667 Add<HPushArgument>(Pop()); 5565 Add<HPushArgument>(Pop());
5668 return BuildCallConstantFunction(info->accessor(), 1); 5566 return BuildCallConstantFunction(info->accessor(), 1);
5669 } 5567 }
5670 } 5568 }
5671 5569
5672 ASSERT(info->lookup()->IsConstant()); 5570 ASSERT(info->lookup()->IsConstant());
5673 return New<HConstant>(info->constant()); 5571 return New<HConstant>(info->constant());
5674 } 5572 }
5675 5573
5676 5574
5575 HInstruction* HOptimizedGraphBuilder::BuildStoreMonomorphic(
5576 PropertyAccessInfo* info,
5577 HValue* checked_object,
5578 HValue* value,
5579 BailoutId ast_id,
5580 BailoutId return_id,
5581 bool can_inline_accessor) {
5582 ASSERT(!info->IsJSObjectFieldAccessor());
5583
5584 if (info->has_holder()) {
5585 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
5586 BuildCheckPrototypeMaps(prototype, info->holder());
5587 }
5588
5589 if (info->lookup()->IsPropertyCallbacks()) {
5590 if (NeedsWrappingFor(info->type(), info->accessor())) {
5591 HValue* function = Add<HConstant>(info->accessor());
5592 Add<HPushArgument>(checked_object);
5593 Add<HPushArgument>(value);
5594 return New<HCallFunction>(function, 2, WRAP_AND_CALL);
5595 } else {
5596 Push(checked_object);
5597 Push(value);
5598 if (FLAG_inline_accessors &&
5599 can_inline_accessor &&
5600 TryInlineSetter(info->accessor(), ast_id, return_id, value)) {
5601 return NULL;
5602 }
5603 PushArgumentsFromEnvironment(2);
5604 return BuildCallConstantFunction(info->accessor(), 2);
5605 }
5606 }
5607
5608 if (info->lookup()->IsConstant()) {
5609 // Check whether we are trying to store the same constant.
5610 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant()));
5611 }
5612
5613 ASSERT(info->lookup()->IsField() || info->lookup()->IsTransition());
5614 return BuildStoreNamedField(info, checked_object, value);
5615 }
5616
5617
5677 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( 5618 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
5678 BailoutId ast_id, 5619 BailoutId ast_id,
5679 BailoutId return_id, 5620 BailoutId return_id,
5680 HValue* object, 5621 HValue* object,
5681 SmallMapList* types, 5622 SmallMapList* types,
5682 Handle<String> name) { 5623 Handle<String> name) {
5683 // Something did not match; must use a polymorphic load. 5624 // Something did not match; must use a polymorphic load.
5684 int count = 0; 5625 int count = 0;
5685 HBasicBlock* join = NULL; 5626 HBasicBlock* join = NULL;
5686 HBasicBlock* number_block = NULL; 5627 HBasicBlock* number_block = NULL;
5687 bool handled_string = false; 5628 bool handled_string = false;
5688 5629
5689 bool handle_smi = false; 5630 bool handle_smi = false;
5690 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { 5631 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
5691 PropertyAccessInfo info(this, ToType(types->at(i)), name); 5632 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
5692 if (info.type()->Is(Type::String())) { 5633 if (info.type()->Is(Type::String())) {
5693 if (handled_string) continue; 5634 if (handled_string) continue;
5694 handled_string = true; 5635 handled_string = true;
5695 } 5636 }
5696 if (info.CanLoadMonomorphic()) { 5637 if (info.CanAccessMonomorphic()) {
5697 count++; 5638 count++;
5698 if (info.type()->Is(Type::Number())) { 5639 if (info.type()->Is(Type::Number())) {
5699 handle_smi = true; 5640 handle_smi = true;
5700 break; 5641 break;
5701 } 5642 }
5702 } 5643 }
5703 } 5644 }
5704 5645
5705 count = 0; 5646 count = 0;
5706 HControlInstruction* smi_check = NULL; 5647 HControlInstruction* smi_check = NULL;
5707 handled_string = false; 5648 handled_string = false;
5708 5649
5709 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { 5650 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
5710 PropertyAccessInfo info(this, ToType(types->at(i)), name); 5651 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
5711 if (info.type()->Is(Type::String())) { 5652 if (info.type()->Is(Type::String())) {
5712 if (handled_string) continue; 5653 if (handled_string) continue;
5713 handled_string = true; 5654 handled_string = true;
5714 } 5655 }
5715 if (!info.CanLoadMonomorphic()) continue; 5656 if (!info.CanAccessMonomorphic()) continue;
5716 5657
5717 if (count == 0) { 5658 if (count == 0) {
5718 join = graph()->CreateBasicBlock(); 5659 join = graph()->CreateBasicBlock();
5719 if (handle_smi) { 5660 if (handle_smi) {
5720 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); 5661 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
5721 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); 5662 HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
5722 number_block = graph()->CreateBasicBlock(); 5663 number_block = graph()->CreateBasicBlock();
5723 smi_check = New<HIsSmiAndBranch>( 5664 smi_check = New<HIsSmiAndBranch>(
5724 object, empty_smi_block, not_smi_block); 5665 object, empty_smi_block, not_smi_block);
5725 FinishCurrentBlock(smi_check); 5666 FinishCurrentBlock(smi_check);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
5794 } 5735 }
5795 } 5736 }
5796 5737
5797 ASSERT(join != NULL); 5738 ASSERT(join != NULL);
5798 join->SetJoinId(ast_id); 5739 join->SetJoinId(ast_id);
5799 set_current_block(join); 5740 set_current_block(join);
5800 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); 5741 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
5801 } 5742 }
5802 5743
5803 5744
5804 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
5805 BailoutId assignment_id,
5806 HValue* object,
5807 HValue* value,
5808 SmallMapList* types,
5809 Handle<String> name) {
5810 // Use monomorphic store if property lookup results in the same field index
5811 // for all maps. Requires special map check on the set of all handled maps.
5812 if (types->length() > kMaxStorePolymorphism) return false;
5813
5814 LookupResult lookup(isolate());
5815 int count;
5816 Representation representation = Representation::None();
5817 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused.
5818 for (count = 0; count < types->length(); ++count) {
5819 Handle<Map> map = types->at(count);
5820 // Pass false to ignore transitions.
5821 if (!ComputeStoreField(ToType(map), name, &lookup, false)) break;
5822 ASSERT(!map->is_observed());
5823
5824 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name);
5825 Representation new_representation = new_access.representation();
5826
5827 if (count == 0) {
5828 // First time through the loop; set access and representation.
5829 access = new_access;
5830 representation = new_representation;
5831 } else if (!representation.IsCompatibleForStore(new_representation)) {
5832 // Representations did not match.
5833 break;
5834 } else if (access.offset() != new_access.offset()) {
5835 // Offsets did not match.
5836 break;
5837 } else if (access.IsInobject() != new_access.IsInobject()) {
5838 // In-objectness did not match.
5839 break;
5840 }
5841 }
5842
5843 if (count != types->length()) return false;
5844
5845 // Everything matched; can use monomorphic store.
5846 BuildCheckHeapObject(object);
5847 HCheckMaps* checked_object = Add<HCheckMaps>(object, types);
5848 HInstruction* store;
5849 CHECK_ALIVE_OR_RETURN(
5850 store = BuildStoreNamedField(
5851 checked_object, name, value, types->at(count - 1), &lookup),
5852 true);
5853 if (!ast_context()->IsEffect()) Push(value);
5854 AddInstruction(store);
5855 Add<HSimulate>(assignment_id);
5856 if (!ast_context()->IsEffect()) Drop(1);
5857 ast_context()->ReturnValue(value);
5858 return true;
5859 }
5860
5861
5862 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( 5745 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
5863 BailoutId assignment_id, 5746 BailoutId assignment_id,
5747 BailoutId return_id,
5864 HValue* object, 5748 HValue* object,
5865 HValue* value, 5749 HValue* value,
5866 SmallMapList* types, 5750 SmallMapList* types,
5867 Handle<String> name) { 5751 Handle<String> name) {
5868 if (TryStorePolymorphicAsMonomorphic(
5869 assignment_id, object, value, types, name)) {
5870 return;
5871 }
5872
5873 // TODO(ager): We should recognize when the prototype chains for different
5874 // maps are identical. In that case we can avoid repeatedly generating the
5875 // same prototype map checks.
5876 int count = 0; 5752 int count = 0;
5877 HBasicBlock* join = NULL; 5753 HBasicBlock* join = NULL;
5754 // TODO(verwaest): Unify with polymorphic load handling.
5878 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { 5755 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
5879 Handle<Map> map = types->at(i); 5756 PropertyAccessInfo info(this, STORE, ToType(types->at(i)), name);
5880 LookupResult lookup(isolate()); 5757 if (info.CanAccessMonomorphic()) {
5881 if (ComputeStoreField(ToType(map), name, &lookup)) {
5882 if (count == 0) { 5758 if (count == 0) {
5883 BuildCheckHeapObject(object); 5759 BuildCheckHeapObject(object);
5884 join = graph()->CreateBasicBlock(); 5760 join = graph()->CreateBasicBlock();
5885 } 5761 }
5886 ++count; 5762 ++count;
5887 HBasicBlock* if_true = graph()->CreateBasicBlock(); 5763 HBasicBlock* if_true = graph()->CreateBasicBlock();
5888 HBasicBlock* if_false = graph()->CreateBasicBlock(); 5764 HBasicBlock* if_false = graph()->CreateBasicBlock();
5889 HCompareMap* compare = New<HCompareMap>(object, map, if_true, if_false); 5765 HCompareMap* compare = New<HCompareMap>(
5766 object, info.map(), if_true, if_false);
5890 FinishCurrentBlock(compare); 5767 FinishCurrentBlock(compare);
5891 5768
5892 set_current_block(if_true); 5769 set_current_block(if_true);
5893 HInstruction* instr;
5894 CHECK_ALIVE(instr = BuildStoreNamedField(
5895 compare, name, value, map, &lookup));
5896 // Goto will add the HSimulate for the store.
5897 AddInstruction(instr);
5898 if (!ast_context()->IsEffect()) Push(value);
5899 Goto(join);
5900 5770
5771 HInstruction* store;
5772 store = BuildStoreMonomorphic(
5773 &info, compare, value, assignment_id, return_id,
5774 FLAG_polymorphic_inlining);
5775
5776 if (store == NULL) {
5777 if (HasStackOverflow()) return;
5778 } else {
5779 ASSERT(!store->IsLinked());
5780 AddInstruction(store);
5781 if (!ast_context()->IsEffect()) Push(value);
5782 }
5783
5784 if (current_block() != NULL) Goto(join);
5901 set_current_block(if_false); 5785 set_current_block(if_false);
5902 } 5786 }
5903 } 5787 }
5904 5788
5905 // Finish up. Unconditionally deoptimize if we've handled all the maps we 5789 // Finish up. Unconditionally deoptimize if we've handled all the maps we
5906 // know about and do not want to handle ones we've never seen. Otherwise 5790 // know about and do not want to handle ones we've never seen. Otherwise
5907 // use a generic IC. 5791 // use a generic IC.
5908 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 5792 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
5909 FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join); 5793 FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join);
5910 } else { 5794 } else {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
5952 if (types != NULL && receiver->HasMonomorphicJSObjectType()) { 5836 if (types != NULL && receiver->HasMonomorphicJSObjectType()) {
5953 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap(); 5837 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
5954 types->FilterForPossibleTransitions(root_map); 5838 types->FilterForPossibleTransitions(root_map);
5955 monomorphic = types->length() == 1; 5839 monomorphic = types->length() == 1;
5956 } 5840 }
5957 return monomorphic && CanInlinePropertyAccess( 5841 return monomorphic && CanInlinePropertyAccess(
5958 IC::MapToType<Type>(types->first(), zone)); 5842 IC::MapToType<Type>(types->first(), zone));
5959 } 5843 }
5960 5844
5961 5845
5846 static bool AreStringTypes(SmallMapList* types) {
5847 for (int i = 0; i < types->length(); i++) {
5848 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
5849 }
5850 return true;
5851 }
5852
5853
5962 void HOptimizedGraphBuilder::BuildStore(Expression* expr, 5854 void HOptimizedGraphBuilder::BuildStore(Expression* expr,
5963 Property* prop, 5855 Property* prop,
5964 BailoutId ast_id, 5856 BailoutId ast_id,
5965 BailoutId return_id, 5857 BailoutId return_id,
5966 bool is_uninitialized) { 5858 bool is_uninitialized) {
5967 HValue* value = environment()->ExpressionStackAt(0);
5968
5969 if (!prop->key()->IsPropertyName()) { 5859 if (!prop->key()->IsPropertyName()) {
5970 // Keyed store. 5860 // Keyed store.
5861 HValue* value = environment()->ExpressionStackAt(0);
5971 HValue* key = environment()->ExpressionStackAt(1); 5862 HValue* key = environment()->ExpressionStackAt(1);
5972 HValue* object = environment()->ExpressionStackAt(2); 5863 HValue* object = environment()->ExpressionStackAt(2);
5973 bool has_side_effects = false; 5864 bool has_side_effects = false;
5974 HandleKeyedElementAccess(object, key, value, expr, 5865 HandleKeyedElementAccess(object, key, value, expr,
5975 true, // is_store 5866 true, // is_store
5976 &has_side_effects); 5867 &has_side_effects);
5977 Drop(3); 5868 Drop(3);
5978 Push(value); 5869 Push(value);
5979 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); 5870 Add<HSimulate>(return_id, REMOVABLE_SIMULATE);
5980 return ast_context()->ReturnValue(Pop()); 5871 return ast_context()->ReturnValue(Pop());
5981 } 5872 }
5982 5873
5983 // Named store. 5874 // Named store.
5984 HValue* object = environment()->ExpressionStackAt(1); 5875 HValue* value = Pop();
5985 5876 HValue* object = Pop();
5986 if (is_uninitialized) {
5987 Add<HDeoptimize>("Insufficient type feedback for property assignment",
5988 Deoptimizer::SOFT);
5989 }
5990 5877
5991 Literal* key = prop->key()->AsLiteral(); 5878 Literal* key = prop->key()->AsLiteral();
5992 Handle<String> name = Handle<String>::cast(key->value()); 5879 Handle<String> name = Handle<String>::cast(key->value());
5993 ASSERT(!name.is_null()); 5880 ASSERT(!name.is_null());
5994 5881
5995 HInstruction* instr = NULL; 5882 HInstruction* instr = NULL;
5996 5883
5997 SmallMapList* types; 5884 SmallMapList* types;
5998 bool monomorphic = ComputeReceiverTypes(expr, object, &types, zone()); 5885 ComputeReceiverTypes(expr, object, &types, zone());
5999 5886
6000 if (monomorphic) { 5887 if (types->length() > 0) {
6001 Handle<Map> map = types->first(); 5888 PropertyAccessInfo info(this, STORE, ToType(types->first()), name);
6002 Handle<JSFunction> setter; 5889 if (!info.CanAccessAsMonomorphic(types)) {
6003 Handle<JSObject> holder; 5890 return HandlePolymorphicStoreNamedField(
6004 if (LookupSetter(map, name, &setter, &holder, zone())) { 5891 ast_id, return_id, object, value, types, name);
6005 AddCheckMap(object, map); 5892 }
6006 AddCheckPrototypeMaps(holder, map); 5893
6007 bool needs_wrapping = NeedsWrappingFor(ToType(map), setter); 5894 ASSERT(!info.type()->Is(Type::Number()));
6008 bool try_inline = FLAG_inline_accessors && !needs_wrapping; 5895 BuildCheckHeapObject(object);
6009 if (try_inline && TryInlineSetter(setter, ast_id, return_id, value)) { 5896 HValue* checked_object;
6010 return; 5897 if (AreStringTypes(types)) {
6011 } 5898 checked_object = Add<HCheckInstanceType>(
6012 Drop(2); 5899 object, HCheckInstanceType::IS_STRING);
6013 Add<HPushArgument>(object);
6014 Add<HPushArgument>(value);
6015 if (needs_wrapping) {
6016 HValue* function = Add<HConstant>(setter);
6017 instr = New<HCallFunction>(function, 2, WRAP_AND_CALL);
6018 } else {
6019 instr = BuildCallConstantFunction(setter, 2);
6020 }
6021 } else { 5900 } else {
6022 Drop(2); 5901 checked_object = Add<HCheckMaps>(object, types);
6023 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object,
6024 name,
6025 value,
6026 map));
6027 } 5902 }
6028 } else if (types != NULL && types->length() > 1) { 5903 instr = BuildStoreMonomorphic(
6029 Drop(2); 5904 &info, checked_object, value, ast_id, return_id);
6030 return HandlePolymorphicStoreNamedField(ast_id, object, value, types, name); 5905 if (instr == NULL) return;
5906 ASSERT(!instr->IsLinked());
6031 } else { 5907 } else {
6032 Drop(2); 5908 instr = BuildStoreNamedGeneric(object, name, value, is_uninitialized);
6033 instr = BuildStoreNamedGeneric(object, name, value);
6034 } 5909 }
6035 5910
6036 if (!ast_context()->IsEffect()) Push(value); 5911 if (!ast_context()->IsEffect()) Push(value);
6037 AddInstruction(instr); 5912 AddInstruction(instr);
6038 if (instr->HasObservableSideEffects()) { 5913 if (instr->HasObservableSideEffects()) {
6039 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 5914 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6040 } 5915 }
6041 if (!ast_context()->IsEffect()) Drop(1); 5916 if (!ast_context()->IsEffect()) Drop(1);
6042 return ast_context()->ReturnValue(value); 5917 return ast_context()->ReturnValue(value);
6043 } 5918 }
(...skipping 787 matching lines...) Expand 10 before | Expand all | Expand 10 after
6831 void HOptimizedGraphBuilder::PushLoad(Property* expr, 6706 void HOptimizedGraphBuilder::PushLoad(Property* expr,
6832 HValue* object, 6707 HValue* object,
6833 HValue* key) { 6708 HValue* key) {
6834 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); 6709 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
6835 Push(object); 6710 Push(object);
6836 if (key != NULL) Push(key); 6711 if (key != NULL) Push(key);
6837 BuildLoad(expr, expr->LoadId()); 6712 BuildLoad(expr, expr->LoadId());
6838 } 6713 }
6839 6714
6840 6715
6841 static bool AreStringTypes(SmallMapList* types) {
6842 for (int i = 0; i < types->length(); i++) {
6843 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
6844 }
6845 return true;
6846 }
6847
6848
6849 void HOptimizedGraphBuilder::BuildLoad(Property* expr, 6716 void HOptimizedGraphBuilder::BuildLoad(Property* expr,
6850 BailoutId ast_id) { 6717 BailoutId ast_id) {
6851 HInstruction* instr = NULL; 6718 HInstruction* instr = NULL;
6852 if (expr->IsStringAccess()) { 6719 if (expr->IsStringAccess()) {
6853 HValue* index = Pop(); 6720 HValue* index = Pop();
6854 HValue* string = Pop(); 6721 HValue* string = Pop();
6855 HInstruction* char_code = BuildStringCharCodeAt(string, index); 6722 HInstruction* char_code = BuildStringCharCodeAt(string, index);
6856 AddInstruction(char_code); 6723 AddInstruction(char_code);
6857 instr = NewUncasted<HStringCharFromCode>(char_code); 6724 instr = NewUncasted<HStringCharFromCode>(char_code);
6858 6725
6859 } else if (expr->IsFunctionPrototype()) { 6726 } else if (expr->IsFunctionPrototype()) {
6860 HValue* function = Pop(); 6727 HValue* function = Pop();
6861 BuildCheckHeapObject(function); 6728 BuildCheckHeapObject(function);
6862 instr = New<HLoadFunctionPrototype>(function); 6729 instr = New<HLoadFunctionPrototype>(function);
6863 6730
6864 } else if (expr->key()->IsPropertyName()) { 6731 } else if (expr->key()->IsPropertyName()) {
6865 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 6732 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
6866 HValue* object = Pop(); 6733 HValue* object = Pop();
6867 6734
6868 SmallMapList* types; 6735 SmallMapList* types;
6869 ComputeReceiverTypes(expr, object, &types, zone()); 6736 ComputeReceiverTypes(expr, object, &types, zone());
6870 ASSERT(types != NULL); 6737 ASSERT(types != NULL);
6871 6738
6872 if (types->length() > 0) { 6739 if (types->length() > 0) {
6873 PropertyAccessInfo info(this, ToType(types->first()), name); 6740 PropertyAccessInfo info(this, LOAD, ToType(types->first()), name);
6874 if (!info.CanLoadAsMonomorphic(types)) { 6741 if (!info.CanAccessAsMonomorphic(types)) {
6875 return HandlePolymorphicLoadNamedField( 6742 return HandlePolymorphicLoadNamedField(
6876 ast_id, expr->LoadId(), object, types, name); 6743 ast_id, expr->LoadId(), object, types, name);
6877 } 6744 }
6878 6745
6879 HValue* checked_object; 6746 HValue* checked_object;
6880 // Type::Number() is only supported by polymorphic load/call handling. 6747 // Type::Number() is only supported by polymorphic load/call handling.
6881 ASSERT(!info.type()->Is(Type::Number())); 6748 ASSERT(!info.type()->Is(Type::Number()));
6882 BuildCheckHeapObject(object); 6749 BuildCheckHeapObject(object);
6883 if (AreStringTypes(types)) { 6750 if (AreStringTypes(types)) {
6884 checked_object = 6751 checked_object =
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
7071 int argument_count = expr->arguments()->length() + 1; // Includes receiver. 6938 int argument_count = expr->arguments()->length() + 1; // Includes receiver.
7072 FunctionSorter order[kMaxCallPolymorphism]; 6939 FunctionSorter order[kMaxCallPolymorphism];
7073 6940
7074 bool handle_smi = false; 6941 bool handle_smi = false;
7075 bool handled_string = false; 6942 bool handled_string = false;
7076 int ordered_functions = 0; 6943 int ordered_functions = 0;
7077 6944
7078 for (int i = 0; 6945 for (int i = 0;
7079 i < types->length() && ordered_functions < kMaxCallPolymorphism; 6946 i < types->length() && ordered_functions < kMaxCallPolymorphism;
7080 ++i) { 6947 ++i) {
7081 PropertyAccessInfo info(this, ToType(types->at(i)), name); 6948 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
7082 if (info.CanLoadMonomorphic() && 6949 if (info.CanAccessMonomorphic() &&
7083 info.lookup()->IsConstant() && 6950 info.lookup()->IsConstant() &&
7084 info.constant()->IsJSFunction()) { 6951 info.constant()->IsJSFunction()) {
7085 if (info.type()->Is(Type::String())) { 6952 if (info.type()->Is(Type::String())) {
7086 if (handled_string) continue; 6953 if (handled_string) continue;
7087 handled_string = true; 6954 handled_string = true;
7088 } 6955 }
7089 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); 6956 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
7090 if (info.type()->Is(Type::Number())) { 6957 if (info.type()->Is(Type::Number())) {
7091 handle_smi = true; 6958 handle_smi = true;
7092 } 6959 }
7093 expr->set_target(target); 6960 expr->set_target(target);
7094 order[ordered_functions++] = 6961 order[ordered_functions++] =
7095 FunctionSorter(i, 6962 FunctionSorter(i,
7096 expr->target()->shared()->profiler_ticks(), 6963 expr->target()->shared()->profiler_ticks(),
7097 InliningAstSize(expr->target()), 6964 InliningAstSize(expr->target()),
7098 expr->target()->shared()->SourceSize()); 6965 expr->target()->shared()->SourceSize());
7099 } 6966 }
7100 } 6967 }
7101 6968
7102 std::sort(order, order + ordered_functions); 6969 std::sort(order, order + ordered_functions);
7103 6970
7104 HBasicBlock* number_block = NULL; 6971 HBasicBlock* number_block = NULL;
7105 HBasicBlock* join = NULL; 6972 HBasicBlock* join = NULL;
7106 handled_string = false; 6973 handled_string = false;
7107 int count = 0; 6974 int count = 0;
7108 6975
7109 for (int fn = 0; fn < ordered_functions; ++fn) { 6976 for (int fn = 0; fn < ordered_functions; ++fn) {
7110 int i = order[fn].index(); 6977 int i = order[fn].index();
7111 PropertyAccessInfo info(this, ToType(types->at(i)), name); 6978 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
7112 if (info.type()->Is(Type::String())) { 6979 if (info.type()->Is(Type::String())) {
7113 if (handled_string) continue; 6980 if (handled_string) continue;
7114 handled_string = true; 6981 handled_string = true;
7115 } 6982 }
7116 // Reloads the target. 6983 // Reloads the target.
7117 info.CanLoadMonomorphic(); 6984 info.CanAccessMonomorphic();
7118 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); 6985 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
7119 6986
7120 expr->set_target(target); 6987 expr->set_target(target);
7121 if (count == 0) { 6988 if (count == 0) {
7122 // Only needed once. 6989 // Only needed once.
7123 join = graph()->CreateBasicBlock(); 6990 join = graph()->CreateBasicBlock();
7124 if (handle_smi) { 6991 if (handle_smi) {
7125 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); 6992 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
7126 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); 6993 HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
7127 number_block = graph()->CreateBasicBlock(); 6994 number_block = graph()->CreateBasicBlock();
(...skipping 966 matching lines...) Expand 10 before | Expand all | Expand 10 after
8094 Property* prop = callee->AsProperty(); 7961 Property* prop = callee->AsProperty();
8095 if (prop != NULL) { 7962 if (prop != NULL) {
8096 CHECK_ALIVE(VisitForValue(prop->obj())); 7963 CHECK_ALIVE(VisitForValue(prop->obj()));
8097 HValue* receiver = Top(); 7964 HValue* receiver = Top();
8098 7965
8099 SmallMapList* types; 7966 SmallMapList* types;
8100 ComputeReceiverTypes(expr, receiver, &types, zone()); 7967 ComputeReceiverTypes(expr, receiver, &types, zone());
8101 7968
8102 if (prop->key()->IsPropertyName() && types->length() > 0) { 7969 if (prop->key()->IsPropertyName() && types->length() > 0) {
8103 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 7970 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
8104 PropertyAccessInfo info(this, ToType(types->first()), name); 7971 PropertyAccessInfo info(this, LOAD, ToType(types->first()), name);
8105 if (!info.CanLoadAsMonomorphic(types)) { 7972 if (!info.CanAccessAsMonomorphic(types)) {
8106 HandlePolymorphicCallNamed(expr, receiver, types, name); 7973 HandlePolymorphicCallNamed(expr, receiver, types, name);
8107 return; 7974 return;
8108 } 7975 }
8109 } 7976 }
8110 7977
8111 HValue* key = NULL; 7978 HValue* key = NULL;
8112 if (!prop->key()->IsPropertyName()) { 7979 if (!prop->key()->IsPropertyName()) {
8113 CHECK_ALIVE(VisitForValue(prop->key())); 7980 CHECK_ALIVE(VisitForValue(prop->key()));
8114 key = Pop(); 7981 key = Pop();
8115 } 7982 }
(...skipping 3244 matching lines...) Expand 10 before | Expand all | Expand 10 after
11360 if (ShouldProduceTraceOutput()) { 11227 if (ShouldProduceTraceOutput()) {
11361 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 11228 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
11362 } 11229 }
11363 11230
11364 #ifdef DEBUG 11231 #ifdef DEBUG
11365 graph_->Verify(false); // No full verify. 11232 graph_->Verify(false); // No full verify.
11366 #endif 11233 #endif
11367 } 11234 }
11368 11235
11369 } } // namespace v8::internal 11236 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698