tor-browser

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

NameOpEmitter.h (5164B)


      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 #ifndef frontend_NameOpEmitter_h
      8 #define frontend_NameOpEmitter_h
      9 
     10 #include "mozilla/Attributes.h"
     11 
     12 #include <stddef.h>
     13 
     14 #include "frontend/NameAnalysisTypes.h"
     15 #include "frontend/ParserAtom.h"  // TaggedParserAtomIndex
     16 #include "vm/SharedStencil.h"     // GCThingIndex
     17 
     18 namespace js {
     19 namespace frontend {
     20 
     21 struct BytecodeEmitter;
     22 enum class ValueUsage;
     23 
     24 // Class for emitting bytecode for name operation.
     25 //
     26 // Usage: (check for the return value is omitted for simplicity)
     27 //
     28 //   `name;`
     29 //     NameOpEmitter noe(this, atom_of_name
     30 //                       NameOpEmitter::Kind::Get);
     31 //     noe.emitGet();
     32 //
     33 //   `name();`
     34 //     this is handled in CallOrNewEmitter
     35 //
     36 //   `name++;`
     37 //     NameOpEmitter noe(this, atom_of_name
     38 //                       NameOpEmitter::Kind::PostIncrement);
     39 //     noe.emitIncDec();
     40 //
     41 //   `name = 10;`
     42 //     NameOpEmitter noe(this, atom_of_name
     43 //                       NameOpEmitter::Kind::SimpleAssignment);
     44 //     noe.prepareForRhs();
     45 //     emit(10);
     46 //     noe.emitAssignment();
     47 //
     48 //   `name += 10;`
     49 //     NameOpEmitter noe(this, atom_of_name
     50 //                       NameOpEmitter::Kind::CompoundAssignment);
     51 //     noe.prepareForRhs();
     52 //     emit(10);
     53 //     emit_add_op_here();
     54 //     noe.emitAssignment();
     55 //
     56 //   `name = 10;` part of `let name = 10;`
     57 //     NameOpEmitter noe(this, atom_of_name
     58 //                       NameOpEmitter::Kind::Initialize);
     59 //     noe.prepareForRhs();
     60 //     emit(10);
     61 //     noe.emitAssignment();
     62 //
     63 class MOZ_STACK_CLASS NameOpEmitter {
     64 public:
     65  enum class Kind {
     66    Get,
     67    Call,
     68    PostIncrement,
     69    PreIncrement,
     70    PostDecrement,
     71    PreDecrement,
     72    SimpleAssignment,
     73    CompoundAssignment,
     74    Initialize
     75  };
     76 
     77 private:
     78  BytecodeEmitter* bce_;
     79 
     80  Kind kind_;
     81 
     82  bool emittedBindOp_ = false;
     83 
     84  TaggedParserAtomIndex name_;
     85 
     86  GCThingIndex atomIndex_;
     87 
     88  NameLocation loc_;
     89 
     90 #ifdef DEBUG
     91  // The state of this emitter.
     92  //
     93  //               [Get]
     94  //               [Call]
     95  // +-------+      emitGet +-----+
     96  // | Start |-+-+--------->| Get |
     97  // +-------+   |          +-----+
     98  //             |
     99  //             | [PostIncrement]
    100  //             | [PreIncrement]
    101  //             | [PostDecrement]
    102  //             | [PreDecrement]
    103  //             |   emitIncDec +--------+
    104  //             +------------->| IncDec |
    105  //             |              +--------+
    106  //             |
    107  //             | [SimpleAssignment]
    108  //             |                        prepareForRhs +-----+
    109  //             +--------------------->+-------------->| Rhs |-+
    110  //             |                      ^               +-----+ |
    111  //             |                      |                       |
    112  //             |                      |    +------------------+
    113  //             | [CompoundAssignment] |    |
    114  //             |   emitGet +-----+    |    | emitAssignment +------------+
    115  //             +---------->| Get |----+    + -------------->| Assignment |
    116  //                         +-----+                          +------------+
    117  enum class State {
    118    // The initial state.
    119    Start,
    120 
    121    // After calling emitGet.
    122    Get,
    123 
    124    // After calling emitIncDec.
    125    IncDec,
    126 
    127    // After calling prepareForRhs.
    128    Rhs,
    129 
    130    // After calling emitAssignment.
    131    Assignment,
    132  };
    133  State state_ = State::Start;
    134 #endif
    135 
    136 public:
    137  NameOpEmitter(BytecodeEmitter* bce, TaggedParserAtomIndex name, Kind kind);
    138  NameOpEmitter(BytecodeEmitter* bce, TaggedParserAtomIndex name,
    139                const NameLocation& loc, Kind kind);
    140 
    141 private:
    142  [[nodiscard]] bool isCall() const { return kind_ == Kind::Call; }
    143 
    144  [[nodiscard]] bool isSimpleAssignment() const {
    145    return kind_ == Kind::SimpleAssignment;
    146  }
    147 
    148  [[nodiscard]] bool isCompoundAssignment() const {
    149    return kind_ == Kind::CompoundAssignment;
    150  }
    151 
    152  [[nodiscard]] bool isIncDec() const {
    153    return isPostIncDec() || isPreIncDec();
    154  }
    155 
    156  [[nodiscard]] bool isPostIncDec() const {
    157    return kind_ == Kind::PostIncrement || kind_ == Kind::PostDecrement;
    158  }
    159 
    160  [[nodiscard]] bool isPreIncDec() const {
    161    return kind_ == Kind::PreIncrement || kind_ == Kind::PreDecrement;
    162  }
    163 
    164  [[nodiscard]] bool isInc() const {
    165    return kind_ == Kind::PostIncrement || kind_ == Kind::PreIncrement;
    166  }
    167 
    168  [[nodiscard]] bool isInitialize() const { return kind_ == Kind::Initialize; }
    169 
    170  JSOp strictifySetNameOp(JSOp op) const;
    171 
    172 public:
    173  [[nodiscard]] bool emittedBindOp() const { return emittedBindOp_; }
    174 
    175  [[nodiscard]] const NameLocation& loc() const { return loc_; }
    176 
    177  [[nodiscard]] bool emitGet();
    178  [[nodiscard]] bool prepareForRhs();
    179  [[nodiscard]] bool emitAssignment();
    180  [[nodiscard]] bool emitIncDec(ValueUsage valueUsage);
    181 
    182  size_t numReferenceSlots() const { return emittedBindOp(); }
    183 };
    184 
    185 } /* namespace frontend */
    186 } /* namespace js */
    187 
    188 #endif /* frontend_NameOpEmitter_h */