tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

WhileEmitter.cpp (2674B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "frontend/WhileEmitter.h"
      8 
      9 #include "frontend/BytecodeEmitter.h"
     10 #include "vm/Opcodes.h"
     11 #include "vm/StencilEnums.h"  // TryNoteKind
     12 
     13 using namespace js;
     14 using namespace js::frontend;
     15 
     16 WhileEmitter::WhileEmitter(BytecodeEmitter* bce) : bce_(bce) {}
     17 
     18 bool WhileEmitter::emitCond(uint32_t whilePos, uint32_t condPos,
     19                            uint32_t endPos) {
     20  MOZ_ASSERT(state_ == State::Start);
     21 
     22  // If we have a single-line while, like "while (x) ;", we want to emit the
     23  // line note before the loop, so that the debugger sees a single entry point.
     24  // This way, if there is a breakpoint on the line, it will only fire once; and
     25  // "next"ing will skip the whole loop. However, for the multi-line case we
     26  // want to emit the line note for the JSOp::LoopHead, so that "cont" stops on
     27  // each iteration -- but without a stop before the first iteration.
     28  if (bce_->errorReporter().lineAt(whilePos) ==
     29      bce_->errorReporter().lineAt(endPos)) {
     30    if (!bce_->updateSourceCoordNotes(whilePos)) {
     31      return false;
     32    }
     33    // Emit a Nop to ensure the source position is not part of the loop.
     34    if (!bce_->emit1(JSOp::Nop)) {
     35      return false;
     36    }
     37  }
     38 
     39  loopInfo_.emplace(bce_, StatementKind::WhileLoop);
     40 
     41  if (!loopInfo_->emitLoopHead(bce_, mozilla::Some(condPos))) {
     42    return false;
     43  }
     44 
     45 #ifdef DEBUG
     46  state_ = State::Cond;
     47 #endif
     48  return true;
     49 }
     50 
     51 bool WhileEmitter::emitBody() {
     52  MOZ_ASSERT(state_ == State::Cond);
     53 
     54  if (!bce_->emitJump(JSOp::JumpIfFalse, &loopInfo_->breaks)) {
     55    return false;
     56  }
     57 
     58  tdzCacheForBody_.emplace(bce_);
     59 
     60 #ifdef DEBUG
     61  state_ = State::Body;
     62 #endif
     63  return true;
     64 }
     65 
     66 bool WhileEmitter::emitEnd() {
     67  MOZ_ASSERT(state_ == State::Body);
     68 
     69  tdzCacheForBody_.reset();
     70 
     71  if (!loopInfo_->emitContinueTarget(bce_)) {
     72    return false;
     73  }
     74 
     75  if (!loopInfo_->emitLoopEnd(bce_, JSOp::Goto, TryNoteKind::Loop)) {
     76    return false;
     77  }
     78 
     79  loopInfo_.reset();
     80 
     81 #ifdef DEBUG
     82  state_ = State::End;
     83 #endif
     84  return true;
     85 }
     86 
     87 #if defined(ENABLE_DECORATORS) || defined(ENABLE_EXPLICIT_RESOURCE_MANAGEMENT)
     88 bool InternalWhileEmitter::emitCond() {
     89  MOZ_ASSERT(state_ == State::Start);
     90 
     91  loopInfo_.emplace(bce_, StatementKind::WhileLoop);
     92 
     93  if (!loopInfo_->emitLoopHead(bce_, mozilla::Nothing())) {
     94    return false;
     95  }
     96 
     97 #  ifdef DEBUG
     98  state_ = State::Cond;
     99 #  endif
    100  return true;
    101 }
    102 #endif