| 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 |