// Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/interpreter/control-flow-builders.h" #include "src/objects-inl.h" namespace v8 { namespace internal { namespace interpreter { BreakableControlFlowBuilder::~BreakableControlFlowBuilder() { DCHECK(break_labels_.empty() || break_labels_.is_bound()); } void BreakableControlFlowBuilder::BindBreakTarget() { break_labels_.Bind(builder()); } void BreakableControlFlowBuilder::EmitJump(BytecodeLabels* sites) { builder()->Jump(sites->New()); } void BreakableControlFlowBuilder::EmitJumpIfTrue(BytecodeLabels* sites) { builder()->JumpIfTrue(sites->New()); } void BreakableControlFlowBuilder::EmitJumpIfFalse(BytecodeLabels* sites) { builder()->JumpIfFalse(sites->New()); } void BreakableControlFlowBuilder::EmitJumpIfUndefined(BytecodeLabels* sites) { builder()->JumpIfUndefined(sites->New()); } void BreakableControlFlowBuilder::EmitJumpIfNull(BytecodeLabels* sites) { builder()->JumpIfNull(sites->New()); } void BlockBuilder::EndBlock() { builder()->Bind(&block_end_); BindBreakTarget(); } LoopBuilder::~LoopBuilder() { DCHECK(continue_labels_.empty() || continue_labels_.is_bound()); DCHECK(header_labels_.empty() || header_labels_.is_bound()); } void LoopBuilder::LoopHeader(ZoneVector* additional_labels) { // Jumps from before the loop header into the loop violate ordering // requirements of bytecode basic blocks. The only entry into a loop // must be the loop header. Surely breaks is okay? Not if nested // and misplaced between the headers. DCHECK(break_labels_.empty() && continue_labels_.empty()); builder()->Bind(&loop_header_); if (additional_labels != nullptr) { for (auto& label : *additional_labels) { builder()->Bind(&label); } } } void LoopBuilder::JumpToHeader(int loop_depth) { // Pass the proper loop nesting level to the backwards branch, to trigger // on-stack replacement when armed for the given loop nesting depth. int level = Min(loop_depth, AbstractCode::kMaxLoopNestingMarker - 1); // Loop must have closed form, i.e. all loop elements are within the loop, // the loop header precedes the body and next elements in the loop. DCHECK(loop_header_.is_bound()); builder()->JumpLoop(&loop_header_, level); } void LoopBuilder::EndLoop() { BindBreakTarget(); header_labels_.BindToLabel(builder(), loop_header_); } void LoopBuilder::BindContinueTarget() { continue_labels_.Bind(builder()); } SwitchBuilder::~SwitchBuilder() { #ifdef DEBUG for (auto site : case_sites_) { DCHECK(site.is_bound()); } #endif } void SwitchBuilder::SetCaseTarget(int index) { BytecodeLabel& site = case_sites_.at(index); builder()->Bind(&site); } void TryCatchBuilder::BeginTry(Register context) { builder()->MarkTryBegin(handler_id_, context); } void TryCatchBuilder::EndTry() { builder()->MarkTryEnd(handler_id_); builder()->Jump(&exit_); builder()->Bind(&handler_); builder()->MarkHandler(handler_id_, catch_prediction_); } void TryCatchBuilder::EndCatch() { builder()->Bind(&exit_); } void TryFinallyBuilder::BeginTry(Register context) { builder()->MarkTryBegin(handler_id_, context); } void TryFinallyBuilder::LeaveTry() { builder()->Jump(finalization_sites_.New()); } void TryFinallyBuilder::EndTry() { builder()->MarkTryEnd(handler_id_); } void TryFinallyBuilder::BeginHandler() { builder()->Bind(&handler_); builder()->MarkHandler(handler_id_, catch_prediction_); } void TryFinallyBuilder::BeginFinally() { finalization_sites_.Bind(builder()); } void TryFinallyBuilder::EndFinally() { // Nothing to be done here. } } // namespace interpreter } // namespace internal } // namespace v8