tor-browser

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

UsingEmitter.h (7899B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #ifndef frontend_UsingEmitter_h
      6 #define frontend_UsingEmitter_h
      7 
      8 #include "mozilla/Attributes.h"
      9 
     10 #include "frontend/TryEmitter.h"
     11 #include "js/UniquePtr.h"
     12 #include "vm/UsingHint.h"
     13 
     14 namespace js::frontend {
     15 
     16 struct BytecodeEmitter;
     17 class EmitterScope;
     18 
     19 // This enum simply refers to the kind of block we are operating in. The present
     20 // use case of this is for disposal related code to special case the handling of
     21 // disposals in different blocks.
     22 enum class BlockKind : uint8_t {
     23  ForOf,
     24 
     25  // Other here refers to any generic block which doesnt require any
     26  // special handling.
     27  Other
     28 };
     29 
     30 // Class for emitting bytecode for disposal loops.
     31 // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposeresources
     32 //
     33 // Usage: (check for the return value is omitted for simplicity)
     34 //
     35 //   at the point where the disposal loop is needed
     36 //     DisposalEmitter de(bce, hasAsyncDisposables, initialCompletion);
     37 //     de.prepareForDisposeCapability();
     38 //     emit_DisposeCapability();
     39 //     de.emitEnd(es);
     40 //
     41 class MOZ_STACK_CLASS DisposalEmitter {
     42 private:
     43  BytecodeEmitter* bce_;
     44  bool hasAsyncDisposables_;
     45 
     46 #ifdef DEBUG
     47  // The state of this emitter.
     48  //
     49  // +-------+  prepareForDisposeCapability  +-----------------------------+
     50  // | Start |------------------------------>| prepareForDisposeCapability |--+
     51  // +-------+                               +-----------------------------+  |
     52  //                                                                          |
     53  //   +----------------------------------------------------------------------+
     54  //   |
     55  //   |  emitEnd  +-----+
     56  //   +---------->| End |
     57  //               +-----+
     58  enum class State {
     59    // The initial state.
     60    Start,
     61 
     62    // After calling prepareForDisposeCapability.
     63    DisposeCapability,
     64 
     65    // After calling emitEnd.
     66    End
     67  };
     68  State state_ = State::Start;
     69 #endif
     70 
     71  [[nodiscard]] bool emitResourcePropertyAccess(TaggedParserAtomIndex prop,
     72                                                unsigned resourcesFromTop = 1);
     73 
     74 public:
     75  DisposalEmitter(BytecodeEmitter* bce, bool hasAsyncDisposables)
     76      : bce_(bce), hasAsyncDisposables_(hasAsyncDisposables) {}
     77 
     78  [[nodiscard]] bool prepareForDisposeCapability();
     79 
     80  [[nodiscard]] bool emitEnd(EmitterScope& es);
     81 };
     82 
     83 // Class for emitting bytecode for using declarations.
     84 //
     85 // Usage: (check for the return value is omitted for simplicity)
     86 //
     87 //  at the point of scope start
     88 //    UsingEmitter ue(bce);
     89 //    ue.prepareForDisposableScopeBody();
     90 //
     91 //  at the point of using decl assignment, e.g. `using x = y;`
     92 //    ue.prepareForAssignment(UsingHint::Normal);
     93 //    emit_Assignment();
     94 //
     95 //  at points requiring non-local jumps, like break, continue
     96 //    ue.emitNonLocalJump(&currentScope);
     97 //
     98 //  at the point of scope end
     99 //    ue.emitEnd();
    100 class MOZ_STACK_CLASS UsingEmitter {
    101 private:
    102  js::UniquePtr<TryEmitter> tryEmitter_;
    103 
    104  bool hasAwaitUsing_ = false;
    105 
    106 #ifdef DEBUG
    107  // The state of this emitter.
    108  //
    109  // +-------+  prepareForDisposableScopeBody
    110  // | Start |---------------------------------+
    111  // +-------+                                 |
    112  //                                           |
    113  //   +---------------------------------------+
    114  //   |
    115  //   |       +---------------------+     emitEnd   +-----+
    116  //   +-->+-->| DisposableScopeBody |--+----------->| End |
    117  //       ^   +---------------------+  |            +-----+
    118  //       |                            |
    119  //       |    prepareForAssignment    |
    120  //       +<---------------------------+
    121  //       ^                            |
    122  //       |    emitNonLocalJump        |
    123  //       +----------------------------+
    124  //
    125  enum class State {
    126    // The initial state.
    127    Start,
    128 
    129    // After calling prepareForDisposableScopeBody.
    130    DisposableScopeBody,
    131 
    132    // After calling emitEnd.
    133    End
    134  };
    135  State state_ = State::Start;
    136 #endif
    137 
    138  [[nodiscard]] bool emitGetDisposeMethod(UsingHint hint);
    139 
    140  [[nodiscard]] bool emitCreateDisposableResource(UsingHint hint);
    141 
    142  [[nodiscard]] bool emitTakeDisposeCapability();
    143 
    144 protected:
    145  BytecodeEmitter* bce_;
    146 
    147  [[nodiscard]] bool emitThrowIfException();
    148 
    149  [[nodiscard]] bool emitDisposeResourcesForEnvironment(EmitterScope& es);
    150 
    151 public:
    152  explicit UsingEmitter(BytecodeEmitter* bce);
    153 
    154  bool hasAwaitUsing() const { return hasAwaitUsing_; }
    155 
    156  void setHasAwaitUsing(bool hasAwaitUsing) { hasAwaitUsing_ = hasAwaitUsing; }
    157 
    158  [[nodiscard]] bool prepareForDisposableScopeBody(BlockKind blockKind);
    159 
    160  [[nodiscard]] bool prepareForAssignment(UsingHint hint);
    161 
    162  [[nodiscard]] bool emitEnd();
    163 };
    164 
    165 // This is a version of UsingEmitter specialized to help emit code for
    166 // using declarations in for-of loop heads e.g.: `for (using x of y) {}`.
    167 //
    168 // Usage: (check for the return value is omitted for simplicity)
    169 //
    170 //   at the point of the for-of loop head
    171 //     ForOfDisposalEmitter disposeBeforeIter(bce, hasAwaitUsing);
    172 //     disposeBeforeIter.prepareForForOfLoopIteration();
    173 //     emit_Loop();
    174 //
    175 //   at the point of loop end
    176 //     prepare_IteratorClose();
    177 //     disposeBeforeIter.emitEnd();
    178 //
    179 class MOZ_STACK_CLASS ForOfDisposalEmitter : protected UsingEmitter {
    180 private:
    181 #ifdef DEBUG
    182  // The state of this emitter.
    183  //
    184  // +-------+  prepareForForOfLoopIteration   +-----------+
    185  // | Start |-------------------------------->| Iteration |--+
    186  // +-------+                                 +-----------+  |
    187  //                                                          |
    188  //   +------------------------------------------------------+
    189  //   |
    190  //   |  emitEnd  +-----+
    191  //   +---------->| End |
    192  //               +-----+
    193  enum class State {
    194    // The initial state.
    195    Start,
    196 
    197    // After calling prepareForForOfLoopIteration.
    198    Iteration,
    199 
    200    // After calling emitEnd.
    201    End
    202  };
    203  State state_ = State::Start;
    204 #endif
    205 public:
    206  explicit ForOfDisposalEmitter(BytecodeEmitter* bce, bool hasAwaitUsing)
    207      : UsingEmitter(bce) {
    208    setHasAwaitUsing(hasAwaitUsing);
    209  }
    210 
    211  [[nodiscard]] bool prepareForForOfLoopIteration();
    212 
    213  [[nodiscard]] bool emitEnd();
    214 };
    215 
    216 // This is a version of UsingEmitter specialized to help emit code for
    217 // non-local jumps in for-of loops for closing iterators.
    218 //
    219 // Usage: (check for the return value is omitted for simplicity)
    220 //
    221 //   at the point of IteratorClose inside non-local jump
    222 //     NonLocalIteratorCloseUsingEmitter disposeBeforeIterClose(bce);
    223 //     disposeBeforeIterClose.prepareForIteratorClose(&currentScope);
    224 //     emit_IteratorClose();
    225 //     disposeBeforeIterClose.emitEnd(&currentScope);
    226 //
    227 class MOZ_STACK_CLASS NonLocalIteratorCloseUsingEmitter
    228    : protected UsingEmitter {
    229 private:
    230  js::UniquePtr<TryEmitter> tryClosingIterator_;
    231 
    232 #ifdef DEBUG
    233  // The state of this emitter.
    234  //
    235  // +-------+  prepareForIteratorClose  +-------------------------+
    236  // | Start |-------------------------->| prepareForIteratorClose |--+
    237  // +-------+                           +-------------------------+  |
    238  //                                                                  |
    239  //   +--------------------------------------------------------------+
    240  //   |
    241  //   |  emitEnd  +-----+
    242  //   +---------->| End |
    243  //               +-----+
    244  enum class State {
    245    // The initial state.
    246    Start,
    247 
    248    // After calling prepareForIteratorClose.
    249    IteratorClose,
    250 
    251    // After calling emitEnd.
    252    End
    253  };
    254  State state_ = State::Start;
    255 #endif
    256 
    257 public:
    258  explicit NonLocalIteratorCloseUsingEmitter(BytecodeEmitter* bce)
    259      : UsingEmitter(bce) {}
    260 
    261  [[nodiscard]] bool prepareForIteratorClose(EmitterScope& es);
    262 
    263  [[nodiscard]] bool emitEnd();
    264 };
    265 
    266 }  // namespace js::frontend
    267 
    268 #endif  // frontend_UsingEmitter_h