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