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 |