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_labels_.empty() || break_labels_.is_bound()); 14 } 15 16 void BreakableControlFlowBuilder::BindBreakTarget() { 17 break_labels_.Bind(builder()); 18 } 19 20 void BreakableControlFlowBuilder::EmitJump(BytecodeLabels* sites) { 21 builder()->Jump(sites->New()); 22 } 23 24 void BreakableControlFlowBuilder::EmitJumpIfTrue(BytecodeLabels* sites) { 25 builder()->JumpIfTrue(sites->New()); 26 } 27 28 void BreakableControlFlowBuilder::EmitJumpIfFalse(BytecodeLabels* sites) { 29 builder()->JumpIfFalse(sites->New()); 30 } 31 32 void BreakableControlFlowBuilder::EmitJumpIfUndefined(BytecodeLabels* sites) { 33 builder()->JumpIfUndefined(sites->New()); 34 } 35 36 void BreakableControlFlowBuilder::EmitJumpIfNull(BytecodeLabels* sites) { 37 builder()->JumpIfNull(sites->New()); 38 } 39 40 41 void BlockBuilder::EndBlock() { 42 builder()->Bind(&block_end_); 43 BindBreakTarget(); 44 } 45 46 LoopBuilder::~LoopBuilder() { 47 DCHECK(continue_labels_.empty() || continue_labels_.is_bound()); 48 DCHECK(header_labels_.empty() || header_labels_.is_bound()); 49 } 50 51 void LoopBuilder::LoopHeader(ZoneVector<BytecodeLabel>* additional_labels) { 52 // Jumps from before the loop header into the loop violate ordering 53 // requirements of bytecode basic blocks. The only entry into a loop 54 // must be the loop header. Surely breaks is okay? Not if nested 55 // and misplaced between the headers. 56 DCHECK(break_labels_.empty() && continue_labels_.empty()); 57 builder()->Bind(&loop_header_); 58 for (auto& label : *additional_labels) { 59 builder()->Bind(&label); 60 } 61 } 62 63 void LoopBuilder::JumpToHeader(int loop_depth) { 64 // Pass the proper loop nesting level to the backwards branch, to trigger 65 // on-stack replacement when armed for the given loop nesting depth. 66 int level = Min(loop_depth, AbstractCode::kMaxLoopNestingMarker - 1); 67 // Loop must have closed form, i.e. all loop elements are within the loop, 68 // the loop header precedes the body and next elements in the loop. 69 DCHECK(loop_header_.is_bound()); 70 builder()->JumpLoop(&loop_header_, level); 71 } 72 73 void LoopBuilder::EndLoop() { 74 BindBreakTarget(); 75 header_labels_.BindToLabel(builder(), loop_header_); 76 } 77 78 void LoopBuilder::BindContinueTarget() { continue_labels_.Bind(builder()); } 79 80 SwitchBuilder::~SwitchBuilder() { 81 #ifdef DEBUG 82 for (auto site : case_sites_) { 83 DCHECK(site.is_bound()); 84 } 85 #endif 86 } 87 88 89 void SwitchBuilder::SetCaseTarget(int index) { 90 BytecodeLabel& site = case_sites_.at(index); 91 builder()->Bind(&site); 92 } 93 94 95 void TryCatchBuilder::BeginTry(Register context) { 96 builder()->MarkTryBegin(handler_id_, context); 97 } 98 99 100 void TryCatchBuilder::EndTry() { 101 builder()->MarkTryEnd(handler_id_); 102 builder()->Jump(&exit_); 103 builder()->Bind(&handler_); 104 builder()->MarkHandler(handler_id_, catch_prediction_); 105 } 106 107 108 void TryCatchBuilder::EndCatch() { builder()->Bind(&exit_); } 109 110 111 void TryFinallyBuilder::BeginTry(Register context) { 112 builder()->MarkTryBegin(handler_id_, context); 113 } 114 115 116 void TryFinallyBuilder::LeaveTry() { 117 builder()->Jump(finalization_sites_.New()); 118 } 119 120 121 void TryFinallyBuilder::EndTry() { 122 builder()->MarkTryEnd(handler_id_); 123 } 124 125 126 void TryFinallyBuilder::BeginHandler() { 127 builder()->Bind(&handler_); 128 builder()->MarkHandler(handler_id_, catch_prediction_); 129 } 130 131 void TryFinallyBuilder::BeginFinally() { finalization_sites_.Bind(builder()); } 132 133 void TryFinallyBuilder::EndFinally() { 134 // Nothing to be done here. 135 } 136 137 } // namespace interpreter 138 } // namespace internal 139 } // namespace v8 140