tor-browser

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

IfEmitter.cpp (7300B)


      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/IfEmitter.h"
      8 
      9 #include "frontend/BytecodeEmitter.h"
     10 #include "vm/Opcodes.h"
     11 
     12 using namespace js;
     13 using namespace js::frontend;
     14 
     15 using mozilla::Maybe;
     16 
     17 BranchEmitterBase::BranchEmitterBase(BytecodeEmitter* bce,
     18                                     LexicalKind lexicalKind)
     19    : bce_(bce), lexicalKind_(lexicalKind) {}
     20 
     21 IfEmitter::IfEmitter(BytecodeEmitter* bce, LexicalKind lexicalKind)
     22    : BranchEmitterBase(bce, lexicalKind) {}
     23 
     24 IfEmitter::IfEmitter(BytecodeEmitter* bce)
     25    : IfEmitter(bce, LexicalKind::MayContainLexicalAccessInBranch) {}
     26 
     27 bool BranchEmitterBase::emitThenInternal(ConditionKind conditionKind) {
     28  // The end of TDZCheckCache for cond for else-if.
     29  if (lexicalKind_ == LexicalKind::MayContainLexicalAccessInBranch) {
     30    tdzCache_.reset();
     31  }
     32 
     33  // Emit a jump around the then part.
     34  JSOp op = conditionKind == ConditionKind::Positive ? JSOp::JumpIfFalse
     35                                                     : JSOp::JumpIfTrue;
     36  if (!bce_->emitJump(op, &jumpAroundThen_)) {
     37    return false;
     38  }
     39 
     40  // To restore stack depth in else part (if present), save depth of the then
     41  // part.
     42  thenDepth_ = bce_->bytecodeSection().stackDepth();
     43 
     44  // Enclose then-branch with TDZCheckCache.
     45  if (lexicalKind_ == LexicalKind::MayContainLexicalAccessInBranch) {
     46    tdzCache_.emplace(bce_);
     47  }
     48 
     49  return true;
     50 }
     51 
     52 void BranchEmitterBase::calculateOrCheckPushed() {
     53 #ifdef DEBUG
     54  if (!calculatedPushed_) {
     55    pushed_ = bce_->bytecodeSection().stackDepth() - thenDepth_;
     56    calculatedPushed_ = true;
     57  } else {
     58    MOZ_ASSERT(pushed_ == bce_->bytecodeSection().stackDepth() - thenDepth_);
     59  }
     60 #endif
     61 }
     62 
     63 bool BranchEmitterBase::emitElseInternal() {
     64  calculateOrCheckPushed();
     65 
     66  // The end of TDZCheckCache for then-clause.
     67  if (lexicalKind_ == LexicalKind::MayContainLexicalAccessInBranch) {
     68    MOZ_ASSERT(tdzCache_.isSome());
     69    tdzCache_.reset();
     70  }
     71 
     72  // Emit a jump from the end of our then part around the else part. The
     73  // patchJumpsToTarget call at the bottom of this function will fix up
     74  // the offset with jumpsAroundElse value.
     75  if (!bce_->emitJump(JSOp::Goto, &jumpsAroundElse_)) {
     76    return false;
     77  }
     78 
     79  // Ensure the branch-if-false comes here, then emit the else.
     80  if (!bce_->emitJumpTargetAndPatch(jumpAroundThen_)) {
     81    return false;
     82  }
     83 
     84  // Clear jumpAroundThen_ offset, to tell emitEnd there was an else part.
     85  jumpAroundThen_ = JumpList();
     86 
     87  // Restore stack depth of the then part.
     88  bce_->bytecodeSection().setStackDepth(thenDepth_);
     89 
     90  // Enclose else-branch with TDZCheckCache.
     91  if (lexicalKind_ == LexicalKind::MayContainLexicalAccessInBranch) {
     92    tdzCache_.emplace(bce_);
     93  }
     94 
     95  return true;
     96 }
     97 
     98 bool BranchEmitterBase::emitEndInternal() {
     99  // The end of TDZCheckCache for then or else-clause.
    100  if (lexicalKind_ == LexicalKind::MayContainLexicalAccessInBranch) {
    101    MOZ_ASSERT(tdzCache_.isSome());
    102    tdzCache_.reset();
    103  }
    104 
    105  calculateOrCheckPushed();
    106 
    107  if (jumpAroundThen_.offset.valid()) {
    108    // No else part for the last branch, fixup the branch-if-false to
    109    // come here.
    110    if (!bce_->emitJumpTargetAndPatch(jumpAroundThen_)) {
    111      return false;
    112    }
    113  }
    114 
    115  // Patch all the jumps around else parts.
    116  if (!bce_->emitJumpTargetAndPatch(jumpsAroundElse_)) {
    117    return false;
    118  }
    119 
    120  return true;
    121 }
    122 
    123 bool IfEmitter::emitIf(const Maybe<uint32_t>& ifPos) {
    124  MOZ_ASSERT(state_ == State::Start);
    125 
    126  if (ifPos) {
    127    // Make sure this code is attributed to the "if" so that it gets a
    128    // useful column number, instead of the default 0 value.
    129    if (!bce_->updateSourceCoordNotes(*ifPos)) {
    130      return false;
    131    }
    132  }
    133 
    134 #ifdef DEBUG
    135  state_ = State::If;
    136 #endif
    137  return true;
    138 }
    139 
    140 bool IfEmitter::emitThen(
    141    ConditionKind conditionKind /* = ConditionKind::Positive */) {
    142  MOZ_ASSERT(state_ == State::If || state_ == State::ElseIf);
    143 
    144  if (lexicalKind_ == LexicalKind::MayContainLexicalAccessInBranch) {
    145    MOZ_ASSERT_IF(state_ == State::ElseIf, tdzCache_.isSome());
    146    MOZ_ASSERT_IF(state_ != State::ElseIf, tdzCache_.isNothing());
    147  }
    148 
    149  if (!emitThenInternal(conditionKind)) {
    150    return false;
    151  }
    152 
    153 #ifdef DEBUG
    154  state_ = State::Then;
    155 #endif
    156  return true;
    157 }
    158 
    159 bool IfEmitter::emitThenElse(
    160    ConditionKind conditionKind /* = ConditionKind::Positive */) {
    161  MOZ_ASSERT(state_ == State::If || state_ == State::ElseIf);
    162 
    163  if (lexicalKind_ == LexicalKind::MayContainLexicalAccessInBranch) {
    164    MOZ_ASSERT_IF(state_ == State::ElseIf, tdzCache_.isSome());
    165    MOZ_ASSERT_IF(state_ != State::ElseIf, tdzCache_.isNothing());
    166  }
    167 
    168  if (!emitThenInternal(conditionKind)) {
    169    return false;
    170  }
    171 
    172 #ifdef DEBUG
    173  state_ = State::ThenElse;
    174 #endif
    175  return true;
    176 }
    177 
    178 bool IfEmitter::emitElseIf(const Maybe<uint32_t>& ifPos) {
    179  MOZ_ASSERT(state_ == State::ThenElse);
    180 
    181  if (!emitElseInternal()) {
    182    return false;
    183  }
    184 
    185  if (ifPos) {
    186    // Make sure this code is attributed to the "if" so that it gets a
    187    // useful column number, instead of the default 0 value.
    188    if (!bce_->updateSourceCoordNotes(*ifPos)) {
    189      return false;
    190    }
    191  }
    192 
    193 #ifdef DEBUG
    194  state_ = State::ElseIf;
    195 #endif
    196  return true;
    197 }
    198 
    199 bool IfEmitter::emitElse() {
    200  MOZ_ASSERT(state_ == State::ThenElse);
    201 
    202  if (!emitElseInternal()) {
    203    return false;
    204  }
    205 
    206 #ifdef DEBUG
    207  state_ = State::Else;
    208 #endif
    209  return true;
    210 }
    211 
    212 bool IfEmitter::emitEnd() {
    213  MOZ_ASSERT(state_ == State::Then || state_ == State::Else);
    214  // If there was an else part for the last branch, jumpAroundThen_ is
    215  // already fixed up when emitting the else part.
    216  MOZ_ASSERT_IF(state_ == State::Then, jumpAroundThen_.offset.valid());
    217  MOZ_ASSERT_IF(state_ == State::Else, !jumpAroundThen_.offset.valid());
    218 
    219  if (!emitEndInternal()) {
    220    return false;
    221  }
    222 
    223 #ifdef DEBUG
    224  state_ = State::End;
    225 #endif
    226  return true;
    227 }
    228 
    229 InternalIfEmitter::InternalIfEmitter(BytecodeEmitter* bce,
    230                                     LexicalKind lexicalKind)
    231    : IfEmitter(bce, lexicalKind) {
    232 #ifdef DEBUG
    233  // Skip emitIf (see the comment above InternalIfEmitter declaration).
    234  state_ = State::If;
    235 #endif
    236 }
    237 
    238 CondEmitter::CondEmitter(BytecodeEmitter* bce)
    239    : BranchEmitterBase(bce, LexicalKind::MayContainLexicalAccessInBranch) {}
    240 
    241 bool CondEmitter::emitCond() {
    242  MOZ_ASSERT(state_ == State::Start);
    243 #ifdef DEBUG
    244  state_ = State::Cond;
    245 #endif
    246  return true;
    247 }
    248 
    249 bool CondEmitter::emitThenElse(
    250    ConditionKind conditionKind /* = ConditionKind::Positive */) {
    251  MOZ_ASSERT(state_ == State::Cond);
    252  if (!emitThenInternal(conditionKind)) {
    253    return false;
    254  }
    255 
    256 #ifdef DEBUG
    257  state_ = State::ThenElse;
    258 #endif
    259  return true;
    260 }
    261 
    262 bool CondEmitter::emitElse() {
    263  MOZ_ASSERT(state_ == State::ThenElse);
    264 
    265  if (!emitElseInternal()) {
    266    return false;
    267  }
    268 
    269 #ifdef DEBUG
    270  state_ = State::Else;
    271 #endif
    272  return true;
    273 }
    274 
    275 bool CondEmitter::emitEnd() {
    276  MOZ_ASSERT(state_ == State::Else);
    277  MOZ_ASSERT(!jumpAroundThen_.offset.valid());
    278 
    279  if (!emitEndInternal()) {
    280    return false;
    281  }
    282 
    283 #ifdef DEBUG
    284  state_ = State::End;
    285 #endif
    286  return true;
    287 }