Chromium Code Reviews| 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 |