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 |