| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 15 matching lines...) Expand all Loading... |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 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-environment-liveness.h" |
| 36 #include "lithium-allocator.h" | 37 #include "lithium-allocator.h" |
| 37 #include "parser.h" | 38 #include "parser.h" |
| 38 #include "scopeinfo.h" | 39 #include "scopeinfo.h" |
| 39 #include "scopes.h" | 40 #include "scopes.h" |
| 40 #include "stub-cache.h" | 41 #include "stub-cache.h" |
| 41 | 42 |
| 42 #if V8_TARGET_ARCH_IA32 | 43 #if V8_TARGET_ARCH_IA32 |
| 43 #include "ia32/lithium-codegen-ia32.h" | 44 #include "ia32/lithium-codegen-ia32.h" |
| 44 #elif V8_TARGET_ARCH_X64 | 45 #elif V8_TARGET_ARCH_X64 |
| 45 #include "x64/lithium-codegen-x64.h" | 46 #include "x64/lithium-codegen-x64.h" |
| (...skipping 18 matching lines...) Expand all Loading... |
| 64 loop_information_(NULL), | 65 loop_information_(NULL), |
| 65 predecessors_(2, graph->zone()), | 66 predecessors_(2, graph->zone()), |
| 66 dominator_(NULL), | 67 dominator_(NULL), |
| 67 dominated_blocks_(4, graph->zone()), | 68 dominated_blocks_(4, graph->zone()), |
| 68 last_environment_(NULL), | 69 last_environment_(NULL), |
| 69 argument_count_(-1), | 70 argument_count_(-1), |
| 70 first_instruction_index_(-1), | 71 first_instruction_index_(-1), |
| 71 last_instruction_index_(-1), | 72 last_instruction_index_(-1), |
| 72 deleted_phis_(4, graph->zone()), | 73 deleted_phis_(4, graph->zone()), |
| 73 parent_loop_header_(NULL), | 74 parent_loop_header_(NULL), |
| 75 inlined_entry_block_(NULL), |
| 74 is_inline_return_target_(false), | 76 is_inline_return_target_(false), |
| 75 is_deoptimizing_(false), | 77 is_deoptimizing_(false), |
| 76 dominates_loop_successors_(false), | 78 dominates_loop_successors_(false), |
| 77 is_osr_entry_(false) { } | 79 is_osr_entry_(false) { } |
| 78 | 80 |
| 79 | 81 |
| 80 Isolate* HBasicBlock::isolate() const { | 82 Isolate* HBasicBlock::isolate() const { |
| 81 return graph_->isolate(); | 83 return graph_->isolate(); |
| 82 } | 84 } |
| 83 | 85 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 first_ = last_ = entry; | 125 first_ = last_ = entry; |
| 124 } | 126 } |
| 125 instr->InsertAfter(last_); | 127 instr->InsertAfter(last_); |
| 126 } | 128 } |
| 127 | 129 |
| 128 | 130 |
| 129 HDeoptimize* HBasicBlock::CreateDeoptimize( | 131 HDeoptimize* HBasicBlock::CreateDeoptimize( |
| 130 HDeoptimize::UseEnvironment has_uses) { | 132 HDeoptimize::UseEnvironment has_uses) { |
| 131 ASSERT(HasEnvironment()); | 133 ASSERT(HasEnvironment()); |
| 132 if (has_uses == HDeoptimize::kNoUses) | 134 if (has_uses == HDeoptimize::kNoUses) |
| 133 return new(zone()) HDeoptimize(0, zone()); | 135 return new(zone()) HDeoptimize(0, 0, 0, zone()); |
| 134 | 136 |
| 135 HEnvironment* environment = last_environment(); | 137 HEnvironment* environment = last_environment(); |
| 136 HDeoptimize* instr = new(zone()) HDeoptimize(environment->length(), zone()); | 138 int first_local_index = environment->first_local_index(); |
| 139 int first_expression_index = environment->first_expression_index(); |
| 140 HDeoptimize* instr = new(zone()) HDeoptimize( |
| 141 environment->length(), first_local_index, first_expression_index, zone()); |
| 137 for (int i = 0; i < environment->length(); i++) { | 142 for (int i = 0; i < environment->length(); i++) { |
| 138 HValue* val = environment->values()->at(i); | 143 HValue* val = environment->values()->at(i); |
| 139 instr->AddEnvironmentValue(val, zone()); | 144 instr->AddEnvironmentValue(val, zone()); |
| 140 } | 145 } |
| 141 | 146 |
| 142 return instr; | 147 return instr; |
| 143 } | 148 } |
| 144 | 149 |
| 145 | 150 |
| 146 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, | 151 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, |
| 147 RemovableSimulate removable) { | 152 RemovableSimulate removable) { |
| 148 ASSERT(HasEnvironment()); | 153 ASSERT(HasEnvironment()); |
| 149 HEnvironment* environment = last_environment(); | 154 HEnvironment* environment = last_environment(); |
| 150 ASSERT(ast_id.IsNone() || | 155 ASSERT(ast_id.IsNone() || |
| 151 ast_id == BailoutId::StubEntry() || | 156 ast_id == BailoutId::StubEntry() || |
| 152 environment->closure()->shared()->VerifyBailoutId(ast_id)); | 157 environment->closure()->shared()->VerifyBailoutId(ast_id)); |
| 153 | 158 |
| 154 int push_count = environment->push_count(); | 159 int push_count = environment->push_count(); |
| 155 int pop_count = environment->pop_count(); | 160 int pop_count = environment->pop_count(); |
| 156 | 161 |
| 157 HSimulate* instr = | 162 HSimulate* instr = |
| 158 new(zone()) HSimulate(ast_id, pop_count, zone(), removable); | 163 new(zone()) HSimulate(ast_id, pop_count, zone(), removable); |
| 164 #ifdef DEBUG |
| 165 instr->set_closure(environment->closure()); |
| 166 #endif |
| 159 // Order of pushed values: newest (top of stack) first. This allows | 167 // Order of pushed values: newest (top of stack) first. This allows |
| 160 // HSimulate::MergeInto() to easily append additional pushed values | 168 // HSimulate::MergeInto() to easily append additional pushed values |
| 161 // that are older (from further down the stack). | 169 // that are older (from further down the stack). |
| 162 for (int i = 0; i < push_count; ++i) { | 170 for (int i = 0; i < push_count; ++i) { |
| 163 instr->AddPushedValue(environment->ExpressionStackAt(i)); | 171 instr->AddPushedValue(environment->ExpressionStackAt(i)); |
| 164 } | 172 } |
| 165 for (GrowableBitVector::Iterator it(environment->assigned_variables(), | 173 for (GrowableBitVector::Iterator it(environment->assigned_variables(), |
| 166 zone()); | 174 zone()); |
| 167 !it.Done(); | 175 !it.Done(); |
| 168 it.Advance()) { | 176 it.Advance()) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 185 | 193 |
| 186 | 194 |
| 187 void HBasicBlock::Goto(HBasicBlock* block, | 195 void HBasicBlock::Goto(HBasicBlock* block, |
| 188 FunctionState* state, | 196 FunctionState* state, |
| 189 bool add_simulate) { | 197 bool add_simulate) { |
| 190 bool drop_extra = state != NULL && | 198 bool drop_extra = state != NULL && |
| 191 state->inlining_kind() == DROP_EXTRA_ON_RETURN; | 199 state->inlining_kind() == DROP_EXTRA_ON_RETURN; |
| 192 | 200 |
| 193 if (block->IsInlineReturnTarget()) { | 201 if (block->IsInlineReturnTarget()) { |
| 194 AddInstruction(new(zone()) HLeaveInlined()); | 202 AddInstruction(new(zone()) HLeaveInlined()); |
| 195 last_environment_ = last_environment()->DiscardInlined(drop_extra); | 203 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); |
| 196 } | 204 } |
| 197 | 205 |
| 198 if (add_simulate) AddSimulate(BailoutId::None()); | 206 if (add_simulate) AddSimulate(BailoutId::None()); |
| 199 HGoto* instr = new(zone()) HGoto(block); | 207 HGoto* instr = new(zone()) HGoto(block); |
| 200 Finish(instr); | 208 Finish(instr); |
| 201 } | 209 } |
| 202 | 210 |
| 203 | 211 |
| 204 void HBasicBlock::AddLeaveInlined(HValue* return_value, | 212 void HBasicBlock::AddLeaveInlined(HValue* return_value, |
| 205 FunctionState* state) { | 213 FunctionState* state) { |
| 206 HBasicBlock* target = state->function_return(); | 214 HBasicBlock* target = state->function_return(); |
| 207 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; | 215 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; |
| 208 | 216 |
| 209 ASSERT(target->IsInlineReturnTarget()); | 217 ASSERT(target->IsInlineReturnTarget()); |
| 210 ASSERT(return_value != NULL); | 218 ASSERT(return_value != NULL); |
| 211 AddInstruction(new(zone()) HLeaveInlined()); | 219 AddInstruction(new(zone()) HLeaveInlined()); |
| 212 last_environment_ = last_environment()->DiscardInlined(drop_extra); | 220 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); |
| 213 last_environment()->Push(return_value); | 221 last_environment()->Push(return_value); |
| 214 AddSimulate(BailoutId::None()); | 222 AddSimulate(BailoutId::None()); |
| 215 HGoto* instr = new(zone()) HGoto(target); | 223 HGoto* instr = new(zone()) HGoto(target); |
| 216 Finish(instr); | 224 Finish(instr); |
| 217 } | 225 } |
| 218 | 226 |
| 219 | 227 |
| 220 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { | 228 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { |
| 221 ASSERT(!HasEnvironment()); | 229 ASSERT(!HasEnvironment()); |
| 222 ASSERT(first() == NULL); | 230 ASSERT(first() == NULL); |
| 223 UpdateEnvironment(env); | 231 UpdateEnvironment(env); |
| 224 } | 232 } |
| 225 | 233 |
| 226 | 234 |
| 235 void HBasicBlock::UpdateEnvironment(HEnvironment* env) { |
| 236 last_environment_ = env; |
| 237 graph()->update_maximum_environment_size(env->first_expression_index()); |
| 238 } |
| 239 |
| 240 |
| 227 void HBasicBlock::SetJoinId(BailoutId ast_id) { | 241 void HBasicBlock::SetJoinId(BailoutId ast_id) { |
| 228 int length = predecessors_.length(); | 242 int length = predecessors_.length(); |
| 229 ASSERT(length > 0); | 243 ASSERT(length > 0); |
| 230 for (int i = 0; i < length; i++) { | 244 for (int i = 0; i < length; i++) { |
| 231 HBasicBlock* predecessor = predecessors_[i]; | 245 HBasicBlock* predecessor = predecessors_[i]; |
| 232 ASSERT(predecessor->end()->IsGoto()); | 246 ASSERT(predecessor->end()->IsGoto()); |
| 233 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous()); | 247 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous()); |
| 234 ASSERT(i != 0 || | 248 ASSERT(i != 0 || |
| 235 (predecessor->last_environment()->closure().is_null() || | 249 (predecessor->last_environment()->closure().is_null() || |
| 236 predecessor->last_environment()->closure()->shared() | 250 predecessor->last_environment()->closure()->shared() |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 724 input_representation); | 738 input_representation); |
| 725 compare->AssumeRepresentation(input_representation); | 739 compare->AssumeRepresentation(input_representation); |
| 726 AddCompare(compare); | 740 AddCompare(compare); |
| 727 return compare; | 741 return compare; |
| 728 } | 742 } |
| 729 | 743 |
| 730 | 744 |
| 731 HInstruction* HGraphBuilder::IfBuilder::IfCompareMap(HValue* left, | 745 HInstruction* HGraphBuilder::IfBuilder::IfCompareMap(HValue* left, |
| 732 Handle<Map> map) { | 746 Handle<Map> map) { |
| 733 HCompareMap* compare = | 747 HCompareMap* compare = |
| 734 new(zone()) HCompareMap(left, map, | 748 new(zone()) HCompareMap(left, map, first_true_block_, first_false_block_); |
| 735 first_true_block_, first_false_block_); | |
| 736 AddCompare(compare); | 749 AddCompare(compare); |
| 737 return compare; | 750 return compare; |
| 738 } | 751 } |
| 739 | 752 |
| 740 | 753 |
| 741 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { | 754 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { |
| 742 if (split_edge_merge_block_ != NULL) { | 755 if (split_edge_merge_block_ != NULL) { |
| 743 HEnvironment* env = first_false_block_->last_environment(); | 756 HEnvironment* env = first_false_block_->last_environment(); |
| 744 HBasicBlock* split_edge = | 757 HBasicBlock* split_edge = |
| 745 builder_->CreateBasicBlock(env->Copy()); | 758 builder_->CreateBasicBlock(env->Copy()); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 804 End(); | 817 End(); |
| 805 } | 818 } |
| 806 | 819 |
| 807 | 820 |
| 808 void HGraphBuilder::IfBuilder::Then() { | 821 void HGraphBuilder::IfBuilder::Then() { |
| 809 ASSERT(!captured_); | 822 ASSERT(!captured_); |
| 810 ASSERT(!finished_); | 823 ASSERT(!finished_); |
| 811 did_then_ = true; | 824 did_then_ = true; |
| 812 if (needs_compare_) { | 825 if (needs_compare_) { |
| 813 // Handle if's without any expressions, they jump directly to the "else" | 826 // Handle if's without any expressions, they jump directly to the "else" |
| 814 // branch. | 827 // branch. However, we must pretend that the "then" branch is reachable, |
| 815 builder_->current_block()->GotoNoSimulate(first_false_block_); | 828 // so that the graph builder visits it and sees any live range extending |
| 816 first_true_block_ = NULL; | 829 // constructs within it. |
| 830 HConstant* constant_false = builder_->graph()->GetConstantFalse(); |
| 831 ToBooleanStub::Types boolean_type = ToBooleanStub::no_types(); |
| 832 boolean_type.Add(ToBooleanStub::BOOLEAN); |
| 833 HBranch* branch = |
| 834 new(zone()) HBranch(constant_false, first_true_block_, |
| 835 first_false_block_, boolean_type); |
| 836 builder_->current_block()->Finish(branch); |
| 817 } | 837 } |
| 818 builder_->set_current_block(first_true_block_); | 838 builder_->set_current_block(first_true_block_); |
| 819 } | 839 } |
| 820 | 840 |
| 821 | 841 |
| 822 void HGraphBuilder::IfBuilder::Else() { | 842 void HGraphBuilder::IfBuilder::Else() { |
| 823 ASSERT(did_then_); | 843 ASSERT(did_then_); |
| 824 ASSERT(!captured_); | 844 ASSERT(!captured_); |
| 825 ASSERT(!finished_); | 845 ASSERT(!finished_); |
| 826 last_true_block_ = builder_->current_block(); | 846 last_true_block_ = builder_->current_block(); |
| (...skipping 1269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2096 blocks_(8, info->zone()), | 2116 blocks_(8, info->zone()), |
| 2097 values_(16, info->zone()), | 2117 values_(16, info->zone()), |
| 2098 phi_list_(NULL), | 2118 phi_list_(NULL), |
| 2099 uint32_instructions_(NULL), | 2119 uint32_instructions_(NULL), |
| 2100 info_(info), | 2120 info_(info), |
| 2101 zone_(info->zone()), | 2121 zone_(info->zone()), |
| 2102 is_recursive_(false), | 2122 is_recursive_(false), |
| 2103 use_optimistic_licm_(false), | 2123 use_optimistic_licm_(false), |
| 2104 has_soft_deoptimize_(false), | 2124 has_soft_deoptimize_(false), |
| 2105 depends_on_empty_array_proto_elements_(false), | 2125 depends_on_empty_array_proto_elements_(false), |
| 2106 type_change_checksum_(0) { | 2126 type_change_checksum_(0), |
| 2127 maximum_environment_size_(0) { |
| 2107 if (info->IsStub()) { | 2128 if (info->IsStub()) { |
| 2108 HydrogenCodeStub* stub = info->code_stub(); | 2129 HydrogenCodeStub* stub = info->code_stub(); |
| 2109 CodeStubInterfaceDescriptor* descriptor = | 2130 CodeStubInterfaceDescriptor* descriptor = |
| 2110 stub->GetInterfaceDescriptor(isolate_); | 2131 stub->GetInterfaceDescriptor(isolate_); |
| 2111 start_environment_ = | 2132 start_environment_ = |
| 2112 new(zone_) HEnvironment(zone_, descriptor->environment_length()); | 2133 new(zone_) HEnvironment(zone_, descriptor->environment_length()); |
| 2113 } else { | 2134 } else { |
| 2114 start_environment_ = | 2135 start_environment_ = |
| 2115 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); | 2136 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); |
| 2116 } | 2137 } |
| (...skipping 2307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4424 function_return_(NULL), | 4445 function_return_(NULL), |
| 4425 test_context_(NULL), | 4446 test_context_(NULL), |
| 4426 entry_(NULL), | 4447 entry_(NULL), |
| 4427 arguments_elements_(NULL), | 4448 arguments_elements_(NULL), |
| 4428 outer_(owner->function_state()) { | 4449 outer_(owner->function_state()) { |
| 4429 if (outer_ != NULL) { | 4450 if (outer_ != NULL) { |
| 4430 // State for an inline function. | 4451 // State for an inline function. |
| 4431 if (owner->ast_context()->IsTest()) { | 4452 if (owner->ast_context()->IsTest()) { |
| 4432 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); | 4453 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); |
| 4433 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); | 4454 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); |
| 4434 if_true->MarkAsInlineReturnTarget(); | 4455 if_true->MarkAsInlineReturnTarget(owner->current_block()); |
| 4435 if_false->MarkAsInlineReturnTarget(); | 4456 if_false->MarkAsInlineReturnTarget(owner->current_block()); |
| 4436 TestContext* outer_test_context = TestContext::cast(owner->ast_context()); | 4457 TestContext* outer_test_context = TestContext::cast(owner->ast_context()); |
| 4437 Expression* cond = outer_test_context->condition(); | 4458 Expression* cond = outer_test_context->condition(); |
| 4438 TypeFeedbackOracle* outer_oracle = outer_test_context->oracle(); | 4459 TypeFeedbackOracle* outer_oracle = outer_test_context->oracle(); |
| 4439 // The AstContext constructor pushed on the context stack. This newed | 4460 // The AstContext constructor pushed on the context stack. This newed |
| 4440 // instance is the reason that AstContext can't be BASE_EMBEDDED. | 4461 // instance is the reason that AstContext can't be BASE_EMBEDDED. |
| 4441 test_context_ = | 4462 test_context_ = |
| 4442 new TestContext(owner, cond, outer_oracle, if_true, if_false); | 4463 new TestContext(owner, cond, outer_oracle, if_true, if_false); |
| 4443 } else { | 4464 } else { |
| 4444 function_return_ = owner->graph()->CreateBasicBlock(); | 4465 function_return_ = owner->graph()->CreateBasicBlock(); |
| 4445 function_return()->MarkAsInlineReturnTarget(); | 4466 function_return()->MarkAsInlineReturnTarget(owner->current_block()); |
| 4446 } | 4467 } |
| 4447 // Set this after possibly allocating a new TestContext above. | 4468 // Set this after possibly allocating a new TestContext above. |
| 4448 call_context_ = owner->ast_context(); | 4469 call_context_ = owner->ast_context(); |
| 4449 } | 4470 } |
| 4450 | 4471 |
| 4451 // Push on the state stack. | 4472 // Push on the state stack. |
| 4452 owner->set_function_state(this); | 4473 owner->set_function_state(this); |
| 4453 } | 4474 } |
| 4454 | 4475 |
| 4455 | 4476 |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4855 // zero-valued constant in the graph together. | 4876 // zero-valued constant in the graph together. |
| 4856 // The constant is needed to make idef-based bounds check work: the pass | 4877 // The constant is needed to make idef-based bounds check work: the pass |
| 4857 // evaluates relations with "zero" and that zero cannot be created after GVN. | 4878 // evaluates relations with "zero" and that zero cannot be created after GVN. |
| 4858 GetConstant0(); | 4879 GetConstant0(); |
| 4859 | 4880 |
| 4860 #ifdef DEBUG | 4881 #ifdef DEBUG |
| 4861 // Do a full verify after building the graph and computing dominators. | 4882 // Do a full verify after building the graph and computing dominators. |
| 4862 Verify(true); | 4883 Verify(true); |
| 4863 #endif | 4884 #endif |
| 4864 | 4885 |
| 4886 if (FLAG_analyze_environment_liveness) { |
| 4887 EnvironmentSlotLivenessAnalyzer esla(this); |
| 4888 esla.AnalyzeAndTrim(); |
| 4889 } |
| 4890 |
| 4865 PropagateDeoptimizingMark(); | 4891 PropagateDeoptimizingMark(); |
| 4866 if (!CheckConstPhiUses()) { | 4892 if (!CheckConstPhiUses()) { |
| 4867 *bailout_reason = SmartArrayPointer<char>(StrDup( | 4893 *bailout_reason = SmartArrayPointer<char>(StrDup( |
| 4868 "Unsupported phi use of const variable")); | 4894 "Unsupported phi use of const variable")); |
| 4869 return false; | 4895 return false; |
| 4870 } | 4896 } |
| 4871 EliminateRedundantPhis(); | 4897 EliminateRedundantPhis(); |
| 4872 if (!CheckArgumentsPhiUses()) { | 4898 if (!CheckArgumentsPhiUses()) { |
| 4873 *bailout_reason = SmartArrayPointer<char>(StrDup( | 4899 *bailout_reason = SmartArrayPointer<char>(StrDup( |
| 4874 "Unsupported phi use of arguments")); | 4900 "Unsupported phi use of arguments")); |
| (...skipping 1671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6546 global_object, | 6572 global_object, |
| 6547 variable->name(), | 6573 variable->name(), |
| 6548 ast_context()->is_for_typeof()); | 6574 ast_context()->is_for_typeof()); |
| 6549 instr->set_position(expr->position()); | 6575 instr->set_position(expr->position()); |
| 6550 return ast_context()->ReturnInstruction(instr, expr->id()); | 6576 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 6551 } | 6577 } |
| 6552 } | 6578 } |
| 6553 | 6579 |
| 6554 case Variable::PARAMETER: | 6580 case Variable::PARAMETER: |
| 6555 case Variable::LOCAL: { | 6581 case Variable::LOCAL: { |
| 6556 HValue* value = environment()->Lookup(variable); | 6582 HValue* value = LookupAndMakeLive(variable); |
| 6557 if (value == graph()->GetConstantHole()) { | 6583 if (value == graph()->GetConstantHole()) { |
| 6558 ASSERT(IsDeclaredVariableMode(variable->mode()) && | 6584 ASSERT(IsDeclaredVariableMode(variable->mode()) && |
| 6559 variable->mode() != VAR); | 6585 variable->mode() != VAR); |
| 6560 return Bailout("reference to uninitialized variable"); | 6586 return Bailout("reference to uninitialized variable"); |
| 6561 } | 6587 } |
| 6562 return ast_context()->ReturnValue(value); | 6588 return ast_context()->ReturnValue(value); |
| 6563 } | 6589 } |
| 6564 | 6590 |
| 6565 case Variable::CONTEXT: { | 6591 case Variable::CONTEXT: { |
| 6566 HValue* context = BuildContextChainWalk(variable); | 6592 HValue* context = BuildContextChainWalk(variable); |
| (...skipping 979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7546 Top(), | 7572 Top(), |
| 7547 expr->position(), | 7573 expr->position(), |
| 7548 expr->AssignmentId()); | 7574 expr->AssignmentId()); |
| 7549 break; | 7575 break; |
| 7550 | 7576 |
| 7551 case Variable::PARAMETER: | 7577 case Variable::PARAMETER: |
| 7552 case Variable::LOCAL: | 7578 case Variable::LOCAL: |
| 7553 if (var->mode() == CONST) { | 7579 if (var->mode() == CONST) { |
| 7554 return Bailout("unsupported const compound assignment"); | 7580 return Bailout("unsupported const compound assignment"); |
| 7555 } | 7581 } |
| 7556 Bind(var, Top()); | 7582 BindIfLive(var, Top()); |
| 7557 break; | 7583 break; |
| 7558 | 7584 |
| 7559 case Variable::CONTEXT: { | 7585 case Variable::CONTEXT: { |
| 7560 // Bail out if we try to mutate a parameter value in a function | 7586 // Bail out if we try to mutate a parameter value in a function |
| 7561 // using the arguments object. We do not (yet) correctly handle the | 7587 // using the arguments object. We do not (yet) correctly handle the |
| 7562 // arguments property of the function. | 7588 // arguments property of the function. |
| 7563 if (info()->scope()->arguments() != NULL) { | 7589 if (info()->scope()->arguments() != NULL) { |
| 7564 // Parameters will be allocated to context slots. We have no | 7590 // Parameters will be allocated to context slots. We have no |
| 7565 // direct way to detect that the variable is a parameter so we do | 7591 // direct way to detect that the variable is a parameter so we do |
| 7566 // a linear search of the parameter variables. | 7592 // a linear search of the parameter variables. |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7775 HValue* env_value = environment()->Lookup(var); | 7801 HValue* env_value = environment()->Lookup(var); |
| 7776 if (env_value == graph()->GetConstantHole()) { | 7802 if (env_value == graph()->GetConstantHole()) { |
| 7777 return Bailout("assignment to let variable before initialization"); | 7803 return Bailout("assignment to let variable before initialization"); |
| 7778 } | 7804 } |
| 7779 } | 7805 } |
| 7780 // We do not allow the arguments object to occur in a context where it | 7806 // We do not allow the arguments object to occur in a context where it |
| 7781 // may escape, but assignments to stack-allocated locals are | 7807 // may escape, but assignments to stack-allocated locals are |
| 7782 // permitted. | 7808 // permitted. |
| 7783 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); | 7809 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); |
| 7784 HValue* value = Pop(); | 7810 HValue* value = Pop(); |
| 7785 Bind(var, value); | 7811 BindIfLive(var, value); |
| 7786 return ast_context()->ReturnValue(value); | 7812 return ast_context()->ReturnValue(value); |
| 7787 } | 7813 } |
| 7788 | 7814 |
| 7789 case Variable::CONTEXT: { | 7815 case Variable::CONTEXT: { |
| 7790 // Bail out if we try to mutate a parameter value in a function using | 7816 // Bail out if we try to mutate a parameter value in a function using |
| 7791 // the arguments object. We do not (yet) correctly handle the | 7817 // the arguments object. We do not (yet) correctly handle the |
| 7792 // arguments property of the function. | 7818 // arguments property of the function. |
| 7793 if (info()->scope()->arguments() != NULL) { | 7819 if (info()->scope()->arguments() != NULL) { |
| 7794 // Parameters will rewrite to context slots. We have no direct way | 7820 // Parameters will rewrite to context slots. We have no direct way |
| 7795 // to detect that the variable is a parameter. | 7821 // to detect that the variable is a parameter. |
| (...skipping 1199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8995 } | 9021 } |
| 8996 } | 9022 } |
| 8997 | 9023 |
| 8998 HEnterInlined* enter_inlined = | 9024 HEnterInlined* enter_inlined = |
| 8999 new(zone()) HEnterInlined(target, | 9025 new(zone()) HEnterInlined(target, |
| 9000 arguments_count, | 9026 arguments_count, |
| 9001 function, | 9027 function, |
| 9002 function_state()->inlining_kind(), | 9028 function_state()->inlining_kind(), |
| 9003 function->scope()->arguments(), | 9029 function->scope()->arguments(), |
| 9004 arguments_values, | 9030 arguments_values, |
| 9005 undefined_receiver); | 9031 undefined_receiver, |
| 9032 zone()); |
| 9006 function_state()->set_entry(enter_inlined); | 9033 function_state()->set_entry(enter_inlined); |
| 9007 AddInstruction(enter_inlined); | 9034 AddInstruction(enter_inlined); |
| 9008 | 9035 |
| 9009 // If the function uses arguments object create and bind one. | 9036 // If the function uses arguments object create and bind one. |
| 9010 if (function->scope()->arguments() != NULL) { | 9037 if (function->scope()->arguments() != NULL) { |
| 9011 ASSERT(function->scope()->arguments()->IsStackAllocated()); | 9038 ASSERT(function->scope()->arguments()->IsStackAllocated()); |
| 9012 inner_env->Bind(function->scope()->arguments(), | 9039 inner_env->Bind(function->scope()->arguments(), |
| 9013 graph()->GetArgumentsObject()); | 9040 graph()->GetArgumentsObject()); |
| 9014 } | 9041 } |
| 9015 | 9042 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9074 current_block()->AddLeaveInlined(undefined, state); | 9101 current_block()->AddLeaveInlined(undefined, state); |
| 9075 } | 9102 } |
| 9076 } | 9103 } |
| 9077 } | 9104 } |
| 9078 | 9105 |
| 9079 // Fix up the function exits. | 9106 // Fix up the function exits. |
| 9080 if (inlined_test_context() != NULL) { | 9107 if (inlined_test_context() != NULL) { |
| 9081 HBasicBlock* if_true = inlined_test_context()->if_true(); | 9108 HBasicBlock* if_true = inlined_test_context()->if_true(); |
| 9082 HBasicBlock* if_false = inlined_test_context()->if_false(); | 9109 HBasicBlock* if_false = inlined_test_context()->if_false(); |
| 9083 | 9110 |
| 9111 HEnterInlined* entry = function_state()->entry(); |
| 9112 |
| 9084 // Pop the return test context from the expression context stack. | 9113 // Pop the return test context from the expression context stack. |
| 9085 ASSERT(ast_context() == inlined_test_context()); | 9114 ASSERT(ast_context() == inlined_test_context()); |
| 9086 ClearInlinedTestContext(); | 9115 ClearInlinedTestContext(); |
| 9087 delete target_state; | 9116 delete target_state; |
| 9088 | 9117 |
| 9089 // Forward to the real test context. | 9118 // Forward to the real test context. |
| 9090 if (if_true->HasPredecessor()) { | 9119 if (if_true->HasPredecessor()) { |
| 9120 entry->RegisterReturnTarget(if_true, zone()); |
| 9091 if_true->SetJoinId(ast_id); | 9121 if_true->SetJoinId(ast_id); |
| 9092 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); | 9122 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); |
| 9093 if_true->Goto(true_target, function_state()); | 9123 if_true->Goto(true_target, function_state()); |
| 9094 } | 9124 } |
| 9095 if (if_false->HasPredecessor()) { | 9125 if (if_false->HasPredecessor()) { |
| 9126 entry->RegisterReturnTarget(if_false, zone()); |
| 9096 if_false->SetJoinId(ast_id); | 9127 if_false->SetJoinId(ast_id); |
| 9097 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); | 9128 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); |
| 9098 if_false->Goto(false_target, function_state()); | 9129 if_false->Goto(false_target, function_state()); |
| 9099 } | 9130 } |
| 9100 set_current_block(NULL); | 9131 set_current_block(NULL); |
| 9101 return true; | 9132 return true; |
| 9102 | 9133 |
| 9103 } else if (function_return()->HasPredecessor()) { | 9134 } else if (function_return()->HasPredecessor()) { |
| 9135 function_state()->entry()->RegisterReturnTarget(function_return(), zone()); |
| 9104 function_return()->SetJoinId(ast_id); | 9136 function_return()->SetJoinId(ast_id); |
| 9105 set_current_block(function_return()); | 9137 set_current_block(function_return()); |
| 9106 } else { | 9138 } else { |
| 9107 set_current_block(NULL); | 9139 set_current_block(NULL); |
| 9108 } | 9140 } |
| 9109 delete target_state; | 9141 delete target_state; |
| 9110 return true; | 9142 return true; |
| 9111 } | 9143 } |
| 9112 | 9144 |
| 9113 | 9145 |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9400 return false; | 9432 return false; |
| 9401 } | 9433 } |
| 9402 | 9434 |
| 9403 if (info()->scope()->arguments() == NULL) return false; | 9435 if (info()->scope()->arguments() == NULL) return false; |
| 9404 | 9436 |
| 9405 ZoneList<Expression*>* args = expr->arguments(); | 9437 ZoneList<Expression*>* args = expr->arguments(); |
| 9406 if (args->length() != 2) return false; | 9438 if (args->length() != 2) return false; |
| 9407 | 9439 |
| 9408 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); | 9440 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
| 9409 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; | 9441 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
| 9410 HValue* arg_two_value = environment()->Lookup(arg_two->var()); | 9442 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); |
| 9411 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | 9443 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
| 9412 | 9444 |
| 9413 // Found pattern f.apply(receiver, arguments). | 9445 // Found pattern f.apply(receiver, arguments). |
| 9414 VisitForValue(prop->obj()); | 9446 VisitForValue(prop->obj()); |
| 9415 if (HasStackOverflow() || current_block() == NULL) return true; | 9447 if (HasStackOverflow() || current_block() == NULL) return true; |
| 9416 HValue* function = Top(); | 9448 HValue* function = Top(); |
| 9417 AddCheckConstantFunction(expr->holder(), function, function_map); | 9449 AddCheckConstantFunction(expr->holder(), function, function_map); |
| 9418 Drop(1); | 9450 Drop(1); |
| 9419 | 9451 |
| 9420 VisitForValue(args->at(0)); | 9452 VisitForValue(args->at(0)); |
| (...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10111 switch (var->location()) { | 10143 switch (var->location()) { |
| 10112 case Variable::UNALLOCATED: | 10144 case Variable::UNALLOCATED: |
| 10113 HandleGlobalVariableAssignment(var, | 10145 HandleGlobalVariableAssignment(var, |
| 10114 after, | 10146 after, |
| 10115 expr->position(), | 10147 expr->position(), |
| 10116 expr->AssignmentId()); | 10148 expr->AssignmentId()); |
| 10117 break; | 10149 break; |
| 10118 | 10150 |
| 10119 case Variable::PARAMETER: | 10151 case Variable::PARAMETER: |
| 10120 case Variable::LOCAL: | 10152 case Variable::LOCAL: |
| 10121 Bind(var, after); | 10153 BindIfLive(var, after); |
| 10122 break; | 10154 break; |
| 10123 | 10155 |
| 10124 case Variable::CONTEXT: { | 10156 case Variable::CONTEXT: { |
| 10125 // Bail out if we try to mutate a parameter value in a function | 10157 // Bail out if we try to mutate a parameter value in a function |
| 10126 // using the arguments object. We do not (yet) correctly handle the | 10158 // using the arguments object. We do not (yet) correctly handle the |
| 10127 // arguments property of the function. | 10159 // arguments property of the function. |
| 10128 if (info()->scope()->arguments() != NULL) { | 10160 if (info()->scope()->arguments() != NULL) { |
| 10129 // Parameters will rewrite to context slots. We have no direct | 10161 // Parameters will rewrite to context slots. We have no direct |
| 10130 // way to detect that the variable is a parameter so we use a | 10162 // way to detect that the variable is a parameter so we use a |
| 10131 // linear search of the parameter list. | 10163 // linear search of the parameter list. |
| (...skipping 1062 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11194 Compiler::BuildFunctionInfo(declaration->fun(), info()->script()); | 11226 Compiler::BuildFunctionInfo(declaration->fun(), info()->script()); |
| 11195 // Check for stack-overflow exception. | 11227 // Check for stack-overflow exception. |
| 11196 if (function.is_null()) return SetStackOverflow(); | 11228 if (function.is_null()) return SetStackOverflow(); |
| 11197 globals_.Add(function, zone()); | 11229 globals_.Add(function, zone()); |
| 11198 return; | 11230 return; |
| 11199 } | 11231 } |
| 11200 case Variable::PARAMETER: | 11232 case Variable::PARAMETER: |
| 11201 case Variable::LOCAL: { | 11233 case Variable::LOCAL: { |
| 11202 CHECK_ALIVE(VisitForValue(declaration->fun())); | 11234 CHECK_ALIVE(VisitForValue(declaration->fun())); |
| 11203 HValue* value = Pop(); | 11235 HValue* value = Pop(); |
| 11204 environment()->Bind(variable, value); | 11236 BindIfLive(variable, value); |
| 11205 break; | 11237 break; |
| 11206 } | 11238 } |
| 11207 case Variable::CONTEXT: { | 11239 case Variable::CONTEXT: { |
| 11208 CHECK_ALIVE(VisitForValue(declaration->fun())); | 11240 CHECK_ALIVE(VisitForValue(declaration->fun())); |
| 11209 HValue* value = Pop(); | 11241 HValue* value = Pop(); |
| 11210 HValue* context = environment()->LookupContext(); | 11242 HValue* context = environment()->LookupContext(); |
| 11211 HStoreContextSlot* store = new(zone()) HStoreContextSlot( | 11243 HStoreContextSlot* store = new(zone()) HStoreContextSlot( |
| 11212 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 11244 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
| 11213 AddInstruction(store); | 11245 AddInstruction(store); |
| 11214 if (store->HasObservableSideEffects()) { | 11246 if (store->HasObservableSideEffects()) { |
| (...skipping 1256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12471 } | 12503 } |
| 12472 } | 12504 } |
| 12473 | 12505 |
| 12474 #ifdef DEBUG | 12506 #ifdef DEBUG |
| 12475 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 12507 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 12476 if (allocator_ != NULL) allocator_->Verify(); | 12508 if (allocator_ != NULL) allocator_->Verify(); |
| 12477 #endif | 12509 #endif |
| 12478 } | 12510 } |
| 12479 | 12511 |
| 12480 } } // namespace v8::internal | 12512 } } // namespace v8::internal |
| OLD | NEW |