| OLD | NEW |
| 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 4919 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4930 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4930 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
| 4931 Handle<FixedArray> literals(closure->literals()); | 4931 Handle<FixedArray> literals(closure->literals()); |
| 4932 HRegExpLiteral* instr = New<HRegExpLiteral>(literals, | 4932 HRegExpLiteral* instr = New<HRegExpLiteral>(literals, |
| 4933 expr->pattern(), | 4933 expr->pattern(), |
| 4934 expr->flags(), | 4934 expr->flags(), |
| 4935 expr->literal_index()); | 4935 expr->literal_index()); |
| 4936 return ast_context()->ReturnInstruction(instr, expr->id()); | 4936 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4937 } | 4937 } |
| 4938 | 4938 |
| 4939 | 4939 |
| 4940 static bool CanInlinePropertyAccess(Handle<HeapType> type) { | 4940 static bool CanInlinePropertyAccess(Type* type) { |
| 4941 if (type->Is(HeapType::NumberOrString())) return true; | 4941 if (type->Is(Type::NumberOrString())) return true; |
| 4942 if (!type->IsClass()) return false; | 4942 if (!type->IsClass()) return false; |
| 4943 Handle<Map> map = type->AsClass(); | 4943 Handle<Map> map = type->AsClass(); |
| 4944 return map->IsJSObjectMap() && | 4944 return map->IsJSObjectMap() && |
| 4945 !map->is_dictionary_map() && | 4945 !map->is_dictionary_map() && |
| 4946 !map->has_named_interceptor(); | 4946 !map->has_named_interceptor(); |
| 4947 } | 4947 } |
| 4948 | 4948 |
| 4949 | 4949 |
| 4950 static void LookupInPrototypes(Handle<Map> map, | 4950 static void LookupInPrototypes(Handle<Map> map, |
| 4951 Handle<String> name, | 4951 Handle<String> name, |
| 4952 LookupResult* lookup) { | 4952 LookupResult* lookup, |
| 4953 Zone* zone) { |
| 4953 while (map->prototype()->IsJSObject()) { | 4954 while (map->prototype()->IsJSObject()) { |
| 4954 Handle<JSObject> holder(JSObject::cast(map->prototype())); | 4955 Handle<JSObject> holder(JSObject::cast(map->prototype())); |
| 4955 map = handle(holder->map()); | 4956 map = handle(holder->map()); |
| 4956 if (!CanInlinePropertyAccess(IC::MapToType(map))) break; | 4957 if (!CanInlinePropertyAccess(IC::MapToType<Type>(map, zone))) break; |
| 4957 map->LookupDescriptor(*holder, *name, lookup); | 4958 map->LookupDescriptor(*holder, *name, lookup); |
| 4958 if (lookup->IsFound()) return; | 4959 if (lookup->IsFound()) return; |
| 4959 } | 4960 } |
| 4960 lookup->NotFound(); | 4961 lookup->NotFound(); |
| 4961 } | 4962 } |
| 4962 | 4963 |
| 4963 | 4964 |
| 4964 // Tries to find a JavaScript accessor of the given name in the prototype chain | 4965 // Tries to find a JavaScript accessor of the given name in the prototype chain |
| 4965 // starting at the given map. Return true iff there is one, including the | 4966 // starting at the given map. Return true iff there is one, including the |
| 4966 // corresponding AccessorPair plus its holder (which could be null when the | 4967 // corresponding AccessorPair plus its holder (which could be null when the |
| 4967 // accessor is found directly in the given map). | 4968 // accessor is found directly in the given map). |
| 4968 static bool LookupAccessorPair(Handle<Map> map, | 4969 static bool LookupAccessorPair(Handle<Map> map, |
| 4969 Handle<String> name, | 4970 Handle<String> name, |
| 4970 Handle<AccessorPair>* accessors, | 4971 Handle<AccessorPair>* accessors, |
| 4971 Handle<JSObject>* holder) { | 4972 Handle<JSObject>* holder, |
| 4973 Zone* zone) { |
| 4972 Isolate* isolate = map->GetIsolate(); | 4974 Isolate* isolate = map->GetIsolate(); |
| 4973 LookupResult lookup(isolate); | 4975 LookupResult lookup(isolate); |
| 4974 | 4976 |
| 4975 // Check for a JavaScript accessor directly in the map. | 4977 // Check for a JavaScript accessor directly in the map. |
| 4976 map->LookupDescriptor(NULL, *name, &lookup); | 4978 map->LookupDescriptor(NULL, *name, &lookup); |
| 4977 if (lookup.IsPropertyCallbacks()) { | 4979 if (lookup.IsPropertyCallbacks()) { |
| 4978 Handle<Object> callback(lookup.GetValueFromMap(*map), isolate); | 4980 Handle<Object> callback(lookup.GetValueFromMap(*map), isolate); |
| 4979 if (!callback->IsAccessorPair()) return false; | 4981 if (!callback->IsAccessorPair()) return false; |
| 4980 *accessors = Handle<AccessorPair>::cast(callback); | 4982 *accessors = Handle<AccessorPair>::cast(callback); |
| 4981 *holder = Handle<JSObject>(); | 4983 *holder = Handle<JSObject>(); |
| 4982 return true; | 4984 return true; |
| 4983 } | 4985 } |
| 4984 | 4986 |
| 4985 // Everything else, e.g. a field, can't be an accessor call. | 4987 // Everything else, e.g. a field, can't be an accessor call. |
| 4986 if (lookup.IsFound()) return false; | 4988 if (lookup.IsFound()) return false; |
| 4987 | 4989 |
| 4988 // Check for a JavaScript accessor somewhere in the proto chain. | 4990 // Check for a JavaScript accessor somewhere in the proto chain. |
| 4989 LookupInPrototypes(map, name, &lookup); | 4991 LookupInPrototypes(map, name, &lookup, zone); |
| 4990 if (lookup.IsPropertyCallbacks()) { | 4992 if (lookup.IsPropertyCallbacks()) { |
| 4991 Handle<Object> callback(lookup.GetValue(), isolate); | 4993 Handle<Object> callback(lookup.GetValue(), isolate); |
| 4992 if (!callback->IsAccessorPair()) return false; | 4994 if (!callback->IsAccessorPair()) return false; |
| 4993 *accessors = Handle<AccessorPair>::cast(callback); | 4995 *accessors = Handle<AccessorPair>::cast(callback); |
| 4994 *holder = Handle<JSObject>(lookup.holder()); | 4996 *holder = Handle<JSObject>(lookup.holder()); |
| 4995 return true; | 4997 return true; |
| 4996 } | 4998 } |
| 4997 | 4999 |
| 4998 // We haven't found a JavaScript accessor anywhere. | 5000 // We haven't found a JavaScript accessor anywhere. |
| 4999 return false; | 5001 return false; |
| 5000 } | 5002 } |
| 5001 | 5003 |
| 5002 | 5004 |
| 5003 static bool LookupSetter(Handle<Map> map, | 5005 static bool LookupSetter(Handle<Map> map, |
| 5004 Handle<String> name, | 5006 Handle<String> name, |
| 5005 Handle<JSFunction>* setter, | 5007 Handle<JSFunction>* setter, |
| 5006 Handle<JSObject>* holder) { | 5008 Handle<JSObject>* holder, |
| 5009 Zone* zone) { |
| 5007 Handle<AccessorPair> accessors; | 5010 Handle<AccessorPair> accessors; |
| 5008 if (LookupAccessorPair(map, name, &accessors, holder) && | 5011 if (LookupAccessorPair(map, name, &accessors, holder, zone) && |
| 5009 accessors->setter()->IsJSFunction()) { | 5012 accessors->setter()->IsJSFunction()) { |
| 5010 Handle<JSFunction> func(JSFunction::cast(accessors->setter())); | 5013 Handle<JSFunction> func(JSFunction::cast(accessors->setter())); |
| 5011 CallOptimization call_optimization(func); | 5014 CallOptimization call_optimization(func); |
| 5012 // TODO(dcarney): temporary hack unless crankshaft can handle api calls. | 5015 // TODO(dcarney): temporary hack unless crankshaft can handle api calls. |
| 5013 if (call_optimization.is_simple_api_call()) return false; | 5016 if (call_optimization.is_simple_api_call()) return false; |
| 5014 *setter = func; | 5017 *setter = func; |
| 5015 return true; | 5018 return true; |
| 5016 } | 5019 } |
| 5017 return false; | 5020 return false; |
| 5018 } | 5021 } |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5159 Handle<Map> map = property->GetReceiverType(); | 5162 Handle<Map> map = property->GetReceiverType(); |
| 5160 Handle<String> name = property->key()->AsPropertyName(); | 5163 Handle<String> name = property->key()->AsPropertyName(); |
| 5161 HInstruction* store; | 5164 HInstruction* store; |
| 5162 if (map.is_null()) { | 5165 if (map.is_null()) { |
| 5163 // If we don't know the monomorphic type, do a generic store. | 5166 // If we don't know the monomorphic type, do a generic store. |
| 5164 CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value)); | 5167 CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value)); |
| 5165 } else { | 5168 } else { |
| 5166 #if DEBUG | 5169 #if DEBUG |
| 5167 Handle<JSFunction> setter; | 5170 Handle<JSFunction> setter; |
| 5168 Handle<JSObject> holder; | 5171 Handle<JSObject> holder; |
| 5169 ASSERT(!LookupSetter(map, name, &setter, &holder)); | 5172 ASSERT(!LookupSetter(map, name, &setter, &holder, zone())); |
| 5170 #endif | 5173 #endif |
| 5171 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, | 5174 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, |
| 5172 name, | 5175 name, |
| 5173 value, | 5176 value, |
| 5174 map)); | 5177 map)); |
| 5175 } | 5178 } |
| 5176 AddInstruction(store); | 5179 AddInstruction(store); |
| 5177 if (store->HasObservableSideEffects()) { | 5180 if (store->HasObservableSideEffects()) { |
| 5178 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); | 5181 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); |
| 5179 } | 5182 } |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5442 HValue* value) { | 5445 HValue* value) { |
| 5443 return New<HStoreNamedGeneric>( | 5446 return New<HStoreNamedGeneric>( |
| 5444 object, | 5447 object, |
| 5445 name, | 5448 name, |
| 5446 value, | 5449 value, |
| 5447 function_strict_mode_flag()); | 5450 function_strict_mode_flag()); |
| 5448 } | 5451 } |
| 5449 | 5452 |
| 5450 | 5453 |
| 5451 // Sets the lookup result and returns true if the load/store can be inlined. | 5454 // Sets the lookup result and returns true if the load/store can be inlined. |
| 5452 static bool ComputeStoreField(Handle<Map> type, | 5455 static bool ComputeStoreField(Type* type, |
| 5453 Handle<String> name, | 5456 Handle<String> name, |
| 5454 LookupResult* lookup, | 5457 LookupResult* lookup, |
| 5455 bool lookup_transition = true) { | 5458 bool lookup_transition = true) { |
| 5456 ASSERT(!type->is_observed()); | 5459 if (!CanInlinePropertyAccess(type) || !type->IsClass()) { |
| 5457 if (!CanInlinePropertyAccess(IC::MapToType(type))) { | |
| 5458 lookup->NotFound(); | 5460 lookup->NotFound(); |
| 5459 return false; | 5461 return false; |
| 5460 } | 5462 } |
| 5463 Handle<Map> map = type->AsClass(); |
| 5464 ASSERT(!map->is_observed()); |
| 5461 // If we directly find a field, the access can be inlined. | 5465 // If we directly find a field, the access can be inlined. |
| 5462 type->LookupDescriptor(NULL, *name, lookup); | 5466 map->LookupDescriptor(NULL, *name, lookup); |
| 5463 if (lookup->IsField()) return true; | 5467 if (lookup->IsField()) return true; |
| 5464 | 5468 |
| 5465 if (!lookup_transition) return false; | 5469 if (!lookup_transition) return false; |
| 5466 | 5470 |
| 5467 type->LookupTransition(NULL, *name, lookup); | 5471 map->LookupTransition(NULL, *name, lookup); |
| 5468 return lookup->IsTransitionToField(*type) && | 5472 return lookup->IsTransitionToField(*map) && map->unused_property_fields() > 0; |
| 5469 (type->unused_property_fields() > 0); | |
| 5470 } | 5473 } |
| 5471 | 5474 |
| 5472 | 5475 |
| 5473 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( | 5476 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( |
| 5474 HValue* object, | 5477 HValue* object, |
| 5475 Handle<String> name, | 5478 Handle<String> name, |
| 5476 HValue* value, | 5479 HValue* value, |
| 5477 Handle<Map> map) { | 5480 Handle<Map> map) { |
| 5478 // Handle a store to a known field. | 5481 // Handle a store to a known field. |
| 5479 LookupResult lookup(isolate()); | 5482 LookupResult lookup(isolate()); |
| 5480 if (ComputeStoreField(map, name, &lookup)) { | 5483 if (ComputeStoreField(ToType(map), name, &lookup)) { |
| 5481 HCheckMaps* checked_object = AddCheckMap(object, map); | 5484 HCheckMaps* checked_object = AddCheckMap(object, map); |
| 5482 return BuildStoreNamedField(checked_object, name, value, map, &lookup); | 5485 return BuildStoreNamedField(checked_object, name, value, map, &lookup); |
| 5483 } | 5486 } |
| 5484 | 5487 |
| 5485 // No luck, do a generic store. | 5488 // No luck, do a generic store. |
| 5486 return BuildStoreNamedGeneric(object, name, value); | 5489 return BuildStoreNamedGeneric(object, name, value); |
| 5487 } | 5490 } |
| 5488 | 5491 |
| 5489 | 5492 |
| 5490 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatibleForLoad( | 5493 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatibleForLoad( |
| 5491 PropertyAccessInfo* info) { | 5494 PropertyAccessInfo* info) { |
| 5492 if (!CanInlinePropertyAccess(type_)) return false; | 5495 if (!CanInlinePropertyAccess(type_)) return false; |
| 5493 | 5496 |
| 5494 // Currently only handle HeapType::Number as a polymorphic case. | 5497 // Currently only handle Type::Number as a polymorphic case. |
| 5495 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber | 5498 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber |
| 5496 // instruction. | 5499 // instruction. |
| 5497 if (type_->Is(HeapType::Number())) return false; | 5500 if (type_->Is(Type::Number())) return false; |
| 5498 | 5501 |
| 5499 // Values are only compatible for monomorphic load if they all behave the same | 5502 // Values are only compatible for monomorphic load if they all behave the same |
| 5500 // regarding value wrappers. | 5503 // regarding value wrappers. |
| 5501 if (type_->Is(HeapType::NumberOrString())) { | 5504 if (type_->Is(Type::NumberOrString())) { |
| 5502 if (!info->type_->Is(HeapType::NumberOrString())) return false; | 5505 if (!info->type_->Is(Type::NumberOrString())) return false; |
| 5503 } else { | 5506 } else { |
| 5504 if (info->type_->Is(HeapType::NumberOrString())) return false; | 5507 if (info->type_->Is(Type::NumberOrString())) return false; |
| 5505 } | 5508 } |
| 5506 | 5509 |
| 5507 if (!LookupDescriptor()) return false; | 5510 if (!LookupDescriptor()) return false; |
| 5508 | 5511 |
| 5509 if (!lookup_.IsFound()) { | 5512 if (!lookup_.IsFound()) { |
| 5510 return (!info->lookup_.IsFound() || info->has_holder()) && | 5513 return (!info->lookup_.IsFound() || info->has_holder()) && |
| 5511 map()->prototype() == info->map()->prototype(); | 5514 map()->prototype() == info->map()->prototype(); |
| 5512 } | 5515 } |
| 5513 | 5516 |
| 5514 // Mismatch if the other access info found the property in the prototype | 5517 // Mismatch if the other access info found the property in the prototype |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5565 | 5568 |
| 5566 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { | 5569 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { |
| 5567 Handle<Map> map = this->map(); | 5570 Handle<Map> map = this->map(); |
| 5568 | 5571 |
| 5569 while (map->prototype()->IsJSObject()) { | 5572 while (map->prototype()->IsJSObject()) { |
| 5570 holder_ = handle(JSObject::cast(map->prototype())); | 5573 holder_ = handle(JSObject::cast(map->prototype())); |
| 5571 if (holder_->map()->is_deprecated()) { | 5574 if (holder_->map()->is_deprecated()) { |
| 5572 JSObject::TryMigrateInstance(holder_); | 5575 JSObject::TryMigrateInstance(holder_); |
| 5573 } | 5576 } |
| 5574 map = Handle<Map>(holder_->map()); | 5577 map = Handle<Map>(holder_->map()); |
| 5575 if (!CanInlinePropertyAccess(IC::MapToType(map))) { | 5578 if (!CanInlinePropertyAccess(ToType(map))) { |
| 5576 lookup_.NotFound(); | 5579 lookup_.NotFound(); |
| 5577 return false; | 5580 return false; |
| 5578 } | 5581 } |
| 5579 map->LookupDescriptor(*holder_, *name_, &lookup_); | 5582 map->LookupDescriptor(*holder_, *name_, &lookup_); |
| 5580 if (lookup_.IsFound()) return LoadResult(map); | 5583 if (lookup_.IsFound()) return LoadResult(map); |
| 5581 } | 5584 } |
| 5582 lookup_.NotFound(); | 5585 lookup_.NotFound(); |
| 5583 return true; | 5586 return true; |
| 5584 } | 5587 } |
| 5585 | 5588 |
| 5586 | 5589 |
| 5587 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadMonomorphic() { | 5590 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadMonomorphic() { |
| 5588 if (!CanInlinePropertyAccess(type_)) return false; | 5591 if (!CanInlinePropertyAccess(type_)) return false; |
| 5589 if (IsJSObjectFieldAccessor()) return true; | 5592 if (IsJSObjectFieldAccessor()) return true; |
| 5590 if (!LookupDescriptor()) return false; | 5593 if (!LookupDescriptor()) return false; |
| 5591 if (lookup_.IsFound()) return true; | 5594 if (lookup_.IsFound()) return true; |
| 5592 return LookupInPrototypes(); | 5595 return LookupInPrototypes(); |
| 5593 } | 5596 } |
| 5594 | 5597 |
| 5595 | 5598 |
| 5596 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadAsMonomorphic( | 5599 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadAsMonomorphic( |
| 5597 SmallMapList* types) { | 5600 SmallMapList* types) { |
| 5598 ASSERT(type_->Is(IC::MapToType(types->first()))); | 5601 ASSERT(type_->Is(ToType(types->first()))); |
| 5599 if (!CanLoadMonomorphic()) return false; | 5602 if (!CanLoadMonomorphic()) return false; |
| 5600 if (types->length() > kMaxLoadPolymorphism) return false; | 5603 if (types->length() > kMaxLoadPolymorphism) return false; |
| 5601 | 5604 |
| 5602 if (IsArrayLength()) { | 5605 if (IsArrayLength()) { |
| 5603 bool is_fast = IsFastElementsKind(map()->elements_kind()); | 5606 bool is_fast = IsFastElementsKind(map()->elements_kind()); |
| 5604 for (int i = 1; i < types->length(); ++i) { | 5607 for (int i = 1; i < types->length(); ++i) { |
| 5605 Handle<Map> test_map = types->at(i); | 5608 Handle<Map> test_map = types->at(i); |
| 5606 if (test_map->instance_type() != JS_ARRAY_TYPE) return false; | 5609 if (test_map->instance_type() != JS_ARRAY_TYPE) return false; |
| 5607 if (IsFastElementsKind(test_map->elements_kind()) != is_fast) { | 5610 if (IsFastElementsKind(test_map->elements_kind()) != is_fast) { |
| 5608 return false; | 5611 return false; |
| 5609 } | 5612 } |
| 5610 } | 5613 } |
| 5611 return true; | 5614 return true; |
| 5612 } | 5615 } |
| 5613 | 5616 |
| 5614 HObjectAccess access = HObjectAccess::ForMap(); // bogus default | 5617 HObjectAccess access = HObjectAccess::ForMap(); // bogus default |
| 5615 if (GetJSObjectFieldAccess(&access)) { | 5618 if (GetJSObjectFieldAccess(&access)) { |
| 5616 for (int i = 1; i < types->length(); ++i) { | 5619 for (int i = 1; i < types->length(); ++i) { |
| 5617 PropertyAccessInfo test_info( | 5620 PropertyAccessInfo test_info(builder_, ToType(types->at(i)), name_); |
| 5618 builder_, IC::MapToType(types->at(i)), name_); | |
| 5619 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default | 5621 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default |
| 5620 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false; | 5622 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false; |
| 5621 if (!access.Equals(test_access)) return false; | 5623 if (!access.Equals(test_access)) return false; |
| 5622 } | 5624 } |
| 5623 return true; | 5625 return true; |
| 5624 } | 5626 } |
| 5625 | 5627 |
| 5626 // Currently only handle HeapType::Number as a polymorphic case. | 5628 // Currently only handle Type::Number as a polymorphic case. |
| 5627 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber | 5629 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber |
| 5628 // instruction. | 5630 // instruction. |
| 5629 if (type_->Is(HeapType::Number())) return false; | 5631 if (type_->Is(Type::Number())) return false; |
| 5630 | 5632 |
| 5631 for (int i = 1; i < types->length(); ++i) { | 5633 for (int i = 1; i < types->length(); ++i) { |
| 5632 PropertyAccessInfo test_info(builder_, IC::MapToType(types->at(i)), name_); | 5634 PropertyAccessInfo test_info(builder_, ToType(types->at(i)), name_); |
| 5633 if (!test_info.IsCompatibleForLoad(this)) return false; | 5635 if (!test_info.IsCompatibleForLoad(this)) return false; |
| 5634 } | 5636 } |
| 5635 | 5637 |
| 5636 return true; | 5638 return true; |
| 5637 } | 5639 } |
| 5638 | 5640 |
| 5639 | 5641 |
| 5640 static bool NeedsWrappingFor(Handle<HeapType> type, Handle<JSFunction> target) { | 5642 static bool NeedsWrappingFor(Type* type, Handle<JSFunction> target) { |
| 5641 return type->Is(HeapType::NumberOrString()) && | 5643 return type->Is(Type::NumberOrString()) && |
| 5642 target->shared()->is_classic_mode() && | 5644 target->shared()->is_classic_mode() && |
| 5643 !target->shared()->native(); | 5645 !target->shared()->native(); |
| 5644 } | 5646 } |
| 5645 | 5647 |
| 5646 | 5648 |
| 5647 HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic( | 5649 HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic( |
| 5648 PropertyAccessInfo* info, | 5650 PropertyAccessInfo* info, |
| 5649 HValue* object, | 5651 HValue* object, |
| 5650 HValue* checked_object, | 5652 HValue* checked_object, |
| 5651 BailoutId ast_id, | 5653 BailoutId ast_id, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5699 SmallMapList* types, | 5701 SmallMapList* types, |
| 5700 Handle<String> name) { | 5702 Handle<String> name) { |
| 5701 // Something did not match; must use a polymorphic load. | 5703 // Something did not match; must use a polymorphic load. |
| 5702 int count = 0; | 5704 int count = 0; |
| 5703 HBasicBlock* join = NULL; | 5705 HBasicBlock* join = NULL; |
| 5704 HBasicBlock* number_block = NULL; | 5706 HBasicBlock* number_block = NULL; |
| 5705 bool handled_string = false; | 5707 bool handled_string = false; |
| 5706 | 5708 |
| 5707 bool handle_smi = false; | 5709 bool handle_smi = false; |
| 5708 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 5710 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
| 5709 PropertyAccessInfo info(this, IC::MapToType(types->at(i)), name); | 5711 PropertyAccessInfo info(this, ToType(types->at(i)), name); |
| 5710 if (info.type()->Is(HeapType::String())) { | 5712 if (info.type()->Is(Type::String())) { |
| 5711 if (handled_string) continue; | 5713 if (handled_string) continue; |
| 5712 handled_string = true; | 5714 handled_string = true; |
| 5713 } | 5715 } |
| 5714 if (info.CanLoadMonomorphic()) { | 5716 if (info.CanLoadMonomorphic()) { |
| 5715 count++; | 5717 count++; |
| 5716 if (info.type()->Is(HeapType::Number())) { | 5718 if (info.type()->Is(Type::Number())) { |
| 5717 handle_smi = true; | 5719 handle_smi = true; |
| 5718 break; | 5720 break; |
| 5719 } | 5721 } |
| 5720 } | 5722 } |
| 5721 } | 5723 } |
| 5722 | 5724 |
| 5723 count = 0; | 5725 count = 0; |
| 5724 HControlInstruction* smi_check = NULL; | 5726 HControlInstruction* smi_check = NULL; |
| 5725 handled_string = false; | 5727 handled_string = false; |
| 5726 | 5728 |
| 5727 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 5729 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
| 5728 PropertyAccessInfo info(this, IC::MapToType(types->at(i)), name); | 5730 PropertyAccessInfo info(this, ToType(types->at(i)), name); |
| 5729 if (info.type()->Is(HeapType::String())) { | 5731 if (info.type()->Is(Type::String())) { |
| 5730 if (handled_string) continue; | 5732 if (handled_string) continue; |
| 5731 handled_string = true; | 5733 handled_string = true; |
| 5732 } | 5734 } |
| 5733 if (!info.CanLoadMonomorphic()) continue; | 5735 if (!info.CanLoadMonomorphic()) continue; |
| 5734 | 5736 |
| 5735 if (count == 0) { | 5737 if (count == 0) { |
| 5736 join = graph()->CreateBasicBlock(); | 5738 join = graph()->CreateBasicBlock(); |
| 5737 if (handle_smi) { | 5739 if (handle_smi) { |
| 5738 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); | 5740 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); |
| 5739 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); | 5741 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); |
| 5740 number_block = graph()->CreateBasicBlock(); | 5742 number_block = graph()->CreateBasicBlock(); |
| 5741 smi_check = New<HIsSmiAndBranch>( | 5743 smi_check = New<HIsSmiAndBranch>( |
| 5742 object, empty_smi_block, not_smi_block); | 5744 object, empty_smi_block, not_smi_block); |
| 5743 FinishCurrentBlock(smi_check); | 5745 FinishCurrentBlock(smi_check); |
| 5744 Goto(empty_smi_block, number_block); | 5746 Goto(empty_smi_block, number_block); |
| 5745 set_current_block(not_smi_block); | 5747 set_current_block(not_smi_block); |
| 5746 } else { | 5748 } else { |
| 5747 BuildCheckHeapObject(object); | 5749 BuildCheckHeapObject(object); |
| 5748 } | 5750 } |
| 5749 } | 5751 } |
| 5750 ++count; | 5752 ++count; |
| 5751 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 5753 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 5752 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 5754 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 5753 HUnaryControlInstruction* compare; | 5755 HUnaryControlInstruction* compare; |
| 5754 | 5756 |
| 5755 HValue* dependency; | 5757 HValue* dependency; |
| 5756 if (info.type()->Is(HeapType::Number())) { | 5758 if (info.type()->Is(Type::Number())) { |
| 5757 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); | 5759 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); |
| 5758 compare = New<HCompareMap>(object, heap_number_map, if_true, if_false); | 5760 compare = New<HCompareMap>(object, heap_number_map, if_true, if_false); |
| 5759 dependency = smi_check; | 5761 dependency = smi_check; |
| 5760 } else if (info.type()->Is(HeapType::String())) { | 5762 } else if (info.type()->Is(Type::String())) { |
| 5761 compare = New<HIsStringAndBranch>(object, if_true, if_false); | 5763 compare = New<HIsStringAndBranch>(object, if_true, if_false); |
| 5762 dependency = compare; | 5764 dependency = compare; |
| 5763 } else { | 5765 } else { |
| 5764 compare = New<HCompareMap>(object, info.map(), if_true, if_false); | 5766 compare = New<HCompareMap>(object, info.map(), if_true, if_false); |
| 5765 dependency = compare; | 5767 dependency = compare; |
| 5766 } | 5768 } |
| 5767 FinishCurrentBlock(compare); | 5769 FinishCurrentBlock(compare); |
| 5768 | 5770 |
| 5769 if (info.type()->Is(HeapType::Number())) { | 5771 if (info.type()->Is(Type::Number())) { |
| 5770 Goto(if_true, number_block); | 5772 Goto(if_true, number_block); |
| 5771 if_true = number_block; | 5773 if_true = number_block; |
| 5772 number_block->SetJoinId(ast_id); | 5774 number_block->SetJoinId(ast_id); |
| 5773 } | 5775 } |
| 5774 | 5776 |
| 5775 set_current_block(if_true); | 5777 set_current_block(if_true); |
| 5776 | 5778 |
| 5777 HInstruction* load = BuildLoadMonomorphic( | 5779 HInstruction* load = BuildLoadMonomorphic( |
| 5778 &info, object, dependency, ast_id, | 5780 &info, object, dependency, ast_id, |
| 5779 return_id, FLAG_polymorphic_inlining); | 5781 return_id, FLAG_polymorphic_inlining); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5829 // for all maps. Requires special map check on the set of all handled maps. | 5831 // for all maps. Requires special map check on the set of all handled maps. |
| 5830 if (types->length() > kMaxStorePolymorphism) return false; | 5832 if (types->length() > kMaxStorePolymorphism) return false; |
| 5831 | 5833 |
| 5832 LookupResult lookup(isolate()); | 5834 LookupResult lookup(isolate()); |
| 5833 int count; | 5835 int count; |
| 5834 Representation representation = Representation::None(); | 5836 Representation representation = Representation::None(); |
| 5835 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. | 5837 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. |
| 5836 for (count = 0; count < types->length(); ++count) { | 5838 for (count = 0; count < types->length(); ++count) { |
| 5837 Handle<Map> map = types->at(count); | 5839 Handle<Map> map = types->at(count); |
| 5838 // Pass false to ignore transitions. | 5840 // Pass false to ignore transitions. |
| 5839 if (!ComputeStoreField(map, name, &lookup, false)) break; | 5841 if (!ComputeStoreField(ToType(map), name, &lookup, false)) break; |
| 5840 ASSERT(!map->is_observed()); | 5842 ASSERT(!map->is_observed()); |
| 5841 | 5843 |
| 5842 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); | 5844 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); |
| 5843 Representation new_representation = new_access.representation(); | 5845 Representation new_representation = new_access.representation(); |
| 5844 | 5846 |
| 5845 if (count == 0) { | 5847 if (count == 0) { |
| 5846 // First time through the loop; set access and representation. | 5848 // First time through the loop; set access and representation. |
| 5847 access = new_access; | 5849 access = new_access; |
| 5848 representation = new_representation; | 5850 representation = new_representation; |
| 5849 } else if (!representation.IsCompatibleForStore(new_representation)) { | 5851 } else if (!representation.IsCompatibleForStore(new_representation)) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5889 } | 5891 } |
| 5890 | 5892 |
| 5891 // TODO(ager): We should recognize when the prototype chains for different | 5893 // TODO(ager): We should recognize when the prototype chains for different |
| 5892 // maps are identical. In that case we can avoid repeatedly generating the | 5894 // maps are identical. In that case we can avoid repeatedly generating the |
| 5893 // same prototype map checks. | 5895 // same prototype map checks. |
| 5894 int count = 0; | 5896 int count = 0; |
| 5895 HBasicBlock* join = NULL; | 5897 HBasicBlock* join = NULL; |
| 5896 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | 5898 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
| 5897 Handle<Map> map = types->at(i); | 5899 Handle<Map> map = types->at(i); |
| 5898 LookupResult lookup(isolate()); | 5900 LookupResult lookup(isolate()); |
| 5899 if (ComputeStoreField(map, name, &lookup)) { | 5901 if (ComputeStoreField(ToType(map), name, &lookup)) { |
| 5900 if (count == 0) { | 5902 if (count == 0) { |
| 5901 BuildCheckHeapObject(object); | 5903 BuildCheckHeapObject(object); |
| 5902 join = graph()->CreateBasicBlock(); | 5904 join = graph()->CreateBasicBlock(); |
| 5903 } | 5905 } |
| 5904 ++count; | 5906 ++count; |
| 5905 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 5907 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 5906 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 5908 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 5907 HCompareMap* compare = New<HCompareMap>(object, map, if_true, if_false); | 5909 HCompareMap* compare = New<HCompareMap>(object, map, if_true, if_false); |
| 5908 FinishCurrentBlock(compare); | 5910 FinishCurrentBlock(compare); |
| 5909 | 5911 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5955 join->SetJoinId(assignment_id); | 5957 join->SetJoinId(assignment_id); |
| 5956 set_current_block(join); | 5958 set_current_block(join); |
| 5957 if (!ast_context()->IsEffect()) { | 5959 if (!ast_context()->IsEffect()) { |
| 5958 ast_context()->ReturnValue(Pop()); | 5960 ast_context()->ReturnValue(Pop()); |
| 5959 } | 5961 } |
| 5960 } | 5962 } |
| 5961 | 5963 |
| 5962 | 5964 |
| 5963 static bool ComputeReceiverTypes(Expression* expr, | 5965 static bool ComputeReceiverTypes(Expression* expr, |
| 5964 HValue* receiver, | 5966 HValue* receiver, |
| 5965 SmallMapList** t) { | 5967 SmallMapList** t, |
| 5968 Zone* zone) { |
| 5966 SmallMapList* types = expr->GetReceiverTypes(); | 5969 SmallMapList* types = expr->GetReceiverTypes(); |
| 5967 *t = types; | 5970 *t = types; |
| 5968 bool monomorphic = expr->IsMonomorphic(); | 5971 bool monomorphic = expr->IsMonomorphic(); |
| 5969 if (types != NULL && receiver->HasMonomorphicJSObjectType()) { | 5972 if (types != NULL && receiver->HasMonomorphicJSObjectType()) { |
| 5970 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap(); | 5973 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap(); |
| 5971 types->FilterForPossibleTransitions(root_map); | 5974 types->FilterForPossibleTransitions(root_map); |
| 5972 monomorphic = types->length() == 1; | 5975 monomorphic = types->length() == 1; |
| 5973 } | 5976 } |
| 5974 return monomorphic && CanInlinePropertyAccess(IC::MapToType(types->first())); | 5977 return monomorphic && CanInlinePropertyAccess( |
| 5978 IC::MapToType<Type>(types->first(), zone)); |
| 5975 } | 5979 } |
| 5976 | 5980 |
| 5977 | 5981 |
| 5978 void HOptimizedGraphBuilder::BuildStore(Expression* expr, | 5982 void HOptimizedGraphBuilder::BuildStore(Expression* expr, |
| 5979 Property* prop, | 5983 Property* prop, |
| 5980 BailoutId ast_id, | 5984 BailoutId ast_id, |
| 5981 BailoutId return_id, | 5985 BailoutId return_id, |
| 5982 bool is_uninitialized) { | 5986 bool is_uninitialized) { |
| 5983 HValue* value = environment()->ExpressionStackAt(0); | 5987 HValue* value = environment()->ExpressionStackAt(0); |
| 5984 | 5988 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 6004 Deoptimizer::SOFT); | 6008 Deoptimizer::SOFT); |
| 6005 } | 6009 } |
| 6006 | 6010 |
| 6007 Literal* key = prop->key()->AsLiteral(); | 6011 Literal* key = prop->key()->AsLiteral(); |
| 6008 Handle<String> name = Handle<String>::cast(key->value()); | 6012 Handle<String> name = Handle<String>::cast(key->value()); |
| 6009 ASSERT(!name.is_null()); | 6013 ASSERT(!name.is_null()); |
| 6010 | 6014 |
| 6011 HInstruction* instr = NULL; | 6015 HInstruction* instr = NULL; |
| 6012 | 6016 |
| 6013 SmallMapList* types; | 6017 SmallMapList* types; |
| 6014 bool monomorphic = ComputeReceiverTypes(expr, object, &types); | 6018 bool monomorphic = ComputeReceiverTypes(expr, object, &types, zone()); |
| 6015 | 6019 |
| 6016 if (monomorphic) { | 6020 if (monomorphic) { |
| 6017 Handle<Map> map = types->first(); | 6021 Handle<Map> map = types->first(); |
| 6018 Handle<JSFunction> setter; | 6022 Handle<JSFunction> setter; |
| 6019 Handle<JSObject> holder; | 6023 Handle<JSObject> holder; |
| 6020 if (LookupSetter(map, name, &setter, &holder)) { | 6024 if (LookupSetter(map, name, &setter, &holder, zone())) { |
| 6021 AddCheckMap(object, map); | 6025 AddCheckMap(object, map); |
| 6022 AddCheckPrototypeMaps(holder, map); | 6026 AddCheckPrototypeMaps(holder, map); |
| 6023 bool needs_wrapping = NeedsWrappingFor(IC::MapToType(map), setter); | 6027 bool needs_wrapping = NeedsWrappingFor(ToType(map), setter); |
| 6024 bool try_inline = FLAG_inline_accessors && !needs_wrapping; | 6028 bool try_inline = FLAG_inline_accessors && !needs_wrapping; |
| 6025 if (try_inline && TryInlineSetter(setter, ast_id, return_id, value)) { | 6029 if (try_inline && TryInlineSetter(setter, ast_id, return_id, value)) { |
| 6026 return; | 6030 return; |
| 6027 } | 6031 } |
| 6028 Drop(2); | 6032 Drop(2); |
| 6029 Add<HPushArgument>(object); | 6033 Add<HPushArgument>(object); |
| 6030 Add<HPushArgument>(value); | 6034 Add<HPushArgument>(value); |
| 6031 if (needs_wrapping) { | 6035 if (needs_wrapping) { |
| 6032 HValue* function = Add<HConstant>(setter); | 6036 HValue* function = Add<HConstant>(setter); |
| 6033 instr = New<HCallFunction>(function, 2, WRAP_AND_CALL); | 6037 instr = New<HCallFunction>(function, 2, WRAP_AND_CALL); |
| (...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6693 HValue* obj, | 6697 HValue* obj, |
| 6694 HValue* key, | 6698 HValue* key, |
| 6695 HValue* val, | 6699 HValue* val, |
| 6696 Expression* expr, | 6700 Expression* expr, |
| 6697 bool is_store, | 6701 bool is_store, |
| 6698 bool* has_side_effects) { | 6702 bool* has_side_effects) { |
| 6699 ASSERT(!expr->IsPropertyName()); | 6703 ASSERT(!expr->IsPropertyName()); |
| 6700 HInstruction* instr = NULL; | 6704 HInstruction* instr = NULL; |
| 6701 | 6705 |
| 6702 SmallMapList* types; | 6706 SmallMapList* types; |
| 6703 bool monomorphic = ComputeReceiverTypes(expr, obj, &types); | 6707 bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone()); |
| 6704 | 6708 |
| 6705 bool force_generic = false; | 6709 bool force_generic = false; |
| 6706 if (is_store && (monomorphic || (types != NULL && !types->is_empty()))) { | 6710 if (is_store && (monomorphic || (types != NULL && !types->is_empty()))) { |
| 6707 // Stores can't be mono/polymorphic if their prototype chain has dictionary | 6711 // Stores can't be mono/polymorphic if their prototype chain has dictionary |
| 6708 // elements. However a receiver map that has dictionary elements itself | 6712 // elements. However a receiver map that has dictionary elements itself |
| 6709 // should be left to normal mono/poly behavior (the other maps may benefit | 6713 // should be left to normal mono/poly behavior (the other maps may benefit |
| 6710 // from highly optimized stores). | 6714 // from highly optimized stores). |
| 6711 for (int i = 0; i < types->length(); i++) { | 6715 for (int i = 0; i < types->length(); i++) { |
| 6712 Handle<Map> current_map = types->at(i); | 6716 Handle<Map> current_map = types->at(i); |
| 6713 if (current_map->DictionaryElementsInPrototypeChainOnly()) { | 6717 if (current_map->DictionaryElementsInPrototypeChainOnly()) { |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6875 } else if (expr->IsFunctionPrototype()) { | 6879 } else if (expr->IsFunctionPrototype()) { |
| 6876 HValue* function = Pop(); | 6880 HValue* function = Pop(); |
| 6877 BuildCheckHeapObject(function); | 6881 BuildCheckHeapObject(function); |
| 6878 instr = New<HLoadFunctionPrototype>(function); | 6882 instr = New<HLoadFunctionPrototype>(function); |
| 6879 | 6883 |
| 6880 } else if (expr->key()->IsPropertyName()) { | 6884 } else if (expr->key()->IsPropertyName()) { |
| 6881 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 6885 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| 6882 HValue* object = Pop(); | 6886 HValue* object = Pop(); |
| 6883 | 6887 |
| 6884 SmallMapList* types; | 6888 SmallMapList* types; |
| 6885 ComputeReceiverTypes(expr, object, &types); | 6889 ComputeReceiverTypes(expr, object, &types, zone()); |
| 6886 ASSERT(types != NULL); | 6890 ASSERT(types != NULL); |
| 6887 | 6891 |
| 6888 if (types->length() > 0) { | 6892 if (types->length() > 0) { |
| 6889 PropertyAccessInfo info(this, IC::MapToType(types->first()), name); | 6893 PropertyAccessInfo info(this, ToType(types->first()), name); |
| 6890 if (!info.CanLoadAsMonomorphic(types)) { | 6894 if (!info.CanLoadAsMonomorphic(types)) { |
| 6891 return HandlePolymorphicLoadNamedField( | 6895 return HandlePolymorphicLoadNamedField( |
| 6892 ast_id, expr->LoadId(), object, types, name); | 6896 ast_id, expr->LoadId(), object, types, name); |
| 6893 } | 6897 } |
| 6894 | 6898 |
| 6895 HValue* checked_object; | 6899 HValue* checked_object; |
| 6896 // HeapType::Number() is only supported by polymorphic load/call handling. | 6900 // Type::Number() is only supported by polymorphic load/call handling. |
| 6897 ASSERT(!info.type()->Is(HeapType::Number())); | 6901 ASSERT(!info.type()->Is(Type::Number())); |
| 6898 BuildCheckHeapObject(object); | 6902 BuildCheckHeapObject(object); |
| 6899 if (AreStringTypes(types)) { | 6903 if (AreStringTypes(types)) { |
| 6900 checked_object = | 6904 checked_object = |
| 6901 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); | 6905 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); |
| 6902 } else { | 6906 } else { |
| 6903 checked_object = Add<HCheckMaps>(object, types); | 6907 checked_object = Add<HCheckMaps>(object, types); |
| 6904 } | 6908 } |
| 6905 instr = BuildLoadMonomorphic( | 6909 instr = BuildLoadMonomorphic( |
| 6906 &info, object, checked_object, ast_id, expr->LoadId()); | 6910 &info, object, checked_object, ast_id, expr->LoadId()); |
| 6907 if (instr == NULL) return; | 6911 if (instr == NULL) return; |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7087 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 7091 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
| 7088 FunctionSorter order[kMaxCallPolymorphism]; | 7092 FunctionSorter order[kMaxCallPolymorphism]; |
| 7089 | 7093 |
| 7090 bool handle_smi = false; | 7094 bool handle_smi = false; |
| 7091 bool handled_string = false; | 7095 bool handled_string = false; |
| 7092 int ordered_functions = 0; | 7096 int ordered_functions = 0; |
| 7093 | 7097 |
| 7094 for (int i = 0; | 7098 for (int i = 0; |
| 7095 i < types->length() && ordered_functions < kMaxCallPolymorphism; | 7099 i < types->length() && ordered_functions < kMaxCallPolymorphism; |
| 7096 ++i) { | 7100 ++i) { |
| 7097 PropertyAccessInfo info(this, IC::MapToType(types->at(i)), name); | 7101 PropertyAccessInfo info(this, ToType(types->at(i)), name); |
| 7098 if (info.CanLoadMonomorphic() && | 7102 if (info.CanLoadMonomorphic() && |
| 7099 info.lookup()->IsConstant() && | 7103 info.lookup()->IsConstant() && |
| 7100 info.constant()->IsJSFunction()) { | 7104 info.constant()->IsJSFunction()) { |
| 7101 if (info.type()->Is(HeapType::String())) { | 7105 if (info.type()->Is(Type::String())) { |
| 7102 if (handled_string) continue; | 7106 if (handled_string) continue; |
| 7103 handled_string = true; | 7107 handled_string = true; |
| 7104 } | 7108 } |
| 7105 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); | 7109 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); |
| 7106 if (info.type()->Is(HeapType::Number())) { | 7110 if (info.type()->Is(Type::Number())) { |
| 7107 handle_smi = true; | 7111 handle_smi = true; |
| 7108 } | 7112 } |
| 7109 expr->set_target(target); | 7113 expr->set_target(target); |
| 7110 order[ordered_functions++] = | 7114 order[ordered_functions++] = |
| 7111 FunctionSorter(i, | 7115 FunctionSorter(i, |
| 7112 expr->target()->shared()->profiler_ticks(), | 7116 expr->target()->shared()->profiler_ticks(), |
| 7113 InliningAstSize(expr->target()), | 7117 InliningAstSize(expr->target()), |
| 7114 expr->target()->shared()->SourceSize()); | 7118 expr->target()->shared()->SourceSize()); |
| 7115 } | 7119 } |
| 7116 } | 7120 } |
| 7117 | 7121 |
| 7118 std::sort(order, order + ordered_functions); | 7122 std::sort(order, order + ordered_functions); |
| 7119 | 7123 |
| 7120 HBasicBlock* number_block = NULL; | 7124 HBasicBlock* number_block = NULL; |
| 7121 HBasicBlock* join = NULL; | 7125 HBasicBlock* join = NULL; |
| 7122 handled_string = false; | 7126 handled_string = false; |
| 7123 int count = 0; | 7127 int count = 0; |
| 7124 | 7128 |
| 7125 for (int fn = 0; fn < ordered_functions; ++fn) { | 7129 for (int fn = 0; fn < ordered_functions; ++fn) { |
| 7126 int i = order[fn].index(); | 7130 int i = order[fn].index(); |
| 7127 PropertyAccessInfo info(this, IC::MapToType(types->at(i)), name); | 7131 PropertyAccessInfo info(this, ToType(types->at(i)), name); |
| 7128 if (info.type()->Is(HeapType::String())) { | 7132 if (info.type()->Is(Type::String())) { |
| 7129 if (handled_string) continue; | 7133 if (handled_string) continue; |
| 7130 handled_string = true; | 7134 handled_string = true; |
| 7131 } | 7135 } |
| 7132 // Reloads the target. | 7136 // Reloads the target. |
| 7133 info.CanLoadMonomorphic(); | 7137 info.CanLoadMonomorphic(); |
| 7134 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); | 7138 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); |
| 7135 | 7139 |
| 7136 expr->set_target(target); | 7140 expr->set_target(target); |
| 7137 if (count == 0) { | 7141 if (count == 0) { |
| 7138 // Only needed once. | 7142 // Only needed once. |
| 7139 join = graph()->CreateBasicBlock(); | 7143 join = graph()->CreateBasicBlock(); |
| 7140 if (handle_smi) { | 7144 if (handle_smi) { |
| 7141 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); | 7145 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); |
| 7142 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); | 7146 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); |
| 7143 number_block = graph()->CreateBasicBlock(); | 7147 number_block = graph()->CreateBasicBlock(); |
| 7144 FinishCurrentBlock(New<HIsSmiAndBranch>( | 7148 FinishCurrentBlock(New<HIsSmiAndBranch>( |
| 7145 receiver, empty_smi_block, not_smi_block)); | 7149 receiver, empty_smi_block, not_smi_block)); |
| 7146 Goto(empty_smi_block, number_block); | 7150 Goto(empty_smi_block, number_block); |
| 7147 set_current_block(not_smi_block); | 7151 set_current_block(not_smi_block); |
| 7148 } else { | 7152 } else { |
| 7149 BuildCheckHeapObject(receiver); | 7153 BuildCheckHeapObject(receiver); |
| 7150 } | 7154 } |
| 7151 } | 7155 } |
| 7152 ++count; | 7156 ++count; |
| 7153 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 7157 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 7154 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 7158 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 7155 HUnaryControlInstruction* compare; | 7159 HUnaryControlInstruction* compare; |
| 7156 | 7160 |
| 7157 Handle<Map> map = info.map(); | 7161 Handle<Map> map = info.map(); |
| 7158 if (info.type()->Is(HeapType::Number())) { | 7162 if (info.type()->Is(Type::Number())) { |
| 7159 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); | 7163 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); |
| 7160 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); | 7164 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); |
| 7161 } else if (info.type()->Is(HeapType::String())) { | 7165 } else if (info.type()->Is(Type::String())) { |
| 7162 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); | 7166 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); |
| 7163 } else { | 7167 } else { |
| 7164 compare = New<HCompareMap>(receiver, map, if_true, if_false); | 7168 compare = New<HCompareMap>(receiver, map, if_true, if_false); |
| 7165 } | 7169 } |
| 7166 FinishCurrentBlock(compare); | 7170 FinishCurrentBlock(compare); |
| 7167 | 7171 |
| 7168 if (info.type()->Is(HeapType::Number())) { | 7172 if (info.type()->Is(Type::Number())) { |
| 7169 Goto(if_true, number_block); | 7173 Goto(if_true, number_block); |
| 7170 if_true = number_block; | 7174 if_true = number_block; |
| 7171 number_block->SetJoinId(expr->id()); | 7175 number_block->SetJoinId(expr->id()); |
| 7172 } | 7176 } |
| 7173 | 7177 |
| 7174 set_current_block(if_true); | 7178 set_current_block(if_true); |
| 7175 | 7179 |
| 7176 AddCheckPrototypeMaps(info.holder(), map); | 7180 AddCheckPrototypeMaps(info.holder(), map); |
| 7177 | 7181 |
| 7178 HValue* function = Add<HConstant>(expr->target()); | 7182 HValue* function = Add<HConstant>(expr->target()); |
| (...skipping 927 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8106 Expression* callee = expr->expression(); | 8110 Expression* callee = expr->expression(); |
| 8107 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 8111 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 8108 HInstruction* call = NULL; | 8112 HInstruction* call = NULL; |
| 8109 | 8113 |
| 8110 Property* prop = callee->AsProperty(); | 8114 Property* prop = callee->AsProperty(); |
| 8111 if (prop != NULL) { | 8115 if (prop != NULL) { |
| 8112 CHECK_ALIVE(VisitForValue(prop->obj())); | 8116 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 8113 HValue* receiver = Top(); | 8117 HValue* receiver = Top(); |
| 8114 | 8118 |
| 8115 SmallMapList* types; | 8119 SmallMapList* types; |
| 8116 ComputeReceiverTypes(expr, receiver, &types); | 8120 ComputeReceiverTypes(expr, receiver, &types, zone()); |
| 8117 | 8121 |
| 8118 if (prop->key()->IsPropertyName() && types->length() > 0) { | 8122 if (prop->key()->IsPropertyName() && types->length() > 0) { |
| 8119 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 8123 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| 8120 PropertyAccessInfo info(this, IC::MapToType(types->first()), name); | 8124 PropertyAccessInfo info(this, ToType(types->first()), name); |
| 8121 if (!info.CanLoadAsMonomorphic(types)) { | 8125 if (!info.CanLoadAsMonomorphic(types)) { |
| 8122 HandlePolymorphicCallNamed(expr, receiver, types, name); | 8126 HandlePolymorphicCallNamed(expr, receiver, types, name); |
| 8123 return; | 8127 return; |
| 8124 } | 8128 } |
| 8125 } | 8129 } |
| 8126 | 8130 |
| 8127 HValue* key = NULL; | 8131 HValue* key = NULL; |
| 8128 if (!prop->key()->IsPropertyName()) { | 8132 if (!prop->key()->IsPropertyName()) { |
| 8129 CHECK_ALIVE(VisitForValue(prop->key())); | 8133 CHECK_ALIVE(VisitForValue(prop->key())); |
| 8130 key = Pop(); | 8134 key = Pop(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 8152 if (FLAG_trace_inlining) { | 8156 if (FLAG_trace_inlining) { |
| 8153 PrintF("Inlining builtin "); | 8157 PrintF("Inlining builtin "); |
| 8154 known_function->ShortPrint(); | 8158 known_function->ShortPrint(); |
| 8155 PrintF("\n"); | 8159 PrintF("\n"); |
| 8156 } | 8160 } |
| 8157 return; | 8161 return; |
| 8158 } | 8162 } |
| 8159 if (TryInlineApiMethodCall(expr, receiver, map)) return; | 8163 if (TryInlineApiMethodCall(expr, receiver, map)) return; |
| 8160 | 8164 |
| 8161 // Wrap the receiver if necessary. | 8165 // Wrap the receiver if necessary. |
| 8162 if (NeedsWrappingFor(IC::MapToType(types->first()), known_function)) { | 8166 if (NeedsWrappingFor(ToType(types->first()), known_function)) { |
| 8163 // Since HWrapReceiver currently cannot actually wrap numbers and | 8167 // Since HWrapReceiver currently cannot actually wrap numbers and |
| 8164 // strings, use the regular CallFunctionStub for method calls to wrap | 8168 // strings, use the regular CallFunctionStub for method calls to wrap |
| 8165 // the receiver. | 8169 // the receiver. |
| 8166 // TODO(verwaest): Support creation of value wrappers directly in | 8170 // TODO(verwaest): Support creation of value wrappers directly in |
| 8167 // HWrapReceiver. | 8171 // HWrapReceiver. |
| 8168 call = New<HCallFunction>( | 8172 call = New<HCallFunction>( |
| 8169 function, argument_count, WRAP_AND_CALL); | 8173 function, argument_count, WRAP_AND_CALL); |
| 8170 } else if (TryInlineCall(expr)) { | 8174 } else if (TryInlineCall(expr)) { |
| 8171 return; | 8175 return; |
| 8172 } else { | 8176 } else { |
| (...skipping 3202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11375 if (ShouldProduceTraceOutput()) { | 11379 if (ShouldProduceTraceOutput()) { |
| 11376 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11380 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 11377 } | 11381 } |
| 11378 | 11382 |
| 11379 #ifdef DEBUG | 11383 #ifdef DEBUG |
| 11380 graph_->Verify(false); // No full verify. | 11384 graph_->Verify(false); // No full verify. |
| 11381 #endif | 11385 #endif |
| 11382 } | 11386 } |
| 11383 | 11387 |
| 11384 } } // namespace v8::internal | 11388 } } // namespace v8::internal |
| OLD | NEW |