tor-browser

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

PropOpEmitter.h (6972B)


      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_PropOpEmitter_h
      8 #define frontend_PropOpEmitter_h
      9 
     10 #include "mozilla/Attributes.h"
     11 
     12 #include <stddef.h>
     13 
     14 #include "vm/SharedStencil.h"  // GCThingIndex
     15 
     16 namespace js {
     17 namespace frontend {
     18 
     19 struct BytecodeEmitter;
     20 class TaggedParserAtomIndex;
     21 enum class ValueUsage;
     22 
     23 // Class for emitting bytecode for property operation.
     24 //
     25 // Usage: (check for the return value is omitted for simplicity)
     26 //
     27 //   `obj.prop;`
     28 //     PropOpEmitter poe(this,
     29 //                       PropOpEmitter::Kind::Get,
     30 //                       PropOpEmitter::ObjKind::Other);
     31 //     poe.prepareForObj();
     32 //     emit(obj);
     33 //     poe.emitGet(atom_of_prop);
     34 //
     35 //   `super.prop;`
     36 //     PropOpEmitter poe(this,
     37 //                       PropOpEmitter::Kind::Get,
     38 //                       PropOpEmitter::ObjKind::Super);
     39 //     poe.prepareForObj();
     40 //     emit(obj);
     41 //     poe.emitGet(atom_of_prop);
     42 //
     43 //   `obj.prop();`
     44 //     PropOpEmitter poe(this,
     45 //                       PropOpEmitter::Kind::Call,
     46 //                       PropOpEmitter::ObjKind::Other);
     47 //     poe.prepareForObj();
     48 //     emit(obj);
     49 //     poe.emitGet(atom_of_prop);
     50 //     emit_call_here();
     51 //
     52 //   `new obj.prop();`
     53 //     PropOpEmitter poe(this,
     54 //                       PropOpEmitter::Kind::Call,
     55 //                       PropOpEmitter::ObjKind::Other);
     56 //     poe.prepareForObj();
     57 //     emit(obj);
     58 //     poe.emitGet(atom_of_prop);
     59 //     emit_call_here();
     60 //
     61 //   `delete obj.prop;`
     62 //     PropOpEmitter poe(this,
     63 //                       PropOpEmitter::Kind::Delete,
     64 //                       PropOpEmitter::ObjKind::Other);
     65 //     poe.prepareForObj();
     66 //     emit(obj);
     67 //     poe.emitDelete(atom_of_prop);
     68 //
     69 //   `delete super.prop;`
     70 //     PropOpEmitter poe(this,
     71 //                       PropOpEmitter::Kind::Delete,
     72 //                       PropOpEmitter::ObjKind::Other);
     73 //     poe.emitDelete(atom_of_prop);
     74 //
     75 //   `obj.prop++;`
     76 //     PropOpEmitter poe(this,
     77 //                       PropOpEmitter::Kind::PostIncrement,
     78 //                       PropOpEmitter::ObjKind::Other);
     79 //     poe.prepareForObj();
     80 //     emit(obj);
     81 //     poe.emitIncDec(atom_of_prop);
     82 //
     83 //   `obj.prop = value;`
     84 //     PropOpEmitter poe(this,
     85 //                       PropOpEmitter::Kind::SimpleAssignment,
     86 //                       PropOpEmitter::ObjKind::Other);
     87 //     poe.prepareForObj();
     88 //     emit(obj);
     89 //     poe.prepareForRhs();
     90 //     emit(value);
     91 //     poe.emitAssignment(atom_of_prop);
     92 //
     93 //   `obj.prop += value;`
     94 //     PropOpEmitter poe(this,
     95 //                       PropOpEmitter::Kind::CompoundAssignment,
     96 //                       PropOpEmitter::ObjKind::Other);
     97 //     poe.prepareForObj();
     98 //     emit(obj);
     99 //     poe.emitGet(atom_of_prop);
    100 //     poe.prepareForRhs();
    101 //     emit(value);
    102 //     emit_add_op_here();
    103 //     poe.emitAssignment(nullptr); // nullptr for CompoundAssignment
    104 //
    105 class MOZ_STACK_CLASS PropOpEmitter {
    106 public:
    107  enum class Kind {
    108    Get,
    109    Call,
    110    Delete,
    111    PostIncrement,
    112    PreIncrement,
    113    PostDecrement,
    114    PreDecrement,
    115    SimpleAssignment,
    116    PropInit,
    117    CompoundAssignment
    118  };
    119  enum class ObjKind { Super, Other };
    120 
    121 private:
    122  BytecodeEmitter* bce_;
    123 
    124  Kind kind_;
    125  ObjKind objKind_;
    126 
    127  // The index for the property name's atom.
    128  GCThingIndex propAtomIndex_;
    129 
    130 #ifdef DEBUG
    131  // The state of this emitter.
    132  //
    133  //
    134  // +-------+   prepareForObj +-----+
    135  // | Start |---------------->| Obj |-+
    136  // +-------+                 +-----+ |
    137  //                                   |
    138  // +---------------------------------+
    139  // |
    140  // |
    141  // | [Get]
    142  // | [Call]
    143  // |   emitGet +-----+
    144  // +---------->| Get |
    145  // |           +-----+
    146  // |
    147  // | [Delete]
    148  // |   emitDelete +--------+
    149  // +------------->| Delete |
    150  // |              +--------+
    151  // |
    152  // | [PostIncrement]
    153  // | [PreIncrement]
    154  // | [PostDecrement]
    155  // | [PreDecrement]
    156  // |   emitIncDec +--------+
    157  // +------------->| IncDec |
    158  // |              +--------+
    159  // |
    160  // | [SimpleAssignment]
    161  // | [PropInit]
    162  // |                        prepareForRhs    +-----+
    163  // +--------------------->+----------------->| Rhs |-+
    164  // |                      ^                  +-----+ |
    165  // |                      |                          |
    166  // |                      |                +---------+
    167  // | [CompoundAssignment] |                |
    168  // |   emitGet +-----+    |                | emitAssignment +------------+
    169  // +---------->| Get |----+                + -------------->| Assignment |
    170  //             +-----+                                      +------------+
    171  enum class State {
    172    // The initial state.
    173    Start,
    174 
    175    // After calling prepareForObj.
    176    Obj,
    177 
    178    // After calling emitGet.
    179    Get,
    180 
    181    // After calling emitDelete.
    182    Delete,
    183 
    184    // After calling emitIncDec.
    185    IncDec,
    186 
    187    // After calling prepareForRhs.
    188    Rhs,
    189 
    190    // After calling emitAssignment.
    191    Assignment,
    192  };
    193  State state_ = State::Start;
    194 #endif
    195 
    196 public:
    197  PropOpEmitter(BytecodeEmitter* bce, Kind kind, ObjKind objKind);
    198 
    199 private:
    200  [[nodiscard]] bool isCall() const { return kind_ == Kind::Call; }
    201 
    202  [[nodiscard]] bool isSuper() const { return objKind_ == ObjKind::Super; }
    203 
    204  [[nodiscard]] bool isSimpleAssignment() const {
    205    return kind_ == Kind::SimpleAssignment;
    206  }
    207 
    208  [[nodiscard]] bool isPropInit() const { return kind_ == Kind::PropInit; }
    209 
    210  [[nodiscard]] bool isDelete() const { return kind_ == Kind::Delete; }
    211 
    212  [[nodiscard]] bool isCompoundAssignment() const {
    213    return kind_ == Kind::CompoundAssignment;
    214  }
    215 
    216  [[nodiscard]] bool isIncDec() const {
    217    return isPostIncDec() || isPreIncDec();
    218  }
    219 
    220  [[nodiscard]] bool isPostIncDec() const {
    221    return kind_ == Kind::PostIncrement || kind_ == Kind::PostDecrement;
    222  }
    223 
    224  [[nodiscard]] bool isPreIncDec() const {
    225    return kind_ == Kind::PreIncrement || kind_ == Kind::PreDecrement;
    226  }
    227 
    228  [[nodiscard]] bool isInc() const {
    229    return kind_ == Kind::PostIncrement || kind_ == Kind::PreIncrement;
    230  }
    231 
    232  [[nodiscard]] bool prepareAtomIndex(TaggedParserAtomIndex prop);
    233 
    234 public:
    235  [[nodiscard]] bool prepareForObj();
    236 
    237  [[nodiscard]] bool emitGet(TaggedParserAtomIndex prop);
    238 
    239  [[nodiscard]] bool prepareForRhs();
    240 
    241  [[nodiscard]] bool emitDelete(TaggedParserAtomIndex prop);
    242 
    243  // `prop` can be nullptr for CompoundAssignment.
    244  [[nodiscard]] bool emitAssignment(TaggedParserAtomIndex prop);
    245 
    246  [[nodiscard]] bool emitIncDec(TaggedParserAtomIndex prop,
    247                                ValueUsage valueUsage);
    248 
    249  size_t numReferenceSlots() const { return 1 + isSuper(); }
    250 };
    251 
    252 } /* namespace frontend */
    253 } /* namespace js */
    254 
    255 #endif /* frontend_PropOpEmitter_h */