Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/hydrogen.cc

Issue 15533004: Liveness analysis for environment slots in Hydrogen (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: fixed bug: markers were deleted too early Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698