| 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 4978 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4989 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4989 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
| 4990 Handle<FixedArray> literals(closure->literals()); | 4990 Handle<FixedArray> literals(closure->literals()); |
| 4991 HRegExpLiteral* instr = New<HRegExpLiteral>(literals, | 4991 HRegExpLiteral* instr = New<HRegExpLiteral>(literals, |
| 4992 expr->pattern(), | 4992 expr->pattern(), |
| 4993 expr->flags(), | 4993 expr->flags(), |
| 4994 expr->literal_index()); | 4994 expr->literal_index()); |
| 4995 return ast_context()->ReturnInstruction(instr, expr->id()); | 4995 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4996 } | 4996 } |
| 4997 | 4997 |
| 4998 | 4998 |
| 4999 static bool CanInlinePropertyAccess(Type* type, PropertyAccessType access) { | 4999 static bool CanInlinePropertyAccess(Type* type) { |
| 5000 if (type->Is(Type::NumberOrString())) return true; | 5000 if (type->Is(Type::NumberOrString())) return true; |
| 5001 if (!type->IsClass()) return false; | 5001 if (!type->IsClass()) return false; |
| 5002 Handle<Map> map = type->AsClass(); | 5002 Handle<Map> map = type->AsClass(); |
| 5003 return map->IsJSObjectMap() && | 5003 return map->IsJSObjectMap() && |
| 5004 !map->is_dictionary_map() && | 5004 !map->is_dictionary_map() && |
| 5005 !map->has_named_interceptor() && | 5005 !map->has_named_interceptor(); |
| 5006 // Must be a LOAD or a non-observed STORE | |
| 5007 (access == LOAD || !map->is_observed()); | |
| 5008 } | 5006 } |
| 5009 | 5007 |
| 5010 | 5008 |
| 5011 // Determines whether the given array or object literal boilerplate satisfies | 5009 // Determines whether the given array or object literal boilerplate satisfies |
| 5012 // all limits to be considered for fast deep-copying and computes the total | 5010 // all limits to be considered for fast deep-copying and computes the total |
| 5013 // size of all objects that are part of the graph. | 5011 // size of all objects that are part of the graph. |
| 5014 static bool IsFastLiteral(Handle<JSObject> boilerplate, | 5012 static bool IsFastLiteral(Handle<JSObject> boilerplate, |
| 5015 int max_depth, | 5013 int max_depth, |
| 5016 int* max_properties) { | 5014 int* max_properties) { |
| 5017 if (boilerplate->map()->is_deprecated()) { | 5015 if (boilerplate->map()->is_deprecated()) { |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5409 HConstant* transition_constant = Add<HConstant>(info->transition()); | 5407 HConstant* transition_constant = Add<HConstant>(info->transition()); |
| 5410 instr->SetTransition(transition_constant, top_info()); | 5408 instr->SetTransition(transition_constant, top_info()); |
| 5411 instr->SetChangesFlag(kMaps); | 5409 instr->SetChangesFlag(kMaps); |
| 5412 } | 5410 } |
| 5413 return instr; | 5411 return instr; |
| 5414 } | 5412 } |
| 5415 | 5413 |
| 5416 | 5414 |
| 5417 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible( | 5415 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible( |
| 5418 PropertyAccessInfo* info) { | 5416 PropertyAccessInfo* info) { |
| 5419 if (!CanInlinePropertyAccess(type_, access_type_)) return false; | 5417 if (!CanInlinePropertyAccess(type_)) return false; |
| 5420 | 5418 |
| 5421 // Currently only handle Type::Number as a polymorphic case. | 5419 // Currently only handle Type::Number as a polymorphic case. |
| 5422 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber | 5420 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber |
| 5423 // instruction. | 5421 // instruction. |
| 5424 if (type_->Is(Type::Number())) return false; | 5422 if (type_->Is(Type::Number())) return false; |
| 5425 | 5423 |
| 5426 // Values are only compatible for monomorphic load if they all behave the same | 5424 // Values are only compatible for monomorphic load if they all behave the same |
| 5427 // regarding value wrappers. | 5425 // regarding value wrappers. |
| 5428 if (type_->Is(Type::NumberOrString())) { | 5426 if (type_->Is(Type::NumberOrString())) { |
| 5429 if (!info->type_->Is(Type::NumberOrString())) return false; | 5427 if (!info->type_->Is(Type::NumberOrString())) return false; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5510 | 5508 |
| 5511 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { | 5509 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { |
| 5512 Handle<Map> map = this->map(); | 5510 Handle<Map> map = this->map(); |
| 5513 | 5511 |
| 5514 while (map->prototype()->IsJSObject()) { | 5512 while (map->prototype()->IsJSObject()) { |
| 5515 holder_ = handle(JSObject::cast(map->prototype())); | 5513 holder_ = handle(JSObject::cast(map->prototype())); |
| 5516 if (holder_->map()->is_deprecated()) { | 5514 if (holder_->map()->is_deprecated()) { |
| 5517 JSObject::TryMigrateInstance(holder_); | 5515 JSObject::TryMigrateInstance(holder_); |
| 5518 } | 5516 } |
| 5519 map = Handle<Map>(holder_->map()); | 5517 map = Handle<Map>(holder_->map()); |
| 5520 if (!CanInlinePropertyAccess(ToType(map), access_type_)) { | 5518 if (!CanInlinePropertyAccess(ToType(map))) { |
| 5521 lookup_.NotFound(); | 5519 lookup_.NotFound(); |
| 5522 return false; | 5520 return false; |
| 5523 } | 5521 } |
| 5524 map->LookupDescriptor(*holder_, *name_, &lookup_); | 5522 map->LookupDescriptor(*holder_, *name_, &lookup_); |
| 5525 if (lookup_.IsFound()) return LoadResult(map); | 5523 if (lookup_.IsFound()) return LoadResult(map); |
| 5526 } | 5524 } |
| 5527 lookup_.NotFound(); | 5525 lookup_.NotFound(); |
| 5528 return true; | 5526 return true; |
| 5529 } | 5527 } |
| 5530 | 5528 |
| 5531 | 5529 |
| 5532 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { | 5530 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { |
| 5533 if (!CanInlinePropertyAccess(type_, access_type_)) return false; | 5531 if (!CanInlinePropertyAccess(type_)) return false; |
| 5534 if (IsJSObjectFieldAccessor()) return IsLoad(); | 5532 if (IsJSObjectFieldAccessor()) return IsLoad(); |
| 5535 if (!LookupDescriptor()) return false; | 5533 if (!LookupDescriptor()) return false; |
| 5536 if (lookup_.IsFound()) { | 5534 if (lookup_.IsFound()) { |
| 5537 if (IsLoad()) return true; | 5535 if (IsLoad()) return true; |
| 5538 return !lookup_.IsReadOnly() && lookup_.IsCacheable(); | 5536 return !lookup_.IsReadOnly() && lookup_.IsCacheable(); |
| 5539 } | 5537 } |
| 5540 if (!LookupInPrototypes()) return false; | 5538 if (!LookupInPrototypes()) return false; |
| 5541 if (IsLoad()) return true; | 5539 if (IsLoad()) return true; |
| 5542 | 5540 |
| 5543 if (lookup_.IsPropertyCallbacks()) return true; | 5541 if (lookup_.IsPropertyCallbacks()) return true; |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5802 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 5800 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| 5803 } else { | 5801 } else { |
| 5804 set_current_block(NULL); | 5802 set_current_block(NULL); |
| 5805 } | 5803 } |
| 5806 } | 5804 } |
| 5807 | 5805 |
| 5808 | 5806 |
| 5809 static bool ComputeReceiverTypes(Expression* expr, | 5807 static bool ComputeReceiverTypes(Expression* expr, |
| 5810 HValue* receiver, | 5808 HValue* receiver, |
| 5811 SmallMapList** t, | 5809 SmallMapList** t, |
| 5812 PropertyAccessType access_type, | |
| 5813 Zone* zone) { | 5810 Zone* zone) { |
| 5814 SmallMapList* types = expr->GetReceiverTypes(); | 5811 SmallMapList* types = expr->GetReceiverTypes(); |
| 5815 *t = types; | 5812 *t = types; |
| 5816 bool monomorphic = expr->IsMonomorphic(); | 5813 bool monomorphic = expr->IsMonomorphic(); |
| 5817 Isolate* isolate = zone->isolate(); | 5814 if (types != NULL && receiver->HasMonomorphicJSObjectType()) { |
| 5818 if (types != NULL) { | 5815 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap(); |
| 5819 if (receiver->HasMonomorphicJSObjectType()) { | 5816 types->FilterForPossibleTransitions(root_map); |
| 5820 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap(); | |
| 5821 types->FilterForPossibleTransitions(root_map); | |
| 5822 } else if (types->is_empty() && | |
| 5823 receiver->IsConstant() && | |
| 5824 HConstant::cast(receiver)->handle(isolate)->IsJSObject()) { | |
| 5825 Handle<Map> map(Handle<JSObject>::cast( | |
| 5826 HConstant::cast(receiver)->handle(isolate))->map()); | |
| 5827 types->Add(map, zone); | |
| 5828 } | |
| 5829 monomorphic = types->length() == 1; | 5817 monomorphic = types->length() == 1; |
| 5830 } | 5818 } |
| 5831 return monomorphic && CanInlinePropertyAccess( | 5819 return monomorphic && CanInlinePropertyAccess( |
| 5832 IC::MapToType<Type>(types->first(), zone), access_type); | 5820 IC::MapToType<Type>(types->first(), zone)); |
| 5833 } | 5821 } |
| 5834 | 5822 |
| 5835 | 5823 |
| 5836 static bool AreStringTypes(SmallMapList* types) { | 5824 static bool AreStringTypes(SmallMapList* types) { |
| 5837 for (int i = 0; i < types->length(); i++) { | 5825 for (int i = 0; i < types->length(); i++) { |
| 5838 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; | 5826 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; |
| 5839 } | 5827 } |
| 5840 return true; | 5828 return true; |
| 5841 } | 5829 } |
| 5842 | 5830 |
| (...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6525 HValue* obj, | 6513 HValue* obj, |
| 6526 HValue* key, | 6514 HValue* key, |
| 6527 HValue* val, | 6515 HValue* val, |
| 6528 Expression* expr, | 6516 Expression* expr, |
| 6529 PropertyAccessType access_type, | 6517 PropertyAccessType access_type, |
| 6530 bool* has_side_effects) { | 6518 bool* has_side_effects) { |
| 6531 ASSERT(!expr->IsPropertyName()); | 6519 ASSERT(!expr->IsPropertyName()); |
| 6532 HInstruction* instr = NULL; | 6520 HInstruction* instr = NULL; |
| 6533 | 6521 |
| 6534 SmallMapList* types; | 6522 SmallMapList* types; |
| 6535 bool monomorphic = ComputeReceiverTypes(expr, | 6523 bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone()); |
| 6536 obj, | |
| 6537 &types, | |
| 6538 access_type, | |
| 6539 zone()); | |
| 6540 | 6524 |
| 6541 bool force_generic = false; | 6525 bool force_generic = false; |
| 6542 if (access_type == STORE && | 6526 if (access_type == STORE && |
| 6543 (monomorphic || (types != NULL && !types->is_empty()))) { | 6527 (monomorphic || (types != NULL && !types->is_empty()))) { |
| 6544 // Stores can't be mono/polymorphic if their prototype chain has dictionary | 6528 // Stores can't be mono/polymorphic if their prototype chain has dictionary |
| 6545 // elements. However a receiver map that has dictionary elements itself | 6529 // elements. However a receiver map that has dictionary elements itself |
| 6546 // should be left to normal mono/poly behavior (the other maps may benefit | 6530 // should be left to normal mono/poly behavior (the other maps may benefit |
| 6547 // from highly optimized stores). | 6531 // from highly optimized stores). |
| 6548 for (int i = 0; i < types->length(); i++) { | 6532 for (int i = 0; i < types->length(); i++) { |
| 6549 Handle<Map> current_map = types->at(i); | 6533 Handle<Map> current_map = types->at(i); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6668 HInstruction* HOptimizedGraphBuilder::BuildNamedAccess( | 6652 HInstruction* HOptimizedGraphBuilder::BuildNamedAccess( |
| 6669 PropertyAccessType access, | 6653 PropertyAccessType access, |
| 6670 BailoutId ast_id, | 6654 BailoutId ast_id, |
| 6671 BailoutId return_id, | 6655 BailoutId return_id, |
| 6672 Expression* expr, | 6656 Expression* expr, |
| 6673 HValue* object, | 6657 HValue* object, |
| 6674 Handle<String> name, | 6658 Handle<String> name, |
| 6675 HValue* value, | 6659 HValue* value, |
| 6676 bool is_uninitialized) { | 6660 bool is_uninitialized) { |
| 6677 SmallMapList* types; | 6661 SmallMapList* types; |
| 6678 ComputeReceiverTypes(expr, object, &types, access, zone()); | 6662 ComputeReceiverTypes(expr, object, &types, zone()); |
| 6679 ASSERT(types != NULL); | 6663 ASSERT(types != NULL); |
| 6680 | 6664 |
| 6681 if (types->length() > 0) { | 6665 if (types->length() > 0) { |
| 6682 PropertyAccessInfo info(this, access, ToType(types->first()), name); | 6666 PropertyAccessInfo info(this, access, ToType(types->first()), name); |
| 6683 if (!info.CanAccessAsMonomorphic(types)) { | 6667 if (!info.CanAccessAsMonomorphic(types)) { |
| 6684 HandlePolymorphicNamedFieldAccess( | 6668 HandlePolymorphicNamedFieldAccess( |
| 6685 access, ast_id, return_id, object, value, types, name); | 6669 access, ast_id, return_id, object, value, types, name); |
| 6686 return NULL; | 6670 return NULL; |
| 6687 } | 6671 } |
| 6688 | 6672 |
| (...skipping 1295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7984 Expression* callee = expr->expression(); | 7968 Expression* callee = expr->expression(); |
| 7985 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 7969 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 7986 HInstruction* call = NULL; | 7970 HInstruction* call = NULL; |
| 7987 | 7971 |
| 7988 Property* prop = callee->AsProperty(); | 7972 Property* prop = callee->AsProperty(); |
| 7989 if (prop != NULL) { | 7973 if (prop != NULL) { |
| 7990 CHECK_ALIVE(VisitForValue(prop->obj())); | 7974 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 7991 HValue* receiver = Top(); | 7975 HValue* receiver = Top(); |
| 7992 | 7976 |
| 7993 SmallMapList* types; | 7977 SmallMapList* types; |
| 7994 ComputeReceiverTypes(expr, receiver, &types, LOAD, zone()); | 7978 ComputeReceiverTypes(expr, receiver, &types, zone()); |
| 7995 | 7979 |
| 7996 if (prop->key()->IsPropertyName() && types->length() > 0) { | 7980 if (prop->key()->IsPropertyName() && types->length() > 0) { |
| 7997 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 7981 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| 7998 PropertyAccessInfo info(this, LOAD, ToType(types->first()), name); | 7982 PropertyAccessInfo info(this, LOAD, ToType(types->first()), name); |
| 7999 if (!info.CanAccessAsMonomorphic(types)) { | 7983 if (!info.CanAccessAsMonomorphic(types)) { |
| 8000 HandlePolymorphicCallNamed(expr, receiver, types, name); | 7984 HandlePolymorphicCallNamed(expr, receiver, types, name); |
| 8001 return; | 7985 return; |
| 8002 } | 7986 } |
| 8003 } | 7987 } |
| 8004 | 7988 |
| (...skipping 3535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11540 if (ShouldProduceTraceOutput()) { | 11524 if (ShouldProduceTraceOutput()) { |
| 11541 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11525 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 11542 } | 11526 } |
| 11543 | 11527 |
| 11544 #ifdef DEBUG | 11528 #ifdef DEBUG |
| 11545 graph_->Verify(false); // No full verify. | 11529 graph_->Verify(false); // No full verify. |
| 11546 #endif | 11530 #endif |
| 11547 } | 11531 } |
| 11548 | 11532 |
| 11549 } } // namespace v8::internal | 11533 } } // namespace v8::internal |
| OLD | NEW |