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

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: platform ports Created 7 years, 7 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
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 enter_inlined_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,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 189
186 190
187 void HBasicBlock::Goto(HBasicBlock* block, 191 void HBasicBlock::Goto(HBasicBlock* block,
188 FunctionState* state, 192 FunctionState* state,
189 bool add_simulate) { 193 bool add_simulate) {
190 bool drop_extra = state != NULL && 194 bool drop_extra = state != NULL &&
191 state->inlining_kind() == DROP_EXTRA_ON_RETURN; 195 state->inlining_kind() == DROP_EXTRA_ON_RETURN;
192 196
193 if (block->IsInlineReturnTarget()) { 197 if (block->IsInlineReturnTarget()) {
194 AddInstruction(new(zone()) HLeaveInlined()); 198 AddInstruction(new(zone()) HLeaveInlined());
195 last_environment_ = last_environment()->DiscardInlined(drop_extra); 199 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
196 } 200 }
197 201
198 if (add_simulate) AddSimulate(BailoutId::None()); 202 if (add_simulate) AddSimulate(BailoutId::None());
199 HGoto* instr = new(zone()) HGoto(block); 203 HGoto* instr = new(zone()) HGoto(block);
200 Finish(instr); 204 Finish(instr);
201 } 205 }
202 206
203 207
204 void HBasicBlock::AddLeaveInlined(HValue* return_value, 208 void HBasicBlock::AddLeaveInlined(HValue* return_value,
205 FunctionState* state) { 209 FunctionState* state) {
206 HBasicBlock* target = state->function_return(); 210 HBasicBlock* target = state->function_return();
207 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; 211 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN;
208 212
209 ASSERT(target->IsInlineReturnTarget()); 213 ASSERT(target->IsInlineReturnTarget());
210 ASSERT(return_value != NULL); 214 ASSERT(return_value != NULL);
211 AddInstruction(new(zone()) HLeaveInlined()); 215 AddInstruction(new(zone()) HLeaveInlined());
212 last_environment_ = last_environment()->DiscardInlined(drop_extra); 216 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
213 last_environment()->Push(return_value); 217 last_environment()->Push(return_value);
214 AddSimulate(BailoutId::None()); 218 AddSimulate(BailoutId::None());
215 HGoto* instr = new(zone()) HGoto(target); 219 HGoto* instr = new(zone()) HGoto(target);
216 Finish(instr); 220 Finish(instr);
217 } 221 }
218 222
219 223
220 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { 224 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
221 ASSERT(!HasEnvironment()); 225 ASSERT(!HasEnvironment());
222 ASSERT(first() == NULL); 226 ASSERT(first() == NULL);
223 UpdateEnvironment(env); 227 UpdateEnvironment(env);
224 } 228 }
225 229
226 230
231 void HBasicBlock::UpdateEnvironment(HEnvironment* env) {
232 last_environment_ = env;
233 graph()->update_biggest_environment_ever(env->first_expression_index());
234 }
235
236
227 void HBasicBlock::SetJoinId(BailoutId ast_id) { 237 void HBasicBlock::SetJoinId(BailoutId ast_id) {
228 int length = predecessors_.length(); 238 int length = predecessors_.length();
229 ASSERT(length > 0); 239 ASSERT(length > 0);
230 for (int i = 0; i < length; i++) { 240 for (int i = 0; i < length; i++) {
231 HBasicBlock* predecessor = predecessors_[i]; 241 HBasicBlock* predecessor = predecessors_[i];
232 ASSERT(predecessor->end()->IsGoto()); 242 ASSERT(predecessor->end()->IsGoto());
233 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous()); 243 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
234 ASSERT(i != 0 || 244 ASSERT(i != 0 ||
235 (predecessor->last_environment()->closure().is_null() || 245 (predecessor->last_environment()->closure().is_null() ||
236 predecessor->last_environment()->closure()->shared() 246 predecessor->last_environment()->closure()->shared()
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 input_representation); 734 input_representation);
725 compare->AssumeRepresentation(input_representation); 735 compare->AssumeRepresentation(input_representation);
726 AddCompare(compare); 736 AddCompare(compare);
727 return compare; 737 return compare;
728 } 738 }
729 739
730 740
731 HInstruction* HGraphBuilder::IfBuilder::IfCompareMap(HValue* left, 741 HInstruction* HGraphBuilder::IfBuilder::IfCompareMap(HValue* left,
732 Handle<Map> map) { 742 Handle<Map> map) {
733 HCompareMap* compare = 743 HCompareMap* compare =
734 new(zone()) HCompareMap(left, map, 744 new(zone()) HCompareMap(left, map, first_true_block_, first_false_block_);
735 first_true_block_, first_false_block_);
736 AddCompare(compare); 745 AddCompare(compare);
737 return compare; 746 return compare;
738 } 747 }
739 748
740 749
741 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { 750 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) {
742 if (split_edge_merge_block_ != NULL) { 751 if (split_edge_merge_block_ != NULL) {
743 HEnvironment* env = first_false_block_->last_environment(); 752 HEnvironment* env = first_false_block_->last_environment();
744 HBasicBlock* split_edge = 753 HBasicBlock* split_edge =
745 builder_->CreateBasicBlock(env->Copy()); 754 builder_->CreateBasicBlock(env->Copy());
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 End(); 813 End();
805 } 814 }
806 815
807 816
808 void HGraphBuilder::IfBuilder::Then() { 817 void HGraphBuilder::IfBuilder::Then() {
809 ASSERT(!captured_); 818 ASSERT(!captured_);
810 ASSERT(!finished_); 819 ASSERT(!finished_);
811 did_then_ = true; 820 did_then_ = true;
812 if (needs_compare_) { 821 if (needs_compare_) {
813 // Handle if's without any expressions, they jump directly to the "else" 822 // Handle if's without any expressions, they jump directly to the "else"
814 // branch. 823 // branch. However, we must pretend that the "then" branch is reachable.
titzer 2013/05/23 12:34:55 Why must we pretend that it's reachable?
Jakob Kummerow 2013/05/24 09:49:35 So that the graph builder visits it and any enviro
815 builder_->current_block()->GotoNoSimulate(first_false_block_); 824 HConstant* constant_false = builder_->graph()->GetConstantFalse();
816 first_true_block_ = NULL; 825 ToBooleanStub::Types boolean_type = ToBooleanStub::no_types();
826 boolean_type.Add(ToBooleanStub::BOOLEAN);
827 HBranch* branch =
828 new(zone()) HBranch(constant_false, first_true_block_,
829 first_false_block_, boolean_type);
830 builder_->current_block()->Finish(branch);
817 } 831 }
818 builder_->set_current_block(first_true_block_); 832 builder_->set_current_block(first_true_block_);
819 } 833 }
820 834
821 835
822 void HGraphBuilder::IfBuilder::Else() { 836 void HGraphBuilder::IfBuilder::Else() {
823 ASSERT(did_then_); 837 ASSERT(did_then_);
824 ASSERT(!captured_); 838 ASSERT(!captured_);
825 ASSERT(!finished_); 839 ASSERT(!finished_);
826 last_true_block_ = builder_->current_block(); 840 last_true_block_ = builder_->current_block();
(...skipping 1269 matching lines...) Expand 10 before | Expand all | Expand 10 after
2096 blocks_(8, info->zone()), 2110 blocks_(8, info->zone()),
2097 values_(16, info->zone()), 2111 values_(16, info->zone()),
2098 phi_list_(NULL), 2112 phi_list_(NULL),
2099 uint32_instructions_(NULL), 2113 uint32_instructions_(NULL),
2100 info_(info), 2114 info_(info),
2101 zone_(info->zone()), 2115 zone_(info->zone()),
2102 is_recursive_(false), 2116 is_recursive_(false),
2103 use_optimistic_licm_(false), 2117 use_optimistic_licm_(false),
2104 has_soft_deoptimize_(false), 2118 has_soft_deoptimize_(false),
2105 depends_on_empty_array_proto_elements_(false), 2119 depends_on_empty_array_proto_elements_(false),
2106 type_change_checksum_(0) { 2120 type_change_checksum_(0),
2121 biggest_environment_ever_(0) {
2107 if (info->IsStub()) { 2122 if (info->IsStub()) {
2108 HydrogenCodeStub* stub = info->code_stub(); 2123 HydrogenCodeStub* stub = info->code_stub();
2109 CodeStubInterfaceDescriptor* descriptor = 2124 CodeStubInterfaceDescriptor* descriptor =
2110 stub->GetInterfaceDescriptor(isolate_); 2125 stub->GetInterfaceDescriptor(isolate_);
2111 start_environment_ = 2126 start_environment_ =
2112 new(zone_) HEnvironment(zone_, descriptor->environment_length()); 2127 new(zone_) HEnvironment(zone_, descriptor->environment_length());
2113 } else { 2128 } else {
2114 start_environment_ = 2129 start_environment_ =
2115 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); 2130 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
2116 } 2131 }
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
2479 block->AssignLoopSuccessorDominators(); 2494 block->AssignLoopSuccessorDominators();
2480 } else { 2495 } else {
2481 for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) { 2496 for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
2482 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); 2497 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
2483 } 2498 }
2484 } 2499 }
2485 } 2500 }
2486 } 2501 }
2487 2502
2488 2503
2504 void HGraph::ZapEnvironmentSlot(int index, HSimulate* simulate) {
2505 int operand_index = simulate->ToOperandIndex(index);
2506 if (operand_index == -1) {
2507 simulate->AddAssignedValue(index, GetConstantUndefined());
2508 } else {
2509 simulate->SetOperandAt(operand_index, GetConstantUndefined());
2510 }
2511 }
2512
2513
2514 void HGraph::EnvironmentLivenessAnalysis() {
2515 HPhase phase("H_EnvironmentLivenessAnalysis", this);
2516 if (biggest_environment_ever_ == 0) return;
2517 int block_count = blocks()->length();
2518 ZoneList<BitVector*> live_at_block_start(block_count, zone());
2519 ZoneList<HSimulate*> first_simulate(block_count, zone());
2520 BitVector* worklist = new(zone()) BitVector(block_count, zone());
2521 for (int i = 0; i < block_count; ++i) {
2522 live_at_block_start.Add(
2523 new(zone()) BitVector(biggest_environment_ever_, zone()),
2524 zone());
2525 first_simulate.Add(NULL, zone());
2526 worklist->Add(i);
2527 }
2528
2529 // Liveness analysis of environment slots: visit blocks in reverse order,
2530 // walk backwards through each block. We need several passes to propagate
2531 // liveness through nested loops correctly.
2532 // During the main iteration, compute liveness of environment slots, and
2533 // store it for each block until it doesn't change any more.
2534 // Then, in a last pass, zap dead environment slots, and remove the
2535 // HEnvironment{Bind,Lookup} markers.
2536 enum Pass { kIterateUntilFixedPoint, kLastPass, kDone };
2537 Pass pass = kIterateUntilFixedPoint;
2538 BitVector live(biggest_environment_ever_, zone());
2539 while (pass != kDone) {
titzer 2013/05/23 12:34:55 I realize there are some tricky cases inside this
2540 for (int block_id = block_count - 1; block_id >= 0; --block_id) {
2541 if (pass == kIterateUntilFixedPoint && !worklist->Contains(block_id)) {
titzer 2013/05/23 12:34:55 Your loop goes through the block order backwards.
Jakob Kummerow 2013/05/24 09:49:35 I'm explicitly going backwards in order to reduce
2542 continue;
2543 }
2544 worklist->Remove(block_id);
2545
2546 // Liveness at the end of each block: union of liveness in successors.
2547 live.Clear();
2548 HBasicBlock* block = blocks()->at(block_id);
2549 for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) {
2550 live.Union(*live_at_block_start[it.Current()->block_id()]);
2551 }
2552
2553 if (pass == kLastPass) {
2554 // When a value is live in successor A but dead in B, we must
2555 // explicitly zap it in B.
2556 for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) {
2557 HBasicBlock* successor = it.Current();
2558 int successor_id = successor->block_id();
2559 BitVector* live_in_successor = live_at_block_start[successor_id];
2560 if (live_in_successor->Equals(live)) continue;
2561 // Find the first simulate in the successor block.
2562 HSimulate* simulate = NULL;
2563 HInstruction* current = successor->first();
2564 while (current != NULL && simulate == NULL) {
2565 if (current->IsSimulate()) simulate = HSimulate::cast(current);
2566 if (current->IsLeaveInlined()) break;
2567 // No need to check for EnterInlined, because there's always
2568 // a simulate before an EnterInlined.
titzer 2013/05/23 12:34:55 Scary and brittle, and no ASSERT.
Jakob Kummerow 2013/05/24 09:49:35 ASSERT added.
2569 current = current->next();
2570 }
2571 if (simulate == NULL) continue;
2572 for (int i = 0; i < live.length(); ++i) {
2573 if (!live.Contains(i)) continue;
2574 if (live_in_successor->Contains(i)) continue;
2575 ZapEnvironmentSlot(i, simulate);
2576 }
2577 }
2578 }
2579
2580 // Walk the block.
2581 HInstruction* instr = block->last();
2582 HInstruction* next = instr->previous();
2583 HSimulate* last_simulate = NULL;
2584 while (instr != NULL) {
2585 if (instr->IsEnvironmentLookup()) {
2586 // Begins an environment slot's live range.
2587 HEnvironmentLookup* lookup = HEnvironmentLookup::cast(instr);
2588 int index = lookup->index();
2589 if (pass == kLastPass &&
2590 !live.Contains(index) && last_simulate != NULL) {
2591 // The Simulate following the point where the environment value
2592 // dies is extended or modified to zap that value's slot.
2593 ZapEnvironmentSlot(index, last_simulate);
2594 }
2595 live.Add(index);
2596 if (pass == kLastPass) lookup->DeleteAndReplaceWith(NULL);
2597 } else if (instr->IsEnvironmentBind()) {
2598 // Ends an environment slot's live range.
2599 HEnvironmentBind* bind = HEnvironmentBind::cast(instr);
2600 int index = bind->index();
2601 if (pass == 2 && !live.Contains(index) && last_simulate != NULL) {
2602 // Don't bother binding this value if it's never looked up.
2603 ZapEnvironmentSlot(index, last_simulate);
2604 }
2605 live.Remove(index);
2606 if (pass == kLastPass) bind->DeleteAndReplaceWith(NULL);
2607 } else if (instr->IsLeaveInlined()) {
2608 // No environment values are live at the end of an inlined section.
2609 live.Clear();
2610 // Simulates are tied to environments, so last_simulate cannot be
2611 // used for what comes next.
2612 last_simulate = NULL;
2613 } else if (instr->IsEnterInlined()) {
titzer 2013/05/23 12:34:55 There is considerably more going on here than meet
2614 HEnterInlined* enter = HEnterInlined::cast(instr);
2615 // Those environment values are live that are live at any return
2616 // target block. Here we make use of the fact that the end of an
2617 // inline sequence always looks like this: HLeaveInlined, HSimulate,
2618 // HGoto (to return_target block), with no environment lookups in
2619 // between.
2620 live.Clear();
2621 for (int j = 0; j < enter->return_targets()->length(); ++j) {
2622 int return_id = enter->return_targets()->at(j)->block_id();
2623 // When an AbnormalExit is involved, it can happen that the return
2624 // target block doesn't actually exist.
2625 if (return_id < block_count) {
2626 live.Union(*live_at_block_start[return_id]);
2627 }
2628 }
2629 if (pass == kLastPass &&
2630 enter->return_targets()->length() == 1 &&
2631 enter->return_targets()->at(0)->block_id() < block_count) {
2632 last_simulate =
2633 first_simulate.at(enter->return_targets()->at(0)->block_id());
2634 } else {
2635 // Out of luck. We're inlining at a control flow split;
2636 // if we wanted to retrieve the correct last_simulate we'd have to
2637 // compute the corresponding join block, which is non-trivial.
2638 last_simulate = NULL;
2639 }
2640 } else if (instr->IsDeoptimize()) {
2641 // Keep all environment slots alive.
2642 HDeoptimize* deopt = HDeoptimize::cast(instr);
2643 for (int j = deopt->first_local_index();
2644 j < deopt->first_expression_index(); ++j) {
2645 live.Add(j);
2646 }
2647 } else if (instr->IsSimulate()) {
2648 last_simulate = HSimulate::cast(instr);
2649 }
2650 instr = next;
2651 next = (instr != NULL) ? instr->previous() : NULL;
2652 }
2653
2654 // Reached the start of the block, do necessary bookkeeping.
2655 if (pass == kIterateUntilFixedPoint &&
2656 live_at_block_start[block_id]->UnionIsChanged(live)) {
2657 for (int j = 0; j < block->predecessors()->length(); ++j) {
2658 worklist->Add(block->predecessors()->at(j)->block_id());
2659 }
2660 if (block->IsInlineReturnTarget()) {
2661 worklist->Add(block->enter_inlined_block()->block_id());
2662 }
2663 }
2664 first_simulate.Set(block_id, last_simulate);
2665 }
2666 if (pass == kIterateUntilFixedPoint && worklist->IsEmpty()) {
2667 pass = kLastPass;
2668 } else if (pass == kLastPass) {
2669 pass = kDone;
2670 }
2671 }
2672 }
2673
2674
2489 // Mark all blocks that are dominated by an unconditional soft deoptimize to 2675 // Mark all blocks that are dominated by an unconditional soft deoptimize to
2490 // prevent code motion across those blocks. 2676 // prevent code motion across those blocks.
2491 void HGraph::PropagateDeoptimizingMark() { 2677 void HGraph::PropagateDeoptimizingMark() {
2492 HPhase phase("H_Propagate deoptimizing mark", this); 2678 HPhase phase("H_Propagate deoptimizing mark", this);
2493 // Skip this phase if there is nothing to be done anyway. 2679 // Skip this phase if there is nothing to be done anyway.
2494 if (!has_soft_deoptimize()) return; 2680 if (!has_soft_deoptimize()) return;
2495 MarkAsDeoptimizingRecursively(entry_block()); 2681 MarkAsDeoptimizingRecursively(entry_block());
2496 NullifyUnreachableInstructions(); 2682 NullifyUnreachableInstructions();
2497 } 2683 }
2498 2684
(...skipping 1925 matching lines...) Expand 10 before | Expand all | Expand 10 after
4424 function_return_(NULL), 4610 function_return_(NULL),
4425 test_context_(NULL), 4611 test_context_(NULL),
4426 entry_(NULL), 4612 entry_(NULL),
4427 arguments_elements_(NULL), 4613 arguments_elements_(NULL),
4428 outer_(owner->function_state()) { 4614 outer_(owner->function_state()) {
4429 if (outer_ != NULL) { 4615 if (outer_ != NULL) {
4430 // State for an inline function. 4616 // State for an inline function.
4431 if (owner->ast_context()->IsTest()) { 4617 if (owner->ast_context()->IsTest()) {
4432 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); 4618 HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
4433 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); 4619 HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
4434 if_true->MarkAsInlineReturnTarget(); 4620 if_true->MarkAsInlineReturnTarget(owner->current_block());
4435 if_false->MarkAsInlineReturnTarget(); 4621 if_false->MarkAsInlineReturnTarget(owner->current_block());
4436 TestContext* outer_test_context = TestContext::cast(owner->ast_context()); 4622 TestContext* outer_test_context = TestContext::cast(owner->ast_context());
4437 Expression* cond = outer_test_context->condition(); 4623 Expression* cond = outer_test_context->condition();
4438 TypeFeedbackOracle* outer_oracle = outer_test_context->oracle(); 4624 TypeFeedbackOracle* outer_oracle = outer_test_context->oracle();
4439 // The AstContext constructor pushed on the context stack. This newed 4625 // The AstContext constructor pushed on the context stack. This newed
4440 // instance is the reason that AstContext can't be BASE_EMBEDDED. 4626 // instance is the reason that AstContext can't be BASE_EMBEDDED.
4441 test_context_ = 4627 test_context_ =
4442 new TestContext(owner, cond, outer_oracle, if_true, if_false); 4628 new TestContext(owner, cond, outer_oracle, if_true, if_false);
4443 } else { 4629 } else {
4444 function_return_ = owner->graph()->CreateBasicBlock(); 4630 function_return_ = owner->graph()->CreateBasicBlock();
4445 function_return()->MarkAsInlineReturnTarget(); 4631 function_return()->MarkAsInlineReturnTarget(owner->current_block());
4446 } 4632 }
4447 // Set this after possibly allocating a new TestContext above. 4633 // Set this after possibly allocating a new TestContext above.
4448 call_context_ = owner->ast_context(); 4634 call_context_ = owner->ast_context();
4449 } 4635 }
4450 4636
4451 // Push on the state stack. 4637 // Push on the state stack.
4452 owner->set_function_state(this); 4638 owner->set_function_state(this);
4453 } 4639 }
4454 4640
4455 4641
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
4855 // zero-valued constant in the graph together. 5041 // zero-valued constant in the graph together.
4856 // The constant is needed to make idef-based bounds check work: the pass 5042 // 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. 5043 // evaluates relations with "zero" and that zero cannot be created after GVN.
4858 GetConstant0(); 5044 GetConstant0();
4859 5045
4860 #ifdef DEBUG 5046 #ifdef DEBUG
4861 // Do a full verify after building the graph and computing dominators. 5047 // Do a full verify after building the graph and computing dominators.
4862 Verify(true); 5048 Verify(true);
4863 #endif 5049 #endif
4864 5050
5051 EnvironmentLivenessAnalysis();
titzer 2013/05/23 12:34:55 This phase should be guarded by a flag, and should
Jakob Kummerow 2013/05/24 09:49:35 Done. Side note: "DeadCodeElimination" isn't a ver
5052
4865 PropagateDeoptimizingMark(); 5053 PropagateDeoptimizingMark();
4866 if (!CheckConstPhiUses()) { 5054 if (!CheckConstPhiUses()) {
4867 *bailout_reason = SmartArrayPointer<char>(StrDup( 5055 *bailout_reason = SmartArrayPointer<char>(StrDup(
4868 "Unsupported phi use of const variable")); 5056 "Unsupported phi use of const variable"));
4869 return false; 5057 return false;
4870 } 5058 }
4871 EliminateRedundantPhis(); 5059 EliminateRedundantPhis();
4872 if (!CheckArgumentsPhiUses()) { 5060 if (!CheckArgumentsPhiUses()) {
4873 *bailout_reason = SmartArrayPointer<char>(StrDup( 5061 *bailout_reason = SmartArrayPointer<char>(StrDup(
4874 "Unsupported phi use of arguments")); 5062 "Unsupported phi use of arguments"));
(...skipping 1671 matching lines...) Expand 10 before | Expand all | Expand 10 after
6546 global_object, 6734 global_object,
6547 variable->name(), 6735 variable->name(),
6548 ast_context()->is_for_typeof()); 6736 ast_context()->is_for_typeof());
6549 instr->set_position(expr->position()); 6737 instr->set_position(expr->position());
6550 return ast_context()->ReturnInstruction(instr, expr->id()); 6738 return ast_context()->ReturnInstruction(instr, expr->id());
6551 } 6739 }
6552 } 6740 }
6553 6741
6554 case Variable::PARAMETER: 6742 case Variable::PARAMETER:
6555 case Variable::LOCAL: { 6743 case Variable::LOCAL: {
6556 HValue* value = environment()->Lookup(variable); 6744 HValue* value = LookupAndMakeLive(variable);
6557 if (value == graph()->GetConstantHole()) { 6745 if (value == graph()->GetConstantHole()) {
6558 ASSERT(IsDeclaredVariableMode(variable->mode()) && 6746 ASSERT(IsDeclaredVariableMode(variable->mode()) &&
6559 variable->mode() != VAR); 6747 variable->mode() != VAR);
6560 return Bailout("reference to uninitialized variable"); 6748 return Bailout("reference to uninitialized variable");
6561 } 6749 }
6562 return ast_context()->ReturnValue(value); 6750 return ast_context()->ReturnValue(value);
6563 } 6751 }
6564 6752
6565 case Variable::CONTEXT: { 6753 case Variable::CONTEXT: {
6566 HValue* context = BuildContextChainWalk(variable); 6754 HValue* context = BuildContextChainWalk(variable);
(...skipping 979 matching lines...) Expand 10 before | Expand all | Expand 10 after
7546 Top(), 7734 Top(),
7547 expr->position(), 7735 expr->position(),
7548 expr->AssignmentId()); 7736 expr->AssignmentId());
7549 break; 7737 break;
7550 7738
7551 case Variable::PARAMETER: 7739 case Variable::PARAMETER:
7552 case Variable::LOCAL: 7740 case Variable::LOCAL:
7553 if (var->mode() == CONST) { 7741 if (var->mode() == CONST) {
7554 return Bailout("unsupported const compound assignment"); 7742 return Bailout("unsupported const compound assignment");
7555 } 7743 }
7556 Bind(var, Top()); 7744 BindIfLive(var, Top());
7557 break; 7745 break;
7558 7746
7559 case Variable::CONTEXT: { 7747 case Variable::CONTEXT: {
7560 // Bail out if we try to mutate a parameter value in a function 7748 // 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 7749 // using the arguments object. We do not (yet) correctly handle the
7562 // arguments property of the function. 7750 // arguments property of the function.
7563 if (info()->scope()->arguments() != NULL) { 7751 if (info()->scope()->arguments() != NULL) {
7564 // Parameters will be allocated to context slots. We have no 7752 // Parameters will be allocated to context slots. We have no
7565 // direct way to detect that the variable is a parameter so we do 7753 // direct way to detect that the variable is a parameter so we do
7566 // a linear search of the parameter variables. 7754 // 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); 7963 HValue* env_value = environment()->Lookup(var);
7776 if (env_value == graph()->GetConstantHole()) { 7964 if (env_value == graph()->GetConstantHole()) {
7777 return Bailout("assignment to let variable before initialization"); 7965 return Bailout("assignment to let variable before initialization");
7778 } 7966 }
7779 } 7967 }
7780 // We do not allow the arguments object to occur in a context where it 7968 // We do not allow the arguments object to occur in a context where it
7781 // may escape, but assignments to stack-allocated locals are 7969 // may escape, but assignments to stack-allocated locals are
7782 // permitted. 7970 // permitted.
7783 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); 7971 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
7784 HValue* value = Pop(); 7972 HValue* value = Pop();
7785 Bind(var, value); 7973 BindIfLive(var, value);
7786 return ast_context()->ReturnValue(value); 7974 return ast_context()->ReturnValue(value);
7787 } 7975 }
7788 7976
7789 case Variable::CONTEXT: { 7977 case Variable::CONTEXT: {
7790 // Bail out if we try to mutate a parameter value in a function using 7978 // 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 7979 // the arguments object. We do not (yet) correctly handle the
7792 // arguments property of the function. 7980 // arguments property of the function.
7793 if (info()->scope()->arguments() != NULL) { 7981 if (info()->scope()->arguments() != NULL) {
7794 // Parameters will rewrite to context slots. We have no direct way 7982 // Parameters will rewrite to context slots. We have no direct way
7795 // to detect that the variable is a parameter. 7983 // to detect that the variable is a parameter.
(...skipping 1199 matching lines...) Expand 10 before | Expand all | Expand 10 after
8995 } 9183 }
8996 } 9184 }
8997 9185
8998 HEnterInlined* enter_inlined = 9186 HEnterInlined* enter_inlined =
8999 new(zone()) HEnterInlined(target, 9187 new(zone()) HEnterInlined(target,
9000 arguments_count, 9188 arguments_count,
9001 function, 9189 function,
9002 function_state()->inlining_kind(), 9190 function_state()->inlining_kind(),
9003 function->scope()->arguments(), 9191 function->scope()->arguments(),
9004 arguments_values, 9192 arguments_values,
9005 undefined_receiver); 9193 undefined_receiver,
9194 zone());
9006 function_state()->set_entry(enter_inlined); 9195 function_state()->set_entry(enter_inlined);
9007 AddInstruction(enter_inlined); 9196 AddInstruction(enter_inlined);
9008 9197
9009 // If the function uses arguments object create and bind one. 9198 // If the function uses arguments object create and bind one.
9010 if (function->scope()->arguments() != NULL) { 9199 if (function->scope()->arguments() != NULL) {
9011 ASSERT(function->scope()->arguments()->IsStackAllocated()); 9200 ASSERT(function->scope()->arguments()->IsStackAllocated());
9012 inner_env->Bind(function->scope()->arguments(), 9201 inner_env->Bind(function->scope()->arguments(),
9013 graph()->GetArgumentsObject()); 9202 graph()->GetArgumentsObject());
9014 } 9203 }
9015 9204
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
9074 current_block()->AddLeaveInlined(undefined, state); 9263 current_block()->AddLeaveInlined(undefined, state);
9075 } 9264 }
9076 } 9265 }
9077 } 9266 }
9078 9267
9079 // Fix up the function exits. 9268 // Fix up the function exits.
9080 if (inlined_test_context() != NULL) { 9269 if (inlined_test_context() != NULL) {
9081 HBasicBlock* if_true = inlined_test_context()->if_true(); 9270 HBasicBlock* if_true = inlined_test_context()->if_true();
9082 HBasicBlock* if_false = inlined_test_context()->if_false(); 9271 HBasicBlock* if_false = inlined_test_context()->if_false();
9083 9272
9273 HEnterInlined* entry = function_state()->entry();
9274
9084 // Pop the return test context from the expression context stack. 9275 // Pop the return test context from the expression context stack.
9085 ASSERT(ast_context() == inlined_test_context()); 9276 ASSERT(ast_context() == inlined_test_context());
9086 ClearInlinedTestContext(); 9277 ClearInlinedTestContext();
9087 delete target_state; 9278 delete target_state;
9088 9279
9089 // Forward to the real test context. 9280 // Forward to the real test context.
9090 if (if_true->HasPredecessor()) { 9281 if (if_true->HasPredecessor()) {
9282 entry->RegisterReturnTarget(if_true, zone());
9091 if_true->SetJoinId(ast_id); 9283 if_true->SetJoinId(ast_id);
9092 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 9284 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
9093 if_true->Goto(true_target, function_state()); 9285 if_true->Goto(true_target, function_state());
9094 } 9286 }
9095 if (if_false->HasPredecessor()) { 9287 if (if_false->HasPredecessor()) {
9288 entry->RegisterReturnTarget(if_false, zone());
9096 if_false->SetJoinId(ast_id); 9289 if_false->SetJoinId(ast_id);
9097 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 9290 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
9098 if_false->Goto(false_target, function_state()); 9291 if_false->Goto(false_target, function_state());
9099 } 9292 }
9100 set_current_block(NULL); 9293 set_current_block(NULL);
9101 return true; 9294 return true;
9102 9295
9103 } else if (function_return()->HasPredecessor()) { 9296 } else if (function_return()->HasPredecessor()) {
9297 function_state()->entry()->RegisterReturnTarget(function_return(), zone());
9104 function_return()->SetJoinId(ast_id); 9298 function_return()->SetJoinId(ast_id);
9105 set_current_block(function_return()); 9299 set_current_block(function_return());
9106 } else { 9300 } else {
9107 set_current_block(NULL); 9301 set_current_block(NULL);
9108 } 9302 }
9109 delete target_state; 9303 delete target_state;
9110 return true; 9304 return true;
9111 } 9305 }
9112 9306
9113 9307
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
9400 return false; 9594 return false;
9401 } 9595 }
9402 9596
9403 if (info()->scope()->arguments() == NULL) return false; 9597 if (info()->scope()->arguments() == NULL) return false;
9404 9598
9405 ZoneList<Expression*>* args = expr->arguments(); 9599 ZoneList<Expression*>* args = expr->arguments();
9406 if (args->length() != 2) return false; 9600 if (args->length() != 2) return false;
9407 9601
9408 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 9602 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
9409 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; 9603 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
9410 HValue* arg_two_value = environment()->Lookup(arg_two->var()); 9604 HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
9411 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; 9605 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
9412 9606
9413 // Found pattern f.apply(receiver, arguments). 9607 // Found pattern f.apply(receiver, arguments).
9414 VisitForValue(prop->obj()); 9608 VisitForValue(prop->obj());
9415 if (HasStackOverflow() || current_block() == NULL) return true; 9609 if (HasStackOverflow() || current_block() == NULL) return true;
9416 HValue* function = Top(); 9610 HValue* function = Top();
9417 AddCheckConstantFunction(expr->holder(), function, function_map); 9611 AddCheckConstantFunction(expr->holder(), function, function_map);
9418 Drop(1); 9612 Drop(1);
9419 9613
9420 VisitForValue(args->at(0)); 9614 VisitForValue(args->at(0));
(...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after
10111 switch (var->location()) { 10305 switch (var->location()) {
10112 case Variable::UNALLOCATED: 10306 case Variable::UNALLOCATED:
10113 HandleGlobalVariableAssignment(var, 10307 HandleGlobalVariableAssignment(var,
10114 after, 10308 after,
10115 expr->position(), 10309 expr->position(),
10116 expr->AssignmentId()); 10310 expr->AssignmentId());
10117 break; 10311 break;
10118 10312
10119 case Variable::PARAMETER: 10313 case Variable::PARAMETER:
10120 case Variable::LOCAL: 10314 case Variable::LOCAL:
10121 Bind(var, after); 10315 BindIfLive(var, after);
10122 break; 10316 break;
10123 10317
10124 case Variable::CONTEXT: { 10318 case Variable::CONTEXT: {
10125 // Bail out if we try to mutate a parameter value in a function 10319 // 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 10320 // using the arguments object. We do not (yet) correctly handle the
10127 // arguments property of the function. 10321 // arguments property of the function.
10128 if (info()->scope()->arguments() != NULL) { 10322 if (info()->scope()->arguments() != NULL) {
10129 // Parameters will rewrite to context slots. We have no direct 10323 // Parameters will rewrite to context slots. We have no direct
10130 // way to detect that the variable is a parameter so we use a 10324 // way to detect that the variable is a parameter so we use a
10131 // linear search of the parameter list. 10325 // 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()); 11388 Compiler::BuildFunctionInfo(declaration->fun(), info()->script());
11195 // Check for stack-overflow exception. 11389 // Check for stack-overflow exception.
11196 if (function.is_null()) return SetStackOverflow(); 11390 if (function.is_null()) return SetStackOverflow();
11197 globals_.Add(function, zone()); 11391 globals_.Add(function, zone());
11198 return; 11392 return;
11199 } 11393 }
11200 case Variable::PARAMETER: 11394 case Variable::PARAMETER:
11201 case Variable::LOCAL: { 11395 case Variable::LOCAL: {
11202 CHECK_ALIVE(VisitForValue(declaration->fun())); 11396 CHECK_ALIVE(VisitForValue(declaration->fun()));
11203 HValue* value = Pop(); 11397 HValue* value = Pop();
11204 environment()->Bind(variable, value); 11398 BindIfLive(variable, value);
11205 break; 11399 break;
11206 } 11400 }
11207 case Variable::CONTEXT: { 11401 case Variable::CONTEXT: {
11208 CHECK_ALIVE(VisitForValue(declaration->fun())); 11402 CHECK_ALIVE(VisitForValue(declaration->fun()));
11209 HValue* value = Pop(); 11403 HValue* value = Pop();
11210 HValue* context = environment()->LookupContext(); 11404 HValue* context = environment()->LookupContext();
11211 HStoreContextSlot* store = new(zone()) HStoreContextSlot( 11405 HStoreContextSlot* store = new(zone()) HStoreContextSlot(
11212 context, variable->index(), HStoreContextSlot::kNoCheck, value); 11406 context, variable->index(), HStoreContextSlot::kNoCheck, value);
11213 AddInstruction(store); 11407 AddInstruction(store);
11214 if (store->HasObservableSideEffects()) { 11408 if (store->HasObservableSideEffects()) {
(...skipping 1256 matching lines...) Expand 10 before | Expand all | Expand 10 after
12471 } 12665 }
12472 } 12666 }
12473 12667
12474 #ifdef DEBUG 12668 #ifdef DEBUG
12475 if (graph_ != NULL) graph_->Verify(false); // No full verify. 12669 if (graph_ != NULL) graph_->Verify(false); // No full verify.
12476 if (allocator_ != NULL) allocator_->Verify(); 12670 if (allocator_ != NULL) allocator_->Verify();
12477 #endif 12671 #endif
12478 } 12672 }
12479 12673
12480 } } // namespace v8::internal 12674 } } // namespace v8::internal
OLDNEW
« src/hydrogen.h ('K') | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698