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 16 matching lines...) Expand all Loading... |
27 | 27 |
28 #include "hydrogen.h" | 28 #include "hydrogen.h" |
29 | 29 |
30 #include <algorithm> | 30 #include <algorithm> |
31 | 31 |
32 #include "v8.h" | 32 #include "v8.h" |
33 #include "codegen.h" | 33 #include "codegen.h" |
34 #include "full-codegen.h" | 34 #include "full-codegen.h" |
35 #include "hashmap.h" | 35 #include "hashmap.h" |
36 #include "hydrogen-bce.h" | 36 #include "hydrogen-bce.h" |
| 37 #include "hydrogen-bch.h" |
37 #include "hydrogen-canonicalize.h" | 38 #include "hydrogen-canonicalize.h" |
38 #include "hydrogen-dce.h" | 39 #include "hydrogen-dce.h" |
39 #include "hydrogen-dehoist.h" | 40 #include "hydrogen-dehoist.h" |
40 #include "hydrogen-deoptimizing-mark.h" | 41 #include "hydrogen-deoptimizing-mark.h" |
41 #include "hydrogen-environment-liveness.h" | 42 #include "hydrogen-environment-liveness.h" |
42 #include "hydrogen-escape-analysis.h" | 43 #include "hydrogen-escape-analysis.h" |
43 #include "hydrogen-infer-representation.h" | 44 #include "hydrogen-infer-representation.h" |
44 #include "hydrogen-infer-types.h" | 45 #include "hydrogen-infer-types.h" |
45 #include "hydrogen-gvn.h" | 46 #include "hydrogen-gvn.h" |
46 #include "hydrogen-minus-zero.h" | 47 #include "hydrogen-minus-zero.h" |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 ASSERT(last_environment() != NULL); | 142 ASSERT(last_environment() != NULL); |
142 ASSERT(!last_environment()->ast_id().IsNone()); | 143 ASSERT(!last_environment()->ast_id().IsNone()); |
143 HBlockEntry* entry = new(zone()) HBlockEntry(); | 144 HBlockEntry* entry = new(zone()) HBlockEntry(); |
144 entry->InitializeAsFirst(this); | 145 entry->InitializeAsFirst(this); |
145 first_ = last_ = entry; | 146 first_ = last_ = entry; |
146 } | 147 } |
147 instr->InsertAfter(last_); | 148 instr->InsertAfter(last_); |
148 } | 149 } |
149 | 150 |
150 | 151 |
151 HDeoptimize* HBasicBlock::CreateDeoptimize( | |
152 HDeoptimize::UseEnvironment has_uses) { | |
153 ASSERT(HasEnvironment()); | |
154 if (has_uses == HDeoptimize::kNoUses) | |
155 return new(zone()) HDeoptimize(0, 0, 0, zone()); | |
156 | |
157 HEnvironment* environment = last_environment(); | |
158 int first_local_index = environment->first_local_index(); | |
159 int first_expression_index = environment->first_expression_index(); | |
160 HDeoptimize* instr = new(zone()) HDeoptimize( | |
161 environment->length(), first_local_index, first_expression_index, zone()); | |
162 for (int i = 0; i < environment->length(); i++) { | |
163 HValue* val = environment->values()->at(i); | |
164 instr->AddEnvironmentValue(val, zone()); | |
165 } | |
166 | |
167 return instr; | |
168 } | |
169 | |
170 | |
171 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, | 152 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, |
172 RemovableSimulate removable) { | 153 RemovableSimulate removable) { |
173 ASSERT(HasEnvironment()); | 154 ASSERT(HasEnvironment()); |
174 HEnvironment* environment = last_environment(); | 155 HEnvironment* environment = last_environment(); |
175 ASSERT(ast_id.IsNone() || | 156 ASSERT(ast_id.IsNone() || |
176 ast_id == BailoutId::StubEntry() || | 157 ast_id == BailoutId::StubEntry() || |
177 environment->closure()->shared()->VerifyBailoutId(ast_id)); | 158 environment->closure()->shared()->VerifyBailoutId(ast_id)); |
178 | 159 |
179 int push_count = environment->push_count(); | 160 int push_count = environment->push_count(); |
180 int pop_count = environment->pop_count(); | 161 int pop_count = environment->pop_count(); |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
695 if (constant == GetConstantHole()) return true; | 676 if (constant == GetConstantHole()) return true; |
696 if (constant == GetConstantNull()) return true; | 677 if (constant == GetConstantNull()) return true; |
697 return false; | 678 return false; |
698 } | 679 } |
699 | 680 |
700 | 681 |
701 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position) | 682 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position) |
702 : builder_(builder), | 683 : builder_(builder), |
703 position_(position), | 684 position_(position), |
704 finished_(false), | 685 finished_(false), |
| 686 deopt_then_(false), |
| 687 deopt_else_(false), |
705 did_then_(false), | 688 did_then_(false), |
706 did_else_(false), | 689 did_else_(false), |
707 did_and_(false), | 690 did_and_(false), |
708 did_or_(false), | 691 did_or_(false), |
709 captured_(false), | 692 captured_(false), |
710 needs_compare_(true), | 693 needs_compare_(true), |
711 split_edge_merge_block_(NULL) { | 694 split_edge_merge_block_(NULL), |
| 695 merge_block_(NULL) { |
712 HEnvironment* env = builder->environment(); | 696 HEnvironment* env = builder->environment(); |
713 first_true_block_ = builder->CreateBasicBlock(env->Copy()); | 697 first_true_block_ = builder->CreateBasicBlock(env->Copy()); |
714 last_true_block_ = NULL; | 698 last_true_block_ = NULL; |
715 first_false_block_ = builder->CreateBasicBlock(env->Copy()); | 699 first_false_block_ = builder->CreateBasicBlock(env->Copy()); |
716 } | 700 } |
717 | 701 |
718 | 702 |
719 HGraphBuilder::IfBuilder::IfBuilder( | 703 HGraphBuilder::IfBuilder::IfBuilder( |
720 HGraphBuilder* builder, | 704 HGraphBuilder* builder, |
721 HIfContinuation* continuation) | 705 HIfContinuation* continuation) |
722 : builder_(builder), | 706 : builder_(builder), |
723 position_(RelocInfo::kNoPosition), | 707 position_(RelocInfo::kNoPosition), |
724 finished_(false), | 708 finished_(false), |
| 709 deopt_then_(false), |
| 710 deopt_else_(false), |
725 did_then_(false), | 711 did_then_(false), |
726 did_else_(false), | 712 did_else_(false), |
727 did_and_(false), | 713 did_and_(false), |
728 did_or_(false), | 714 did_or_(false), |
729 captured_(false), | 715 captured_(false), |
730 needs_compare_(false), | 716 needs_compare_(false), |
731 first_true_block_(NULL), | 717 first_true_block_(NULL), |
732 first_false_block_(NULL), | 718 first_false_block_(NULL), |
733 split_edge_merge_block_(NULL), | 719 split_edge_merge_block_(NULL), |
734 merge_block_(NULL) { | 720 merge_block_(NULL) { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
831 ASSERT(!captured_); | 817 ASSERT(!captured_); |
832 ASSERT(!finished_); | 818 ASSERT(!finished_); |
833 last_true_block_ = builder_->current_block(); | 819 last_true_block_ = builder_->current_block(); |
834 ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished()); | 820 ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished()); |
835 builder_->set_current_block(first_false_block_); | 821 builder_->set_current_block(first_false_block_); |
836 did_else_ = true; | 822 did_else_ = true; |
837 } | 823 } |
838 | 824 |
839 | 825 |
840 void HGraphBuilder::IfBuilder::Deopt() { | 826 void HGraphBuilder::IfBuilder::Deopt() { |
841 HBasicBlock* block = builder_->current_block(); | 827 ASSERT(did_then_); |
842 block->FinishExitWithDeoptimization(HDeoptimize::kUseAll); | |
843 builder_->set_current_block(NULL); | |
844 if (did_else_) { | 828 if (did_else_) { |
845 first_false_block_ = NULL; | 829 deopt_else_ = true; |
846 } else { | 830 } else { |
847 first_true_block_ = NULL; | 831 deopt_then_ = true; |
848 } | 832 } |
| 833 builder_->Add<HDeoptimize>(Deoptimizer::EAGER); |
849 } | 834 } |
850 | 835 |
851 | 836 |
852 void HGraphBuilder::IfBuilder::Return(HValue* value) { | 837 void HGraphBuilder::IfBuilder::Return(HValue* value) { |
853 HBasicBlock* block = builder_->current_block(); | 838 HBasicBlock* block = builder_->current_block(); |
854 HValue* context = builder_->environment()->LookupContext(); | 839 HValue* context = builder_->environment()->LookupContext(); |
855 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); | 840 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); |
856 block->FinishExit(new(zone()) HReturn(value, context, parameter_count)); | 841 block->FinishExit(new(zone()) HReturn(value, context, parameter_count)); |
857 builder_->set_current_block(NULL); | 842 builder_->set_current_block(NULL); |
858 if (did_else_) { | 843 if (did_else_) { |
859 first_false_block_ = NULL; | 844 first_false_block_ = NULL; |
860 } else { | 845 } else { |
861 first_true_block_ = NULL; | 846 first_true_block_ = NULL; |
862 } | 847 } |
863 } | 848 } |
864 | 849 |
865 | 850 |
866 void HGraphBuilder::IfBuilder::End() { | 851 void HGraphBuilder::IfBuilder::End() { |
867 if (!captured_) { | 852 if (!captured_) { |
868 ASSERT(did_then_); | 853 ASSERT(did_then_); |
869 if (!did_else_) { | 854 if (!did_else_) { |
870 last_true_block_ = builder_->current_block(); | 855 last_true_block_ = builder_->current_block(); |
871 } | 856 } |
872 if (first_true_block_ == NULL) { | 857 if (first_true_block_ == NULL) { |
873 // Deopt on true. Nothing to do, just continue the false block. | 858 // Return on true. Nothing to do, just continue the false block. |
874 } else if (first_false_block_ == NULL) { | 859 } else if (first_false_block_ == NULL) { |
875 // Deopt on false. Nothing to do except switching to the true block. | 860 // Deopt on false. Nothing to do except switching to the true block. |
876 builder_->set_current_block(last_true_block_); | 861 builder_->set_current_block(last_true_block_); |
877 } else { | 862 } else { |
878 HEnvironment* merge_env = last_true_block_->last_environment()->Copy(); | 863 merge_block_ = builder_->graph()->CreateBasicBlock(); |
879 merge_block_ = builder_->CreateBasicBlock(merge_env); | |
880 ASSERT(!finished_); | 864 ASSERT(!finished_); |
881 if (!did_else_) Else(); | 865 if (!did_else_) Else(); |
882 ASSERT(!last_true_block_->IsFinished()); | 866 ASSERT(!last_true_block_->IsFinished()); |
883 HBasicBlock* last_false_block = builder_->current_block(); | 867 HBasicBlock* last_false_block = builder_->current_block(); |
884 ASSERT(!last_false_block->IsFinished()); | 868 ASSERT(!last_false_block->IsFinished()); |
885 last_true_block_->GotoNoSimulate(merge_block_); | 869 if (deopt_then_) { |
886 last_false_block->GotoNoSimulate(merge_block_); | 870 last_false_block->GotoNoSimulate(merge_block_); |
| 871 builder_->PadEnvironmentForContinuation(last_true_block_, |
| 872 merge_block_); |
| 873 last_true_block_->GotoNoSimulate(merge_block_); |
| 874 } else { |
| 875 last_true_block_->GotoNoSimulate(merge_block_); |
| 876 if (deopt_else_) { |
| 877 builder_->PadEnvironmentForContinuation(last_false_block, |
| 878 merge_block_); |
| 879 } |
| 880 last_false_block->GotoNoSimulate(merge_block_); |
| 881 } |
887 builder_->set_current_block(merge_block_); | 882 builder_->set_current_block(merge_block_); |
888 } | 883 } |
889 } | 884 } |
890 finished_ = true; | 885 finished_ = true; |
891 } | 886 } |
892 | 887 |
893 | 888 |
894 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, | 889 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, |
895 HValue* context, | 890 HValue* context, |
896 LoopBuilder::Direction direction) | 891 LoopBuilder::Direction direction) |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 981 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
987 ASSERT(current_block() != NULL); | 982 ASSERT(current_block() != NULL); |
988 current_block()->AddInstruction(instr); | 983 current_block()->AddInstruction(instr); |
989 if (no_side_effects_scope_count_ > 0) { | 984 if (no_side_effects_scope_count_ > 0) { |
990 instr->SetFlag(HValue::kHasNoObservableSideEffects); | 985 instr->SetFlag(HValue::kHasNoObservableSideEffects); |
991 } | 986 } |
992 return instr; | 987 return instr; |
993 } | 988 } |
994 | 989 |
995 | 990 |
996 void HGraphBuilder::AddSimulate(BailoutId id, | |
997 RemovableSimulate removable) { | |
998 ASSERT(current_block() != NULL); | |
999 ASSERT(no_side_effects_scope_count_ == 0); | |
1000 current_block()->AddSimulate(id, removable); | |
1001 } | |
1002 | |
1003 | |
1004 HReturn* HGraphBuilder::AddReturn(HValue* value) { | |
1005 HValue* context = environment()->LookupContext(); | |
1006 int num_parameters = graph()->info()->num_parameters(); | |
1007 HValue* params = Add<HConstant>(num_parameters); | |
1008 HReturn* return_instruction = new(graph()->zone()) | |
1009 HReturn(value, context, params); | |
1010 current_block()->FinishExit(return_instruction); | |
1011 return return_instruction; | |
1012 } | |
1013 | |
1014 | |
1015 void HGraphBuilder::AddSoftDeoptimize(SoftDeoptimizeMode mode) { | |
1016 isolate()->counters()->soft_deopts_requested()->Increment(); | |
1017 if (FLAG_always_opt && mode == CAN_OMIT_SOFT_DEOPT) return; | |
1018 if (current_block()->IsDeoptimizing()) return; | |
1019 Add<HSoftDeoptimize>(); | |
1020 isolate()->counters()->soft_deopts_inserted()->Increment(); | |
1021 current_block()->MarkAsDeoptimizing(); | |
1022 graph()->set_has_soft_deoptimize(true); | |
1023 } | |
1024 | |
1025 | |
1026 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { | 991 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { |
1027 HBasicBlock* b = graph()->CreateBasicBlock(); | 992 HBasicBlock* b = graph()->CreateBasicBlock(); |
1028 b->SetInitialEnvironment(env); | 993 b->SetInitialEnvironment(env); |
1029 return b; | 994 return b; |
1030 } | 995 } |
1031 | 996 |
1032 | 997 |
1033 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { | 998 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { |
1034 HBasicBlock* header = graph()->CreateBasicBlock(); | 999 HBasicBlock* header = graph()->CreateBasicBlock(); |
1035 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 1000 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); |
1036 header->SetInitialEnvironment(entry_env); | 1001 header->SetInitialEnvironment(entry_env); |
1037 header->AttachLoopInformation(); | 1002 header->AttachLoopInformation(); |
1038 return header; | 1003 return header; |
1039 } | 1004 } |
1040 | 1005 |
1041 | 1006 |
1042 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { | 1007 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { |
1043 if (obj->type().IsHeapObject()) return obj; | 1008 if (obj->type().IsHeapObject()) return obj; |
1044 return Add<HCheckHeapObject>(obj); | 1009 return Add<HCheckHeapObject>(obj); |
1045 } | 1010 } |
1046 | 1011 |
1047 | 1012 |
1048 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, | 1013 void HGraphBuilder::FinishExitWithHardDeoptimization( |
1049 Handle<Map> map) { | 1014 HBasicBlock* continuation) { |
1050 HCheckMaps* check = HCheckMaps::New(obj, map, zone()); | 1015 PadEnvironmentForContinuation(current_block(), continuation); |
| 1016 Add<HDeoptimize>(Deoptimizer::EAGER); |
| 1017 if (no_side_effects_scope_count_ > 0) { |
| 1018 current_block()->GotoNoSimulate(continuation); |
| 1019 } else { |
| 1020 current_block()->Goto(continuation); |
| 1021 } |
| 1022 } |
| 1023 |
| 1024 |
| 1025 void HGraphBuilder::PadEnvironmentForContinuation( |
| 1026 HBasicBlock* from, |
| 1027 HBasicBlock* continuation) { |
| 1028 if (continuation->last_environment() != NULL) { |
| 1029 // When merging from a deopt block to a continuation, resolve differences in |
| 1030 // environment by pushing undefined and popping extra values so that the |
| 1031 // environments match during the join. |
| 1032 int continuation_env_length = continuation->last_environment()->length(); |
| 1033 while (continuation_env_length != from->last_environment()->length()) { |
| 1034 if (continuation_env_length > from->last_environment()->length()) { |
| 1035 from->last_environment()->Push(graph()->GetConstantUndefined()); |
| 1036 } else { |
| 1037 from->last_environment()->Pop(); |
| 1038 } |
| 1039 } |
| 1040 } else { |
| 1041 ASSERT(continuation->predecessors()->length() == 0); |
| 1042 } |
| 1043 } |
| 1044 |
| 1045 |
| 1046 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) { |
| 1047 HCheckMaps* check = HCheckMaps::New(obj, map, zone(), top_info()); |
1051 AddInstruction(check); | 1048 AddInstruction(check); |
1052 return check; | 1049 return check; |
1053 } | 1050 } |
1054 | 1051 |
1055 | 1052 |
| 1053 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) { |
| 1054 if (object->type().IsJSObject()) return object; |
| 1055 return Add<HWrapReceiver>(object, function); |
| 1056 } |
| 1057 |
| 1058 |
1056 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, | 1059 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, |
1057 HValue* elements, | 1060 HValue* elements, |
1058 ElementsKind kind, | 1061 ElementsKind kind, |
1059 HValue* length, | 1062 HValue* length, |
1060 HValue* key, | 1063 HValue* key, |
1061 bool is_js_array) { | 1064 bool is_js_array) { |
1062 Zone* zone = this->zone(); | 1065 Zone* zone = this->zone(); |
1063 IfBuilder length_checker(this); | 1066 IfBuilder length_checker(this); |
1064 | 1067 |
1065 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ; | 1068 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ; |
(...skipping 21 matching lines...) Expand all Loading... |
1087 capacity_checker.Else(); | 1090 capacity_checker.Else(); |
1088 | 1091 |
1089 environment()->Push(elements); | 1092 environment()->Push(elements); |
1090 capacity_checker.End(); | 1093 capacity_checker.End(); |
1091 | 1094 |
1092 if (is_js_array) { | 1095 if (is_js_array) { |
1093 HValue* new_length = AddInstruction( | 1096 HValue* new_length = AddInstruction( |
1094 HAdd::New(zone, context, key, graph_->GetConstant1())); | 1097 HAdd::New(zone, context, key, graph_->GetConstant1())); |
1095 new_length->ClearFlag(HValue::kCanOverflow); | 1098 new_length->ClearFlag(HValue::kCanOverflow); |
1096 | 1099 |
1097 Representation representation = IsFastElementsKind(kind) | 1100 AddStore(object, HObjectAccess::ForArrayLength(kind), new_length); |
1098 ? Representation::Smi() : Representation::Tagged(); | |
1099 AddStore(object, HObjectAccess::ForArrayLength(), new_length, | |
1100 representation); | |
1101 } | 1101 } |
1102 | 1102 |
1103 length_checker.Else(); | 1103 length_checker.Else(); |
1104 Add<HBoundsCheck>(key, length); | 1104 Add<HBoundsCheck>(key, length); |
1105 | 1105 |
1106 environment()->Push(elements); | 1106 environment()->Push(elements); |
1107 length_checker.End(); | 1107 length_checker.End(); |
1108 | 1108 |
1109 return environment()->Pop(); | 1109 return environment()->Pop(); |
1110 } | 1110 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 | 1158 |
1159 IfBuilder if_builder(this); | 1159 IfBuilder if_builder(this); |
1160 | 1160 |
1161 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); | 1161 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); |
1162 | 1162 |
1163 if_builder.Then(); | 1163 if_builder.Then(); |
1164 | 1164 |
1165 HInstruction* elements_length = AddLoadFixedArrayLength(elements); | 1165 HInstruction* elements_length = AddLoadFixedArrayLength(elements); |
1166 | 1166 |
1167 HInstruction* array_length = is_jsarray | 1167 HInstruction* array_length = is_jsarray |
1168 ? AddLoad(object, HObjectAccess::ForArrayLength(), | 1168 ? AddLoad(object, HObjectAccess::ForArrayLength(from_kind), NULL) |
1169 NULL, Representation::Smi()) | |
1170 : elements_length; | 1169 : elements_length; |
1171 array_length->set_type(HType::Smi()); | |
1172 | 1170 |
1173 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, | 1171 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, |
1174 array_length, elements_length); | 1172 array_length, elements_length); |
1175 | 1173 |
1176 if_builder.End(); | 1174 if_builder.End(); |
1177 } | 1175 } |
1178 | 1176 |
1179 AddStore(object, HObjectAccess::ForMap(), map); | 1177 AddStore(object, HObjectAccess::ForMap(), map); |
1180 } | 1178 } |
1181 | 1179 |
(...skipping 21 matching lines...) Expand all Loading... |
1203 if (mapcheck != NULL) { | 1201 if (mapcheck != NULL) { |
1204 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 1202 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
1205 } | 1203 } |
1206 } | 1204 } |
1207 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); | 1205 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); |
1208 bool fast_elements = IsFastObjectElementsKind(elements_kind); | 1206 bool fast_elements = IsFastObjectElementsKind(elements_kind); |
1209 HValue* elements = AddLoadElements(object, mapcheck); | 1207 HValue* elements = AddLoadElements(object, mapcheck); |
1210 if (is_store && (fast_elements || fast_smi_only_elements) && | 1208 if (is_store && (fast_elements || fast_smi_only_elements) && |
1211 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 1209 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
1212 HCheckMaps* check_cow_map = HCheckMaps::New( | 1210 HCheckMaps* check_cow_map = HCheckMaps::New( |
1213 elements, isolate()->factory()->fixed_array_map(), zone); | 1211 elements, isolate()->factory()->fixed_array_map(), zone, top_info()); |
1214 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1212 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
1215 AddInstruction(check_cow_map); | 1213 AddInstruction(check_cow_map); |
1216 } | 1214 } |
1217 HInstruction* length = NULL; | 1215 HInstruction* length = NULL; |
1218 if (is_js_array) { | 1216 if (is_js_array) { |
1219 length = AddLoad(object, HObjectAccess::ForArrayLength(), mapcheck, | 1217 length = AddLoad(object, HObjectAccess::ForArrayLength(elements_kind), |
1220 Representation::Smi()); | 1218 mapcheck); |
1221 } else { | 1219 } else { |
1222 length = AddLoadFixedArrayLength(elements); | 1220 length = AddLoadFixedArrayLength(elements); |
1223 } | 1221 } |
1224 length->set_type(HType::Smi()); | 1222 length->set_type(HType::Smi()); |
1225 HValue* checked_key = NULL; | 1223 HValue* checked_key = NULL; |
1226 if (IsExternalArrayElementsKind(elements_kind)) { | 1224 if (IsExternalArrayElementsKind(elements_kind)) { |
1227 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 1225 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
1228 NoObservableSideEffectsScope no_effects(this); | 1226 NoObservableSideEffectsScope no_effects(this); |
1229 HLoadExternalArrayPointer* external_elements = | 1227 HLoadExternalArrayPointer* external_elements = |
1230 Add<HLoadExternalArrayPointer>(elements); | 1228 Add<HLoadExternalArrayPointer>(elements); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1271 checked_key = Add<HBoundsCheck>(key, length); | 1269 checked_key = Add<HBoundsCheck>(key, length); |
1272 | 1270 |
1273 if (is_store && (fast_elements || fast_smi_only_elements)) { | 1271 if (is_store && (fast_elements || fast_smi_only_elements)) { |
1274 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { | 1272 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { |
1275 NoObservableSideEffectsScope no_effects(this); | 1273 NoObservableSideEffectsScope no_effects(this); |
1276 | 1274 |
1277 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, | 1275 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, |
1278 length); | 1276 length); |
1279 } else { | 1277 } else { |
1280 HCheckMaps* check_cow_map = HCheckMaps::New( | 1278 HCheckMaps* check_cow_map = HCheckMaps::New( |
1281 elements, isolate()->factory()->fixed_array_map(), zone); | 1279 elements, isolate()->factory()->fixed_array_map(), |
| 1280 zone, top_info()); |
1282 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1281 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
1283 AddInstruction(check_cow_map); | 1282 AddInstruction(check_cow_map); |
1284 } | 1283 } |
1285 } | 1284 } |
1286 } | 1285 } |
1287 return AddFastElementAccess(elements, checked_key, val, mapcheck, | 1286 return AddFastElementAccess(elements, checked_key, val, mapcheck, |
1288 elements_kind, is_store, load_mode, store_mode); | 1287 elements_kind, is_store, load_mode, store_mode); |
1289 } | 1288 } |
1290 | 1289 |
1291 | 1290 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1325 | 1324 |
1326 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, | 1325 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, |
1327 ElementsKind kind, | 1326 ElementsKind kind, |
1328 HValue* capacity) { | 1327 HValue* capacity) { |
1329 Factory* factory = isolate()->factory(); | 1328 Factory* factory = isolate()->factory(); |
1330 Handle<Map> map = IsFastDoubleElementsKind(kind) | 1329 Handle<Map> map = IsFastDoubleElementsKind(kind) |
1331 ? factory->fixed_double_array_map() | 1330 ? factory->fixed_double_array_map() |
1332 : factory->fixed_array_map(); | 1331 : factory->fixed_array_map(); |
1333 | 1332 |
1334 AddStoreMapConstant(elements, map); | 1333 AddStoreMapConstant(elements, map); |
1335 Representation representation = IsFastElementsKind(kind) | 1334 AddStore(elements, HObjectAccess::ForFixedArrayLength(), capacity); |
1336 ? Representation::Smi() : Representation::Tagged(); | |
1337 AddStore(elements, HObjectAccess::ForFixedArrayLength(), capacity, | |
1338 representation); | |
1339 } | 1335 } |
1340 | 1336 |
1341 | 1337 |
1342 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( | 1338 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( |
1343 HValue* context, | 1339 HValue* context, |
1344 ElementsKind kind, | 1340 ElementsKind kind, |
1345 HValue* capacity) { | 1341 HValue* capacity) { |
1346 HValue* new_elements = BuildAllocateElements(context, kind, capacity); | 1342 HValue* new_elements = BuildAllocateElements(context, kind, capacity); |
1347 BuildInitializeElementsHeader(new_elements, kind, capacity); | 1343 BuildInitializeElementsHeader(new_elements, kind, capacity); |
1348 return new_elements; | 1344 return new_elements; |
1349 } | 1345 } |
1350 | 1346 |
1351 | 1347 |
1352 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, | 1348 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, |
1353 HValue* array_map, | 1349 HValue* array_map, |
1354 AllocationSiteMode mode, | 1350 AllocationSiteMode mode, |
| 1351 ElementsKind elements_kind, |
1355 HValue* allocation_site_payload, | 1352 HValue* allocation_site_payload, |
1356 HValue* length_field) { | 1353 HValue* length_field) { |
1357 | 1354 |
1358 AddStore(array, HObjectAccess::ForMap(), array_map); | 1355 AddStore(array, HObjectAccess::ForMap(), array_map); |
1359 | 1356 |
1360 HConstant* empty_fixed_array = | 1357 HConstant* empty_fixed_array = |
1361 Add<HConstant>(isolate()->factory()->empty_fixed_array()); | 1358 Add<HConstant>(isolate()->factory()->empty_fixed_array()); |
1362 | 1359 |
1363 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 1360 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
1364 AddStore(array, access, empty_fixed_array); | 1361 AddStore(array, access, empty_fixed_array); |
1365 AddStore(array, HObjectAccess::ForArrayLength(), length_field); | 1362 AddStore(array, HObjectAccess::ForArrayLength(elements_kind), length_field); |
1366 | 1363 |
1367 if (mode == TRACK_ALLOCATION_SITE) { | 1364 if (mode == TRACK_ALLOCATION_SITE) { |
1368 BuildCreateAllocationMemento(array, | 1365 BuildCreateAllocationMemento(array, |
1369 JSArray::kSize, | 1366 JSArray::kSize, |
1370 allocation_site_payload); | 1367 allocation_site_payload); |
1371 } | 1368 } |
1372 | 1369 |
1373 int elements_location = JSArray::kSize; | 1370 int elements_location = JSArray::kSize; |
1374 if (mode == TRACK_ALLOCATION_SITE) { | 1371 if (mode == TRACK_ALLOCATION_SITE) { |
1375 elements_location += AllocationMemento::kSize; | 1372 elements_location += AllocationMemento::kSize; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1462 } | 1459 } |
1463 | 1460 |
1464 | 1461 |
1465 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, | 1462 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, |
1466 HValue* typecheck) { | 1463 HValue* typecheck) { |
1467 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); | 1464 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); |
1468 } | 1465 } |
1469 | 1466 |
1470 | 1467 |
1471 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { | 1468 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { |
1472 HLoadNamedField* instr = AddLoad(object, HObjectAccess::ForFixedArrayLength(), | 1469 return AddLoad(object, HObjectAccess::ForFixedArrayLength()); |
1473 NULL, Representation::Smi()); | |
1474 instr->set_type(HType::Smi()); | |
1475 return instr; | |
1476 } | 1470 } |
1477 | 1471 |
1478 | 1472 |
1479 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, | 1473 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, |
1480 HValue* old_capacity) { | 1474 HValue* old_capacity) { |
1481 Zone* zone = this->zone(); | 1475 Zone* zone = this->zone(); |
1482 HValue* half_old_capacity = | 1476 HValue* half_old_capacity = |
1483 AddInstruction(HShr::New(zone, context, old_capacity, | 1477 AddInstruction(HShr::New(zone, context, old_capacity, |
1484 graph_->GetConstant1())); | 1478 graph_->GetConstant1())); |
1485 half_old_capacity->ClearFlag(HValue::kCanOverflow); | 1479 half_old_capacity->ClearFlag(HValue::kCanOverflow); |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1714 | 1708 |
1715 switch (operation) { | 1709 switch (operation) { |
1716 default: | 1710 default: |
1717 UNREACHABLE(); | 1711 UNREACHABLE(); |
1718 case Token::SUB: { | 1712 case Token::SUB: { |
1719 HInstruction* instr = | 1713 HInstruction* instr = |
1720 HMul::New(zone(), environment()->LookupContext(), | 1714 HMul::New(zone(), environment()->LookupContext(), |
1721 input, graph()->GetConstantMinus1()); | 1715 input, graph()->GetConstantMinus1()); |
1722 Representation rep = Representation::FromType(type); | 1716 Representation rep = Representation::FromType(type); |
1723 if (type->Is(Type::None())) { | 1717 if (type->Is(Type::None())) { |
1724 AddSoftDeoptimize(); | 1718 Add<HDeoptimize>(Deoptimizer::SOFT); |
1725 } | 1719 } |
1726 if (instr->IsBinaryOperation()) { | 1720 if (instr->IsBinaryOperation()) { |
1727 HBinaryOperation* binop = HBinaryOperation::cast(instr); | 1721 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
1728 binop->set_observed_input_representation(1, rep); | 1722 binop->set_observed_input_representation(1, rep); |
1729 binop->set_observed_input_representation(2, rep); | 1723 binop->set_observed_input_representation(2, rep); |
1730 } | 1724 } |
1731 return instr; | 1725 return instr; |
1732 } | 1726 } |
1733 case Token::BIT_NOT: | 1727 case Token::BIT_NOT: |
1734 if (type->Is(Type::None())) { | 1728 if (type->Is(Type::None())) { |
1735 AddSoftDeoptimize(); | 1729 Add<HDeoptimize>(Deoptimizer::SOFT); |
1736 } | 1730 } |
1737 return new(zone()) HBitNot(input); | 1731 return new(zone()) HBitNot(input); |
1738 } | 1732 } |
1739 } | 1733 } |
1740 | 1734 |
1741 | 1735 |
1742 void HGraphBuilder::BuildCompareNil( | 1736 void HGraphBuilder::BuildCompareNil( |
1743 HValue* value, | 1737 HValue* value, |
1744 Handle<Type> type, | 1738 Handle<Type> type, |
1745 int position, | 1739 int position, |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1836 allocation_site_payload_(NULL), | 1830 allocation_site_payload_(NULL), |
1837 constructor_function_(constructor_function) { | 1831 constructor_function_(constructor_function) { |
1838 } | 1832 } |
1839 | 1833 |
1840 | 1834 |
1841 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { | 1835 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { |
1842 if (kind_ == GetInitialFastElementsKind()) { | 1836 if (kind_ == GetInitialFastElementsKind()) { |
1843 // No need for a context lookup if the kind_ matches the initial | 1837 // No need for a context lookup if the kind_ matches the initial |
1844 // map, because we can just load the map in that case. | 1838 // map, because we can just load the map in that case. |
1845 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1839 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
1846 HInstruction* load = | 1840 return builder()->AddInstruction( |
1847 builder()->BuildLoadNamedField(constructor_function_, | 1841 builder()->BuildLoadNamedField(constructor_function_, access)); |
1848 access, | |
1849 Representation::Tagged()); | |
1850 return builder()->AddInstruction(load); | |
1851 } | 1842 } |
1852 | 1843 |
1853 HInstruction* native_context = builder()->BuildGetNativeContext(context); | 1844 HInstruction* native_context = builder()->BuildGetNativeContext(context); |
1854 HInstruction* index = builder()->Add<HConstant>( | 1845 HInstruction* index = builder()->Add<HConstant>( |
1855 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); | 1846 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); |
1856 | 1847 |
1857 HInstruction* map_array = builder()->Add<HLoadKeyed>( | 1848 HInstruction* map_array = builder()->Add<HLoadKeyed>( |
1858 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1849 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
1859 | 1850 |
1860 HInstruction* kind_index = builder()->Add<HConstant>(kind_); | 1851 HInstruction* kind_index = builder()->Add<HConstant>(kind_); |
1861 | 1852 |
1862 return builder()->Add<HLoadKeyed>( | 1853 return builder()->Add<HLoadKeyed>( |
1863 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1854 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
1864 } | 1855 } |
1865 | 1856 |
1866 | 1857 |
1867 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { | 1858 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { |
1868 // Find the map near the constructor function | 1859 // Find the map near the constructor function |
1869 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1860 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
1870 return builder()->AddInstruction( | 1861 return builder()->AddInstruction( |
1871 builder()->BuildLoadNamedField(constructor_function_, | 1862 builder()->BuildLoadNamedField(constructor_function_, access)); |
1872 access, | |
1873 Representation::Tagged())); | |
1874 } | 1863 } |
1875 | 1864 |
1876 | 1865 |
1877 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( | 1866 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( |
1878 HValue* length_node) { | 1867 HValue* length_node) { |
1879 HValue* context = builder()->environment()->LookupContext(); | 1868 HValue* context = builder()->environment()->LookupContext(); |
1880 ASSERT(length_node != NULL); | 1869 ASSERT(length_node != NULL); |
1881 | 1870 |
1882 int base_size = JSArray::kSize; | 1871 int base_size = JSArray::kSize; |
1883 if (mode_ == TRACK_ALLOCATION_SITE) { | 1872 if (mode_ == TRACK_ALLOCATION_SITE) { |
1884 base_size += AllocationMemento::kSize; | 1873 base_size += AllocationMemento::kSize; |
1885 } | 1874 } |
1886 | 1875 |
1887 if (IsFastDoubleElementsKind(kind_)) { | 1876 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); |
1888 base_size += FixedDoubleArray::kHeaderSize; | 1877 base_size += FixedArray::kHeaderSize; |
1889 } else { | |
1890 base_size += FixedArray::kHeaderSize; | |
1891 } | |
1892 | 1878 |
1893 HInstruction* elements_size_value = | 1879 HInstruction* elements_size_value = |
1894 builder()->Add<HConstant>(elements_size()); | 1880 builder()->Add<HConstant>(elements_size()); |
1895 HInstruction* mul = HMul::New(zone(), context, length_node, | 1881 HInstruction* mul = HMul::New(zone(), context, length_node, |
1896 elements_size_value); | 1882 elements_size_value); |
1897 mul->ClearFlag(HValue::kCanOverflow); | 1883 mul->ClearFlag(HValue::kCanOverflow); |
1898 builder()->AddInstruction(mul); | 1884 builder()->AddInstruction(mul); |
1899 | 1885 |
1900 HInstruction* base = builder()->Add<HConstant>(base_size); | 1886 HInstruction* base = builder()->Add<HConstant>(base_size); |
1901 HInstruction* total_size = HAdd::New(zone(), context, base, mul); | 1887 HInstruction* total_size = HAdd::New(zone(), context, base, mul); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1951 // Fill in the fields: map, properties, length | 1937 // Fill in the fields: map, properties, length |
1952 HValue* map; | 1938 HValue* map; |
1953 if (allocation_site_payload_ == NULL) { | 1939 if (allocation_site_payload_ == NULL) { |
1954 map = EmitInternalMapCode(); | 1940 map = EmitInternalMapCode(); |
1955 } else { | 1941 } else { |
1956 map = EmitMapCode(context); | 1942 map = EmitMapCode(context); |
1957 } | 1943 } |
1958 elements_location_ = builder()->BuildJSArrayHeader(new_object, | 1944 elements_location_ = builder()->BuildJSArrayHeader(new_object, |
1959 map, | 1945 map, |
1960 mode_, | 1946 mode_, |
| 1947 kind_, |
1961 allocation_site_payload_, | 1948 allocation_site_payload_, |
1962 length_field); | 1949 length_field); |
1963 | 1950 |
1964 // Initialize the elements | 1951 // Initialize the elements |
1965 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); | 1952 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); |
1966 | 1953 |
1967 if (fill_with_hole) { | 1954 if (fill_with_hole) { |
1968 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, | 1955 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, |
1969 graph()->GetConstant0(), capacity); | 1956 graph()->GetConstant0(), capacity); |
1970 } | 1957 } |
1971 | 1958 |
1972 return new_object; | 1959 return new_object; |
1973 } | 1960 } |
1974 | 1961 |
1975 | 1962 |
1976 HStoreNamedField* HGraphBuilder::AddStore(HValue *object, | 1963 HStoreNamedField* HGraphBuilder::AddStore(HValue *object, |
1977 HObjectAccess access, | 1964 HObjectAccess access, |
1978 HValue *val, | 1965 HValue *val) { |
1979 Representation representation) { | 1966 return Add<HStoreNamedField>(object, access, val); |
1980 return Add<HStoreNamedField>(object, access, val, representation); | |
1981 } | 1967 } |
1982 | 1968 |
1983 | 1969 |
1984 HLoadNamedField* HGraphBuilder::AddLoad(HValue *object, | 1970 HLoadNamedField* HGraphBuilder::AddLoad(HValue *object, |
1985 HObjectAccess access, | 1971 HObjectAccess access, |
1986 HValue *typecheck, | 1972 HValue *typecheck) { |
1987 Representation representation) { | 1973 return Add<HLoadNamedField>(object, access, typecheck); |
1988 return Add<HLoadNamedField>(object, access, typecheck, representation); | |
1989 } | 1974 } |
1990 | 1975 |
1991 | 1976 |
1992 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, | 1977 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, |
1993 Handle<Map> map) { | 1978 Handle<Map> map) { |
1994 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), | 1979 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), |
1995 Add<HConstant>(map)); | 1980 Add<HConstant>(map)); |
1996 } | 1981 } |
1997 | 1982 |
1998 | 1983 |
(...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2633 | 2618 |
2634 void TestContext::ReturnValue(HValue* value) { | 2619 void TestContext::ReturnValue(HValue* value) { |
2635 BuildBranch(value); | 2620 BuildBranch(value); |
2636 } | 2621 } |
2637 | 2622 |
2638 | 2623 |
2639 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 2624 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
2640 ASSERT(!instr->IsControlInstruction()); | 2625 ASSERT(!instr->IsControlInstruction()); |
2641 owner()->AddInstruction(instr); | 2626 owner()->AddInstruction(instr); |
2642 if (instr->HasObservableSideEffects()) { | 2627 if (instr->HasObservableSideEffects()) { |
2643 owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE); | 2628 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
2644 } | 2629 } |
2645 } | 2630 } |
2646 | 2631 |
2647 | 2632 |
2648 void EffectContext::ReturnControl(HControlInstruction* instr, | 2633 void EffectContext::ReturnControl(HControlInstruction* instr, |
2649 BailoutId ast_id) { | 2634 BailoutId ast_id) { |
2650 ASSERT(!instr->HasObservableSideEffects()); | 2635 ASSERT(!instr->HasObservableSideEffects()); |
2651 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 2636 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
2652 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 2637 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
2653 instr->SetSuccessorAt(0, empty_true); | 2638 instr->SetSuccessorAt(0, empty_true); |
(...skipping 21 matching lines...) Expand all Loading... |
2675 | 2660 |
2676 | 2661 |
2677 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 2662 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
2678 ASSERT(!instr->IsControlInstruction()); | 2663 ASSERT(!instr->IsControlInstruction()); |
2679 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 2664 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
2680 return owner()->Bailout("bad value context for arguments object value"); | 2665 return owner()->Bailout("bad value context for arguments object value"); |
2681 } | 2666 } |
2682 owner()->AddInstruction(instr); | 2667 owner()->AddInstruction(instr); |
2683 owner()->Push(instr); | 2668 owner()->Push(instr); |
2684 if (instr->HasObservableSideEffects()) { | 2669 if (instr->HasObservableSideEffects()) { |
2685 owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE); | 2670 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
2686 } | 2671 } |
2687 } | 2672 } |
2688 | 2673 |
2689 | 2674 |
2690 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 2675 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
2691 ASSERT(!instr->HasObservableSideEffects()); | 2676 ASSERT(!instr->HasObservableSideEffects()); |
2692 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 2677 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
2693 return owner()->Bailout("bad value context for arguments object value"); | 2678 return owner()->Bailout("bad value context for arguments object value"); |
2694 } | 2679 } |
2695 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); | 2680 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2731 | 2716 |
2732 | 2717 |
2733 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 2718 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
2734 ASSERT(!instr->IsControlInstruction()); | 2719 ASSERT(!instr->IsControlInstruction()); |
2735 HOptimizedGraphBuilder* builder = owner(); | 2720 HOptimizedGraphBuilder* builder = owner(); |
2736 builder->AddInstruction(instr); | 2721 builder->AddInstruction(instr); |
2737 // We expect a simulate after every expression with side effects, though | 2722 // We expect a simulate after every expression with side effects, though |
2738 // this one isn't actually needed (and wouldn't work if it were targeted). | 2723 // this one isn't actually needed (and wouldn't work if it were targeted). |
2739 if (instr->HasObservableSideEffects()) { | 2724 if (instr->HasObservableSideEffects()) { |
2740 builder->Push(instr); | 2725 builder->Push(instr); |
2741 builder->AddSimulate(ast_id, REMOVABLE_SIMULATE); | 2726 builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
2742 builder->Pop(); | 2727 builder->Pop(); |
2743 } | 2728 } |
2744 BuildBranch(instr); | 2729 BuildBranch(instr); |
2745 } | 2730 } |
2746 | 2731 |
2747 | 2732 |
2748 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 2733 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
2749 ASSERT(!instr->HasObservableSideEffects()); | 2734 ASSERT(!instr->HasObservableSideEffects()); |
2750 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 2735 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
2751 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 2736 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2919 current_block()->Goto(body_entry); | 2904 current_block()->Goto(body_entry); |
2920 body_entry->SetJoinId(BailoutId::FunctionEntry()); | 2905 body_entry->SetJoinId(BailoutId::FunctionEntry()); |
2921 set_current_block(body_entry); | 2906 set_current_block(body_entry); |
2922 | 2907 |
2923 // Handle implicit declaration of the function name in named function | 2908 // Handle implicit declaration of the function name in named function |
2924 // expressions before other declarations. | 2909 // expressions before other declarations. |
2925 if (scope->is_function_scope() && scope->function() != NULL) { | 2910 if (scope->is_function_scope() && scope->function() != NULL) { |
2926 VisitVariableDeclaration(scope->function()); | 2911 VisitVariableDeclaration(scope->function()); |
2927 } | 2912 } |
2928 VisitDeclarations(scope->declarations()); | 2913 VisitDeclarations(scope->declarations()); |
2929 AddSimulate(BailoutId::Declarations()); | 2914 Add<HSimulate>(BailoutId::Declarations()); |
2930 | 2915 |
2931 HValue* context = environment()->LookupContext(); | 2916 HValue* context = environment()->LookupContext(); |
2932 Add<HStackCheck>(context, HStackCheck::kFunctionEntry); | 2917 Add<HStackCheck>(context, HStackCheck::kFunctionEntry); |
2933 | 2918 |
2934 VisitStatements(current_info()->function()->body()); | 2919 VisitStatements(current_info()->function()->body()); |
2935 if (HasStackOverflow()) return false; | 2920 if (HasStackOverflow()) return false; |
2936 | 2921 |
2937 if (current_block() != NULL) { | 2922 if (current_block() != NULL) { |
2938 AddReturn(graph()->GetConstantUndefined()); | 2923 Add<HReturn>(graph()->GetConstantUndefined()); |
2939 set_current_block(NULL); | 2924 set_current_block(NULL); |
2940 } | 2925 } |
2941 | 2926 |
2942 // If the checksum of the number of type info changes is the same as the | 2927 // If the checksum of the number of type info changes is the same as the |
2943 // last time this function was compiled, then this recompile is likely not | 2928 // last time this function was compiled, then this recompile is likely not |
2944 // due to missing/inadequate type feedback, but rather too aggressive | 2929 // due to missing/inadequate type feedback, but rather too aggressive |
2945 // optimization. Disable optimistic LICM in that case. | 2930 // optimization. Disable optimistic LICM in that case. |
2946 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); | 2931 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); |
2947 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | 2932 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
2948 Handle<TypeFeedbackInfo> type_info( | 2933 Handle<TypeFeedbackInfo> type_info( |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3026 | 3011 |
3027 Run<HComputeMinusZeroChecksPhase>(); | 3012 Run<HComputeMinusZeroChecksPhase>(); |
3028 | 3013 |
3029 // Eliminate redundant stack checks on backwards branches. | 3014 // Eliminate redundant stack checks on backwards branches. |
3030 Run<HStackCheckEliminationPhase>(); | 3015 Run<HStackCheckEliminationPhase>(); |
3031 | 3016 |
3032 if (FLAG_idefs) SetupInformativeDefinitions(); | 3017 if (FLAG_idefs) SetupInformativeDefinitions(); |
3033 if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) { | 3018 if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) { |
3034 Run<HBoundsCheckEliminationPhase>(); | 3019 Run<HBoundsCheckEliminationPhase>(); |
3035 } | 3020 } |
| 3021 if (FLAG_array_bounds_checks_hoisting && !FLAG_idefs) { |
| 3022 Run<HBoundsCheckHoistingPhase>(); |
| 3023 } |
3036 if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>(); | 3024 if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>(); |
3037 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); | 3025 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); |
3038 | 3026 |
3039 RestoreActualValues(); | 3027 RestoreActualValues(); |
3040 | 3028 |
3041 return true; | 3029 return true; |
3042 } | 3030 } |
3043 | 3031 |
3044 | 3032 |
3045 void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) { | 3033 void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3107 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand()); | 3095 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand()); |
3108 } else { | 3096 } else { |
3109 instruction->ReplaceAllUsesWith(instruction->ActualValue()); | 3097 instruction->ReplaceAllUsesWith(instruction->ActualValue()); |
3110 } | 3098 } |
3111 } | 3099 } |
3112 } | 3100 } |
3113 } | 3101 } |
3114 } | 3102 } |
3115 | 3103 |
3116 | 3104 |
3117 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { | 3105 void HGraphBuilder::PushAndAdd(HInstruction* instr) { |
3118 Push(instr); | 3106 Push(instr); |
3119 AddInstruction(instr); | 3107 AddInstruction(instr); |
3120 } | 3108 } |
3121 | 3109 |
3122 | 3110 |
3123 template <class Instruction> | 3111 template <class Instruction> |
3124 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { | 3112 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { |
3125 int count = call->argument_count(); | 3113 int count = call->argument_count(); |
3126 ZoneList<HValue*> arguments(count, zone()); | 3114 ZoneList<HValue*> arguments(count, zone()); |
3127 for (int i = 0; i < count; ++i) { | 3115 for (int i = 0; i < count; ++i) { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3218 ASSERT(current_block() != NULL); | 3206 ASSERT(current_block() != NULL); |
3219 ASSERT(current_block()->HasPredecessor()); | 3207 ASSERT(current_block()->HasPredecessor()); |
3220 } | 3208 } |
3221 | 3209 |
3222 | 3210 |
3223 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) { | 3211 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) { |
3224 ASSERT(!HasStackOverflow()); | 3212 ASSERT(!HasStackOverflow()); |
3225 ASSERT(current_block() != NULL); | 3213 ASSERT(current_block() != NULL); |
3226 ASSERT(current_block()->HasPredecessor()); | 3214 ASSERT(current_block()->HasPredecessor()); |
3227 if (stmt->condition()->ToBooleanIsTrue()) { | 3215 if (stmt->condition()->ToBooleanIsTrue()) { |
3228 AddSimulate(stmt->ThenId()); | 3216 Add<HSimulate>(stmt->ThenId()); |
3229 Visit(stmt->then_statement()); | 3217 Visit(stmt->then_statement()); |
3230 } else if (stmt->condition()->ToBooleanIsFalse()) { | 3218 } else if (stmt->condition()->ToBooleanIsFalse()) { |
3231 AddSimulate(stmt->ElseId()); | 3219 Add<HSimulate>(stmt->ElseId()); |
3232 Visit(stmt->else_statement()); | 3220 Visit(stmt->else_statement()); |
3233 } else { | 3221 } else { |
3234 HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 3222 HBasicBlock* cond_true = graph()->CreateBasicBlock(); |
3235 HBasicBlock* cond_false = graph()->CreateBasicBlock(); | 3223 HBasicBlock* cond_false = graph()->CreateBasicBlock(); |
3236 CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false)); | 3224 CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false)); |
3237 | 3225 |
3238 if (cond_true->HasPredecessor()) { | 3226 if (cond_true->HasPredecessor()) { |
3239 cond_true->SetJoinId(stmt->ThenId()); | 3227 cond_true->SetJoinId(stmt->ThenId()); |
3240 set_current_block(cond_true); | 3228 set_current_block(cond_true); |
3241 CHECK_BAILOUT(Visit(stmt->then_statement())); | 3229 CHECK_BAILOUT(Visit(stmt->then_statement())); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3328 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 3316 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
3329 ASSERT(!HasStackOverflow()); | 3317 ASSERT(!HasStackOverflow()); |
3330 ASSERT(current_block() != NULL); | 3318 ASSERT(current_block() != NULL); |
3331 ASSERT(current_block()->HasPredecessor()); | 3319 ASSERT(current_block()->HasPredecessor()); |
3332 FunctionState* state = function_state(); | 3320 FunctionState* state = function_state(); |
3333 AstContext* context = call_context(); | 3321 AstContext* context = call_context(); |
3334 if (context == NULL) { | 3322 if (context == NULL) { |
3335 // Not an inlined return, so an actual one. | 3323 // Not an inlined return, so an actual one. |
3336 CHECK_ALIVE(VisitForValue(stmt->expression())); | 3324 CHECK_ALIVE(VisitForValue(stmt->expression())); |
3337 HValue* result = environment()->Pop(); | 3325 HValue* result = environment()->Pop(); |
3338 AddReturn(result); | 3326 Add<HReturn>(result); |
3339 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { | 3327 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { |
3340 // Return from an inlined construct call. In a test context the return value | 3328 // Return from an inlined construct call. In a test context the return value |
3341 // will always evaluate to true, in a value context the return value needs | 3329 // will always evaluate to true, in a value context the return value needs |
3342 // to be a JSObject. | 3330 // to be a JSObject. |
3343 if (context->IsTest()) { | 3331 if (context->IsTest()) { |
3344 TestContext* test = TestContext::cast(context); | 3332 TestContext* test = TestContext::cast(context); |
3345 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 3333 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
3346 current_block()->Goto(test->if_true(), state); | 3334 current_block()->Goto(test->if_true(), state); |
3347 } else if (context->IsEffect()) { | 3335 } else if (context->IsEffect()) { |
3348 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 3336 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3420 } | 3408 } |
3421 | 3409 |
3422 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); | 3410 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); |
3423 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { | 3411 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { |
3424 return Bailout("SwitchStatement: mixed or non-literal switch labels"); | 3412 return Bailout("SwitchStatement: mixed or non-literal switch labels"); |
3425 } | 3413 } |
3426 | 3414 |
3427 HValue* context = environment()->LookupContext(); | 3415 HValue* context = environment()->LookupContext(); |
3428 | 3416 |
3429 CHECK_ALIVE(VisitForValue(stmt->tag())); | 3417 CHECK_ALIVE(VisitForValue(stmt->tag())); |
3430 AddSimulate(stmt->EntryId()); | 3418 Add<HSimulate>(stmt->EntryId()); |
3431 HValue* tag_value = Pop(); | 3419 HValue* tag_value = Pop(); |
3432 HBasicBlock* first_test_block = current_block(); | 3420 HBasicBlock* first_test_block = current_block(); |
3433 | 3421 |
3434 HUnaryControlInstruction* string_check = NULL; | 3422 HUnaryControlInstruction* string_check = NULL; |
3435 HBasicBlock* not_string_block = NULL; | 3423 HBasicBlock* not_string_block = NULL; |
3436 | 3424 |
3437 // Test switch's tag value if all clauses are string literals | 3425 // Test switch's tag value if all clauses are string literals |
3438 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { | 3426 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { |
3439 string_check = new(zone()) HIsStringAndBranch(tag_value); | 3427 string_check = new(zone()) HIsStringAndBranch(tag_value); |
3440 first_test_block = graph()->CreateBasicBlock(); | 3428 first_test_block = graph()->CreateBasicBlock(); |
(...skipping 19 matching lines...) Expand all Loading... |
3460 CHECK_ALIVE(VisitForValue(clause->label())); | 3448 CHECK_ALIVE(VisitForValue(clause->label())); |
3461 HValue* label_value = Pop(); | 3449 HValue* label_value = Pop(); |
3462 | 3450 |
3463 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); | 3451 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); |
3464 HBasicBlock* body_block = graph()->CreateBasicBlock(); | 3452 HBasicBlock* body_block = graph()->CreateBasicBlock(); |
3465 | 3453 |
3466 HControlInstruction* compare; | 3454 HControlInstruction* compare; |
3467 | 3455 |
3468 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { | 3456 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { |
3469 if (!clause->compare_type()->Is(Type::Smi())) { | 3457 if (!clause->compare_type()->Is(Type::Smi())) { |
3470 AddSoftDeoptimize(); | 3458 Add<HDeoptimize>(Deoptimizer::SOFT); |
3471 } | 3459 } |
3472 | 3460 |
3473 HCompareNumericAndBranch* compare_ = | 3461 HCompareNumericAndBranch* compare_ = |
3474 new(zone()) HCompareNumericAndBranch(tag_value, | 3462 new(zone()) HCompareNumericAndBranch(tag_value, |
3475 label_value, | 3463 label_value, |
3476 Token::EQ_STRICT); | 3464 Token::EQ_STRICT); |
3477 compare_->set_observed_input_representation( | 3465 compare_->set_observed_input_representation( |
3478 Representation::Smi(), Representation::Smi()); | 3466 Representation::Smi(), Representation::Smi()); |
3479 compare = compare_; | 3467 compare = compare_; |
3480 } else { | 3468 } else { |
(...skipping 29 matching lines...) Expand all Loading... |
3510 CaseClause* clause = clauses->at(i); | 3498 CaseClause* clause = clauses->at(i); |
3511 | 3499 |
3512 // Identify the block where normal (non-fall-through) control flow | 3500 // Identify the block where normal (non-fall-through) control flow |
3513 // goes to. | 3501 // goes to. |
3514 HBasicBlock* normal_block = NULL; | 3502 HBasicBlock* normal_block = NULL; |
3515 if (clause->is_default()) { | 3503 if (clause->is_default()) { |
3516 if (last_block != NULL) { | 3504 if (last_block != NULL) { |
3517 normal_block = last_block; | 3505 normal_block = last_block; |
3518 last_block = NULL; // Cleared to indicate we've handled it. | 3506 last_block = NULL; // Cleared to indicate we've handled it. |
3519 } | 3507 } |
3520 } else if (!curr_test_block->end()->IsDeoptimize()) { | 3508 } else { |
3521 normal_block = curr_test_block->end()->FirstSuccessor(); | 3509 normal_block = curr_test_block->end()->FirstSuccessor(); |
3522 curr_test_block = curr_test_block->end()->SecondSuccessor(); | 3510 curr_test_block = curr_test_block->end()->SecondSuccessor(); |
3523 } | 3511 } |
3524 | 3512 |
3525 // Identify a block to emit the body into. | 3513 // Identify a block to emit the body into. |
3526 if (normal_block == NULL) { | 3514 if (normal_block == NULL) { |
3527 if (fall_through_block == NULL) { | 3515 if (fall_through_block == NULL) { |
3528 // (a) Unreachable. | 3516 // (a) Unreachable. |
3529 if (clause->is_default()) { | 3517 if (clause->is_default()) { |
3530 continue; // Might still be reachable clause bodies. | 3518 continue; // Might still be reachable clause bodies. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3564 break_block->SetJoinId(stmt->ExitId()); | 3552 break_block->SetJoinId(stmt->ExitId()); |
3565 set_current_block(break_block); | 3553 set_current_block(break_block); |
3566 } | 3554 } |
3567 } | 3555 } |
3568 | 3556 |
3569 | 3557 |
3570 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, | 3558 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, |
3571 HBasicBlock* loop_entry, | 3559 HBasicBlock* loop_entry, |
3572 BreakAndContinueInfo* break_info) { | 3560 BreakAndContinueInfo* break_info) { |
3573 BreakAndContinueScope push(break_info, this); | 3561 BreakAndContinueScope push(break_info, this); |
3574 AddSimulate(stmt->StackCheckId()); | 3562 Add<HSimulate>(stmt->StackCheckId()); |
3575 HValue* context = environment()->LookupContext(); | 3563 HValue* context = environment()->LookupContext(); |
3576 HStackCheck* stack_check = Add<HStackCheck>( | 3564 HStackCheck* stack_check = Add<HStackCheck>( |
3577 context, HStackCheck::kBackwardsBranch); | 3565 context, HStackCheck::kBackwardsBranch); |
3578 ASSERT(loop_entry->IsLoopHeader()); | 3566 ASSERT(loop_entry->IsLoopHeader()); |
3579 loop_entry->loop_information()->set_stack_check(stack_check); | 3567 loop_entry->loop_information()->set_stack_check(stack_check); |
3580 CHECK_BAILOUT(Visit(stmt->body())); | 3568 CHECK_BAILOUT(Visit(stmt->body())); |
3581 } | 3569 } |
3582 | 3570 |
3583 | 3571 |
3584 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 3572 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3725 return Bailout("ForInStatement with non-local each variable"); | 3713 return Bailout("ForInStatement with non-local each variable"); |
3726 } | 3714 } |
3727 | 3715 |
3728 Variable* each_var = stmt->each()->AsVariableProxy()->var(); | 3716 Variable* each_var = stmt->each()->AsVariableProxy()->var(); |
3729 | 3717 |
3730 CHECK_ALIVE(VisitForValue(stmt->enumerable())); | 3718 CHECK_ALIVE(VisitForValue(stmt->enumerable())); |
3731 HValue* enumerable = Top(); // Leave enumerable at the top. | 3719 HValue* enumerable = Top(); // Leave enumerable at the top. |
3732 | 3720 |
3733 HInstruction* map = Add<HForInPrepareMap>( | 3721 HInstruction* map = Add<HForInPrepareMap>( |
3734 environment()->LookupContext(), enumerable); | 3722 environment()->LookupContext(), enumerable); |
3735 AddSimulate(stmt->PrepareId()); | 3723 Add<HSimulate>(stmt->PrepareId()); |
3736 | 3724 |
3737 HInstruction* array = Add<HForInCacheArray>( | 3725 HInstruction* array = Add<HForInCacheArray>( |
3738 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex); | 3726 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex); |
3739 | 3727 |
3740 HInstruction* enum_length = Add<HMapEnumLength>(map); | 3728 HInstruction* enum_length = Add<HMapEnumLength>(map); |
3741 | 3729 |
3742 HInstruction* start_index = Add<HConstant>(0); | 3730 HInstruction* start_index = Add<HConstant>(0); |
3743 | 3731 |
3744 Push(map); | 3732 Push(map); |
3745 Push(array); | 3733 Push(array); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3794 JoinContinue(stmt, current_block(), break_info.continue_block()); | 3782 JoinContinue(stmt, current_block(), break_info.continue_block()); |
3795 | 3783 |
3796 if (body_exit != NULL) { | 3784 if (body_exit != NULL) { |
3797 set_current_block(body_exit); | 3785 set_current_block(body_exit); |
3798 | 3786 |
3799 HValue* current_index = Pop(); | 3787 HValue* current_index = Pop(); |
3800 HInstruction* new_index = HAdd::New(zone(), | 3788 HInstruction* new_index = HAdd::New(zone(), |
3801 environment()->LookupContext(), | 3789 environment()->LookupContext(), |
3802 current_index, | 3790 current_index, |
3803 graph()->GetConstant1()); | 3791 graph()->GetConstant1()); |
3804 new_index->AssumeRepresentation(Representation::Integer32()); | |
3805 PushAndAdd(new_index); | 3792 PushAndAdd(new_index); |
3806 body_exit = current_block(); | 3793 body_exit = current_block(); |
3807 } | 3794 } |
3808 | 3795 |
3809 HBasicBlock* loop_exit = CreateLoop(stmt, | 3796 HBasicBlock* loop_exit = CreateLoop(stmt, |
3810 loop_entry, | 3797 loop_entry, |
3811 body_exit, | 3798 body_exit, |
3812 loop_successor, | 3799 loop_successor, |
3813 break_info.break_block()); | 3800 break_info.break_block()); |
3814 | 3801 |
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4322 Handle<JSObject> holder; | 4309 Handle<JSObject> holder; |
4323 ASSERT(!LookupSetter(map, name, &setter, &holder)); | 4310 ASSERT(!LookupSetter(map, name, &setter, &holder)); |
4324 #endif | 4311 #endif |
4325 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, | 4312 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, |
4326 name, | 4313 name, |
4327 value, | 4314 value, |
4328 map)); | 4315 map)); |
4329 } | 4316 } |
4330 AddInstruction(store); | 4317 AddInstruction(store); |
4331 if (store->HasObservableSideEffects()) { | 4318 if (store->HasObservableSideEffects()) { |
4332 AddSimulate(key->id(), REMOVABLE_SIMULATE); | 4319 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); |
4333 } | 4320 } |
4334 } else { | 4321 } else { |
4335 CHECK_ALIVE(VisitForEffect(value)); | 4322 CHECK_ALIVE(VisitForEffect(value)); |
4336 } | 4323 } |
4337 break; | 4324 break; |
4338 } | 4325 } |
4339 // Fall through. | 4326 // Fall through. |
4340 case ObjectLiteral::Property::PROTOTYPE: | 4327 case ObjectLiteral::Property::PROTOTYPE: |
4341 case ObjectLiteral::Property::SETTER: | 4328 case ObjectLiteral::Property::SETTER: |
4342 case ObjectLiteral::Property::GETTER: | 4329 case ObjectLiteral::Property::GETTER: |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4445 Runtime::FunctionId function_id = (expr->depth() > 1) | 4432 Runtime::FunctionId function_id = (expr->depth() > 1) |
4446 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; | 4433 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; |
4447 literal = Add<HCallRuntime>(context, | 4434 literal = Add<HCallRuntime>(context, |
4448 isolate()->factory()->empty_string(), | 4435 isolate()->factory()->empty_string(), |
4449 Runtime::FunctionForId(function_id), | 4436 Runtime::FunctionForId(function_id), |
4450 3); | 4437 3); |
4451 | 4438 |
4452 // De-opt if elements kind changed from boilerplate_elements_kind. | 4439 // De-opt if elements kind changed from boilerplate_elements_kind. |
4453 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), | 4440 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), |
4454 isolate()); | 4441 isolate()); |
4455 AddInstruction(HCheckMaps::New(literal, map, zone())); | 4442 AddInstruction(HCheckMaps::New(literal, map, zone(), top_info())); |
4456 } | 4443 } |
4457 | 4444 |
4458 // The array is expected in the bailout environment during computation | 4445 // The array is expected in the bailout environment during computation |
4459 // of the property values and is the value of the entire expression. | 4446 // of the property values and is the value of the entire expression. |
4460 Push(literal); | 4447 Push(literal); |
4461 // The literal index is on the stack, too. | 4448 // The literal index is on the stack, too. |
4462 Push(Add<HConstant>(expr->literal_index())); | 4449 Push(Add<HConstant>(expr->literal_index())); |
4463 | 4450 |
4464 HInstruction* elements = NULL; | 4451 HInstruction* elements = NULL; |
4465 | 4452 |
(...skipping 21 matching lines...) Expand all Loading... |
4487 HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value, | 4474 HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value, |
4488 boilerplate_elements_kind); | 4475 boilerplate_elements_kind); |
4489 instr->SetUninitialized(uninitialized); | 4476 instr->SetUninitialized(uninitialized); |
4490 break; | 4477 break; |
4491 } | 4478 } |
4492 default: | 4479 default: |
4493 UNREACHABLE(); | 4480 UNREACHABLE(); |
4494 break; | 4481 break; |
4495 } | 4482 } |
4496 | 4483 |
4497 AddSimulate(expr->GetIdForElement(i)); | 4484 Add<HSimulate>(expr->GetIdForElement(i)); |
4498 } | 4485 } |
4499 | 4486 |
4500 Drop(1); // array literal index | 4487 Drop(1); // array literal index |
4501 return ast_context()->ReturnValue(Pop()); | 4488 return ast_context()->ReturnValue(Pop()); |
4502 } | 4489 } |
4503 | 4490 |
4504 | 4491 |
4505 // Sets the lookup result and returns true if the load/store can be inlined. | 4492 // Sets the lookup result and returns true if the load/store can be inlined. |
4506 static bool ComputeLoadStoreField(Handle<Map> type, | 4493 static bool ComputeLoadStoreField(Handle<Map> type, |
4507 Handle<String> name, | 4494 Handle<String> name, |
(...skipping 12 matching lines...) Expand all Loading... |
4520 if (!is_store) return false; | 4507 if (!is_store) return false; |
4521 | 4508 |
4522 // 2nd chance: A store into a non-existent field can still be inlined if we | 4509 // 2nd chance: A store into a non-existent field can still be inlined if we |
4523 // have a matching transition and some room left in the object. | 4510 // have a matching transition and some room left in the object. |
4524 type->LookupTransition(NULL, *name, lookup); | 4511 type->LookupTransition(NULL, *name, lookup); |
4525 return lookup->IsTransitionToField(*type) && | 4512 return lookup->IsTransitionToField(*type) && |
4526 (type->unused_property_fields() > 0); | 4513 (type->unused_property_fields() > 0); |
4527 } | 4514 } |
4528 | 4515 |
4529 | 4516 |
4530 static Representation ComputeLoadStoreRepresentation(Handle<Map> type, | |
4531 LookupResult* lookup) { | |
4532 if (lookup->IsField()) { | |
4533 return lookup->representation(); | |
4534 } else { | |
4535 Map* transition = lookup->GetTransitionMapFromMap(*type); | |
4536 int descriptor = transition->LastAdded(); | |
4537 PropertyDetails details = | |
4538 transition->instance_descriptors()->GetDetails(descriptor); | |
4539 return details.representation(); | |
4540 } | |
4541 } | |
4542 | |
4543 | |
4544 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) { | 4517 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) { |
4545 BuildCheckHeapObject(object); | 4518 BuildCheckHeapObject(object); |
4546 AddInstruction(HCheckMaps::New(object, map, zone())); | 4519 AddInstruction(HCheckMaps::New(object, map, zone(), top_info())); |
4547 } | 4520 } |
4548 | 4521 |
4549 | 4522 |
4550 void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object, | 4523 void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object, |
4551 Handle<Map> map) { | 4524 Handle<Map> map) { |
4552 BuildCheckHeapObject(object); | 4525 BuildCheckHeapObject(object); |
4553 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); | 4526 AddInstruction(HCheckMaps::NewWithTransitions( |
| 4527 object, map, zone(), top_info())); |
4554 } | 4528 } |
4555 | 4529 |
4556 | 4530 |
4557 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( | 4531 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( |
4558 HValue* object, | 4532 HValue* object, |
4559 Handle<String> name, | 4533 Handle<String> name, |
4560 HValue* value, | 4534 HValue* value, |
4561 Handle<Map> map, | 4535 Handle<Map> map, |
4562 LookupResult* lookup) { | 4536 LookupResult* lookup) { |
4563 ASSERT(lookup->IsFound()); | 4537 ASSERT(lookup->IsFound()); |
(...skipping 20 matching lines...) Expand all Loading... |
4584 } | 4558 } |
4585 ASSERT(proto->GetPrototype(isolate())->IsNull()); | 4559 ASSERT(proto->GetPrototype(isolate())->IsNull()); |
4586 } | 4560 } |
4587 ASSERT(proto->IsJSObject()); | 4561 ASSERT(proto->IsJSObject()); |
4588 Add<HCheckPrototypeMaps>(Handle<JSObject>(JSObject::cast(map->prototype())), | 4562 Add<HCheckPrototypeMaps>(Handle<JSObject>(JSObject::cast(map->prototype())), |
4589 Handle<JSObject>(JSObject::cast(proto)), | 4563 Handle<JSObject>(JSObject::cast(proto)), |
4590 zone(), top_info()); | 4564 zone(), top_info()); |
4591 } | 4565 } |
4592 | 4566 |
4593 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); | 4567 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); |
4594 Representation representation = ComputeLoadStoreRepresentation(map, lookup); | |
4595 bool transition_to_field = lookup->IsTransitionToField(*map); | 4568 bool transition_to_field = lookup->IsTransitionToField(*map); |
4596 | 4569 |
4597 HStoreNamedField *instr; | 4570 HStoreNamedField *instr; |
4598 if (FLAG_track_double_fields && representation.IsDouble()) { | 4571 if (FLAG_track_double_fields && field_access.representation().IsDouble()) { |
| 4572 HObjectAccess heap_number_access = |
| 4573 field_access.WithRepresentation(Representation::Tagged()); |
4599 if (transition_to_field) { | 4574 if (transition_to_field) { |
4600 // The store requires a mutable HeapNumber to be allocated. | 4575 // The store requires a mutable HeapNumber to be allocated. |
4601 NoObservableSideEffectsScope no_side_effects(this); | 4576 NoObservableSideEffectsScope no_side_effects(this); |
4602 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); | 4577 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); |
4603 HInstruction* double_box = Add<HAllocate>( | 4578 HInstruction* heap_number = Add<HAllocate>( |
4604 environment()->LookupContext(), heap_number_size, | 4579 environment()->LookupContext(), heap_number_size, |
4605 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE); | 4580 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE); |
4606 AddStoreMapConstant(double_box, isolate()->factory()->heap_number_map()); | 4581 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map()); |
4607 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), | 4582 AddStore(heap_number, HObjectAccess::ForHeapNumberValue(), value); |
4608 value, Representation::Double()); | 4583 instr = new(zone()) HStoreNamedField( |
4609 instr = new(zone()) HStoreNamedField(object, field_access, double_box); | 4584 object, heap_number_access, heap_number); |
4610 } else { | 4585 } else { |
4611 // Already holds a HeapNumber; load the box and write its value field. | 4586 // Already holds a HeapNumber; load the box and write its value field. |
4612 HInstruction* double_box = AddLoad(object, field_access); | 4587 HInstruction* heap_number = AddLoad(object, heap_number_access); |
4613 double_box->set_type(HType::HeapNumber()); | 4588 heap_number->set_type(HType::HeapNumber()); |
4614 instr = new(zone()) HStoreNamedField(double_box, | 4589 instr = new(zone()) HStoreNamedField(heap_number, |
4615 HObjectAccess::ForHeapNumberValue(), value, Representation::Double()); | 4590 HObjectAccess::ForHeapNumberValue(), value); |
4616 } | 4591 } |
4617 } else { | 4592 } else { |
4618 // This is a non-double store. | 4593 // This is a normal store. |
4619 instr = new(zone()) HStoreNamedField( | 4594 instr = new(zone()) HStoreNamedField(object, field_access, value); |
4620 object, field_access, value, representation); | |
4621 } | 4595 } |
4622 | 4596 |
4623 if (transition_to_field) { | 4597 if (transition_to_field) { |
4624 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 4598 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
4625 instr->SetTransition(transition, top_info()); | 4599 instr->SetTransition(transition, top_info()); |
4626 // TODO(fschneider): Record the new map type of the object in the IR to | 4600 // TODO(fschneider): Record the new map type of the object in the IR to |
4627 // enable elimination of redundant checks after the transition store. | 4601 // enable elimination of redundant checks after the transition store. |
4628 instr->SetGVNFlag(kChangesMaps); | 4602 instr->SetGVNFlag(kChangesMaps); |
4629 } | 4603 } |
4630 return instr; | 4604 return instr; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4677 Property* expr, | 4651 Property* expr, |
4678 HValue* object, | 4652 HValue* object, |
4679 SmallMapList* types, | 4653 SmallMapList* types, |
4680 Handle<String> name) { | 4654 Handle<String> name) { |
4681 // Use monomorphic load if property lookup results in the same field index | 4655 // Use monomorphic load if property lookup results in the same field index |
4682 // for all maps. Requires special map check on the set of all handled maps. | 4656 // for all maps. Requires special map check on the set of all handled maps. |
4683 if (types->length() > kMaxLoadPolymorphism) return NULL; | 4657 if (types->length() > kMaxLoadPolymorphism) return NULL; |
4684 | 4658 |
4685 LookupResult lookup(isolate()); | 4659 LookupResult lookup(isolate()); |
4686 int count; | 4660 int count; |
4687 Representation representation = Representation::None(); | |
4688 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. | 4661 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. |
4689 for (count = 0; count < types->length(); ++count) { | 4662 for (count = 0; count < types->length(); ++count) { |
4690 Handle<Map> map = types->at(count); | 4663 Handle<Map> map = types->at(count); |
4691 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; | 4664 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; |
4692 | 4665 |
4693 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); | 4666 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); |
4694 Representation new_representation = | |
4695 ComputeLoadStoreRepresentation(map, &lookup); | |
4696 | 4667 |
4697 if (count == 0) { | 4668 if (count == 0) { |
4698 // First time through the loop; set access and representation. | 4669 // First time through the loop; set access and representation. |
4699 access = new_access; | 4670 access = new_access; |
4700 } else if (!representation.IsCompatibleForLoad(new_representation)) { | 4671 } else if (!access.representation().IsCompatibleForLoad( |
| 4672 new_access.representation())) { |
4701 // Representations did not match. | 4673 // Representations did not match. |
4702 break; | 4674 break; |
4703 } else if (access.offset() != new_access.offset()) { | 4675 } else if (access.offset() != new_access.offset()) { |
4704 // Offsets did not match. | 4676 // Offsets did not match. |
4705 break; | 4677 break; |
4706 } else if (access.IsInobject() != new_access.IsInobject()) { | 4678 } else if (access.IsInobject() != new_access.IsInobject()) { |
4707 // In-objectness did not match. | 4679 // In-objectness did not match. |
4708 break; | 4680 break; |
4709 } | 4681 } |
4710 representation = representation.generalize(new_representation); | 4682 access = access.WithRepresentation( |
| 4683 access.representation().generalize(new_access.representation())); |
4711 } | 4684 } |
4712 | 4685 |
4713 if (count == types->length()) { | 4686 if (count == types->length()) { |
4714 // Everything matched; can use monomorphic load. | 4687 // Everything matched; can use monomorphic load. |
4715 BuildCheckHeapObject(object); | 4688 BuildCheckHeapObject(object); |
4716 AddInstruction(HCheckMaps::New(object, types, zone())); | 4689 AddInstruction(HCheckMaps::New(object, types, zone())); |
4717 return BuildLoadNamedField(object, access, representation); | 4690 return BuildLoadNamedField(object, access); |
4718 } | 4691 } |
4719 | 4692 |
4720 if (count != 0) return NULL; | 4693 if (count != 0) return NULL; |
4721 | 4694 |
4722 // Second chance: the property is on the prototype and all maps have the | 4695 // Second chance: the property is on the prototype and all maps have the |
4723 // same prototype. | 4696 // same prototype. |
4724 Handle<Map> map(types->at(0)); | 4697 Handle<Map> map(types->at(0)); |
4725 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL; | 4698 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL; |
4726 | 4699 |
4727 Handle<Object> prototype(map->prototype(), isolate()); | 4700 Handle<Object> prototype(map->prototype(), isolate()); |
4728 for (count = 1; count < types->length(); ++count) { | 4701 for (count = 1; count < types->length(); ++count) { |
4729 Handle<Map> test_map(types->at(count)); | 4702 Handle<Map> test_map(types->at(count)); |
4730 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL; | 4703 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL; |
4731 if (test_map->prototype() != *prototype) return NULL; | 4704 if (test_map->prototype() != *prototype) return NULL; |
4732 } | 4705 } |
4733 | 4706 |
4734 LookupInPrototypes(map, name, &lookup); | 4707 LookupInPrototypes(map, name, &lookup); |
4735 if (!lookup.IsField()) return NULL; | 4708 if (!lookup.IsField()) return NULL; |
4736 | 4709 |
4737 BuildCheckHeapObject(object); | 4710 BuildCheckHeapObject(object); |
4738 AddInstruction(HCheckMaps::New(object, types, zone())); | 4711 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 4712 |
4739 Handle<JSObject> holder(lookup.holder()); | 4713 Handle<JSObject> holder(lookup.holder()); |
4740 Handle<Map> holder_map(holder->map()); | 4714 Handle<Map> holder_map(holder->map()); |
4741 AddInstruction(new(zone()) HCheckPrototypeMaps( | 4715 AddInstruction(new(zone()) HCheckPrototypeMaps( |
4742 Handle<JSObject>::cast(prototype), holder, zone(), top_info())); | 4716 Handle<JSObject>::cast(prototype), holder, zone(), top_info())); |
4743 HValue* holder_value = AddInstruction(new(zone()) HConstant(holder)); | 4717 HValue* holder_value = AddInstruction(new(zone()) HConstant(holder)); |
4744 return BuildLoadNamedField(holder_value, | 4718 return BuildLoadNamedField(holder_value, |
4745 HObjectAccess::ForField(holder_map, &lookup, name), | 4719 HObjectAccess::ForField(holder_map, &lookup, name)); |
4746 ComputeLoadStoreRepresentation(map, &lookup)); | |
4747 } | 4720 } |
4748 | 4721 |
4749 | 4722 |
4750 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 4723 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
4751 Property* expr, | 4724 Property* expr, |
4752 HValue* object, | 4725 HValue* object, |
4753 SmallMapList* types, | 4726 SmallMapList* types, |
4754 Handle<String> name) { | 4727 Handle<String> name) { |
4755 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( | 4728 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( |
4756 expr, object, types, name); | 4729 expr, object, types, name); |
(...skipping 28 matching lines...) Expand all Loading... |
4785 int count; | 4758 int count; |
4786 Representation representation = Representation::None(); | 4759 Representation representation = Representation::None(); |
4787 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. | 4760 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. |
4788 for (count = 0; count < types->length(); ++count) { | 4761 for (count = 0; count < types->length(); ++count) { |
4789 Handle<Map> map = types->at(count); | 4762 Handle<Map> map = types->at(count); |
4790 // Pass false to ignore transitions. | 4763 // Pass false to ignore transitions. |
4791 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; | 4764 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; |
4792 ASSERT(!map->is_observed()); | 4765 ASSERT(!map->is_observed()); |
4793 | 4766 |
4794 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); | 4767 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); |
4795 Representation new_representation = | 4768 Representation new_representation = new_access.representation(); |
4796 ComputeLoadStoreRepresentation(map, &lookup); | |
4797 | 4769 |
4798 if (count == 0) { | 4770 if (count == 0) { |
4799 // First time through the loop; set access and representation. | 4771 // First time through the loop; set access and representation. |
4800 access = new_access; | 4772 access = new_access; |
4801 representation = new_representation; | 4773 representation = new_representation; |
4802 } else if (!representation.IsCompatibleForStore(new_representation)) { | 4774 } else if (!representation.IsCompatibleForStore(new_representation)) { |
4803 // Representations did not match. | 4775 // Representations did not match. |
4804 break; | 4776 break; |
4805 } else if (access.offset() != new_access.offset()) { | 4777 } else if (access.offset() != new_access.offset()) { |
4806 // Offsets did not match. | 4778 // Offsets did not match. |
(...skipping 10 matching lines...) Expand all Loading... |
4817 BuildCheckHeapObject(object); | 4789 BuildCheckHeapObject(object); |
4818 AddInstruction(HCheckMaps::New(object, types, zone())); | 4790 AddInstruction(HCheckMaps::New(object, types, zone())); |
4819 HInstruction* store; | 4791 HInstruction* store; |
4820 CHECK_ALIVE_OR_RETURN( | 4792 CHECK_ALIVE_OR_RETURN( |
4821 store = BuildStoreNamedField( | 4793 store = BuildStoreNamedField( |
4822 object, name, store_value, types->at(count - 1), &lookup), | 4794 object, name, store_value, types->at(count - 1), &lookup), |
4823 true); | 4795 true); |
4824 if (!ast_context()->IsEffect()) Push(result_value); | 4796 if (!ast_context()->IsEffect()) Push(result_value); |
4825 store->set_position(position); | 4797 store->set_position(position); |
4826 AddInstruction(store); | 4798 AddInstruction(store); |
4827 AddSimulate(assignment_id); | 4799 Add<HSimulate>(assignment_id); |
4828 if (!ast_context()->IsEffect()) Drop(1); | 4800 if (!ast_context()->IsEffect()) Drop(1); |
4829 ast_context()->ReturnValue(result_value); | 4801 ast_context()->ReturnValue(result_value); |
4830 return true; | 4802 return true; |
4831 } | 4803 } |
4832 | 4804 |
4833 | 4805 |
4834 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 4806 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
4835 int position, | 4807 int position, |
4836 BailoutId assignment_id, | 4808 BailoutId assignment_id, |
4837 HValue* object, | 4809 HValue* object, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4876 current_block()->Goto(join); | 4848 current_block()->Goto(join); |
4877 | 4849 |
4878 set_current_block(if_false); | 4850 set_current_block(if_false); |
4879 } | 4851 } |
4880 } | 4852 } |
4881 | 4853 |
4882 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 4854 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
4883 // know about and do not want to handle ones we've never seen. Otherwise | 4855 // know about and do not want to handle ones we've never seen. Otherwise |
4884 // use a generic IC. | 4856 // use a generic IC. |
4885 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 4857 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
4886 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 4858 FinishExitWithHardDeoptimization(join); |
4887 } else { | 4859 } else { |
4888 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); | 4860 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); |
4889 instr->set_position(position); | 4861 instr->set_position(position); |
4890 AddInstruction(instr); | 4862 AddInstruction(instr); |
4891 | 4863 |
4892 if (join != NULL) { | 4864 if (join != NULL) { |
4893 if (!ast_context()->IsEffect()) { | 4865 if (!ast_context()->IsEffect()) { |
4894 Push(result_value); | 4866 Push(result_value); |
4895 } | 4867 } |
4896 current_block()->Goto(join); | 4868 current_block()->Goto(join); |
4897 } else { | 4869 } else { |
4898 // The HSimulate for the store should not see the stored value in | 4870 // The HSimulate for the store should not see the stored value in |
4899 // effect contexts (it is not materialized at expr->id() in the | 4871 // effect contexts (it is not materialized at expr->id() in the |
4900 // unoptimized code). | 4872 // unoptimized code). |
4901 if (instr->HasObservableSideEffects()) { | 4873 if (instr->HasObservableSideEffects()) { |
4902 if (ast_context()->IsEffect()) { | 4874 if (ast_context()->IsEffect()) { |
4903 AddSimulate(assignment_id, REMOVABLE_SIMULATE); | 4875 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); |
4904 } else { | 4876 } else { |
4905 Push(result_value); | 4877 Push(result_value); |
4906 AddSimulate(assignment_id, REMOVABLE_SIMULATE); | 4878 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); |
4907 Drop(1); | 4879 Drop(1); |
4908 } | 4880 } |
4909 } | 4881 } |
4910 return ast_context()->ReturnValue(result_value); | 4882 return ast_context()->ReturnValue(result_value); |
4911 } | 4883 } |
4912 } | 4884 } |
4913 | 4885 |
4914 ASSERT(join != NULL); | 4886 ASSERT(join != NULL); |
4915 join->SetJoinId(assignment_id); | 4887 join->SetJoinId(assignment_id); |
4916 set_current_block(join); | 4888 set_current_block(join); |
4917 if (!ast_context()->IsEffect()) { | 4889 if (!ast_context()->IsEffect()) { |
4918 ast_context()->ReturnValue(Pop()); | 4890 ast_context()->ReturnValue(Pop()); |
4919 } | 4891 } |
4920 } | 4892 } |
4921 | 4893 |
4922 | 4894 |
4923 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 4895 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
4924 Property* prop = expr->target()->AsProperty(); | 4896 Property* prop = expr->target()->AsProperty(); |
4925 ASSERT(prop != NULL); | 4897 ASSERT(prop != NULL); |
4926 CHECK_ALIVE(VisitForValue(prop->obj())); | 4898 CHECK_ALIVE(VisitForValue(prop->obj())); |
4927 | 4899 |
4928 if (prop->key()->IsPropertyName()) { | 4900 if (prop->key()->IsPropertyName()) { |
4929 // Named store. | 4901 // Named store. |
4930 CHECK_ALIVE(VisitForValue(expr->value())); | 4902 CHECK_ALIVE(VisitForValue(expr->value())); |
4931 HValue* value = environment()->ExpressionStackAt(0); | 4903 HValue* value = environment()->ExpressionStackAt(0); |
4932 HValue* object = environment()->ExpressionStackAt(1); | 4904 HValue* object = environment()->ExpressionStackAt(1); |
4933 | 4905 |
4934 if (expr->IsUninitialized()) AddSoftDeoptimize(); | 4906 if (expr->IsUninitialized()) Add<HDeoptimize>(Deoptimizer::SOFT); |
4935 return BuildStoreNamed(expr, expr->id(), expr->position(), | 4907 return BuildStoreNamed(expr, expr->id(), expr->position(), |
4936 expr->AssignmentId(), prop, object, value, value); | 4908 expr->AssignmentId(), prop, object, value, value); |
4937 } else { | 4909 } else { |
4938 // Keyed store. | 4910 // Keyed store. |
4939 CHECK_ALIVE(VisitForValue(prop->key())); | 4911 CHECK_ALIVE(VisitForValue(prop->key())); |
4940 CHECK_ALIVE(VisitForValue(expr->value())); | 4912 CHECK_ALIVE(VisitForValue(expr->value())); |
4941 HValue* value = environment()->ExpressionStackAt(0); | 4913 HValue* value = environment()->ExpressionStackAt(0); |
4942 HValue* key = environment()->ExpressionStackAt(1); | 4914 HValue* key = environment()->ExpressionStackAt(1); |
4943 HValue* object = environment()->ExpressionStackAt(2); | 4915 HValue* object = environment()->ExpressionStackAt(2); |
4944 bool has_side_effects = false; | 4916 bool has_side_effects = false; |
4945 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), | 4917 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), |
4946 expr->position(), | 4918 expr->position(), |
4947 true, // is_store | 4919 true, // is_store |
4948 &has_side_effects); | 4920 &has_side_effects); |
4949 Drop(3); | 4921 Drop(3); |
4950 Push(value); | 4922 Push(value); |
4951 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 4923 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
4952 return ast_context()->ReturnValue(Pop()); | 4924 return ast_context()->ReturnValue(Pop()); |
4953 } | 4925 } |
4954 } | 4926 } |
4955 | 4927 |
4956 | 4928 |
4957 // Because not every expression has a position and there is not common | 4929 // Because not every expression has a position and there is not common |
4958 // superclass of Assignment and CountOperation, we cannot just pass the | 4930 // superclass of Assignment and CountOperation, we cannot just pass the |
4959 // owning expression instead of position and ast_id separately. | 4931 // owning expression instead of position and ast_id separately. |
4960 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 4932 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
4961 Variable* var, | 4933 Variable* var, |
4962 HValue* value, | 4934 HValue* value, |
4963 int position, | 4935 int position, |
4964 BailoutId ast_id) { | 4936 BailoutId ast_id) { |
4965 LookupResult lookup(isolate()); | 4937 LookupResult lookup(isolate()); |
4966 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 4938 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
4967 if (type == kUseCell) { | 4939 if (type == kUseCell) { |
4968 Handle<GlobalObject> global(current_info()->global_object()); | 4940 Handle<GlobalObject> global(current_info()->global_object()); |
4969 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); | 4941 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
4970 if (cell->type()->IsConstant()) { | 4942 if (cell->type()->IsConstant()) { |
4971 IfBuilder builder(this); | 4943 IfBuilder builder(this); |
4972 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); | 4944 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); |
4973 if (cell->type()->AsConstant()->IsNumber()) { | 4945 if (cell->type()->AsConstant()->IsNumber()) { |
4974 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); | 4946 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); |
4975 } else { | 4947 } else { |
4976 builder.If<HCompareObjectEqAndBranch>(value, constant); | 4948 builder.If<HCompareObjectEqAndBranch>(value, constant); |
4977 } | 4949 } |
4978 builder.Then(); | 4950 builder.Then(); |
4979 builder.Else(); | 4951 builder.Else(); |
4980 AddSoftDeoptimize(MUST_EMIT_SOFT_DEOPT); | 4952 Add<HDeoptimize>(Deoptimizer::EAGER); |
4981 builder.End(); | 4953 builder.End(); |
4982 } | 4954 } |
4983 HInstruction* instr = | 4955 HInstruction* instr = |
4984 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); | 4956 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); |
4985 instr->set_position(position); | 4957 instr->set_position(position); |
4986 if (instr->HasObservableSideEffects()) { | 4958 if (instr->HasObservableSideEffects()) { |
4987 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 4959 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
4988 } | 4960 } |
4989 } else { | 4961 } else { |
4990 HValue* context = environment()->LookupContext(); | 4962 HValue* context = environment()->LookupContext(); |
4991 HGlobalObject* global_object = Add<HGlobalObject>(context); | 4963 HGlobalObject* global_object = Add<HGlobalObject>(context); |
4992 HStoreGlobalGeneric* instr = | 4964 HStoreGlobalGeneric* instr = |
4993 Add<HStoreGlobalGeneric>(context, global_object, var->name(), | 4965 Add<HStoreGlobalGeneric>(context, global_object, var->name(), |
4994 value, function_strict_mode_flag()); | 4966 value, function_strict_mode_flag()); |
4995 instr->set_position(position); | 4967 instr->set_position(position); |
4996 ASSERT(instr->HasObservableSideEffects()); | 4968 ASSERT(instr->HasObservableSideEffects()); |
4997 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 4969 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
4998 } | 4970 } |
4999 } | 4971 } |
5000 | 4972 |
5001 | 4973 |
5002 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, | 4974 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, |
5003 BailoutId id, | 4975 BailoutId id, |
5004 int position, | 4976 int position, |
5005 BailoutId assignment_id, | 4977 BailoutId assignment_id, |
5006 Property* prop, | 4978 Property* prop, |
5007 HValue* object, | 4979 HValue* object, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5049 store_value, result_value, types, name); | 5021 store_value, result_value, types, name); |
5050 } else { | 5022 } else { |
5051 Drop(2); | 5023 Drop(2); |
5052 instr = BuildStoreNamedGeneric(object, name, store_value); | 5024 instr = BuildStoreNamedGeneric(object, name, store_value); |
5053 } | 5025 } |
5054 | 5026 |
5055 if (!ast_context()->IsEffect()) Push(result_value); | 5027 if (!ast_context()->IsEffect()) Push(result_value); |
5056 instr->set_position(position); | 5028 instr->set_position(position); |
5057 AddInstruction(instr); | 5029 AddInstruction(instr); |
5058 if (instr->HasObservableSideEffects()) { | 5030 if (instr->HasObservableSideEffects()) { |
5059 AddSimulate(id, REMOVABLE_SIMULATE); | 5031 Add<HSimulate>(id, REMOVABLE_SIMULATE); |
5060 } | 5032 } |
5061 if (!ast_context()->IsEffect()) Drop(1); | 5033 if (!ast_context()->IsEffect()) Drop(1); |
5062 return ast_context()->ReturnValue(result_value); | 5034 return ast_context()->ReturnValue(result_value); |
5063 } | 5035 } |
5064 | 5036 |
5065 | 5037 |
5066 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5038 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
5067 Expression* target = expr->target(); | 5039 Expression* target = expr->target(); |
5068 VariableProxy* proxy = target->AsVariableProxy(); | 5040 VariableProxy* proxy = target->AsVariableProxy(); |
5069 Property* prop = target->AsProperty(); | 5041 Property* prop = target->AsProperty(); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5127 // perform checks here | 5099 // perform checks here |
5128 UNREACHABLE(); | 5100 UNREACHABLE(); |
5129 default: | 5101 default: |
5130 mode = HStoreContextSlot::kNoCheck; | 5102 mode = HStoreContextSlot::kNoCheck; |
5131 } | 5103 } |
5132 | 5104 |
5133 HValue* context = BuildContextChainWalk(var); | 5105 HValue* context = BuildContextChainWalk(var); |
5134 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 5106 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
5135 mode, Top()); | 5107 mode, Top()); |
5136 if (instr->HasObservableSideEffects()) { | 5108 if (instr->HasObservableSideEffects()) { |
5137 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5109 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5138 } | 5110 } |
5139 break; | 5111 break; |
5140 } | 5112 } |
5141 | 5113 |
5142 case Variable::LOOKUP: | 5114 case Variable::LOOKUP: |
5143 return Bailout("compound assignment to lookup slot"); | 5115 return Bailout("compound assignment to lookup slot"); |
5144 } | 5116 } |
5145 return ast_context()->ReturnValue(Pop()); | 5117 return ast_context()->ReturnValue(Pop()); |
5146 | 5118 |
5147 } else if (prop != NULL) { | 5119 } else if (prop != NULL) { |
(...skipping 20 matching lines...) Expand all Loading... |
5168 load = BuildCallGetter(object, map, getter, holder); | 5140 load = BuildCallGetter(object, map, getter, holder); |
5169 } else { | 5141 } else { |
5170 load = BuildLoadNamedMonomorphic(object, name, prop, map); | 5142 load = BuildLoadNamedMonomorphic(object, name, prop, map); |
5171 } | 5143 } |
5172 } else if (types != NULL && types->length() > 1) { | 5144 } else if (types != NULL && types->length() > 1) { |
5173 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); | 5145 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); |
5174 } | 5146 } |
5175 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); | 5147 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); |
5176 PushAndAdd(load); | 5148 PushAndAdd(load); |
5177 if (load->HasObservableSideEffects()) { | 5149 if (load->HasObservableSideEffects()) { |
5178 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 5150 Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); |
5179 } | 5151 } |
5180 | 5152 |
5181 CHECK_ALIVE(VisitForValue(expr->value())); | 5153 CHECK_ALIVE(VisitForValue(expr->value())); |
5182 HValue* right = Pop(); | 5154 HValue* right = Pop(); |
5183 HValue* left = Pop(); | 5155 HValue* left = Pop(); |
5184 | 5156 |
5185 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5157 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
5186 PushAndAdd(instr); | 5158 PushAndAdd(instr); |
5187 if (instr->HasObservableSideEffects()) { | 5159 if (instr->HasObservableSideEffects()) { |
5188 AddSimulate(operation->id(), REMOVABLE_SIMULATE); | 5160 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); |
5189 } | 5161 } |
5190 | 5162 |
5191 return BuildStoreNamed(prop, expr->id(), expr->position(), | 5163 return BuildStoreNamed(prop, expr->id(), expr->position(), |
5192 expr->AssignmentId(), prop, object, instr, instr); | 5164 expr->AssignmentId(), prop, object, instr, instr); |
5193 } else { | 5165 } else { |
5194 // Keyed property. | 5166 // Keyed property. |
5195 CHECK_ALIVE(VisitForValue(prop->obj())); | 5167 CHECK_ALIVE(VisitForValue(prop->obj())); |
5196 CHECK_ALIVE(VisitForValue(prop->key())); | 5168 CHECK_ALIVE(VisitForValue(prop->key())); |
5197 HValue* obj = environment()->ExpressionStackAt(1); | 5169 HValue* obj = environment()->ExpressionStackAt(1); |
5198 HValue* key = environment()->ExpressionStackAt(0); | 5170 HValue* key = environment()->ExpressionStackAt(0); |
5199 | 5171 |
5200 bool has_side_effects = false; | 5172 bool has_side_effects = false; |
5201 HValue* load = HandleKeyedElementAccess( | 5173 HValue* load = HandleKeyedElementAccess( |
5202 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 5174 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
5203 false, // is_store | 5175 false, // is_store |
5204 &has_side_effects); | 5176 &has_side_effects); |
5205 Push(load); | 5177 Push(load); |
5206 if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 5178 if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); |
5207 | 5179 |
5208 CHECK_ALIVE(VisitForValue(expr->value())); | 5180 CHECK_ALIVE(VisitForValue(expr->value())); |
5209 HValue* right = Pop(); | 5181 HValue* right = Pop(); |
5210 HValue* left = Pop(); | 5182 HValue* left = Pop(); |
5211 | 5183 |
5212 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5184 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
5213 PushAndAdd(instr); | 5185 PushAndAdd(instr); |
5214 if (instr->HasObservableSideEffects()) { | 5186 if (instr->HasObservableSideEffects()) { |
5215 AddSimulate(operation->id(), REMOVABLE_SIMULATE); | 5187 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); |
5216 } | 5188 } |
5217 | 5189 |
5218 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), | 5190 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), |
5219 RelocInfo::kNoPosition, | 5191 RelocInfo::kNoPosition, |
5220 true, // is_store | 5192 true, // is_store |
5221 &has_side_effects); | 5193 &has_side_effects); |
5222 | 5194 |
5223 // Drop the simulated receiver, key, and value. Return the value. | 5195 // Drop the simulated receiver, key, and value. Return the value. |
5224 Drop(3); | 5196 Drop(3); |
5225 Push(instr); | 5197 Push(instr); |
5226 ASSERT(has_side_effects); // Stores always have side effects. | 5198 ASSERT(has_side_effects); // Stores always have side effects. |
5227 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5199 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5228 return ast_context()->ReturnValue(Pop()); | 5200 return ast_context()->ReturnValue(Pop()); |
5229 } | 5201 } |
5230 | 5202 |
5231 } else { | 5203 } else { |
5232 return Bailout("invalid lhs in compound assignment"); | 5204 return Bailout("invalid lhs in compound assignment"); |
5233 } | 5205 } |
5234 } | 5206 } |
5235 | 5207 |
5236 | 5208 |
5237 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { | 5209 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5339 } else { | 5311 } else { |
5340 ASSERT(expr->op() == Token::INIT_CONST); | 5312 ASSERT(expr->op() == Token::INIT_CONST); |
5341 | 5313 |
5342 mode = HStoreContextSlot::kCheckIgnoreAssignment; | 5314 mode = HStoreContextSlot::kCheckIgnoreAssignment; |
5343 } | 5315 } |
5344 | 5316 |
5345 HValue* context = BuildContextChainWalk(var); | 5317 HValue* context = BuildContextChainWalk(var); |
5346 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 5318 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
5347 mode, Top()); | 5319 mode, Top()); |
5348 if (instr->HasObservableSideEffects()) { | 5320 if (instr->HasObservableSideEffects()) { |
5349 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5321 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5350 } | 5322 } |
5351 return ast_context()->ReturnValue(Pop()); | 5323 return ast_context()->ReturnValue(Pop()); |
5352 } | 5324 } |
5353 | 5325 |
5354 case Variable::LOOKUP: | 5326 case Variable::LOOKUP: |
5355 return Bailout("assignment to LOOKUP variable"); | 5327 return Bailout("assignment to LOOKUP variable"); |
5356 } | 5328 } |
5357 } else { | 5329 } else { |
5358 return Bailout("invalid left-hand side in assignment"); | 5330 return Bailout("invalid left-hand side in assignment"); |
5359 } | 5331 } |
(...skipping 13 matching lines...) Expand all Loading... |
5373 // We don't optimize functions with invalid left-hand sides in | 5345 // We don't optimize functions with invalid left-hand sides in |
5374 // assignments, count operations, or for-in. Consequently throw can | 5346 // assignments, count operations, or for-in. Consequently throw can |
5375 // currently only occur in an effect context. | 5347 // currently only occur in an effect context. |
5376 ASSERT(ast_context()->IsEffect()); | 5348 ASSERT(ast_context()->IsEffect()); |
5377 CHECK_ALIVE(VisitForValue(expr->exception())); | 5349 CHECK_ALIVE(VisitForValue(expr->exception())); |
5378 | 5350 |
5379 HValue* context = environment()->LookupContext(); | 5351 HValue* context = environment()->LookupContext(); |
5380 HValue* value = environment()->Pop(); | 5352 HValue* value = environment()->Pop(); |
5381 HThrow* instr = Add<HThrow>(context, value); | 5353 HThrow* instr = Add<HThrow>(context, value); |
5382 instr->set_position(expr->position()); | 5354 instr->set_position(expr->position()); |
5383 AddSimulate(expr->id()); | 5355 Add<HSimulate>(expr->id()); |
5384 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5356 current_block()->FinishExit(new(zone()) HAbnormalExit); |
5385 set_current_block(NULL); | 5357 set_current_block(NULL); |
5386 } | 5358 } |
5387 | 5359 |
5388 | 5360 |
5389 HLoadNamedField* HGraphBuilder::BuildLoadNamedField( | 5361 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
5390 HValue* object, | 5362 HObjectAccess access) { |
5391 HObjectAccess access, | 5363 if (FLAG_track_double_fields && access.representation().IsDouble()) { |
5392 Representation representation) { | 5364 // load the heap number |
5393 bool load_double = false; | 5365 HLoadNamedField* heap_number = |
5394 if (representation.IsDouble()) { | 5366 AddLoad(object, access.WithRepresentation(Representation::Tagged())); |
5395 representation = Representation::Tagged(); | 5367 heap_number->set_type(HType::HeapNumber()); |
5396 load_double = FLAG_track_double_fields; | 5368 // load the double value from it |
| 5369 return new(zone()) HLoadNamedField(heap_number, |
| 5370 HObjectAccess::ForHeapNumberValue(), NULL); |
5397 } | 5371 } |
5398 HLoadNamedField* field = | 5372 return new(zone()) HLoadNamedField(object, access, NULL); |
5399 new(zone()) HLoadNamedField(object, access, NULL, representation); | |
5400 if (load_double) { | |
5401 AddInstruction(field); | |
5402 field->set_type(HType::HeapNumber()); | |
5403 return new(zone()) HLoadNamedField(field, | |
5404 HObjectAccess::ForHeapNumberValue(), NULL, Representation::Double()); | |
5405 } | |
5406 return field; | |
5407 } | 5373 } |
5408 | 5374 |
5409 | 5375 |
5410 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 5376 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
5411 HValue* object, | 5377 HValue* object, |
5412 Handle<String> name, | 5378 Handle<String> name, |
5413 Property* expr) { | 5379 Property* expr) { |
5414 if (expr->IsUninitialized()) { | 5380 if (expr->IsUninitialized()) { |
5415 AddSoftDeoptimize(); | 5381 Add<HDeoptimize>(Deoptimizer::SOFT); |
5416 } | 5382 } |
5417 HValue* context = environment()->LookupContext(); | 5383 HValue* context = environment()->LookupContext(); |
5418 return new(zone()) HLoadNamedGeneric(context, object, name); | 5384 return new(zone()) HLoadNamedGeneric(context, object, name); |
5419 } | 5385 } |
5420 | 5386 |
5421 | 5387 |
5422 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( | 5388 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( |
5423 HValue* object, | 5389 HValue* object, |
5424 Handle<Map> map, | 5390 Handle<Map> map, |
5425 Handle<JSFunction> getter, | 5391 Handle<JSFunction> getter, |
(...skipping 10 matching lines...) Expand all Loading... |
5436 Property* expr, | 5402 Property* expr, |
5437 Handle<Map> map) { | 5403 Handle<Map> map) { |
5438 // Handle a load from a known field. | 5404 // Handle a load from a known field. |
5439 ASSERT(!map->is_dictionary_map()); | 5405 ASSERT(!map->is_dictionary_map()); |
5440 | 5406 |
5441 // Handle access to various length properties | 5407 // Handle access to various length properties |
5442 if (name->Equals(isolate()->heap()->length_string())) { | 5408 if (name->Equals(isolate()->heap()->length_string())) { |
5443 if (map->instance_type() == JS_ARRAY_TYPE) { | 5409 if (map->instance_type() == JS_ARRAY_TYPE) { |
5444 AddCheckMapsWithTransitions(object, map); | 5410 AddCheckMapsWithTransitions(object, map); |
5445 return new(zone()) HLoadNamedField(object, | 5411 return new(zone()) HLoadNamedField(object, |
5446 HObjectAccess::ForArrayLength()); | 5412 HObjectAccess::ForArrayLength(map->elements_kind())); |
5447 } | 5413 } |
5448 } | 5414 } |
5449 | 5415 |
5450 LookupResult lookup(isolate()); | 5416 LookupResult lookup(isolate()); |
5451 map->LookupDescriptor(NULL, *name, &lookup); | 5417 map->LookupDescriptor(NULL, *name, &lookup); |
5452 if (lookup.IsField()) { | 5418 if (lookup.IsField()) { |
5453 AddCheckMap(object, map); | 5419 AddCheckMap(object, map); |
5454 return BuildLoadNamedField(object, | 5420 return BuildLoadNamedField(object, |
5455 HObjectAccess::ForField(map, &lookup, name), | 5421 HObjectAccess::ForField(map, &lookup, name)); |
5456 ComputeLoadStoreRepresentation(map, &lookup)); | |
5457 } | 5422 } |
5458 | 5423 |
5459 // Handle a load of a constant known function. | 5424 // Handle a load of a constant known function. |
5460 if (lookup.IsConstantFunction()) { | 5425 if (lookup.IsConstant()) { |
5461 AddCheckMap(object, map); | 5426 AddCheckMap(object, map); |
5462 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); | 5427 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); |
5463 return new(zone()) HConstant(function); | 5428 return new(zone()) HConstant(constant); |
5464 } | 5429 } |
5465 | 5430 |
5466 // Handle a load from a known field somewhere in the prototype chain. | 5431 // Handle a load from a known field somewhere in the prototype chain. |
5467 LookupInPrototypes(map, name, &lookup); | 5432 LookupInPrototypes(map, name, &lookup); |
5468 if (lookup.IsField()) { | 5433 if (lookup.IsField()) { |
5469 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5434 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
5470 Handle<JSObject> holder(lookup.holder()); | 5435 Handle<JSObject> holder(lookup.holder()); |
5471 Handle<Map> holder_map(holder->map()); | 5436 Handle<Map> holder_map(holder->map()); |
5472 AddCheckMap(object, map); | 5437 AddCheckMap(object, map); |
5473 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); | 5438 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); |
5474 HValue* holder_value = Add<HConstant>(holder); | 5439 HValue* holder_value = Add<HConstant>(holder); |
5475 return BuildLoadNamedField(holder_value, | 5440 return BuildLoadNamedField(holder_value, |
5476 HObjectAccess::ForField(holder_map, &lookup, name), | 5441 HObjectAccess::ForField(holder_map, &lookup, name)); |
5477 ComputeLoadStoreRepresentation(map, &lookup)); | |
5478 } | 5442 } |
5479 | 5443 |
5480 // Handle a load of a constant function somewhere in the prototype chain. | 5444 // Handle a load of a constant function somewhere in the prototype chain. |
5481 if (lookup.IsConstantFunction()) { | 5445 if (lookup.IsConstant()) { |
5482 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5446 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
5483 Handle<JSObject> holder(lookup.holder()); | 5447 Handle<JSObject> holder(lookup.holder()); |
5484 Handle<Map> holder_map(holder->map()); | 5448 Handle<Map> holder_map(holder->map()); |
5485 AddCheckMap(object, map); | 5449 AddCheckMap(object, map); |
5486 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); | 5450 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); |
5487 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); | 5451 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); |
5488 return new(zone()) HConstant(function); | 5452 return new(zone()) HConstant(constant); |
5489 } | 5453 } |
5490 | 5454 |
5491 // No luck, do a generic load. | 5455 // No luck, do a generic load. |
5492 return BuildLoadNamedGeneric(object, name, expr); | 5456 return BuildLoadNamedGeneric(object, name, expr); |
5493 } | 5457 } |
5494 | 5458 |
5495 | 5459 |
5496 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 5460 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
5497 HValue* key) { | 5461 HValue* key) { |
5498 HValue* context = environment()->LookupContext(); | 5462 HValue* context = environment()->LookupContext(); |
5499 return new(zone()) HLoadKeyedGeneric(context, object, key); | 5463 return new(zone()) HLoadKeyedGeneric(context, object, key); |
5500 } | 5464 } |
5501 | 5465 |
5502 | 5466 |
5503 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( | 5467 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( |
5504 HValue* object, | 5468 HValue* object, |
5505 HValue* key, | 5469 HValue* key, |
5506 HValue* val, | 5470 HValue* val, |
5507 HValue* dependency, | 5471 HValue* dependency, |
5508 Handle<Map> map, | 5472 Handle<Map> map, |
5509 bool is_store, | 5473 bool is_store, |
5510 KeyedAccessStoreMode store_mode) { | 5474 KeyedAccessStoreMode store_mode) { |
5511 HCheckMaps* mapcheck = HCheckMaps::New(object, map, zone(), dependency); | 5475 HCheckMaps* mapcheck = HCheckMaps::New( |
| 5476 object, map, zone(), top_info(), dependency); |
5512 AddInstruction(mapcheck); | 5477 AddInstruction(mapcheck); |
5513 if (dependency) { | 5478 if (dependency) { |
5514 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 5479 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
5515 } | 5480 } |
5516 | 5481 |
5517 // Loads from a "stock" fast holey double arrays can elide the hole check. | 5482 // Loads from a "stock" fast holey double arrays can elide the hole check. |
5518 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; | 5483 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; |
5519 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && | 5484 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && |
5520 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { | 5485 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
5521 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); | 5486 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5685 new(zone()) HCompareMap(object, map, this_map, other_map); | 5650 new(zone()) HCompareMap(object, map, this_map, other_map); |
5686 current_block()->Finish(mapcompare); | 5651 current_block()->Finish(mapcompare); |
5687 | 5652 |
5688 set_current_block(this_map); | 5653 set_current_block(this_map); |
5689 HInstruction* checked_key = NULL; | 5654 HInstruction* checked_key = NULL; |
5690 HInstruction* access = NULL; | 5655 HInstruction* access = NULL; |
5691 if (IsFastElementsKind(elements_kind)) { | 5656 if (IsFastElementsKind(elements_kind)) { |
5692 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { | 5657 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { |
5693 AddInstruction(HCheckMaps::New( | 5658 AddInstruction(HCheckMaps::New( |
5694 elements, isolate()->factory()->fixed_array_map(), | 5659 elements, isolate()->factory()->fixed_array_map(), |
5695 zone(), mapcompare)); | 5660 zone(), top_info(), mapcompare)); |
5696 } | 5661 } |
5697 if (map->IsJSArray()) { | 5662 if (map->instance_type() == JS_ARRAY_TYPE) { |
5698 HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(), | 5663 HInstruction* length = AddLoad( |
5699 mapcompare, Representation::Smi()); | 5664 object, HObjectAccess::ForArrayLength(elements_kind), mapcompare); |
5700 length->set_type(HType::Smi()); | |
5701 checked_key = Add<HBoundsCheck>(key, length); | 5665 checked_key = Add<HBoundsCheck>(key, length); |
5702 } else { | 5666 } else { |
5703 HInstruction* length = AddLoadFixedArrayLength(elements); | 5667 HInstruction* length = AddLoadFixedArrayLength(elements); |
5704 checked_key = Add<HBoundsCheck>(key, length); | 5668 checked_key = Add<HBoundsCheck>(key, length); |
5705 } | 5669 } |
5706 access = AddFastElementAccess( | 5670 access = AddFastElementAccess( |
5707 elements, checked_key, val, mapcompare, | 5671 elements, checked_key, val, mapcompare, |
5708 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE); | 5672 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE); |
5709 } else if (IsDictionaryElementsKind(elements_kind)) { | 5673 } else if (IsDictionaryElementsKind(elements_kind)) { |
5710 if (is_store) { | 5674 if (is_store) { |
(...skipping 16 matching lines...) Expand all Loading... |
5727 access->SetFlag(HValue::kHasNoObservableSideEffects); | 5691 access->SetFlag(HValue::kHasNoObservableSideEffects); |
5728 if (position != RelocInfo::kNoPosition) access->set_position(position); | 5692 if (position != RelocInfo::kNoPosition) access->set_position(position); |
5729 if (!is_store) { | 5693 if (!is_store) { |
5730 Push(access); | 5694 Push(access); |
5731 } | 5695 } |
5732 current_block()->GotoNoSimulate(join); | 5696 current_block()->GotoNoSimulate(join); |
5733 set_current_block(other_map); | 5697 set_current_block(other_map); |
5734 } | 5698 } |
5735 | 5699 |
5736 // Deopt if none of the cases matched. | 5700 // Deopt if none of the cases matched. |
5737 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 5701 NoObservableSideEffectsScope scope(this); |
| 5702 FinishExitWithHardDeoptimization(join); |
5738 set_current_block(join); | 5703 set_current_block(join); |
5739 return is_store ? NULL : Pop(); | 5704 return is_store ? NULL : Pop(); |
5740 } | 5705 } |
5741 | 5706 |
5742 | 5707 |
5743 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 5708 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
5744 HValue* obj, | 5709 HValue* obj, |
5745 HValue* key, | 5710 HValue* key, |
5746 HValue* val, | 5711 HValue* val, |
5747 Expression* expr, | 5712 Expression* expr, |
(...skipping 15 matching lines...) Expand all Loading... |
5763 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); | 5728 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); |
5764 } | 5729 } |
5765 } else if (expr->GetReceiverTypes() != NULL && | 5730 } else if (expr->GetReceiverTypes() != NULL && |
5766 !expr->GetReceiverTypes()->is_empty()) { | 5731 !expr->GetReceiverTypes()->is_empty()) { |
5767 return HandlePolymorphicElementAccess( | 5732 return HandlePolymorphicElementAccess( |
5768 obj, key, val, expr, ast_id, position, is_store, | 5733 obj, key, val, expr, ast_id, position, is_store, |
5769 expr->GetStoreMode(), has_side_effects); | 5734 expr->GetStoreMode(), has_side_effects); |
5770 } else { | 5735 } else { |
5771 if (is_store) { | 5736 if (is_store) { |
5772 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { | 5737 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { |
5773 AddSoftDeoptimize(); | 5738 Add<HDeoptimize>(Deoptimizer::SOFT); |
5774 } | 5739 } |
5775 instr = BuildStoreKeyedGeneric(obj, key, val); | 5740 instr = BuildStoreKeyedGeneric(obj, key, val); |
5776 } else { | 5741 } else { |
5777 if (expr->AsProperty()->IsUninitialized()) { | 5742 if (expr->AsProperty()->IsUninitialized()) { |
5778 AddSoftDeoptimize(); | 5743 Add<HDeoptimize>(Deoptimizer::SOFT); |
5779 } | 5744 } |
5780 instr = BuildLoadKeyedGeneric(obj, key); | 5745 instr = BuildLoadKeyedGeneric(obj, key); |
5781 } | 5746 } |
5782 AddInstruction(instr); | 5747 AddInstruction(instr); |
5783 } | 5748 } |
5784 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 5749 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
5785 *has_side_effects = instr->HasObservableSideEffects(); | 5750 *has_side_effects = instr->HasObservableSideEffects(); |
5786 return instr; | 5751 return instr; |
5787 } | 5752 } |
5788 | 5753 |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5947 HValue* key = Pop(); | 5912 HValue* key = Pop(); |
5948 HValue* obj = Pop(); | 5913 HValue* obj = Pop(); |
5949 | 5914 |
5950 bool has_side_effects = false; | 5915 bool has_side_effects = false; |
5951 HValue* load = HandleKeyedElementAccess( | 5916 HValue* load = HandleKeyedElementAccess( |
5952 obj, key, NULL, expr, expr->id(), expr->position(), | 5917 obj, key, NULL, expr, expr->id(), expr->position(), |
5953 false, // is_store | 5918 false, // is_store |
5954 &has_side_effects); | 5919 &has_side_effects); |
5955 if (has_side_effects) { | 5920 if (has_side_effects) { |
5956 if (ast_context()->IsEffect()) { | 5921 if (ast_context()->IsEffect()) { |
5957 AddSimulate(expr->id(), REMOVABLE_SIMULATE); | 5922 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
5958 } else { | 5923 } else { |
5959 Push(load); | 5924 Push(load); |
5960 AddSimulate(expr->id(), REMOVABLE_SIMULATE); | 5925 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
5961 Drop(1); | 5926 Drop(1); |
5962 } | 5927 } |
5963 } | 5928 } |
5964 return ast_context()->ReturnValue(load); | 5929 return ast_context()->ReturnValue(load); |
5965 } | 5930 } |
5966 instr->set_position(expr->position()); | 5931 instr->set_position(expr->position()); |
5967 return ast_context()->ReturnInstruction(instr, expr->id()); | 5932 return ast_context()->ReturnInstruction(instr, expr->id()); |
5968 } | 5933 } |
5969 | 5934 |
5970 | 5935 |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6052 } | 6017 } |
6053 | 6018 |
6054 if (!TryInlineCall(expr)) { | 6019 if (!TryInlineCall(expr)) { |
6055 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 6020 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
6056 HCallConstantFunction* call = | 6021 HCallConstantFunction* call = |
6057 new(zone()) HCallConstantFunction(expr->target(), argument_count); | 6022 new(zone()) HCallConstantFunction(expr->target(), argument_count); |
6058 call->set_position(expr->position()); | 6023 call->set_position(expr->position()); |
6059 PreProcessCall(call); | 6024 PreProcessCall(call); |
6060 AddInstruction(call); | 6025 AddInstruction(call); |
6061 if (!ast_context()->IsEffect()) Push(call); | 6026 if (!ast_context()->IsEffect()) Push(call); |
6062 AddSimulate(expr->id(), REMOVABLE_SIMULATE); | 6027 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
6063 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 6028 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
6064 } | 6029 } |
6065 | 6030 |
6066 return true; | 6031 return true; |
6067 } | 6032 } |
6068 | 6033 |
6069 | 6034 |
6070 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( | 6035 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( |
6071 Call* expr, | 6036 Call* expr, |
6072 HValue* receiver, | 6037 HValue* receiver, |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6184 } | 6149 } |
6185 | 6150 |
6186 if (current_block() != NULL) current_block()->Goto(join); | 6151 if (current_block() != NULL) current_block()->Goto(join); |
6187 set_current_block(if_false); | 6152 set_current_block(if_false); |
6188 } | 6153 } |
6189 | 6154 |
6190 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6155 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
6191 // know about and do not want to handle ones we've never seen. Otherwise | 6156 // know about and do not want to handle ones we've never seen. Otherwise |
6192 // use a generic IC. | 6157 // use a generic IC. |
6193 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 6158 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
6194 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 6159 // Because the deopt may be the only path in the polymorphic call, make sure |
| 6160 // that the environment stack matches the depth on deopt that it otherwise |
| 6161 // would have had after a successful call. |
| 6162 Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1)); |
| 6163 FinishExitWithHardDeoptimization(join); |
6195 } else { | 6164 } else { |
6196 HValue* context = environment()->LookupContext(); | 6165 HValue* context = environment()->LookupContext(); |
6197 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); | 6166 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); |
6198 call->set_position(expr->position()); | 6167 call->set_position(expr->position()); |
6199 PreProcessCall(call); | 6168 PreProcessCall(call); |
6200 | 6169 |
6201 if (join != NULL) { | 6170 if (join != NULL) { |
6202 AddInstruction(call); | 6171 AddInstruction(call); |
6203 if (!ast_context()->IsEffect()) Push(call); | 6172 if (!ast_context()->IsEffect()) Push(call); |
6204 current_block()->Goto(join); | 6173 current_block()->Goto(join); |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6442 #if V8_TARGET_ARCH_IA32 | 6411 #if V8_TARGET_ARCH_IA32 |
6443 // IA32 only, overwrite the caller's context in the deoptimization | 6412 // IA32 only, overwrite the caller's context in the deoptimization |
6444 // environment with the correct one. | 6413 // environment with the correct one. |
6445 // | 6414 // |
6446 // TODO(kmillikin): implement the same inlining on other platforms so we | 6415 // TODO(kmillikin): implement the same inlining on other platforms so we |
6447 // can remove the unsightly ifdefs in this function. | 6416 // can remove the unsightly ifdefs in this function. |
6448 HConstant* context = Add<HConstant>(Handle<Context>(target->context())); | 6417 HConstant* context = Add<HConstant>(Handle<Context>(target->context())); |
6449 inner_env->BindContext(context); | 6418 inner_env->BindContext(context); |
6450 #endif | 6419 #endif |
6451 | 6420 |
6452 AddSimulate(return_id); | 6421 Add<HSimulate>(return_id); |
6453 current_block()->UpdateEnvironment(inner_env); | 6422 current_block()->UpdateEnvironment(inner_env); |
6454 HArgumentsObject* arguments_object = NULL; | 6423 HArgumentsObject* arguments_object = NULL; |
6455 | 6424 |
6456 // If the function uses arguments object create and bind one, also copy | 6425 // If the function uses arguments object create and bind one, also copy |
6457 // current arguments values to use them for materialization. | 6426 // current arguments values to use them for materialization. |
6458 if (function->scope()->arguments() != NULL) { | 6427 if (function->scope()->arguments() != NULL) { |
6459 ASSERT(function->scope()->arguments()->IsStackAllocated()); | 6428 ASSERT(function->scope()->arguments()->IsStackAllocated()); |
6460 HEnvironment* arguments_env = inner_env->arguments_environment(); | 6429 HEnvironment* arguments_env = inner_env->arguments_environment(); |
6461 int arguments_count = arguments_env->parameter_count(); | 6430 int arguments_count = arguments_env->parameter_count(); |
6462 arguments_object = Add<HArgumentsObject>(arguments_count, zone()); | 6431 arguments_object = Add<HArgumentsObject>(arguments_count, zone()); |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6876 AddCheckConstantFunction(expr->holder(), function, function_map); | 6845 AddCheckConstantFunction(expr->holder(), function, function_map); |
6877 Drop(1); | 6846 Drop(1); |
6878 | 6847 |
6879 VisitForValue(args->at(0)); | 6848 VisitForValue(args->at(0)); |
6880 if (HasStackOverflow() || current_block() == NULL) return true; | 6849 if (HasStackOverflow() || current_block() == NULL) return true; |
6881 HValue* receiver = Pop(); | 6850 HValue* receiver = Pop(); |
6882 | 6851 |
6883 if (function_state()->outer() == NULL) { | 6852 if (function_state()->outer() == NULL) { |
6884 HInstruction* elements = Add<HArgumentsElements>(false); | 6853 HInstruction* elements = Add<HArgumentsElements>(false); |
6885 HInstruction* length = Add<HArgumentsLength>(elements); | 6854 HInstruction* length = Add<HArgumentsLength>(elements); |
6886 HValue* wrapped_receiver = Add<HWrapReceiver>(receiver, function); | 6855 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function); |
6887 HInstruction* result = | 6856 HInstruction* result = |
6888 new(zone()) HApplyArguments(function, | 6857 new(zone()) HApplyArguments(function, |
6889 wrapped_receiver, | 6858 wrapped_receiver, |
6890 length, | 6859 length, |
6891 elements); | 6860 elements); |
6892 result->set_position(expr->position()); | 6861 result->set_position(expr->position()); |
6893 ast_context()->ReturnInstruction(result, expr->id()); | 6862 ast_context()->ReturnInstruction(result, expr->id()); |
6894 return true; | 6863 return true; |
6895 } else { | 6864 } else { |
6896 // We are inside inlined function and we know exactly what is inside | 6865 // We are inside inlined function and we know exactly what is inside |
6897 // arguments object. But we need to be able to materialize at deopt. | 6866 // arguments object. But we need to be able to materialize at deopt. |
6898 ASSERT_EQ(environment()->arguments_environment()->parameter_count(), | 6867 ASSERT_EQ(environment()->arguments_environment()->parameter_count(), |
6899 function_state()->entry()->arguments_object()->arguments_count()); | 6868 function_state()->entry()->arguments_object()->arguments_count()); |
6900 HArgumentsObject* args = function_state()->entry()->arguments_object(); | 6869 HArgumentsObject* args = function_state()->entry()->arguments_object(); |
6901 const ZoneList<HValue*>* arguments_values = args->arguments_values(); | 6870 const ZoneList<HValue*>* arguments_values = args->arguments_values(); |
6902 int arguments_count = arguments_values->length(); | 6871 int arguments_count = arguments_values->length(); |
6903 PushAndAdd(new(zone()) HWrapReceiver(receiver, function)); | 6872 Push(BuildWrapReceiver(receiver, function)); |
6904 for (int i = 1; i < arguments_count; i++) { | 6873 for (int i = 1; i < arguments_count; i++) { |
6905 Push(arguments_values->at(i)); | 6874 Push(arguments_values->at(i)); |
6906 } | 6875 } |
6907 | 6876 |
6908 Handle<JSFunction> known_function; | 6877 Handle<JSFunction> known_function; |
6909 if (function->IsConstant()) { | 6878 if (function->IsConstant()) { |
6910 HConstant* constant_function = HConstant::cast(function); | 6879 HConstant* constant_function = HConstant::cast(function); |
6911 known_function = Handle<JSFunction>::cast(constant_function->handle()); | 6880 known_function = Handle<JSFunction>::cast(constant_function->handle()); |
6912 int args_count = arguments_count - 1; // Excluding receiver. | 6881 int args_count = arguments_count - 1; // Excluding receiver. |
6913 if (TryInlineApply(known_function, expr, args_count)) return true; | 6882 if (TryInlineApply(known_function, expr, args_count)) return true; |
(...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7455 CHECK_ALIVE(VisitForTypeOf(expr->expression())); | 7424 CHECK_ALIVE(VisitForTypeOf(expr->expression())); |
7456 HValue* value = Pop(); | 7425 HValue* value = Pop(); |
7457 HValue* context = environment()->LookupContext(); | 7426 HValue* context = environment()->LookupContext(); |
7458 HInstruction* instr = new(zone()) HTypeof(context, value); | 7427 HInstruction* instr = new(zone()) HTypeof(context, value); |
7459 return ast_context()->ReturnInstruction(instr, expr->id()); | 7428 return ast_context()->ReturnInstruction(instr, expr->id()); |
7460 } | 7429 } |
7461 | 7430 |
7462 | 7431 |
7463 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { | 7432 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { |
7464 CHECK_ALIVE(VisitForValue(expr->expression())); | 7433 CHECK_ALIVE(VisitForValue(expr->expression())); |
7465 HValue* value = Pop(); | |
7466 Handle<Type> operand_type = expr->expression()->bounds().lower; | 7434 Handle<Type> operand_type = expr->expression()->bounds().lower; |
| 7435 HValue* value = TruncateToNumber(Pop(), &operand_type); |
7467 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB); | 7436 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB); |
7468 return ast_context()->ReturnInstruction(instr, expr->id()); | 7437 return ast_context()->ReturnInstruction(instr, expr->id()); |
7469 } | 7438 } |
7470 | 7439 |
7471 | 7440 |
7472 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { | 7441 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
7473 CHECK_ALIVE(VisitForValue(expr->expression())); | 7442 CHECK_ALIVE(VisitForValue(expr->expression())); |
7474 HValue* value = Pop(); | |
7475 Handle<Type> operand_type = expr->expression()->bounds().lower; | 7443 Handle<Type> operand_type = expr->expression()->bounds().lower; |
| 7444 HValue* value = TruncateToNumber(Pop(), &operand_type); |
7476 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::BIT_NOT); | 7445 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::BIT_NOT); |
7477 return ast_context()->ReturnInstruction(instr, expr->id()); | 7446 return ast_context()->ReturnInstruction(instr, expr->id()); |
7478 } | 7447 } |
7479 | 7448 |
7480 | 7449 |
7481 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { | 7450 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { |
7482 if (ast_context()->IsTest()) { | 7451 if (ast_context()->IsTest()) { |
7483 TestContext* context = TestContext::cast(ast_context()); | 7452 TestContext* context = TestContext::cast(ast_context()); |
7484 VisitForControl(expr->expression(), | 7453 VisitForControl(expr->expression(), |
7485 context->if_false(), | 7454 context->if_false(), |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7620 } | 7589 } |
7621 } | 7590 } |
7622 } | 7591 } |
7623 | 7592 |
7624 HValue* context = BuildContextChainWalk(var); | 7593 HValue* context = BuildContextChainWalk(var); |
7625 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) | 7594 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) |
7626 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; | 7595 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; |
7627 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 7596 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
7628 mode, after); | 7597 mode, after); |
7629 if (instr->HasObservableSideEffects()) { | 7598 if (instr->HasObservableSideEffects()) { |
7630 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 7599 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
7631 } | 7600 } |
7632 break; | 7601 break; |
7633 } | 7602 } |
7634 | 7603 |
7635 case Variable::LOOKUP: | 7604 case Variable::LOOKUP: |
7636 return Bailout("lookup variable in count operation"); | 7605 return Bailout("lookup variable in count operation"); |
7637 } | 7606 } |
7638 | 7607 |
7639 } else { | 7608 } else { |
7640 // Argument of the count operation is a property. | 7609 // Argument of the count operation is a property. |
(...skipping 22 matching lines...) Expand all Loading... |
7663 load = BuildCallGetter(object, map, getter, holder); | 7632 load = BuildCallGetter(object, map, getter, holder); |
7664 } else { | 7633 } else { |
7665 load = BuildLoadNamedMonomorphic(object, name, prop, map); | 7634 load = BuildLoadNamedMonomorphic(object, name, prop, map); |
7666 } | 7635 } |
7667 } else if (types != NULL && types->length() > 1) { | 7636 } else if (types != NULL && types->length() > 1) { |
7668 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); | 7637 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); |
7669 } | 7638 } |
7670 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); | 7639 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); |
7671 PushAndAdd(load); | 7640 PushAndAdd(load); |
7672 if (load->HasObservableSideEffects()) { | 7641 if (load->HasObservableSideEffects()) { |
7673 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7642 Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); |
7674 } | 7643 } |
7675 | 7644 |
7676 after = BuildIncrement(returns_original_input, expr); | 7645 after = BuildIncrement(returns_original_input, expr); |
7677 HValue* result = returns_original_input ? Pop() : after; | 7646 HValue* result = returns_original_input ? Pop() : after; |
7678 | 7647 |
7679 return BuildStoreNamed(prop, expr->id(), expr->position(), | 7648 return BuildStoreNamed(prop, expr->id(), expr->position(), |
7680 expr->AssignmentId(), prop, object, after, result); | 7649 expr->AssignmentId(), prop, object, after, result); |
7681 } else { | 7650 } else { |
7682 // Keyed property. | 7651 // Keyed property. |
7683 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 7652 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
7684 | 7653 |
7685 CHECK_ALIVE(VisitForValue(prop->obj())); | 7654 CHECK_ALIVE(VisitForValue(prop->obj())); |
7686 CHECK_ALIVE(VisitForValue(prop->key())); | 7655 CHECK_ALIVE(VisitForValue(prop->key())); |
7687 HValue* obj = environment()->ExpressionStackAt(1); | 7656 HValue* obj = environment()->ExpressionStackAt(1); |
7688 HValue* key = environment()->ExpressionStackAt(0); | 7657 HValue* key = environment()->ExpressionStackAt(0); |
7689 | 7658 |
7690 bool has_side_effects = false; | 7659 bool has_side_effects = false; |
7691 HValue* load = HandleKeyedElementAccess( | 7660 HValue* load = HandleKeyedElementAccess( |
7692 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 7661 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
7693 false, // is_store | 7662 false, // is_store |
7694 &has_side_effects); | 7663 &has_side_effects); |
7695 Push(load); | 7664 Push(load); |
7696 if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7665 if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); |
7697 | 7666 |
7698 after = BuildIncrement(returns_original_input, expr); | 7667 after = BuildIncrement(returns_original_input, expr); |
7699 input = environment()->ExpressionStackAt(0); | 7668 input = environment()->ExpressionStackAt(0); |
7700 | 7669 |
7701 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), | 7670 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), |
7702 RelocInfo::kNoPosition, | 7671 RelocInfo::kNoPosition, |
7703 true, // is_store | 7672 true, // is_store |
7704 &has_side_effects); | 7673 &has_side_effects); |
7705 | 7674 |
7706 // Drop the key and the original value from the bailout environment. | 7675 // Drop the key and the original value from the bailout environment. |
7707 // Overwrite the receiver with the result of the operation, and the | 7676 // Overwrite the receiver with the result of the operation, and the |
7708 // placeholder with the original value if necessary. | 7677 // placeholder with the original value if necessary. |
7709 Drop(2); | 7678 Drop(2); |
7710 environment()->SetExpressionStackAt(0, after); | 7679 environment()->SetExpressionStackAt(0, after); |
7711 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | 7680 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
7712 ASSERT(has_side_effects); // Stores always have side effects. | 7681 ASSERT(has_side_effects); // Stores always have side effects. |
7713 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 7682 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
7714 } | 7683 } |
7715 } | 7684 } |
7716 | 7685 |
7717 Drop(returns_original_input ? 2 : 1); | 7686 Drop(returns_original_input ? 2 : 1); |
7718 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); | 7687 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
7719 } | 7688 } |
7720 | 7689 |
7721 | 7690 |
7722 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( | 7691 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( |
7723 HValue* context, | 7692 HValue* context, |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7795 HConstant* right_const = HConstant::cast(right); | 7764 HConstant* right_const = HConstant::cast(right); |
7796 if (right_const->HasInteger32Value() && | 7765 if (right_const->HasInteger32Value() && |
7797 (right_const->Integer32Value() & 0x1f) != 0) { | 7766 (right_const->Integer32Value() & 0x1f) != 0) { |
7798 return false; | 7767 return false; |
7799 } | 7768 } |
7800 } | 7769 } |
7801 return true; | 7770 return true; |
7802 } | 7771 } |
7803 | 7772 |
7804 | 7773 |
| 7774 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { |
| 7775 if (value->IsConstant()) { |
| 7776 HConstant* constant = HConstant::cast(value); |
| 7777 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); |
| 7778 if (number.has_value) { |
| 7779 *expected = handle(Type::Number(), isolate()); |
| 7780 return AddInstruction(number.value); |
| 7781 } |
| 7782 return value; |
| 7783 } |
| 7784 |
| 7785 Handle<Type> expected_type = *expected; |
| 7786 Representation rep = Representation::FromType(expected_type); |
| 7787 if (!rep.IsTagged()) return value; |
| 7788 |
| 7789 // If our type feedback suggests that we can non-observably truncate to number |
| 7790 // we introduce the appropriate check here. This avoids 'value' having a |
| 7791 // tagged representation later on. |
| 7792 if (expected_type->Is(Type::Oddball())) { |
| 7793 // TODO(olivf) The BinaryOpStub only records undefined. It might pay off to |
| 7794 // also record booleans and convert them to 0/1 here. |
| 7795 IfBuilder if_nan(this); |
| 7796 if_nan.If<HCompareObjectEqAndBranch>(value, |
| 7797 graph()->GetConstantUndefined()); |
| 7798 if_nan.Then(); |
| 7799 if_nan.ElseDeopt(); |
| 7800 if_nan.End(); |
| 7801 return Add<HConstant>(OS::nan_value(), Representation::Double()); |
| 7802 } |
| 7803 |
| 7804 return value; |
| 7805 } |
| 7806 |
| 7807 |
7805 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 7808 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
7806 BinaryOperation* expr, | 7809 BinaryOperation* expr, |
7807 HValue* left, | 7810 HValue* left, |
7808 HValue* right) { | 7811 HValue* right) { |
7809 HValue* context = environment()->LookupContext(); | 7812 HValue* context = environment()->LookupContext(); |
7810 Handle<Type> left_type = expr->left()->bounds().lower; | 7813 Handle<Type> left_type = expr->left()->bounds().lower; |
7811 Handle<Type> right_type = expr->right()->bounds().lower; | 7814 Handle<Type> right_type = expr->right()->bounds().lower; |
7812 Handle<Type> result_type = expr->bounds().lower; | 7815 Handle<Type> result_type = expr->bounds().lower; |
7813 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 7816 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
7814 Representation left_rep = Representation::FromType(left_type); | 7817 Representation left_rep = Representation::FromType(left_type); |
7815 Representation right_rep = Representation::FromType(right_type); | 7818 Representation right_rep = Representation::FromType(right_type); |
7816 Representation result_rep = Representation::FromType(result_type); | 7819 Representation result_rep = Representation::FromType(result_type); |
7817 | 7820 |
| 7821 if (expr->op() != Token::ADD || |
| 7822 (left->type().IsNonString() && right->type().IsNonString())) { |
| 7823 // For addition we can only truncate the arguments to number if we can |
| 7824 // prove that we will not end up in string concatenation mode. |
| 7825 left = TruncateToNumber(left, &left_type); |
| 7826 right = TruncateToNumber(right, &right_type); |
| 7827 } |
| 7828 |
7818 if (left_type->Is(Type::None())) { | 7829 if (left_type->Is(Type::None())) { |
7819 AddSoftDeoptimize(); | 7830 Add<HDeoptimize>(Deoptimizer::SOFT); |
7820 // TODO(rossberg): we should be able to get rid of non-continuous defaults. | 7831 // TODO(rossberg): we should be able to get rid of non-continuous defaults. |
7821 left_type = handle(Type::Any(), isolate()); | 7832 left_type = handle(Type::Any(), isolate()); |
7822 } | 7833 } |
7823 if (right_type->Is(Type::None())) { | 7834 if (right_type->Is(Type::None())) { |
7824 AddSoftDeoptimize(); | 7835 Add<HDeoptimize>(Deoptimizer::SOFT); |
7825 right_type = handle(Type::Any(), isolate()); | 7836 right_type = handle(Type::Any(), isolate()); |
7826 } | 7837 } |
7827 HInstruction* instr = NULL; | 7838 HInstruction* instr = NULL; |
7828 switch (expr->op()) { | 7839 switch (expr->op()) { |
7829 case Token::ADD: | 7840 case Token::ADD: |
7830 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { | 7841 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { |
7831 BuildCheckHeapObject(left); | 7842 BuildCheckHeapObject(left); |
7832 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 7843 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
7833 BuildCheckHeapObject(right); | 7844 BuildCheckHeapObject(right); |
7834 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 7845 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8164 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 8175 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
8165 // even though we are certain to pass the correct number of arguments here. | 8176 // even though we are certain to pass the correct number of arguments here. |
8166 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); | 8177 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); |
8167 result->set_position(expr->position()); | 8178 result->set_position(expr->position()); |
8168 return ast_context()->ReturnInstruction(result, expr->id()); | 8179 return ast_context()->ReturnInstruction(result, expr->id()); |
8169 } | 8180 } |
8170 | 8181 |
8171 // Cases handled below depend on collected type feedback. They should | 8182 // Cases handled below depend on collected type feedback. They should |
8172 // soft deoptimize when there is no type feedback. | 8183 // soft deoptimize when there is no type feedback. |
8173 if (combined_type->Is(Type::None())) { | 8184 if (combined_type->Is(Type::None())) { |
8174 AddSoftDeoptimize(); | 8185 Add<HDeoptimize>(Deoptimizer::SOFT); |
8175 combined_type = left_type = right_type = handle(Type::Any(), isolate()); | 8186 combined_type = left_type = right_type = handle(Type::Any(), isolate()); |
8176 } | 8187 } |
8177 | 8188 |
8178 if (combined_type->Is(Type::Receiver())) { | 8189 if (combined_type->Is(Type::Receiver())) { |
8179 switch (op) { | 8190 switch (op) { |
8180 case Token::EQ: | 8191 case Token::EQ: |
8181 case Token::EQ_STRICT: { | 8192 case Token::EQ_STRICT: { |
8182 // Can we get away with map check and not instance type check? | 8193 // Can we get away with map check and not instance type check? |
8183 if (combined_type->IsClass()) { | 8194 if (combined_type->IsClass()) { |
8184 Handle<Map> map = combined_type->AsClass(); | 8195 Handle<Map> map = combined_type->AsClass(); |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8440 AddStore(object_header, access, properties); | 8451 AddStore(object_header, access, properties); |
8441 | 8452 |
8442 if (boilerplate_object->IsJSArray()) { | 8453 if (boilerplate_object->IsJSArray()) { |
8443 Handle<JSArray> boilerplate_array = | 8454 Handle<JSArray> boilerplate_array = |
8444 Handle<JSArray>::cast(boilerplate_object); | 8455 Handle<JSArray>::cast(boilerplate_object); |
8445 Handle<Object> length_field = | 8456 Handle<Object> length_field = |
8446 Handle<Object>(boilerplate_array->length(), isolate()); | 8457 Handle<Object>(boilerplate_array->length(), isolate()); |
8447 HInstruction* length = Add<HConstant>(length_field); | 8458 HInstruction* length = Add<HConstant>(length_field); |
8448 | 8459 |
8449 ASSERT(boilerplate_array->length()->IsSmi()); | 8460 ASSERT(boilerplate_array->length()->IsSmi()); |
8450 Representation representation = | 8461 AddStore(object_header, HObjectAccess::ForArrayLength( |
8451 IsFastElementsKind(boilerplate_array->GetElementsKind()) | 8462 boilerplate_array->GetElementsKind()), length); |
8452 ? Representation::Smi() : Representation::Tagged(); | |
8453 AddStore(object_header, HObjectAccess::ForArrayLength(), | |
8454 length, representation); | |
8455 } | 8463 } |
8456 | 8464 |
8457 return result; | 8465 return result; |
8458 } | 8466 } |
8459 | 8467 |
8460 | 8468 |
8461 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( | 8469 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( |
8462 Handle<JSObject> boilerplate_object, | 8470 Handle<JSObject> boilerplate_object, |
8463 Handle<JSObject> original_boilerplate_object, | 8471 Handle<JSObject> original_boilerplate_object, |
8464 HValue* object_properties, | 8472 HValue* object_properties, |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8510 if (data_target != NULL) { | 8518 if (data_target != NULL) { |
8511 double_box = Add<HInnerAllocatedObject>(data_target, *data_offset); | 8519 double_box = Add<HInnerAllocatedObject>(data_target, *data_offset); |
8512 *data_offset += HeapNumber::kSize; | 8520 *data_offset += HeapNumber::kSize; |
8513 } else { | 8521 } else { |
8514 double_box = Add<HInnerAllocatedObject>(target, *offset); | 8522 double_box = Add<HInnerAllocatedObject>(target, *offset); |
8515 *offset += HeapNumber::kSize; | 8523 *offset += HeapNumber::kSize; |
8516 } | 8524 } |
8517 AddStoreMapConstant(double_box, | 8525 AddStoreMapConstant(double_box, |
8518 isolate()->factory()->heap_number_map()); | 8526 isolate()->factory()->heap_number_map()); |
8519 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), | 8527 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), |
8520 value_instruction, Representation::Double()); | 8528 value_instruction); |
8521 value_instruction = double_box; | 8529 value_instruction = double_box; |
8522 } | 8530 } |
8523 | 8531 |
8524 AddStore(object_properties, access, value_instruction); | 8532 AddStore(object_properties, access, value_instruction); |
8525 } | 8533 } |
8526 } | 8534 } |
8527 | 8535 |
8528 int inobject_properties = boilerplate_object->map()->inobject_properties(); | 8536 int inobject_properties = boilerplate_object->map()->inobject_properties(); |
8529 HInstruction* value_instruction = | 8537 HInstruction* value_instruction = |
8530 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); | 8538 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8667 environment()->Bind(variable, value); | 8675 environment()->Bind(variable, value); |
8668 } | 8676 } |
8669 break; | 8677 break; |
8670 case Variable::CONTEXT: | 8678 case Variable::CONTEXT: |
8671 if (hole_init) { | 8679 if (hole_init) { |
8672 HValue* value = graph()->GetConstantHole(); | 8680 HValue* value = graph()->GetConstantHole(); |
8673 HValue* context = environment()->LookupContext(); | 8681 HValue* context = environment()->LookupContext(); |
8674 HStoreContextSlot* store = Add<HStoreContextSlot>( | 8682 HStoreContextSlot* store = Add<HStoreContextSlot>( |
8675 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8683 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
8676 if (store->HasObservableSideEffects()) { | 8684 if (store->HasObservableSideEffects()) { |
8677 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8685 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); |
8678 } | 8686 } |
8679 } | 8687 } |
8680 break; | 8688 break; |
8681 case Variable::LOOKUP: | 8689 case Variable::LOOKUP: |
8682 return Bailout("unsupported lookup slot in declaration"); | 8690 return Bailout("unsupported lookup slot in declaration"); |
8683 } | 8691 } |
8684 } | 8692 } |
8685 | 8693 |
8686 | 8694 |
8687 void HOptimizedGraphBuilder::VisitFunctionDeclaration( | 8695 void HOptimizedGraphBuilder::VisitFunctionDeclaration( |
(...skipping 17 matching lines...) Expand all Loading... |
8705 BindIfLive(variable, value); | 8713 BindIfLive(variable, value); |
8706 break; | 8714 break; |
8707 } | 8715 } |
8708 case Variable::CONTEXT: { | 8716 case Variable::CONTEXT: { |
8709 CHECK_ALIVE(VisitForValue(declaration->fun())); | 8717 CHECK_ALIVE(VisitForValue(declaration->fun())); |
8710 HValue* value = Pop(); | 8718 HValue* value = Pop(); |
8711 HValue* context = environment()->LookupContext(); | 8719 HValue* context = environment()->LookupContext(); |
8712 HStoreContextSlot* store = Add<HStoreContextSlot>( | 8720 HStoreContextSlot* store = Add<HStoreContextSlot>( |
8713 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8721 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
8714 if (store->HasObservableSideEffects()) { | 8722 if (store->HasObservableSideEffects()) { |
8715 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8723 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); |
8716 } | 8724 } |
8717 break; | 8725 break; |
8718 } | 8726 } |
8719 case Variable::LOOKUP: | 8727 case Variable::LOOKUP: |
8720 return Bailout("unsupported lookup slot in declaration"); | 8728 return Bailout("unsupported lookup slot in declaration"); |
8721 } | 8729 } |
8722 } | 8730 } |
8723 | 8731 |
8724 | 8732 |
8725 void HOptimizedGraphBuilder::VisitModuleDeclaration( | 8733 void HOptimizedGraphBuilder::VisitModuleDeclaration( |
(...skipping 1180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9906 if (ShouldProduceTraceOutput()) { | 9914 if (ShouldProduceTraceOutput()) { |
9907 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9915 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9908 } | 9916 } |
9909 | 9917 |
9910 #ifdef DEBUG | 9918 #ifdef DEBUG |
9911 graph_->Verify(false); // No full verify. | 9919 graph_->Verify(false); // No full verify. |
9912 #endif | 9920 #endif |
9913 } | 9921 } |
9914 | 9922 |
9915 } } // namespace v8::internal | 9923 } } // namespace v8::internal |
OLD | NEW |