tor-browser

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

ElemOpEmitter.h (7056B)


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