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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
64 loop_information_(NULL), | 64 loop_information_(NULL), |
65 predecessors_(2, graph->zone()), | 65 predecessors_(2, graph->zone()), |
66 dominator_(NULL), | 66 dominator_(NULL), |
67 dominated_blocks_(4, graph->zone()), | 67 dominated_blocks_(4, graph->zone()), |
68 last_environment_(NULL), | 68 last_environment_(NULL), |
69 argument_count_(-1), | 69 argument_count_(-1), |
70 first_instruction_index_(-1), | 70 first_instruction_index_(-1), |
71 last_instruction_index_(-1), | 71 last_instruction_index_(-1), |
72 deleted_phis_(4, graph->zone()), | 72 deleted_phis_(4, graph->zone()), |
73 parent_loop_header_(NULL), | 73 parent_loop_header_(NULL), |
74 inlined_entry_block_(NULL), | |
74 is_inline_return_target_(false), | 75 is_inline_return_target_(false), |
75 is_deoptimizing_(false), | 76 is_deoptimizing_(false), |
76 dominates_loop_successors_(false), | 77 dominates_loop_successors_(false), |
77 is_osr_entry_(false) { } | 78 is_osr_entry_(false) { } |
78 | 79 |
79 | 80 |
80 Isolate* HBasicBlock::isolate() const { | 81 Isolate* HBasicBlock::isolate() const { |
81 return graph_->isolate(); | 82 return graph_->isolate(); |
82 } | 83 } |
83 | 84 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
123 first_ = last_ = entry; | 124 first_ = last_ = entry; |
124 } | 125 } |
125 instr->InsertAfter(last_); | 126 instr->InsertAfter(last_); |
126 } | 127 } |
127 | 128 |
128 | 129 |
129 HDeoptimize* HBasicBlock::CreateDeoptimize( | 130 HDeoptimize* HBasicBlock::CreateDeoptimize( |
130 HDeoptimize::UseEnvironment has_uses) { | 131 HDeoptimize::UseEnvironment has_uses) { |
131 ASSERT(HasEnvironment()); | 132 ASSERT(HasEnvironment()); |
132 if (has_uses == HDeoptimize::kNoUses) | 133 if (has_uses == HDeoptimize::kNoUses) |
133 return new(zone()) HDeoptimize(0, zone()); | 134 return new(zone()) HDeoptimize(0, 0, 0, zone()); |
134 | 135 |
135 HEnvironment* environment = last_environment(); | 136 HEnvironment* environment = last_environment(); |
136 HDeoptimize* instr = new(zone()) HDeoptimize(environment->length(), zone()); | 137 int first_local_index = environment->first_local_index(); |
138 int first_expression_index = environment->first_expression_index(); | |
139 HDeoptimize* instr = new(zone()) HDeoptimize( | |
140 environment->length(), first_local_index, first_expression_index, zone()); | |
137 for (int i = 0; i < environment->length(); i++) { | 141 for (int i = 0; i < environment->length(); i++) { |
138 HValue* val = environment->values()->at(i); | 142 HValue* val = environment->values()->at(i); |
139 instr->AddEnvironmentValue(val, zone()); | 143 instr->AddEnvironmentValue(val, zone()); |
140 } | 144 } |
141 | 145 |
142 return instr; | 146 return instr; |
143 } | 147 } |
144 | 148 |
145 | 149 |
146 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, | 150 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, |
147 RemovableSimulate removable) { | 151 RemovableSimulate removable) { |
148 ASSERT(HasEnvironment()); | 152 ASSERT(HasEnvironment()); |
149 HEnvironment* environment = last_environment(); | 153 HEnvironment* environment = last_environment(); |
150 ASSERT(ast_id.IsNone() || | 154 ASSERT(ast_id.IsNone() || |
151 ast_id == BailoutId::StubEntry() || | 155 ast_id == BailoutId::StubEntry() || |
152 environment->closure()->shared()->VerifyBailoutId(ast_id)); | 156 environment->closure()->shared()->VerifyBailoutId(ast_id)); |
153 | 157 |
154 int push_count = environment->push_count(); | 158 int push_count = environment->push_count(); |
155 int pop_count = environment->pop_count(); | 159 int pop_count = environment->pop_count(); |
156 | 160 |
157 HSimulate* instr = | 161 HSimulate* instr = |
158 new(zone()) HSimulate(ast_id, pop_count, zone(), removable); | 162 new(zone()) HSimulate(ast_id, pop_count, zone(), removable); |
163 #ifdef DEBUG | |
164 instr->set_closure(environment->closure()); | |
165 #endif | |
159 // Order of pushed values: newest (top of stack) first. This allows | 166 // Order of pushed values: newest (top of stack) first. This allows |
160 // HSimulate::MergeInto() to easily append additional pushed values | 167 // HSimulate::MergeInto() to easily append additional pushed values |
161 // that are older (from further down the stack). | 168 // that are older (from further down the stack). |
162 for (int i = 0; i < push_count; ++i) { | 169 for (int i = 0; i < push_count; ++i) { |
163 instr->AddPushedValue(environment->ExpressionStackAt(i)); | 170 instr->AddPushedValue(environment->ExpressionStackAt(i)); |
164 } | 171 } |
165 for (GrowableBitVector::Iterator it(environment->assigned_variables(), | 172 for (GrowableBitVector::Iterator it(environment->assigned_variables(), |
166 zone()); | 173 zone()); |
167 !it.Done(); | 174 !it.Done(); |
168 it.Advance()) { | 175 it.Advance()) { |
(...skipping 16 matching lines...) Expand all Loading... | |
185 | 192 |
186 | 193 |
187 void HBasicBlock::Goto(HBasicBlock* block, | 194 void HBasicBlock::Goto(HBasicBlock* block, |
188 FunctionState* state, | 195 FunctionState* state, |
189 bool add_simulate) { | 196 bool add_simulate) { |
190 bool drop_extra = state != NULL && | 197 bool drop_extra = state != NULL && |
191 state->inlining_kind() == DROP_EXTRA_ON_RETURN; | 198 state->inlining_kind() == DROP_EXTRA_ON_RETURN; |
192 | 199 |
193 if (block->IsInlineReturnTarget()) { | 200 if (block->IsInlineReturnTarget()) { |
194 AddInstruction(new(zone()) HLeaveInlined()); | 201 AddInstruction(new(zone()) HLeaveInlined()); |
195 last_environment_ = last_environment()->DiscardInlined(drop_extra); | 202 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); |
196 } | 203 } |
197 | 204 |
198 if (add_simulate) AddSimulate(BailoutId::None()); | 205 if (add_simulate) AddSimulate(BailoutId::None()); |
199 HGoto* instr = new(zone()) HGoto(block); | 206 HGoto* instr = new(zone()) HGoto(block); |
200 Finish(instr); | 207 Finish(instr); |
201 } | 208 } |
202 | 209 |
203 | 210 |
204 void HBasicBlock::AddLeaveInlined(HValue* return_value, | 211 void HBasicBlock::AddLeaveInlined(HValue* return_value, |
205 FunctionState* state) { | 212 FunctionState* state) { |
206 HBasicBlock* target = state->function_return(); | 213 HBasicBlock* target = state->function_return(); |
207 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; | 214 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; |
208 | 215 |
209 ASSERT(target->IsInlineReturnTarget()); | 216 ASSERT(target->IsInlineReturnTarget()); |
210 ASSERT(return_value != NULL); | 217 ASSERT(return_value != NULL); |
211 AddInstruction(new(zone()) HLeaveInlined()); | 218 AddInstruction(new(zone()) HLeaveInlined()); |
212 last_environment_ = last_environment()->DiscardInlined(drop_extra); | 219 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); |
213 last_environment()->Push(return_value); | 220 last_environment()->Push(return_value); |
214 AddSimulate(BailoutId::None()); | 221 AddSimulate(BailoutId::None()); |
215 HGoto* instr = new(zone()) HGoto(target); | 222 HGoto* instr = new(zone()) HGoto(target); |
216 Finish(instr); | 223 Finish(instr); |
217 } | 224 } |
218 | 225 |
219 | 226 |
220 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { | 227 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { |
221 ASSERT(!HasEnvironment()); | 228 ASSERT(!HasEnvironment()); |
222 ASSERT(first() == NULL); | 229 ASSERT(first() == NULL); |
223 UpdateEnvironment(env); | 230 UpdateEnvironment(env); |
224 } | 231 } |
225 | 232 |
226 | 233 |
234 void HBasicBlock::UpdateEnvironment(HEnvironment* env) { | |
235 last_environment_ = env; | |
236 graph()->update_maximum_environment_size(env->first_expression_index()); | |
237 } | |
238 | |
239 | |
227 void HBasicBlock::SetJoinId(BailoutId ast_id) { | 240 void HBasicBlock::SetJoinId(BailoutId ast_id) { |
228 int length = predecessors_.length(); | 241 int length = predecessors_.length(); |
229 ASSERT(length > 0); | 242 ASSERT(length > 0); |
230 for (int i = 0; i < length; i++) { | 243 for (int i = 0; i < length; i++) { |
231 HBasicBlock* predecessor = predecessors_[i]; | 244 HBasicBlock* predecessor = predecessors_[i]; |
232 ASSERT(predecessor->end()->IsGoto()); | 245 ASSERT(predecessor->end()->IsGoto()); |
233 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous()); | 246 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous()); |
234 ASSERT(i != 0 || | 247 ASSERT(i != 0 || |
235 (predecessor->last_environment()->closure().is_null() || | 248 (predecessor->last_environment()->closure().is_null() || |
236 predecessor->last_environment()->closure()->shared() | 249 predecessor->last_environment()->closure()->shared() |
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
724 input_representation); | 737 input_representation); |
725 compare->AssumeRepresentation(input_representation); | 738 compare->AssumeRepresentation(input_representation); |
726 AddCompare(compare); | 739 AddCompare(compare); |
727 return compare; | 740 return compare; |
728 } | 741 } |
729 | 742 |
730 | 743 |
731 HInstruction* HGraphBuilder::IfBuilder::IfCompareMap(HValue* left, | 744 HInstruction* HGraphBuilder::IfBuilder::IfCompareMap(HValue* left, |
732 Handle<Map> map) { | 745 Handle<Map> map) { |
733 HCompareMap* compare = | 746 HCompareMap* compare = |
734 new(zone()) HCompareMap(left, map, | 747 new(zone()) HCompareMap(left, map, first_true_block_, first_false_block_); |
735 first_true_block_, first_false_block_); | |
736 AddCompare(compare); | 748 AddCompare(compare); |
737 return compare; | 749 return compare; |
738 } | 750 } |
739 | 751 |
740 | 752 |
741 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { | 753 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { |
742 if (split_edge_merge_block_ != NULL) { | 754 if (split_edge_merge_block_ != NULL) { |
743 HEnvironment* env = first_false_block_->last_environment(); | 755 HEnvironment* env = first_false_block_->last_environment(); |
744 HBasicBlock* split_edge = | 756 HBasicBlock* split_edge = |
745 builder_->CreateBasicBlock(env->Copy()); | 757 builder_->CreateBasicBlock(env->Copy()); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
804 End(); | 816 End(); |
805 } | 817 } |
806 | 818 |
807 | 819 |
808 void HGraphBuilder::IfBuilder::Then() { | 820 void HGraphBuilder::IfBuilder::Then() { |
809 ASSERT(!captured_); | 821 ASSERT(!captured_); |
810 ASSERT(!finished_); | 822 ASSERT(!finished_); |
811 did_then_ = true; | 823 did_then_ = true; |
812 if (needs_compare_) { | 824 if (needs_compare_) { |
813 // Handle if's without any expressions, they jump directly to the "else" | 825 // Handle if's without any expressions, they jump directly to the "else" |
814 // branch. | 826 // branch. However, we must pretend that the "then" branch is reachable, |
815 builder_->current_block()->GotoNoSimulate(first_false_block_); | 827 // so that the graph builder visits it and sees any live range extending |
816 first_true_block_ = NULL; | 828 // constructs within it. |
829 HConstant* constant_false = builder_->graph()->GetConstantFalse(); | |
830 ToBooleanStub::Types boolean_type = ToBooleanStub::no_types(); | |
831 boolean_type.Add(ToBooleanStub::BOOLEAN); | |
832 HBranch* branch = | |
833 new(zone()) HBranch(constant_false, first_true_block_, | |
834 first_false_block_, boolean_type); | |
835 builder_->current_block()->Finish(branch); | |
817 } | 836 } |
818 builder_->set_current_block(first_true_block_); | 837 builder_->set_current_block(first_true_block_); |
819 } | 838 } |
820 | 839 |
821 | 840 |
822 void HGraphBuilder::IfBuilder::Else() { | 841 void HGraphBuilder::IfBuilder::Else() { |
823 ASSERT(did_then_); | 842 ASSERT(did_then_); |
824 ASSERT(!captured_); | 843 ASSERT(!captured_); |
825 ASSERT(!finished_); | 844 ASSERT(!finished_); |
826 last_true_block_ = builder_->current_block(); | 845 last_true_block_ = builder_->current_block(); |
(...skipping 1269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2096 blocks_(8, info->zone()), | 2115 blocks_(8, info->zone()), |
2097 values_(16, info->zone()), | 2116 values_(16, info->zone()), |
2098 phi_list_(NULL), | 2117 phi_list_(NULL), |
2099 uint32_instructions_(NULL), | 2118 uint32_instructions_(NULL), |
2100 info_(info), | 2119 info_(info), |
2101 zone_(info->zone()), | 2120 zone_(info->zone()), |
2102 is_recursive_(false), | 2121 is_recursive_(false), |
2103 use_optimistic_licm_(false), | 2122 use_optimistic_licm_(false), |
2104 has_soft_deoptimize_(false), | 2123 has_soft_deoptimize_(false), |
2105 depends_on_empty_array_proto_elements_(false), | 2124 depends_on_empty_array_proto_elements_(false), |
2106 type_change_checksum_(0) { | 2125 type_change_checksum_(0), |
2126 maximum_environment_size_(0) { | |
2107 if (info->IsStub()) { | 2127 if (info->IsStub()) { |
2108 HydrogenCodeStub* stub = info->code_stub(); | 2128 HydrogenCodeStub* stub = info->code_stub(); |
2109 CodeStubInterfaceDescriptor* descriptor = | 2129 CodeStubInterfaceDescriptor* descriptor = |
2110 stub->GetInterfaceDescriptor(isolate_); | 2130 stub->GetInterfaceDescriptor(isolate_); |
2111 start_environment_ = | 2131 start_environment_ = |
2112 new(zone_) HEnvironment(zone_, descriptor->environment_length()); | 2132 new(zone_) HEnvironment(zone_, descriptor->environment_length()); |
2113 } else { | 2133 } else { |
2114 start_environment_ = | 2134 start_environment_ = |
2115 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); | 2135 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); |
2116 } | 2136 } |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2479 block->AssignLoopSuccessorDominators(); | 2499 block->AssignLoopSuccessorDominators(); |
2480 } else { | 2500 } else { |
2481 for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) { | 2501 for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) { |
2482 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); | 2502 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); |
2483 } | 2503 } |
2484 } | 2504 } |
2485 } | 2505 } |
2486 } | 2506 } |
2487 | 2507 |
2488 | 2508 |
2509 HSimulate* HGraph::ZapEnvironmentSlotInNextSimulate(int index, | |
titzer
2013/05/27 11:35:28
In this function, we have to walk forward in the g
| |
2510 HInstruction* from_here) { | |
2511 HInstruction* current = from_here; | |
2512 for (; current != NULL && !current->IsSimulate(); current = current->next()) { | |
2513 if (current->IsLeaveInlined()) return NULL; | |
2514 // There's always a simulate before an EnterInlined. | |
2515 ASSERT(!current->IsEnterInlined()); | |
2516 // Don't zap if a new live range starts before the next simulate. | |
2517 if (current->IsEnvironmentBind() && | |
2518 HEnvironmentBind::cast(current)->index() == index) { | |
2519 return NULL; | |
2520 } | |
2521 } | |
2522 if (current == NULL) return NULL; | |
2523 HSimulate* simulate = HSimulate::cast(current); | |
2524 int operand_index = simulate->ToOperandIndex(index); | |
2525 if (operand_index == -1) { | |
2526 simulate->AddAssignedValue(index, GetConstantUndefined()); | |
2527 } else { | |
2528 simulate->SetOperandAt(operand_index, GetConstantUndefined()); | |
2529 } | |
2530 return simulate; | |
2531 } | |
2532 | |
2533 | |
2534 void HGraph::ZapEnvironmentSlotsInSuccessors( | |
2535 BitVector* live, | |
2536 HBasicBlock* block, | |
2537 ZoneList<BitVector*>* live_at_block_start) { | |
2538 // When a value is live in successor A but dead in B, we must | |
2539 // explicitly zap it in B. | |
2540 for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) { | |
2541 HBasicBlock* successor = it.Current(); | |
2542 int successor_id = successor->block_id(); | |
2543 BitVector* live_in_successor = live_at_block_start->at(successor_id); | |
2544 if (live_in_successor->Equals(*live)) continue; | |
2545 for (int i = 0; i < live->length(); ++i) { | |
2546 if (!live->Contains(i)) continue; | |
2547 if (live_in_successor->Contains(i)) continue; | |
2548 HSimulate* sim = ZapEnvironmentSlotInNextSimulate(i, successor->first()); | |
2549 ASSERT(sim == NULL || | |
2550 sim->closure().is_identical_to( | |
2551 block->last_environment()->closure())); | |
2552 USE(sim); | |
2553 } | |
2554 } | |
2555 } | |
2556 | |
2557 | |
2558 void HGraph::ZapEnvironmentSlotsForInstruction(BitVector* live, | |
2559 HInstruction* instr) { | |
2560 switch (instr->opcode()) { | |
2561 case HValue::kEnvironmentLookup: { | |
2562 int index = HEnvironmentLookup::cast(instr)->index(); | |
2563 if (!live->Contains(index)) { | |
2564 // The Simulate following the point where the environment value | |
2565 // dies is extended or modified to zap that value's slot. | |
2566 HSimulate* sim = ZapEnvironmentSlotInNextSimulate(index, instr->next()); | |
2567 ASSERT(sim == NULL || | |
2568 sim->closure().is_identical_to( | |
2569 HEnvironmentLookup::cast(instr)->closure())); | |
2570 USE(sim); | |
2571 } | |
2572 break; | |
2573 } | |
2574 case HValue::kEnvironmentBind: { | |
2575 int index = HEnvironmentBind::cast(instr)->index(); | |
2576 if (!live->Contains(index)) { | |
2577 // Don't bother binding this value if it's never looked up. | |
2578 HSimulate* sim = ZapEnvironmentSlotInNextSimulate(index, instr->next()); | |
2579 ASSERT(sim == NULL || | |
2580 sim->closure().is_identical_to( | |
2581 HEnvironmentBind::cast(instr)->closure())); | |
2582 USE(sim); | |
2583 } | |
2584 break; | |
2585 } | |
2586 default: | |
2587 break; | |
2588 } | |
2589 } | |
2590 | |
2591 | |
2592 void HGraph::UpdateLivenessAtBlockEnd( | |
2593 BitVector* live, | |
2594 HBasicBlock* block, | |
2595 ZoneList<BitVector*>* live_at_block_start) { | |
2596 // Liveness at the end of each block: union of liveness in successors. | |
2597 live->Clear(); | |
2598 for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) { | |
2599 live->Union(*live_at_block_start->at(it.Current()->block_id())); | |
2600 } | |
2601 } | |
2602 | |
2603 | |
2604 void HGraph::UpdateLivenessAtInstruction( | |
2605 BitVector* live, | |
2606 HInstruction* instr, | |
2607 ZoneList<BitVector*>* live_at_block_start) { | |
2608 switch (instr->opcode()) { | |
2609 case HValue::kEnvironmentLookup: | |
2610 live->Add(HEnvironmentLookup::cast(instr)->index()); | |
2611 break; | |
2612 case HValue::kEnvironmentBind: | |
2613 live->Remove(HEnvironmentBind::cast(instr)->index()); | |
2614 break; | |
2615 case HValue::kLeaveInlined: | |
2616 // No environment values are live at the end of an inlined section. | |
2617 live->Clear(); | |
2618 | |
2619 // The following ASSERTs guard the assumption used in case | |
2620 // kEnterInlined below: | |
2621 ASSERT(instr->next()->IsSimulate()); | |
2622 ASSERT(instr->next()->next()->IsGoto()); | |
2623 | |
2624 break; | |
2625 case HValue::kEnterInlined: { | |
2626 // Those environment values are live that are live at any return | |
2627 // target block. Here we make use of the fact that the end of an | |
2628 // inline sequence always looks like this: HLeaveInlined, HSimulate, | |
2629 // HGoto (to return_target block), with no environment lookups in | |
2630 // between (see ASSERTs above). | |
2631 HEnterInlined* enter = HEnterInlined::cast(instr); | |
2632 live->Clear(); | |
2633 for (int i = 0; i < enter->return_targets()->length(); ++i) { | |
2634 int return_id = enter->return_targets()->at(i)->block_id(); | |
2635 // When an AbnormalExit is involved, it can happen that the return | |
2636 // target block doesn't actually exist. | |
2637 if (return_id < live_at_block_start->length()) { | |
2638 live->Union(*live_at_block_start->at(return_id)); | |
2639 } | |
2640 } | |
2641 break; | |
2642 } | |
2643 case HValue::kDeoptimize: { | |
2644 // Keep all environment slots alive. | |
2645 HDeoptimize* deopt = HDeoptimize::cast(instr); | |
2646 for (int i = deopt->first_local_index(); | |
2647 i < deopt->first_expression_index(); ++i) { | |
2648 live->Add(i); | |
2649 } | |
2650 break; | |
2651 } | |
2652 default: | |
2653 break; | |
2654 } | |
2655 } | |
2656 | |
2657 | |
2658 // Values in the environment are kept alive by every subsequent LInstruction | |
2659 // that is assigned an LEnvironment. This creates register pressure and | |
2660 // unnecessary spill slot moves. Therefore it is beneficial to trim the | |
2661 // live ranges of environment slots by zapping them with a constant after | |
2662 // the last lookup that refers to them. This is similar but not identical | |
2663 // to live range analysis for HValues, so we perform an explicit liveness | |
2664 // analysis on environment slots (identified by their index). | |
2665 // This only affects slots whitelisted by | |
2666 // HOptimizedGraphBuilder::IsEligibleForEnvironmentLivenessAnalysis(). | |
2667 void HGraph::AnalyzeAndPruneEnvironmentLiveness() { | |
2668 HPhase phase("H_EnvironmentLivenessAnalysis", this); | |
2669 if (maximum_environment_size_ == 0) return; | |
2670 int block_count = blocks()->length(); | |
2671 ZoneList<BitVector*> live_at_block_start(block_count, zone()); | |
2672 BitVector* worklist = new(zone()) BitVector(block_count, zone()); | |
2673 for (int i = 0; i < block_count; ++i) { | |
2674 live_at_block_start.Add( | |
2675 new(zone()) BitVector(maximum_environment_size_, zone()), | |
2676 zone()); | |
2677 worklist->Add(i); | |
2678 } | |
2679 BitVector live(maximum_environment_size_, zone()); | |
2680 | |
2681 // Main iteration. Compute liveness of environment slots, and store it | |
2682 // for each block until it doesn't change any more. For efficiency, visit | |
2683 // blocks in reverse order and walk backwards through each block. We | |
2684 // need several iterations to propagate liveness through nested loops. | |
2685 while (!worklist->IsEmpty()) { | |
2686 for (int block_id = block_count - 1; block_id >= 0; --block_id) { | |
2687 if (!worklist->Contains(block_id)) { | |
2688 continue; | |
2689 } | |
2690 worklist->Remove(block_id); | |
2691 | |
2692 HBasicBlock* block = blocks()->at(block_id); | |
2693 UpdateLivenessAtBlockEnd(&live, block, &live_at_block_start); | |
2694 | |
2695 for (HInstruction* instr = block->last(); instr != NULL; | |
2696 instr = instr->previous()) { | |
2697 UpdateLivenessAtInstruction(&live, instr, &live_at_block_start); | |
2698 } | |
2699 | |
2700 // Reached the start of the block, do necessary bookkeeping. | |
2701 if (live_at_block_start[block_id]->UnionIsChanged(live)) { | |
2702 for (int i = 0; i < block->predecessors()->length(); ++i) { | |
2703 worklist->Add(block->predecessors()->at(i)->block_id()); | |
2704 } | |
2705 if (block->IsInlineReturnTarget()) { | |
2706 worklist->Add(block->inlined_entry_block()->block_id()); | |
2707 } | |
2708 } | |
2709 } | |
2710 } | |
2711 | |
2712 // Analysis finished. Zap dead environment slots. | |
titzer
2013/05/27 11:35:28
I don't think we need the last pass over the block
| |
2713 for (int block_id = block_count - 1; block_id >= 0; --block_id) { | |
2714 HBasicBlock* block = blocks()->at(block_id); | |
2715 UpdateLivenessAtBlockEnd(&live, block, &live_at_block_start); | |
2716 ZapEnvironmentSlotsInSuccessors(&live, block, &live_at_block_start); | |
2717 | |
2718 for (HInstruction* instr = block->last(); instr != NULL; | |
2719 instr = instr->previous()) { | |
2720 ZapEnvironmentSlotsForInstruction(&live, instr); | |
2721 UpdateLivenessAtInstruction(&live, instr, &live_at_block_start); | |
2722 } | |
2723 } | |
2724 | |
2725 // Finally, remove the HEnvironment{Bind,Lookup} markers. | |
2726 for (int block_id = block_count - 1; block_id >= 0; --block_id) { | |
2727 HBasicBlock* block = blocks()->at(block_id); | |
2728 for (HInstruction* instr = block->last(); instr != NULL; | |
2729 instr = instr->previous()) { | |
2730 if (instr->IsEnvironmentBind() || instr->IsEnvironmentLookup()) { | |
2731 instr->DeleteAndReplaceWith(NULL); | |
2732 } | |
2733 } | |
2734 } | |
2735 } | |
2736 | |
2737 | |
2489 // Mark all blocks that are dominated by an unconditional soft deoptimize to | 2738 // Mark all blocks that are dominated by an unconditional soft deoptimize to |
2490 // prevent code motion across those blocks. | 2739 // prevent code motion across those blocks. |
2491 void HGraph::PropagateDeoptimizingMark() { | 2740 void HGraph::PropagateDeoptimizingMark() { |
2492 HPhase phase("H_Propagate deoptimizing mark", this); | 2741 HPhase phase("H_Propagate deoptimizing mark", this); |
2493 // Skip this phase if there is nothing to be done anyway. | 2742 // Skip this phase if there is nothing to be done anyway. |
2494 if (!has_soft_deoptimize()) return; | 2743 if (!has_soft_deoptimize()) return; |
2495 MarkAsDeoptimizingRecursively(entry_block()); | 2744 MarkAsDeoptimizingRecursively(entry_block()); |
2496 NullifyUnreachableInstructions(); | 2745 NullifyUnreachableInstructions(); |
2497 } | 2746 } |
2498 | 2747 |
(...skipping 1925 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4424 function_return_(NULL), | 4673 function_return_(NULL), |
4425 test_context_(NULL), | 4674 test_context_(NULL), |
4426 entry_(NULL), | 4675 entry_(NULL), |
4427 arguments_elements_(NULL), | 4676 arguments_elements_(NULL), |
4428 outer_(owner->function_state()) { | 4677 outer_(owner->function_state()) { |
4429 if (outer_ != NULL) { | 4678 if (outer_ != NULL) { |
4430 // State for an inline function. | 4679 // State for an inline function. |
4431 if (owner->ast_context()->IsTest()) { | 4680 if (owner->ast_context()->IsTest()) { |
4432 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); | 4681 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); |
4433 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); | 4682 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); |
4434 if_true->MarkAsInlineReturnTarget(); | 4683 if_true->MarkAsInlineReturnTarget(owner->current_block()); |
4435 if_false->MarkAsInlineReturnTarget(); | 4684 if_false->MarkAsInlineReturnTarget(owner->current_block()); |
4436 TestContext* outer_test_context = TestContext::cast(owner->ast_context()); | 4685 TestContext* outer_test_context = TestContext::cast(owner->ast_context()); |
4437 Expression* cond = outer_test_context->condition(); | 4686 Expression* cond = outer_test_context->condition(); |
4438 TypeFeedbackOracle* outer_oracle = outer_test_context->oracle(); | 4687 TypeFeedbackOracle* outer_oracle = outer_test_context->oracle(); |
4439 // The AstContext constructor pushed on the context stack. This newed | 4688 // The AstContext constructor pushed on the context stack. This newed |
4440 // instance is the reason that AstContext can't be BASE_EMBEDDED. | 4689 // instance is the reason that AstContext can't be BASE_EMBEDDED. |
4441 test_context_ = | 4690 test_context_ = |
4442 new TestContext(owner, cond, outer_oracle, if_true, if_false); | 4691 new TestContext(owner, cond, outer_oracle, if_true, if_false); |
4443 } else { | 4692 } else { |
4444 function_return_ = owner->graph()->CreateBasicBlock(); | 4693 function_return_ = owner->graph()->CreateBasicBlock(); |
4445 function_return()->MarkAsInlineReturnTarget(); | 4694 function_return()->MarkAsInlineReturnTarget(owner->current_block()); |
4446 } | 4695 } |
4447 // Set this after possibly allocating a new TestContext above. | 4696 // Set this after possibly allocating a new TestContext above. |
4448 call_context_ = owner->ast_context(); | 4697 call_context_ = owner->ast_context(); |
4449 } | 4698 } |
4450 | 4699 |
4451 // Push on the state stack. | 4700 // Push on the state stack. |
4452 owner->set_function_state(this); | 4701 owner->set_function_state(this); |
4453 } | 4702 } |
4454 | 4703 |
4455 | 4704 |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4855 // zero-valued constant in the graph together. | 5104 // zero-valued constant in the graph together. |
4856 // The constant is needed to make idef-based bounds check work: the pass | 5105 // 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. | 5106 // evaluates relations with "zero" and that zero cannot be created after GVN. |
4858 GetConstant0(); | 5107 GetConstant0(); |
4859 | 5108 |
4860 #ifdef DEBUG | 5109 #ifdef DEBUG |
4861 // Do a full verify after building the graph and computing dominators. | 5110 // Do a full verify after building the graph and computing dominators. |
4862 Verify(true); | 5111 Verify(true); |
4863 #endif | 5112 #endif |
4864 | 5113 |
5114 if (FLAG_analyze_environment_liveness) { | |
5115 AnalyzeAndPruneEnvironmentLiveness(); | |
5116 } | |
5117 | |
4865 PropagateDeoptimizingMark(); | 5118 PropagateDeoptimizingMark(); |
4866 if (!CheckConstPhiUses()) { | 5119 if (!CheckConstPhiUses()) { |
4867 *bailout_reason = SmartArrayPointer<char>(StrDup( | 5120 *bailout_reason = SmartArrayPointer<char>(StrDup( |
4868 "Unsupported phi use of const variable")); | 5121 "Unsupported phi use of const variable")); |
4869 return false; | 5122 return false; |
4870 } | 5123 } |
4871 EliminateRedundantPhis(); | 5124 EliminateRedundantPhis(); |
4872 if (!CheckArgumentsPhiUses()) { | 5125 if (!CheckArgumentsPhiUses()) { |
4873 *bailout_reason = SmartArrayPointer<char>(StrDup( | 5126 *bailout_reason = SmartArrayPointer<char>(StrDup( |
4874 "Unsupported phi use of arguments")); | 5127 "Unsupported phi use of arguments")); |
(...skipping 1671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6546 global_object, | 6799 global_object, |
6547 variable->name(), | 6800 variable->name(), |
6548 ast_context()->is_for_typeof()); | 6801 ast_context()->is_for_typeof()); |
6549 instr->set_position(expr->position()); | 6802 instr->set_position(expr->position()); |
6550 return ast_context()->ReturnInstruction(instr, expr->id()); | 6803 return ast_context()->ReturnInstruction(instr, expr->id()); |
6551 } | 6804 } |
6552 } | 6805 } |
6553 | 6806 |
6554 case Variable::PARAMETER: | 6807 case Variable::PARAMETER: |
6555 case Variable::LOCAL: { | 6808 case Variable::LOCAL: { |
6556 HValue* value = environment()->Lookup(variable); | 6809 HValue* value = LookupAndMakeLive(variable); |
6557 if (value == graph()->GetConstantHole()) { | 6810 if (value == graph()->GetConstantHole()) { |
6558 ASSERT(IsDeclaredVariableMode(variable->mode()) && | 6811 ASSERT(IsDeclaredVariableMode(variable->mode()) && |
6559 variable->mode() != VAR); | 6812 variable->mode() != VAR); |
6560 return Bailout("reference to uninitialized variable"); | 6813 return Bailout("reference to uninitialized variable"); |
6561 } | 6814 } |
6562 return ast_context()->ReturnValue(value); | 6815 return ast_context()->ReturnValue(value); |
6563 } | 6816 } |
6564 | 6817 |
6565 case Variable::CONTEXT: { | 6818 case Variable::CONTEXT: { |
6566 HValue* context = BuildContextChainWalk(variable); | 6819 HValue* context = BuildContextChainWalk(variable); |
(...skipping 979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7546 Top(), | 7799 Top(), |
7547 expr->position(), | 7800 expr->position(), |
7548 expr->AssignmentId()); | 7801 expr->AssignmentId()); |
7549 break; | 7802 break; |
7550 | 7803 |
7551 case Variable::PARAMETER: | 7804 case Variable::PARAMETER: |
7552 case Variable::LOCAL: | 7805 case Variable::LOCAL: |
7553 if (var->mode() == CONST) { | 7806 if (var->mode() == CONST) { |
7554 return Bailout("unsupported const compound assignment"); | 7807 return Bailout("unsupported const compound assignment"); |
7555 } | 7808 } |
7556 Bind(var, Top()); | 7809 BindIfLive(var, Top()); |
7557 break; | 7810 break; |
7558 | 7811 |
7559 case Variable::CONTEXT: { | 7812 case Variable::CONTEXT: { |
7560 // Bail out if we try to mutate a parameter value in a function | 7813 // 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 | 7814 // using the arguments object. We do not (yet) correctly handle the |
7562 // arguments property of the function. | 7815 // arguments property of the function. |
7563 if (info()->scope()->arguments() != NULL) { | 7816 if (info()->scope()->arguments() != NULL) { |
7564 // Parameters will be allocated to context slots. We have no | 7817 // Parameters will be allocated to context slots. We have no |
7565 // direct way to detect that the variable is a parameter so we do | 7818 // direct way to detect that the variable is a parameter so we do |
7566 // a linear search of the parameter variables. | 7819 // 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); | 8028 HValue* env_value = environment()->Lookup(var); |
7776 if (env_value == graph()->GetConstantHole()) { | 8029 if (env_value == graph()->GetConstantHole()) { |
7777 return Bailout("assignment to let variable before initialization"); | 8030 return Bailout("assignment to let variable before initialization"); |
7778 } | 8031 } |
7779 } | 8032 } |
7780 // We do not allow the arguments object to occur in a context where it | 8033 // We do not allow the arguments object to occur in a context where it |
7781 // may escape, but assignments to stack-allocated locals are | 8034 // may escape, but assignments to stack-allocated locals are |
7782 // permitted. | 8035 // permitted. |
7783 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); | 8036 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); |
7784 HValue* value = Pop(); | 8037 HValue* value = Pop(); |
7785 Bind(var, value); | 8038 BindIfLive(var, value); |
7786 return ast_context()->ReturnValue(value); | 8039 return ast_context()->ReturnValue(value); |
7787 } | 8040 } |
7788 | 8041 |
7789 case Variable::CONTEXT: { | 8042 case Variable::CONTEXT: { |
7790 // Bail out if we try to mutate a parameter value in a function using | 8043 // 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 | 8044 // the arguments object. We do not (yet) correctly handle the |
7792 // arguments property of the function. | 8045 // arguments property of the function. |
7793 if (info()->scope()->arguments() != NULL) { | 8046 if (info()->scope()->arguments() != NULL) { |
7794 // Parameters will rewrite to context slots. We have no direct way | 8047 // Parameters will rewrite to context slots. We have no direct way |
7795 // to detect that the variable is a parameter. | 8048 // to detect that the variable is a parameter. |
(...skipping 1199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8995 } | 9248 } |
8996 } | 9249 } |
8997 | 9250 |
8998 HEnterInlined* enter_inlined = | 9251 HEnterInlined* enter_inlined = |
8999 new(zone()) HEnterInlined(target, | 9252 new(zone()) HEnterInlined(target, |
9000 arguments_count, | 9253 arguments_count, |
9001 function, | 9254 function, |
9002 function_state()->inlining_kind(), | 9255 function_state()->inlining_kind(), |
9003 function->scope()->arguments(), | 9256 function->scope()->arguments(), |
9004 arguments_values, | 9257 arguments_values, |
9005 undefined_receiver); | 9258 undefined_receiver, |
9259 zone()); | |
9006 function_state()->set_entry(enter_inlined); | 9260 function_state()->set_entry(enter_inlined); |
9007 AddInstruction(enter_inlined); | 9261 AddInstruction(enter_inlined); |
9008 | 9262 |
9009 // If the function uses arguments object create and bind one. | 9263 // If the function uses arguments object create and bind one. |
9010 if (function->scope()->arguments() != NULL) { | 9264 if (function->scope()->arguments() != NULL) { |
9011 ASSERT(function->scope()->arguments()->IsStackAllocated()); | 9265 ASSERT(function->scope()->arguments()->IsStackAllocated()); |
9012 inner_env->Bind(function->scope()->arguments(), | 9266 inner_env->Bind(function->scope()->arguments(), |
9013 graph()->GetArgumentsObject()); | 9267 graph()->GetArgumentsObject()); |
9014 } | 9268 } |
9015 | 9269 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9074 current_block()->AddLeaveInlined(undefined, state); | 9328 current_block()->AddLeaveInlined(undefined, state); |
9075 } | 9329 } |
9076 } | 9330 } |
9077 } | 9331 } |
9078 | 9332 |
9079 // Fix up the function exits. | 9333 // Fix up the function exits. |
9080 if (inlined_test_context() != NULL) { | 9334 if (inlined_test_context() != NULL) { |
9081 HBasicBlock* if_true = inlined_test_context()->if_true(); | 9335 HBasicBlock* if_true = inlined_test_context()->if_true(); |
9082 HBasicBlock* if_false = inlined_test_context()->if_false(); | 9336 HBasicBlock* if_false = inlined_test_context()->if_false(); |
9083 | 9337 |
9338 HEnterInlined* entry = function_state()->entry(); | |
9339 | |
9084 // Pop the return test context from the expression context stack. | 9340 // Pop the return test context from the expression context stack. |
9085 ASSERT(ast_context() == inlined_test_context()); | 9341 ASSERT(ast_context() == inlined_test_context()); |
9086 ClearInlinedTestContext(); | 9342 ClearInlinedTestContext(); |
9087 delete target_state; | 9343 delete target_state; |
9088 | 9344 |
9089 // Forward to the real test context. | 9345 // Forward to the real test context. |
9090 if (if_true->HasPredecessor()) { | 9346 if (if_true->HasPredecessor()) { |
9347 entry->RegisterReturnTarget(if_true, zone()); | |
9091 if_true->SetJoinId(ast_id); | 9348 if_true->SetJoinId(ast_id); |
9092 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); | 9349 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); |
9093 if_true->Goto(true_target, function_state()); | 9350 if_true->Goto(true_target, function_state()); |
9094 } | 9351 } |
9095 if (if_false->HasPredecessor()) { | 9352 if (if_false->HasPredecessor()) { |
9353 entry->RegisterReturnTarget(if_false, zone()); | |
9096 if_false->SetJoinId(ast_id); | 9354 if_false->SetJoinId(ast_id); |
9097 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); | 9355 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); |
9098 if_false->Goto(false_target, function_state()); | 9356 if_false->Goto(false_target, function_state()); |
9099 } | 9357 } |
9100 set_current_block(NULL); | 9358 set_current_block(NULL); |
9101 return true; | 9359 return true; |
9102 | 9360 |
9103 } else if (function_return()->HasPredecessor()) { | 9361 } else if (function_return()->HasPredecessor()) { |
9362 function_state()->entry()->RegisterReturnTarget(function_return(), zone()); | |
9104 function_return()->SetJoinId(ast_id); | 9363 function_return()->SetJoinId(ast_id); |
9105 set_current_block(function_return()); | 9364 set_current_block(function_return()); |
9106 } else { | 9365 } else { |
9107 set_current_block(NULL); | 9366 set_current_block(NULL); |
9108 } | 9367 } |
9109 delete target_state; | 9368 delete target_state; |
9110 return true; | 9369 return true; |
9111 } | 9370 } |
9112 | 9371 |
9113 | 9372 |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9400 return false; | 9659 return false; |
9401 } | 9660 } |
9402 | 9661 |
9403 if (info()->scope()->arguments() == NULL) return false; | 9662 if (info()->scope()->arguments() == NULL) return false; |
9404 | 9663 |
9405 ZoneList<Expression*>* args = expr->arguments(); | 9664 ZoneList<Expression*>* args = expr->arguments(); |
9406 if (args->length() != 2) return false; | 9665 if (args->length() != 2) return false; |
9407 | 9666 |
9408 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); | 9667 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
9409 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; | 9668 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
9410 HValue* arg_two_value = environment()->Lookup(arg_two->var()); | 9669 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); |
9411 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | 9670 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
9412 | 9671 |
9413 // Found pattern f.apply(receiver, arguments). | 9672 // Found pattern f.apply(receiver, arguments). |
9414 VisitForValue(prop->obj()); | 9673 VisitForValue(prop->obj()); |
9415 if (HasStackOverflow() || current_block() == NULL) return true; | 9674 if (HasStackOverflow() || current_block() == NULL) return true; |
9416 HValue* function = Top(); | 9675 HValue* function = Top(); |
9417 AddCheckConstantFunction(expr->holder(), function, function_map); | 9676 AddCheckConstantFunction(expr->holder(), function, function_map); |
9418 Drop(1); | 9677 Drop(1); |
9419 | 9678 |
9420 VisitForValue(args->at(0)); | 9679 VisitForValue(args->at(0)); |
(...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10111 switch (var->location()) { | 10370 switch (var->location()) { |
10112 case Variable::UNALLOCATED: | 10371 case Variable::UNALLOCATED: |
10113 HandleGlobalVariableAssignment(var, | 10372 HandleGlobalVariableAssignment(var, |
10114 after, | 10373 after, |
10115 expr->position(), | 10374 expr->position(), |
10116 expr->AssignmentId()); | 10375 expr->AssignmentId()); |
10117 break; | 10376 break; |
10118 | 10377 |
10119 case Variable::PARAMETER: | 10378 case Variable::PARAMETER: |
10120 case Variable::LOCAL: | 10379 case Variable::LOCAL: |
10121 Bind(var, after); | 10380 BindIfLive(var, after); |
10122 break; | 10381 break; |
10123 | 10382 |
10124 case Variable::CONTEXT: { | 10383 case Variable::CONTEXT: { |
10125 // Bail out if we try to mutate a parameter value in a function | 10384 // 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 | 10385 // using the arguments object. We do not (yet) correctly handle the |
10127 // arguments property of the function. | 10386 // arguments property of the function. |
10128 if (info()->scope()->arguments() != NULL) { | 10387 if (info()->scope()->arguments() != NULL) { |
10129 // Parameters will rewrite to context slots. We have no direct | 10388 // Parameters will rewrite to context slots. We have no direct |
10130 // way to detect that the variable is a parameter so we use a | 10389 // way to detect that the variable is a parameter so we use a |
10131 // linear search of the parameter list. | 10390 // 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()); | 11453 Compiler::BuildFunctionInfo(declaration->fun(), info()->script()); |
11195 // Check for stack-overflow exception. | 11454 // Check for stack-overflow exception. |
11196 if (function.is_null()) return SetStackOverflow(); | 11455 if (function.is_null()) return SetStackOverflow(); |
11197 globals_.Add(function, zone()); | 11456 globals_.Add(function, zone()); |
11198 return; | 11457 return; |
11199 } | 11458 } |
11200 case Variable::PARAMETER: | 11459 case Variable::PARAMETER: |
11201 case Variable::LOCAL: { | 11460 case Variable::LOCAL: { |
11202 CHECK_ALIVE(VisitForValue(declaration->fun())); | 11461 CHECK_ALIVE(VisitForValue(declaration->fun())); |
11203 HValue* value = Pop(); | 11462 HValue* value = Pop(); |
11204 environment()->Bind(variable, value); | 11463 BindIfLive(variable, value); |
11205 break; | 11464 break; |
11206 } | 11465 } |
11207 case Variable::CONTEXT: { | 11466 case Variable::CONTEXT: { |
11208 CHECK_ALIVE(VisitForValue(declaration->fun())); | 11467 CHECK_ALIVE(VisitForValue(declaration->fun())); |
11209 HValue* value = Pop(); | 11468 HValue* value = Pop(); |
11210 HValue* context = environment()->LookupContext(); | 11469 HValue* context = environment()->LookupContext(); |
11211 HStoreContextSlot* store = new(zone()) HStoreContextSlot( | 11470 HStoreContextSlot* store = new(zone()) HStoreContextSlot( |
11212 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 11471 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
11213 AddInstruction(store); | 11472 AddInstruction(store); |
11214 if (store->HasObservableSideEffects()) { | 11473 if (store->HasObservableSideEffects()) { |
(...skipping 1256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
12471 } | 12730 } |
12472 } | 12731 } |
12473 | 12732 |
12474 #ifdef DEBUG | 12733 #ifdef DEBUG |
12475 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 12734 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
12476 if (allocator_ != NULL) allocator_->Verify(); | 12735 if (allocator_ != NULL) allocator_->Verify(); |
12477 #endif | 12736 #endif |
12478 } | 12737 } |
12479 | 12738 |
12480 } } // namespace v8::internal | 12739 } } // namespace v8::internal |
OLD | NEW |