OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/crankshaft/hydrogen.h" | 5 #include "src/crankshaft/hydrogen.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/allocation-site-scopes.h" | 9 #include "src/allocation-site-scopes.h" |
10 #include "src/ast/ast-numbering.h" | 10 #include "src/ast/ast-numbering.h" |
(...skipping 6762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6773 DCHECK(join != NULL); | 6773 DCHECK(join != NULL); |
6774 if (join->HasPredecessor()) { | 6774 if (join->HasPredecessor()) { |
6775 join->SetJoinId(ast_id); | 6775 join->SetJoinId(ast_id); |
6776 set_current_block(join); | 6776 set_current_block(join); |
6777 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 6777 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
6778 } else { | 6778 } else { |
6779 set_current_block(NULL); | 6779 set_current_block(NULL); |
6780 } | 6780 } |
6781 } | 6781 } |
6782 | 6782 |
6783 | 6783 static bool ComputeReceiverTypes(Expression* expr, HValue* receiver, |
6784 static bool ComputeReceiverTypes(Expression* expr, | |
6785 HValue* receiver, | |
6786 SmallMapList** t, | 6784 SmallMapList** t, |
6787 Zone* zone) { | 6785 HOptimizedGraphBuilder* builder) { |
| 6786 Zone* zone = builder->zone(); |
6788 SmallMapList* maps = expr->GetReceiverTypes(); | 6787 SmallMapList* maps = expr->GetReceiverTypes(); |
6789 *t = maps; | 6788 *t = maps; |
6790 bool monomorphic = expr->IsMonomorphic(); | 6789 bool monomorphic = expr->IsMonomorphic(); |
6791 if (maps != NULL && receiver->HasMonomorphicJSObjectType()) { | 6790 if (maps != NULL && receiver->HasMonomorphicJSObjectType()) { |
6792 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap(); | 6791 if (maps->length() > 0) { |
6793 maps->FilterForPossibleTransitions(root_map); | 6792 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap(); |
6794 monomorphic = maps->length() == 1; | 6793 maps->FilterForPossibleTransitions(root_map); |
| 6794 monomorphic = maps->length() == 1; |
| 6795 } else { |
| 6796 // No type feedback, see if we can infer the type. This is safely |
| 6797 // possible if the receiver had a known map at some point, and no |
| 6798 // map-changing stores have happened to it since. |
| 6799 Handle<Map> candidate_map = receiver->GetMonomorphicJSObjectMap(); |
| 6800 if (candidate_map->is_observed()) return false; |
| 6801 for (HInstruction* current = builder->current_block()->last(); |
| 6802 current != nullptr; current = current->previous()) { |
| 6803 if (current->IsBlockEntry()) break; |
| 6804 if (current->CheckChangesFlag(kMaps)) { |
| 6805 // Only allow map changes that store the candidate map. We don't |
| 6806 // need to care which object the map is being written into. |
| 6807 if (!current->IsStoreNamedField()) break; |
| 6808 HStoreNamedField* map_change = HStoreNamedField::cast(current); |
| 6809 if (!map_change->value()->IsConstant()) break; |
| 6810 HConstant* map_constant = HConstant::cast(map_change->value()); |
| 6811 if (!map_constant->representation().IsTagged()) break; |
| 6812 Handle<Object> map = map_constant->handle(builder->isolate()); |
| 6813 if (!map.is_identical_to(candidate_map)) break; |
| 6814 } |
| 6815 if (current == receiver) { |
| 6816 // We made it all the way back to the receiver without encountering |
| 6817 // a map change! So we can assume that the receiver still has the |
| 6818 // candidate_map we know about. |
| 6819 maps->Add(candidate_map, zone); |
| 6820 monomorphic = true; |
| 6821 break; |
| 6822 } |
| 6823 } |
| 6824 } |
6795 } | 6825 } |
6796 return monomorphic && CanInlinePropertyAccess(maps->first()); | 6826 return monomorphic && CanInlinePropertyAccess(maps->first()); |
6797 } | 6827 } |
6798 | 6828 |
6799 | 6829 |
6800 static bool AreStringTypes(SmallMapList* maps) { | 6830 static bool AreStringTypes(SmallMapList* maps) { |
6801 for (int i = 0; i < maps->length(); i++) { | 6831 for (int i = 0; i < maps->length(); i++) { |
6802 if (maps->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; | 6832 if (maps->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; |
6803 } | 6833 } |
6804 return true; | 6834 return true; |
(...skipping 888 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7693 *has_side_effects = instr->HasObservableSideEffects(); | 7723 *has_side_effects = instr->HasObservableSideEffects(); |
7694 } | 7724 } |
7695 return access; | 7725 return access; |
7696 } | 7726 } |
7697 } | 7727 } |
7698 | 7728 |
7699 DCHECK(!expr->IsPropertyName()); | 7729 DCHECK(!expr->IsPropertyName()); |
7700 HInstruction* instr = NULL; | 7730 HInstruction* instr = NULL; |
7701 | 7731 |
7702 SmallMapList* maps; | 7732 SmallMapList* maps; |
7703 bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, zone()); | 7733 bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, this); |
7704 | 7734 |
7705 bool force_generic = false; | 7735 bool force_generic = false; |
7706 if (expr->GetKeyType() == PROPERTY) { | 7736 if (expr->GetKeyType() == PROPERTY) { |
7707 // Non-Generic accesses assume that elements are being accessed, and will | 7737 // Non-Generic accesses assume that elements are being accessed, and will |
7708 // deopt for non-index keys, which the IC knows will occur. | 7738 // deopt for non-index keys, which the IC knows will occur. |
7709 // TODO(jkummerow): Consider adding proper support for property accesses. | 7739 // TODO(jkummerow): Consider adding proper support for property accesses. |
7710 force_generic = true; | 7740 force_generic = true; |
7711 monomorphic = false; | 7741 monomorphic = false; |
7712 } else if (access_type == STORE && | 7742 } else if (access_type == STORE && |
7713 (monomorphic || (maps != NULL && !maps->is_empty()))) { | 7743 (monomorphic || (maps != NULL && !maps->is_empty()))) { |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7850 ast_context()->ReturnInstruction(result, expr->id()); | 7880 ast_context()->ReturnInstruction(result, expr->id()); |
7851 return true; | 7881 return true; |
7852 } | 7882 } |
7853 | 7883 |
7854 | 7884 |
7855 HValue* HOptimizedGraphBuilder::BuildNamedAccess( | 7885 HValue* HOptimizedGraphBuilder::BuildNamedAccess( |
7856 PropertyAccessType access, BailoutId ast_id, BailoutId return_id, | 7886 PropertyAccessType access, BailoutId ast_id, BailoutId return_id, |
7857 Expression* expr, FeedbackVectorSlot slot, HValue* object, | 7887 Expression* expr, FeedbackVectorSlot slot, HValue* object, |
7858 Handle<Name> name, HValue* value, bool is_uninitialized) { | 7888 Handle<Name> name, HValue* value, bool is_uninitialized) { |
7859 SmallMapList* maps; | 7889 SmallMapList* maps; |
7860 ComputeReceiverTypes(expr, object, &maps, zone()); | 7890 ComputeReceiverTypes(expr, object, &maps, this); |
7861 DCHECK(maps != NULL); | 7891 DCHECK(maps != NULL); |
7862 | 7892 |
7863 if (maps->length() > 0) { | 7893 if (maps->length() > 0) { |
7864 PropertyAccessInfo info(this, access, maps->first(), name); | 7894 PropertyAccessInfo info(this, access, maps->first(), name); |
7865 if (!info.CanAccessAsMonomorphic(maps)) { | 7895 if (!info.CanAccessAsMonomorphic(maps)) { |
7866 HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id, | 7896 HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id, |
7867 object, value, maps, name); | 7897 object, value, maps, name); |
7868 return NULL; | 7898 return NULL; |
7869 } | 7899 } |
7870 | 7900 |
(...skipping 1823 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9694 Expression* callee = expr->expression(); | 9724 Expression* callee = expr->expression(); |
9695 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 9725 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
9696 HInstruction* call = NULL; | 9726 HInstruction* call = NULL; |
9697 | 9727 |
9698 Property* prop = callee->AsProperty(); | 9728 Property* prop = callee->AsProperty(); |
9699 if (prop != NULL) { | 9729 if (prop != NULL) { |
9700 CHECK_ALIVE(VisitForValue(prop->obj())); | 9730 CHECK_ALIVE(VisitForValue(prop->obj())); |
9701 HValue* receiver = Top(); | 9731 HValue* receiver = Top(); |
9702 | 9732 |
9703 SmallMapList* maps; | 9733 SmallMapList* maps; |
9704 ComputeReceiverTypes(expr, receiver, &maps, zone()); | 9734 ComputeReceiverTypes(expr, receiver, &maps, this); |
9705 | 9735 |
9706 if (prop->key()->IsPropertyName() && maps->length() > 0) { | 9736 if (prop->key()->IsPropertyName() && maps->length() > 0) { |
9707 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 9737 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
9708 PropertyAccessInfo info(this, LOAD, maps->first(), name); | 9738 PropertyAccessInfo info(this, LOAD, maps->first(), name); |
9709 if (!info.CanAccessAsMonomorphic(maps)) { | 9739 if (!info.CanAccessAsMonomorphic(maps)) { |
9710 HandlePolymorphicCallNamed(expr, receiver, maps, name); | 9740 HandlePolymorphicCallNamed(expr, receiver, maps, name); |
9711 return; | 9741 return; |
9712 } | 9742 } |
9713 } | 9743 } |
9714 HValue* key = NULL; | 9744 HValue* key = NULL; |
(...skipping 3869 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13584 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13614 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13585 } | 13615 } |
13586 | 13616 |
13587 #ifdef DEBUG | 13617 #ifdef DEBUG |
13588 graph_->Verify(false); // No full verify. | 13618 graph_->Verify(false); // No full verify. |
13589 #endif | 13619 #endif |
13590 } | 13620 } |
13591 | 13621 |
13592 } // namespace internal | 13622 } // namespace internal |
13593 } // namespace v8 | 13623 } // namespace v8 |
OLD | NEW |