1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/interpreter/control-flow-builders.h" 6 7 namespace v8 { 8 namespace internal { 9 namespace interpreter { 10 11 12 BreakableControlFlowBuilder::~BreakableControlFlowBuilder() { 13 DCHECK(break_sites_.empty()); 14 } 15 16 17 void BreakableControlFlowBuilder::SetBreakTarget(const BytecodeLabel& target) { 18 BindLabels(target, &break_sites_); 19 } 20 21 22 void BreakableControlFlowBuilder::EmitJump(ZoneVector<BytecodeLabel>* sites) { 23 sites->push_back(BytecodeLabel()); 24 builder()->Jump(&sites->back()); 25 } 26 27 28 void BreakableControlFlowBuilder::EmitJumpIfTrue( 29 ZoneVector<BytecodeLabel>* sites) { 30 sites->push_back(BytecodeLabel()); 31 builder()->JumpIfTrue(&sites->back()); 32 } 33 34 35 void BreakableControlFlowBuilder::EmitJumpIfFalse( 36 ZoneVector<BytecodeLabel>* sites) { 37 sites->push_back(BytecodeLabel()); 38 builder()->JumpIfFalse(&sites->back()); 39 } 40 41 42 void BreakableControlFlowBuilder::EmitJumpIfUndefined( 43 ZoneVector<BytecodeLabel>* sites) { 44 sites->push_back(BytecodeLabel()); 45 builder()->JumpIfUndefined(&sites->back()); 46 } 47 48 49 void BreakableControlFlowBuilder::EmitJumpIfNull( 50 ZoneVector<BytecodeLabel>* sites) { 51 sites->push_back(BytecodeLabel()); 52 builder()->JumpIfNull(&sites->back()); 53 } 54 55 56 void BreakableControlFlowBuilder::EmitJump(ZoneVector<BytecodeLabel>* sites, 57 int index) { 58 builder()->Jump(&sites->at(index)); 59 } 60 61 62 void BreakableControlFlowBuilder::EmitJumpIfTrue( 63 ZoneVector<BytecodeLabel>* sites, int index) { 64 builder()->JumpIfTrue(&sites->at(index)); 65 } 66 67 68 void BreakableControlFlowBuilder::EmitJumpIfFalse( 69 ZoneVector<BytecodeLabel>* sites, int index) { 70 builder()->JumpIfFalse(&sites->at(index)); 71 } 72 73 74 void BreakableControlFlowBuilder::BindLabels(const BytecodeLabel& target, 75 ZoneVector<BytecodeLabel>* sites) { 76 for (size_t i = 0; i < sites->size(); i++) { 77 BytecodeLabel& site = sites->at(i); 78 builder()->Bind(target, &site); 79 } 80 sites->clear(); 81 } 82 83 84 void BlockBuilder::EndBlock() { 85 builder()->Bind(&block_end_); 86 SetBreakTarget(block_end_); 87 } 88 89 90 LoopBuilder::~LoopBuilder() { DCHECK(continue_sites_.empty()); } 91 92 93 void LoopBuilder::LoopHeader(ZoneVector<BytecodeLabel>* additional_labels) { 94 // Jumps from before the loop header into the loop violate ordering 95 // requirements of bytecode basic blocks. The only entry into a loop 96 // must be the loop header. Surely breaks is okay? Not if nested 97 // and misplaced between the headers. 98 DCHECK(break_sites_.empty() && continue_sites_.empty()); 99 builder()->Bind(&loop_header_); 100 for (auto& label : *additional_labels) { 101 builder()->Bind(loop_header_, &label); 102 } 103 } 104 105 106 void LoopBuilder::EndLoop() { 107 // Loop must have closed form, i.e. all loop elements are within the loop, 108 // the loop header precedes the body and next elements in the loop. 109 DCHECK(loop_header_.is_bound()); 110 builder()->Bind(&loop_end_); 111 SetBreakTarget(loop_end_); 112 } 113 114 void LoopBuilder::SetContinueTarget() { 115 BytecodeLabel target; 116 builder()->Bind(&target); 117 BindLabels(target, &continue_sites_); 118 } 119 120 121 SwitchBuilder::~SwitchBuilder() { 122 #ifdef DEBUG 123 for (auto site : case_sites_) { 124 DCHECK(site.is_bound()); 125 } 126 #endif 127 } 128 129 130 void SwitchBuilder::SetCaseTarget(int index) { 131 BytecodeLabel& site = case_sites_.at(index); 132 builder()->Bind(&site); 133 } 134 135 136 void TryCatchBuilder::BeginTry(Register context) { 137 builder()->MarkTryBegin(handler_id_, context); 138 } 139 140 141 void TryCatchBuilder::EndTry() { 142 builder()->MarkTryEnd(handler_id_); 143 builder()->Jump(&exit_); 144 builder()->Bind(&handler_); 145 builder()->MarkHandler(handler_id_, true); 146 } 147 148 149 void TryCatchBuilder::EndCatch() { builder()->Bind(&exit_); } 150 151 152 void TryFinallyBuilder::BeginTry(Register context) { 153 builder()->MarkTryBegin(handler_id_, context); 154 } 155 156 157 void TryFinallyBuilder::LeaveTry() { 158 finalization_sites_.push_back(BytecodeLabel()); 159 builder()->Jump(&finalization_sites_.back()); 160 } 161 162 163 void TryFinallyBuilder::EndTry() { 164 builder()->MarkTryEnd(handler_id_); 165 } 166 167 168 void TryFinallyBuilder::BeginHandler() { 169 builder()->Bind(&handler_); 170 builder()->MarkHandler(handler_id_, will_catch_); 171 } 172 173 174 void TryFinallyBuilder::BeginFinally() { 175 for (size_t i = 0; i < finalization_sites_.size(); i++) { 176 BytecodeLabel& site = finalization_sites_.at(i); 177 builder()->Bind(&site); 178 } 179 } 180 181 182 void TryFinallyBuilder::EndFinally() { 183 // Nothing to be done here. 184 } 185 186 } // namespace interpreter 187 } // namespace internal 188 } // namespace v8 189