tor-browser

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

Interpreter.h (28330B)


      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 vm_Interpreter_h
      8 #define vm_Interpreter_h
      9 
     10 /*
     11 * JS interpreter interface.
     12 */
     13 
     14 #include "jspubtd.h"
     15 
     16 #include "vm/BuiltinObjectKind.h"
     17 #include "vm/CheckIsObjectKind.h"  // CheckIsObjectKind
     18 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
     19 #  include "vm/ErrorObject.h"
     20 #  include "vm/UsingHint.h"
     21 #endif
     22 #include "vm/Stack.h"
     23 
     24 namespace js {
     25 
     26 class WithScope;
     27 class EnvironmentIter;
     28 class PlainObject;
     29 
     30 /*
     31 * Convert null/undefined |thisv| into the global lexical's |this| object, and
     32 * replace other primitives with boxed versions.
     33 */
     34 extern JSObject* BoxNonStrictThis(JSContext* cx, HandleValue thisv);
     35 
     36 extern bool GetFunctionThis(JSContext* cx, AbstractFramePtr frame,
     37                            MutableHandleValue res);
     38 
     39 extern void GetNonSyntacticGlobalThis(JSContext* cx, HandleObject envChain,
     40                                      MutableHandleValue res);
     41 
     42 /*
     43 * numToSkip is the number of stack values the expression decompiler should skip
     44 * before it reaches |v|. If it's -1, the decompiler will search the stack.
     45 */
     46 extern bool ReportIsNotFunction(JSContext* cx, HandleValue v, int numToSkip,
     47                                MaybeConstruct construct = NO_CONSTRUCT);
     48 
     49 /* See ReportIsNotFunction comment for the meaning of numToSkip. */
     50 extern JSObject* ValueToCallable(JSContext* cx, HandleValue v,
     51                                 int numToSkip = -1,
     52                                 MaybeConstruct construct = NO_CONSTRUCT);
     53 
     54 // Reasons why a call could be performed, for passing onto the debugger's
     55 // `onNativeCall` hook.
     56 // `onNativeCall` hook disabled all JITs, and this needs to be handled only in
     57 // the interpreter.
     58 enum class CallReason {
     59  Call,
     60  // callContentFunction or constructContentFunction in self-hosted JS.
     61  CallContent,
     62  // Function.prototype.call or Function.prototype.apply.
     63  FunCall,
     64  Getter,
     65  Setter,
     66 };
     67 
     68 /*
     69 * Call or construct arguments that are stored in rooted memory.
     70 *
     71 * NOTE: Any necessary |GetThisValue| computation must have been performed on
     72 *       |args.thisv()|, likely by the interpreter when pushing |this| onto the
     73 *       stack.  If you're not sure whether |GetThisValue| processing has been
     74 *       performed, use |Invoke|.
     75 */
     76 extern bool InternalCallOrConstruct(JSContext* cx, const CallArgs& args,
     77                                    MaybeConstruct construct,
     78                                    CallReason reason = CallReason::Call);
     79 
     80 /*
     81 * These helpers take care of the infinite-recursion check necessary for
     82 * getter/setter calls.
     83 */
     84 extern bool CallGetter(JSContext* cx, HandleValue thisv, HandleValue getter,
     85                       MutableHandleValue rval);
     86 
     87 extern bool CallSetter(JSContext* cx, HandleValue thisv, HandleValue setter,
     88                       HandleValue rval);
     89 
     90 // ES7 rev 0c1bd3004329336774cbc90de727cd0cf5f11e93
     91 // 7.3.12 Call(F, V, argumentsList).
     92 // All parameters are required, hopefully forcing callers to be careful not to
     93 // (say) blindly pass callee as |newTarget| when a different value should have
     94 // been passed.  Behavior is unspecified if any element of |args| isn't
     95 // initialized.
     96 //
     97 // |rval| is written to *only* after |fval| and |thisv| have been consumed, so
     98 // |rval| *may* alias either argument.
     99 extern bool Call(JSContext* cx, HandleValue fval, HandleValue thisv,
    100                 const AnyInvokeArgs& args, MutableHandleValue rval,
    101                 CallReason reason = CallReason::Call);
    102 
    103 inline bool Call(JSContext* cx, HandleValue fval, HandleValue thisv,
    104                 MutableHandleValue rval) {
    105  FixedInvokeArgs<0> args(cx);
    106  return Call(cx, fval, thisv, args, rval);
    107 }
    108 
    109 inline bool Call(JSContext* cx, HandleValue fval, JSObject* thisObj,
    110                 MutableHandleValue rval) {
    111  RootedValue thisv(cx, ObjectOrNullValue(thisObj));
    112  FixedInvokeArgs<0> args(cx);
    113  return Call(cx, fval, thisv, args, rval);
    114 }
    115 
    116 inline bool Call(JSContext* cx, HandleValue fval, HandleValue thisv,
    117                 HandleValue arg0, MutableHandleValue rval) {
    118  FixedInvokeArgs<1> args(cx);
    119  args[0].set(arg0);
    120  return Call(cx, fval, thisv, args, rval);
    121 }
    122 
    123 inline bool Call(JSContext* cx, HandleValue fval, JSObject* thisObj,
    124                 HandleValue arg0, MutableHandleValue rval) {
    125  RootedValue thisv(cx, ObjectOrNullValue(thisObj));
    126  FixedInvokeArgs<1> args(cx);
    127  args[0].set(arg0);
    128  return Call(cx, fval, thisv, args, rval);
    129 }
    130 
    131 inline bool Call(JSContext* cx, HandleValue fval, HandleValue thisv,
    132                 HandleValue arg0, HandleValue arg1, MutableHandleValue rval) {
    133  FixedInvokeArgs<2> args(cx);
    134  args[0].set(arg0);
    135  args[1].set(arg1);
    136  return Call(cx, fval, thisv, args, rval);
    137 }
    138 
    139 inline bool Call(JSContext* cx, HandleValue fval, JSObject* thisObj,
    140                 HandleValue arg0, HandleValue arg1, MutableHandleValue rval) {
    141  RootedValue thisv(cx, ObjectOrNullValue(thisObj));
    142  FixedInvokeArgs<2> args(cx);
    143  args[0].set(arg0);
    144  args[1].set(arg1);
    145  return Call(cx, fval, thisv, args, rval);
    146 }
    147 
    148 inline bool Call(JSContext* cx, HandleValue fval, JSObject* thisObj,
    149                 HandleValue arg0, HandleValue arg1, HandleValue arg2,
    150                 MutableHandleValue rval) {
    151  RootedValue thisv(cx, ObjectOrNullValue(thisObj));
    152  FixedInvokeArgs<3> args(cx);
    153  args[0].set(arg0);
    154  args[1].set(arg1);
    155  args[2].set(arg2);
    156  return Call(cx, fval, thisv, args, rval);
    157 }
    158 
    159 // Perform the above Call() operation using the given arguments.  Similar to
    160 // ConstructFromStack() below, this handles |!IsCallable(args.calleev())|.
    161 //
    162 // This internal operation is intended only for use with arguments known to be
    163 // on the JS stack, or at least in carefully-rooted memory. The vast majority of
    164 // potential users should instead use InvokeArgs in concert with Call().
    165 extern bool CallFromStack(JSContext* cx, const CallArgs& args,
    166                          CallReason reason = CallReason::Call);
    167 
    168 // ES6 7.3.13 Construct(F, argumentsList, newTarget).  All parameters are
    169 // required, hopefully forcing callers to be careful not to (say) blindly pass
    170 // callee as |newTarget| when a different value should have been passed.
    171 // Behavior is unspecified if any element of |args| isn't initialized.
    172 //
    173 // |rval| is written to *only* after |fval| and |newTarget| have been consumed,
    174 // so |rval| *may* alias either argument.
    175 //
    176 // NOTE: As with the ES6 spec operation, it's the caller's responsibility to
    177 //       ensure |fval| and |newTarget| are both |IsConstructor|.
    178 extern bool Construct(JSContext* cx, HandleValue fval,
    179                      const AnyConstructArgs& args, HandleValue newTarget,
    180                      MutableHandleObject objp);
    181 
    182 // Check that in the given |args|, which must be |args.isConstructing()|, that
    183 // |IsConstructor(args.callee())|. If this is not the case, throw a TypeError.
    184 // Otherwise, the user must ensure that, additionally,
    185 // |IsConstructor(args.newTarget())|. (If |args| comes directly from the
    186 // interpreter stack, as set up by JSOp::New, this comes for free.) Then perform
    187 // a Construct() operation using |args|.
    188 //
    189 // This internal operation is intended only for use with arguments known to be
    190 // on the JS stack, or at least in carefully-rooted memory. The vast majority of
    191 // potential users should instead use ConstructArgs in concert with Construct().
    192 extern bool ConstructFromStack(JSContext* cx, const CallArgs& args,
    193                               CallReason reason = CallReason::Call);
    194 
    195 // Call Construct(fval, args, newTarget), but use the given |thisv| as |this|
    196 // during construction of |fval|.
    197 //
    198 // |rval| is written to *only* after |fval|, |thisv|, and |newTarget| have been
    199 // consumed, so |rval| *may* alias any of these arguments.
    200 //
    201 // This method exists only for very rare cases where a |this| was created
    202 // caller-side for construction of |fval|: basically only for JITs using
    203 // |CreateThis|.  If that's not you, use Construct()!
    204 extern bool InternalConstructWithProvidedThis(JSContext* cx, HandleValue fval,
    205                                              HandleValue thisv,
    206                                              const AnyConstructArgs& args,
    207                                              HandleValue newTarget,
    208                                              MutableHandleValue rval);
    209 
    210 /*
    211 * Executes a script with the given envChain. To support debugging, the
    212 * evalInFrame parameter can point to an arbitrary frame in the context's call
    213 * stack to simulate executing an eval in that frame.
    214 */
    215 extern bool ExecuteKernel(JSContext* cx, HandleScript script,
    216                          HandleObject envChainArg,
    217                          AbstractFramePtr evalInFrame,
    218                          MutableHandleValue result);
    219 
    220 /* Execute a script with the given envChain as global code. */
    221 extern bool Execute(JSContext* cx, HandleScript script, HandleObject envChain,
    222                    MutableHandleValue rval);
    223 
    224 class ExecuteState;
    225 class InvokeState;
    226 
    227 // RunState is passed to RunScript and RunScript then either passes it to the
    228 // interpreter or to the JITs. RunState contains all information we need to
    229 // construct an interpreter or JIT frame.
    230 class MOZ_RAII RunState {
    231 protected:
    232  enum Kind { Execute, Invoke };
    233  Kind kind_;
    234 
    235  RootedScript script_;
    236 
    237  explicit RunState(JSContext* cx, Kind kind, JSScript* script)
    238      : kind_(kind), script_(cx, script) {}
    239 
    240 public:
    241  bool isExecute() const { return kind_ == Execute; }
    242  bool isInvoke() const { return kind_ == Invoke; }
    243 
    244  ExecuteState* asExecute() const {
    245    MOZ_ASSERT(isExecute());
    246    return (ExecuteState*)this;
    247  }
    248  InvokeState* asInvoke() const {
    249    MOZ_ASSERT(isInvoke());
    250    return (InvokeState*)this;
    251  }
    252 
    253  JS::HandleScript script() const { return script_; }
    254 
    255  InterpreterFrame* pushInterpreterFrame(JSContext* cx);
    256  inline void setReturnValue(const Value& v);
    257 
    258 private:
    259  RunState(const RunState& other) = delete;
    260  RunState(const ExecuteState& other) = delete;
    261  RunState(const InvokeState& other) = delete;
    262  void operator=(const RunState& other) = delete;
    263 };
    264 
    265 // Eval or global script.
    266 class MOZ_RAII ExecuteState : public RunState {
    267  HandleObject envChain_;
    268 
    269  AbstractFramePtr evalInFrame_;
    270  MutableHandleValue result_;
    271 
    272 public:
    273  ExecuteState(JSContext* cx, JSScript* script, HandleObject envChain,
    274               AbstractFramePtr evalInFrame, MutableHandleValue result)
    275      : RunState(cx, Execute, script),
    276        envChain_(envChain),
    277        evalInFrame_(evalInFrame),
    278        result_(result) {}
    279 
    280  JSObject* environmentChain() const { return envChain_; }
    281  bool isDebuggerEval() const { return !!evalInFrame_; }
    282 
    283  InterpreterFrame* pushInterpreterFrame(JSContext* cx);
    284 
    285  void setReturnValue(const Value& v) { result_.set(v); }
    286 };
    287 
    288 // Data to invoke a function.
    289 class MOZ_RAII InvokeState final : public RunState {
    290  const CallArgs& args_;
    291  MaybeConstruct construct_;
    292 
    293 public:
    294  InvokeState(JSContext* cx, const CallArgs& args, MaybeConstruct construct)
    295      : RunState(cx, Invoke, args.callee().as<JSFunction>().nonLazyScript()),
    296        args_(args),
    297        construct_(construct) {}
    298 
    299  bool constructing() const { return construct_; }
    300  const CallArgs& args() const { return args_; }
    301 
    302  InterpreterFrame* pushInterpreterFrame(JSContext* cx);
    303 
    304  void setReturnValue(const Value& v) { args_.rval().set(v); }
    305 };
    306 
    307 inline void RunState::setReturnValue(const Value& v) {
    308  if (isInvoke()) {
    309    asInvoke()->setReturnValue(v);
    310  } else {
    311    asExecute()->setReturnValue(v);
    312  }
    313 }
    314 
    315 extern bool RunScript(JSContext* cx, RunState& state);
    316 extern bool Interpret(JSContext* cx, RunState& state);
    317 
    318 extern JSType TypeOfObject(JSObject* obj);
    319 
    320 extern JSType TypeOfValue(const Value& v);
    321 
    322 // Implementation of
    323 // https://www.ecma-international.org/ecma-262/6.0/#sec-instanceofoperator
    324 extern bool InstanceofOperator(JSContext* cx, HandleObject obj, HandleValue v,
    325                               bool* bp);
    326 
    327 // Unwind environment chain and iterator to match the scope corresponding to
    328 // the given bytecode position.
    329 extern void UnwindEnvironment(JSContext* cx, EnvironmentIter& ei,
    330                              jsbytecode* pc);
    331 
    332 // Unwind all environments.
    333 extern void UnwindAllEnvironmentsInFrame(JSContext* cx, EnvironmentIter& ei);
    334 
    335 // Compute the pc needed to unwind the scope to the beginning of the block
    336 // pointed to by the try note.
    337 extern jsbytecode* UnwindEnvironmentToTryPc(JSScript* script,
    338                                            const TryNote* tn);
    339 
    340 namespace detail {
    341 
    342 template <class TryNoteFilter>
    343 class MOZ_STACK_CLASS BaseTryNoteIter {
    344  uint32_t pcOffset_;
    345  TryNoteFilter isTryNoteValid_;
    346 
    347  const TryNote* tn_;
    348  const TryNote* tnEnd_;
    349 
    350  void settle() {
    351    for (; tn_ != tnEnd_; ++tn_) {
    352      if (!pcInRange()) {
    353        continue;
    354      }
    355 
    356      /*  Try notes cannot be disjoint. That is, we can't have
    357       *  multiple notes with disjoint pc ranges jumping to the same
    358       *  catch block. This interacts awkwardly with for-of loops, in
    359       *  which calls to IteratorClose emitted due to abnormal
    360       *  completion (break, throw, return) are emitted inline, at the
    361       *  source location of the break, throw, or return
    362       *  statement. For example:
    363       *
    364       *      for (x of iter) {
    365       *        try { return; } catch (e) { }
    366       *      }
    367       *
    368       *  From the try-note nesting's perspective, the IteratorClose
    369       *  resulting from |return| is covered by the inner try, when it
    370       *  should not be. If IteratorClose throws, we don't want to
    371       *  catch it here.
    372       *
    373       *  To make this work, we use TryNoteKind::ForOfIterClose try-notes,
    374       *  which cover the range of the abnormal completion. When
    375       *  looking up trynotes, a for-of iterclose note indicates that
    376       *  the enclosing for-of has just been terminated. As a result,
    377       *  trynotes within that for-of are no longer active. When we
    378       *  see a for-of-iterclose, we skip ahead in the trynotes list
    379       *  until we see the matching for-of.
    380       *
    381       *  Breaking out of multiple levels of for-of at once is handled
    382       *  using nested TryNoteKind::ForOfIterClose try-notes. Consider this
    383       * code:
    384       *
    385       *  try {
    386       *    loop: for (i of first) {
    387       *      <A>
    388       *      for (j of second) {
    389       *        <B>
    390       *        break loop; // <C1/2>
    391       *      }
    392       *    }
    393       *  } catch {...}
    394       *
    395       *  Here is the mapping from various PCs to try-notes that we
    396       *  want to return:
    397       *
    398       *        A     B     C1     C2
    399       *        |     |     |      |
    400       *        |     |     |  [---|---]     ForOfIterClose (outer)
    401       *        |     | [---|------|---]     ForOfIterClose (inner)
    402       *        |  [--X-----|------|----]    ForOf (inner)
    403       *    [---X-----------X------|-----]   ForOf (outer)
    404       *  [------------------------X------]  TryCatch
    405       *
    406       *  - At A, we find the outer for-of.
    407       *  - At B, we find the inner for-of.
    408       *  - At C1, we find one TryNoteKind::ForOfIterClose, skip past one
    409       *    TryNoteKind::ForOf, and find the outer for-of. (This occurs if an
    410       *    exception is thrown while closing the inner iterator.)
    411       *  - At C2, we find two TryNoteKind::ForOfIterClose, skip past two
    412       *    TryNoteKind::ForOf, and reach the outer try-catch. (This occurs if
    413       *    an exception is thrown while closing the outer iterator.)
    414       */
    415      if (tn_->kind() == TryNoteKind::ForOfIterClose) {
    416        uint32_t iterCloseDepth = 1;
    417        do {
    418          ++tn_;
    419          MOZ_ASSERT(tn_ != tnEnd_);
    420          if (pcInRange()) {
    421            if (tn_->kind() == TryNoteKind::ForOfIterClose) {
    422              iterCloseDepth++;
    423            } else if (tn_->kind() == TryNoteKind::ForOf) {
    424              iterCloseDepth--;
    425            }
    426          }
    427        } while (iterCloseDepth > 0);
    428 
    429        // Advance to trynote following the enclosing for-of.
    430        continue;
    431      }
    432 
    433      /*
    434       * We have a note that covers the exception pc but we must check
    435       * whether the interpreter has already executed the corresponding
    436       * handler. This is possible when the executed bytecode implements
    437       * break or return from inside a for-in loop.
    438       *
    439       * In this case the emitter generates additional [enditer] and [goto]
    440       * opcodes to close all outstanding iterators and execute the finally
    441       * blocks. If such an [enditer] throws an exception, its pc can still
    442       * be inside several nested for-in loops and try-finally statements
    443       * even if we have already closed the corresponding iterators and
    444       * invoked the finally blocks.
    445       *
    446       * To address this, we make [enditer] always decrease the stack even
    447       * when its implementation throws an exception. Thus already executed
    448       * [enditer] and [goto] opcodes will have try notes with the stack
    449       * depth exceeding the current one and this condition is what we use to
    450       * filter them out.
    451       */
    452      if (tn_ == tnEnd_ || isTryNoteValid_(tn_)) {
    453        return;
    454      }
    455    }
    456  }
    457 
    458 public:
    459  BaseTryNoteIter(JSScript* script, jsbytecode* pc,
    460                  TryNoteFilter isTryNoteValid)
    461      : pcOffset_(script->pcToOffset(pc)), isTryNoteValid_(isTryNoteValid) {
    462    // NOTE: The Span is a temporary so we can't use begin()/end()
    463    // here or the iterator will outlive the span.
    464    auto trynotes = script->trynotes();
    465    tn_ = trynotes.data();
    466    tnEnd_ = tn_ + trynotes.size();
    467 
    468    settle();
    469  }
    470 
    471  void operator++() {
    472    ++tn_;
    473    settle();
    474  }
    475 
    476  bool pcInRange() const {
    477    // This checks both ends of the range at once
    478    // because unsigned integers wrap on underflow.
    479    uint32_t offset = pcOffset_;
    480    uint32_t start = tn_->start;
    481    uint32_t length = tn_->length;
    482    return offset - start < length;
    483  }
    484  bool done() const { return tn_ == tnEnd_; }
    485  const TryNote* operator*() const { return tn_; }
    486 };
    487 
    488 }  // namespace detail
    489 
    490 template <class TryNoteFilter>
    491 class MOZ_STACK_CLASS TryNoteIter
    492    : public detail::BaseTryNoteIter<TryNoteFilter> {
    493  using Base = detail::BaseTryNoteIter<TryNoteFilter>;
    494 
    495  // Keep the script alive as long as the iterator is live.
    496  RootedScript script_;
    497 
    498 public:
    499  TryNoteIter(JSContext* cx, JSScript* script, jsbytecode* pc,
    500              TryNoteFilter isTryNoteValid)
    501      : Base(script, pc, isTryNoteValid), script_(cx, script) {}
    502 };
    503 
    504 class NoOpTryNoteFilter {
    505 public:
    506  explicit NoOpTryNoteFilter() = default;
    507  bool operator()(const TryNote*) { return true; }
    508 };
    509 
    510 // Iterator over all try notes. Code using this iterator is not allowed to
    511 // trigger GC to make sure the script stays alive. See TryNoteIter above for the
    512 // can-GC version.
    513 class MOZ_STACK_CLASS TryNoteIterAllNoGC
    514    : public detail::BaseTryNoteIter<NoOpTryNoteFilter> {
    515  using Base = detail::BaseTryNoteIter<NoOpTryNoteFilter>;
    516  JS::AutoCheckCannotGC nogc;
    517 
    518 public:
    519  TryNoteIterAllNoGC(JSScript* script, jsbytecode* pc)
    520      : Base(script, pc, NoOpTryNoteFilter()) {}
    521 };
    522 
    523 bool HandleClosingGeneratorReturn(JSContext* cx, AbstractFramePtr frame,
    524                                  bool ok);
    525 
    526 /************************************************************************/
    527 
    528 bool ThrowOperation(JSContext* cx, HandleValue v);
    529 
    530 bool ThrowWithStackOperation(JSContext* cx, HandleValue v, HandleValue stack);
    531 
    532 bool GetPendingExceptionStack(JSContext* cx, MutableHandleValue vp);
    533 
    534 bool GetProperty(JSContext* cx, HandleValue value, Handle<PropertyName*> name,
    535                 MutableHandleValue vp);
    536 
    537 JSObject* LambdaBaselineFallback(JSContext* cx, HandleFunction fun,
    538                                 HandleObject parent, gc::AllocSite* site);
    539 JSObject* LambdaOptimizedFallback(JSContext* cx, HandleFunction fun,
    540                                  HandleObject parent, gc::Heap heap);
    541 JSObject* Lambda(JSContext* cx, HandleFunction fun, HandleObject parent,
    542                 gc::Heap heap = gc::Heap::Default,
    543                 gc::AllocSite* site = nullptr);
    544 
    545 bool SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index,
    546                      HandleValue value, bool strict);
    547 
    548 bool SetObjectElementWithReceiver(JSContext* cx, HandleObject obj,
    549                                  HandleValue index, HandleValue value,
    550                                  HandleValue receiver, bool strict);
    551 
    552 bool AddValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
    553               MutableHandleValue res);
    554 
    555 bool SubValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
    556               MutableHandleValue res);
    557 
    558 bool MulValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
    559               MutableHandleValue res);
    560 
    561 bool DivValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
    562               MutableHandleValue res);
    563 
    564 bool ModValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
    565               MutableHandleValue res);
    566 
    567 bool PowValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
    568               MutableHandleValue res);
    569 
    570 bool BitNot(JSContext* cx, MutableHandleValue in, MutableHandleValue res);
    571 
    572 bool BitXor(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
    573            MutableHandleValue res);
    574 
    575 bool BitOr(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
    576           MutableHandleValue res);
    577 
    578 bool BitAnd(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
    579            MutableHandleValue res);
    580 
    581 bool BitLsh(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
    582            MutableHandleValue res);
    583 
    584 bool BitRsh(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
    585            MutableHandleValue res);
    586 
    587 bool UrshValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
    588                MutableHandleValue res);
    589 
    590 bool LessThan(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
    591              bool* res);
    592 
    593 bool LessThanOrEqual(JSContext* cx, MutableHandleValue lhs,
    594                     MutableHandleValue rhs, bool* res);
    595 
    596 bool GreaterThan(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
    597                 bool* res);
    598 
    599 bool GreaterThanOrEqual(JSContext* cx, MutableHandleValue lhs,
    600                        MutableHandleValue rhs, bool* res);
    601 
    602 template <bool strict>
    603 bool DelPropOperation(JSContext* cx, HandleValue val,
    604                      Handle<PropertyName*> name, bool* res);
    605 
    606 template <bool strict>
    607 bool DelElemOperation(JSContext* cx, HandleValue val, HandleValue index,
    608                      bool* res);
    609 
    610 JSObject* BindVarOperation(JSContext* cx, JSObject* envChain);
    611 
    612 JSObject* ImportMetaOperation(JSContext* cx, HandleScript script);
    613 
    614 JSObject* BuiltinObjectOperation(JSContext* cx, BuiltinObjectKind kind);
    615 
    616 bool ThrowMsgOperation(JSContext* cx, const unsigned throwMsgKind);
    617 
    618 bool GetAndClearException(JSContext* cx, MutableHandleValue res);
    619 
    620 bool GetAndClearExceptionAndStack(JSContext* cx, MutableHandleValue res,
    621                                  MutableHandle<SavedFrame*> stack);
    622 
    623 bool DeleteNameOperation(JSContext* cx, Handle<PropertyName*> name,
    624                         HandleObject envChain, MutableHandleValue res);
    625 
    626 void ImplicitThisOperation(JSContext* cx, HandleObject env,
    627                           MutableHandleValue res);
    628 
    629 bool InitPropGetterSetterOperation(JSContext* cx, jsbytecode* pc,
    630                                   HandleObject obj, Handle<PropertyName*> name,
    631                                   HandleObject val);
    632 
    633 unsigned GetInitDataPropAttrs(JSOp op);
    634 
    635 bool EnterWithOperation(JSContext* cx, AbstractFramePtr frame, HandleValue val,
    636                        Handle<WithScope*> scope);
    637 
    638 bool InitElemGetterSetterOperation(JSContext* cx, jsbytecode* pc,
    639                                   HandleObject obj, HandleValue idval,
    640                                   HandleObject val);
    641 
    642 bool SpreadCallOperation(JSContext* cx, HandleScript script, jsbytecode* pc,
    643                         HandleValue thisv, HandleValue callee, HandleValue arr,
    644                         HandleValue newTarget, MutableHandleValue res);
    645 
    646 bool OptimizeSpreadCall(JSContext* cx, HandleValue arg,
    647                        MutableHandleValue result);
    648 
    649 bool OptimizeGetIterator(Value arg, JSContext* cx);
    650 
    651 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    652 enum class SyncDisposalClosureSlots : uint8_t {
    653  Method,
    654 };
    655 bool SyncDisposalClosure(JSContext* cx, unsigned argc, JS::Value* vp);
    656 
    657 ErrorObject* CreateSuppressedError(JSContext* cx, JS::Handle<JS::Value> error,
    658                                   JS::Handle<JS::Value> suppressed);
    659 
    660 bool AddDisposableResourceToCapability(JSContext* cx, JS::Handle<JSObject*> env,
    661                                       JS::Handle<JS::Value> val,
    662                                       JS::Handle<JS::Value> method,
    663                                       bool needsClosure, UsingHint hint);
    664 #endif
    665 
    666 ArrayObject* ArrayFromArgumentsObject(JSContext* cx,
    667                                      Handle<ArgumentsObject*> args);
    668 
    669 JSObject* NewObjectOperation(JSContext* cx, HandleScript script,
    670                             const jsbytecode* pc);
    671 
    672 JSObject* NewPlainObjectBaselineFallback(JSContext* cx,
    673                                         Handle<SharedShape*> shape,
    674                                         gc::AllocKind allocKind,
    675                                         gc::AllocSite* site);
    676 
    677 JSObject* NewPlainObjectOptimizedFallback(JSContext* cx,
    678                                          Handle<SharedShape*> shape,
    679                                          gc::AllocKind allocKind,
    680                                          gc::Heap initialHeap);
    681 
    682 ArrayObject* NewArrayOperation(JSContext* cx, uint32_t length,
    683                               NewObjectKind newKind = GenericObject);
    684 
    685 // Called from JIT code when inline array allocation fails.
    686 ArrayObject* NewArrayObjectBaselineFallback(JSContext* cx, uint32_t length,
    687                                            gc::AllocKind allocKind,
    688                                            gc::AllocSite* site);
    689 ArrayObject* NewArrayObjectOptimizedFallback(JSContext* cx, uint32_t length,
    690                                             gc::AllocKind allocKind,
    691                                             NewObjectKind newKind);
    692 
    693 [[nodiscard]] bool GetImportOperation(JSContext* cx, HandleObject envChain,
    694                                      HandleScript script, jsbytecode* pc,
    695                                      MutableHandleValue vp);
    696 
    697 void ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber,
    698                               HandleId id);
    699 
    700 void ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber,
    701                               Handle<PropertyName*> name);
    702 
    703 void ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber,
    704                               HandleScript script, jsbytecode* pc);
    705 
    706 void ReportInNotObjectError(JSContext* cx, HandleValue lref, HandleValue rref);
    707 
    708 bool ThrowCheckIsObject(JSContext* cx, CheckIsObjectKind kind);
    709 
    710 bool ThrowUninitializedThis(JSContext* cx);
    711 
    712 bool ThrowInitializedThis(JSContext* cx);
    713 
    714 bool ThrowObjectCoercible(JSContext* cx, HandleValue value);
    715 
    716 bool Debug_CheckSelfHosted(JSContext* cx, HandleValue funVal);
    717 
    718 bool CheckClassHeritageOperation(JSContext* cx, HandleValue heritage);
    719 
    720 PlainObject* ObjectWithProtoOperation(JSContext* cx, HandleValue proto);
    721 
    722 JSObject* FunWithProtoOperation(JSContext* cx, HandleFunction fun,
    723                                HandleObject parent, HandleObject proto);
    724 
    725 bool SetPropertySuper(JSContext* cx, HandleValue lval, HandleValue receiver,
    726                      Handle<PropertyName*> name, HandleValue rval,
    727                      bool strict);
    728 
    729 bool SetElementSuper(JSContext* cx, HandleValue lval, HandleValue receiver,
    730                     HandleValue index, HandleValue rval, bool strict);
    731 
    732 bool LoadAliasedDebugVar(JSContext* cx, JSObject* env, jsbytecode* pc,
    733                         MutableHandleValue result);
    734 
    735 bool CloseIterOperation(JSContext* cx, HandleObject iter, CompletionKind kind);
    736 } /* namespace js */
    737 
    738 #endif /* vm_Interpreter_h */