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 |