Home | History | Annotate | Download | only in interpreter
      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() {
     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 }
    101 
    102 
    103 void LoopBuilder::EndLoop() {
    104   // Loop must have closed form, i.e. all loop elements are within the loop,
    105   // the loop header precedes the body and next elements in the loop.
    106   DCHECK(loop_header_.is_bound());
    107   builder()->Bind(&loop_end_);
    108   SetBreakTarget(loop_end_);
    109   if (next_.is_bound()) {
    110     DCHECK(!condition_.is_bound() || next_.offset() >= condition_.offset());
    111     SetContinueTarget(next_);
    112   } else {
    113     DCHECK(condition_.is_bound());
    114     DCHECK_GE(condition_.offset(), loop_header_.offset());
    115     DCHECK_LE(condition_.offset(), loop_end_.offset());
    116     SetContinueTarget(condition_);
    117   }
    118 }
    119 
    120 
    121 void LoopBuilder::SetContinueTarget(const BytecodeLabel& target) {
    122   BindLabels(target, &continue_sites_);
    123 }
    124 
    125 
    126 SwitchBuilder::~SwitchBuilder() {
    127 #ifdef DEBUG
    128   for (auto site : case_sites_) {
    129     DCHECK(site.is_bound());
    130   }
    131 #endif
    132 }
    133 
    134 
    135 void SwitchBuilder::SetCaseTarget(int index) {
    136   BytecodeLabel& site = case_sites_.at(index);
    137   builder()->Bind(&site);
    138 }
    139 
    140 }  // namespace interpreter
    141 }  // namespace internal
    142 }  // namespace v8
    143