tor-browser

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

RematerializedFrame.h (7432B)


      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 jit_RematerializedFrame_h
      8 #define jit_RematerializedFrame_h
      9 
     10 #include "mozilla/Assertions.h"
     11 
     12 #include <algorithm>
     13 #include <stddef.h>
     14 #include <stdint.h>
     15 
     16 #include "jstypes.h"
     17 
     18 #include "jit/JitFrames.h"
     19 #include "jit/ScriptFromCalleeToken.h"
     20 #include "js/GCVector.h"
     21 #include "js/TypeDecls.h"
     22 #include "js/UniquePtr.h"
     23 #include "js/Value.h"
     24 #include "vm/JSFunction.h"
     25 #include "vm/JSScript.h"
     26 #include "vm/Stack.h"
     27 
     28 class JS_PUBLIC_API JSTracer;
     29 
     30 namespace js {
     31 
     32 class ArgumentsObject;
     33 class CallObject;
     34 
     35 namespace jit {
     36 
     37 class InlineFrameIterator;
     38 struct MaybeReadFallback;
     39 
     40 // RematerializedFrame: An optimized frame that has been rematerialized with
     41 // values read out of Snapshots.
     42 //
     43 // If the Debugger API tries to inspect or modify an IonMonkey frame, much of
     44 // the information it expects to find in a frame is missing: function calls may
     45 // have been inlined, variables may have been optimized out, and so on. So when
     46 // this happens, SpiderMonkey builds one or more Rematerialized frames from the
     47 // IonMonkey frame, using the snapshot metadata built by Ion to reconstruct the
     48 // missing parts. The Rematerialized frames are now the authority on the state
     49 // of those frames, and the Ion frame is ignored: stack iterators ignore the Ion
     50 // frame, producing the Rematerialized frames in their stead; and when control
     51 // returns to the Ion frame, we pop it, rebuild Baseline frames from the
     52 // Rematerialized frames, and resume execution in Baseline.
     53 class RematerializedFrame {
     54  // See DebugScopes::updateLiveScopes.
     55  bool prevUpToDate_;
     56 
     57  // Propagated to the Baseline frame once this is popped.
     58  bool isDebuggee_;
     59 
     60  // Has an initial environment has been pushed on the environment chain for
     61  // function frames that need a CallObject or eval frames that need a
     62  // VarEnvironmentObject?
     63  bool hasInitialEnv_;
     64 
     65  // Is this frame constructing?
     66  bool isConstructing_;
     67 
     68  // If true, this frame has been on the stack when
     69  // |js::SavedStacks::saveCurrentStack| was called, and so there is a
     70  // |js::SavedFrame| object cached for this frame.
     71  bool hasCachedSavedFrame_;
     72 
     73  // The fp of the top frame associated with this possibly inlined frame.
     74  uint8_t* top_;
     75 
     76  // The bytecode at the time of rematerialization.
     77  jsbytecode* pc_;
     78 
     79  size_t frameNo_;
     80  unsigned numActualArgs_;
     81 
     82  JSScript* script_;
     83  JSObject* envChain_;
     84  JSFunction* callee_;
     85  ArgumentsObject* argsObj_;
     86 
     87  Value returnValue_;
     88  Value thisArgument_;
     89  Value slots_[1];
     90 
     91  RematerializedFrame(JSContext* cx, uint8_t* top, unsigned numActualArgs,
     92                      InlineFrameIterator& iter, MaybeReadFallback& fallback);
     93 
     94 public:
     95  static RematerializedFrame* New(JSContext* cx, uint8_t* top,
     96                                  InlineFrameIterator& iter,
     97                                  MaybeReadFallback& fallback);
     98 
     99  // RematerializedFrame are allocated on non-GC heap, so use GCVector and
    100  // UniquePtr to ensure they are traced and cleaned up correctly.
    101  using RematerializedFrameVector = GCVector<UniquePtr<RematerializedFrame>>;
    102 
    103  // Rematerialize all remaining frames pointed to by |iter| into |frames|
    104  // in older-to-younger order, e.g., frames[0] is the oldest frame.
    105  [[nodiscard]] static bool RematerializeInlineFrames(
    106      JSContext* cx, uint8_t* top, InlineFrameIterator& iter,
    107      MaybeReadFallback& fallback, RematerializedFrameVector& frames);
    108 
    109  bool prevUpToDate() const { return prevUpToDate_; }
    110  void setPrevUpToDate() { prevUpToDate_ = true; }
    111  void unsetPrevUpToDate() { prevUpToDate_ = false; }
    112 
    113  bool isDebuggee() const { return isDebuggee_; }
    114  void setIsDebuggee() { isDebuggee_ = true; }
    115  inline void unsetIsDebuggee();
    116 
    117  uint8_t* top() const { return top_; }
    118  JSScript* outerScript() const {
    119    JitFrameLayout* jsFrame = (JitFrameLayout*)top_;
    120    return ScriptFromCalleeToken(jsFrame->calleeToken());
    121  }
    122  jsbytecode* pc() const { return pc_; }
    123  size_t frameNo() const { return frameNo_; }
    124  bool inlined() const { return frameNo_ > 0; }
    125 
    126  JSObject* environmentChain() const { return envChain_; }
    127 
    128  template <typename SpecificEnvironment>
    129  void pushOnEnvironmentChain(SpecificEnvironment& env) {
    130    MOZ_ASSERT(*environmentChain() == env.enclosingEnvironment());
    131    envChain_ = &env;
    132    if (IsFrameInitialEnvironment(this, env)) {
    133      hasInitialEnv_ = true;
    134    }
    135  }
    136 
    137  template <typename SpecificEnvironment>
    138  void popOffEnvironmentChain() {
    139    MOZ_ASSERT(envChain_->is<SpecificEnvironment>());
    140    envChain_ = &envChain_->as<SpecificEnvironment>().enclosingEnvironment();
    141  }
    142 
    143  [[nodiscard]] bool initFunctionEnvironmentObjects(JSContext* cx);
    144  [[nodiscard]] bool pushVarEnvironment(JSContext* cx, Handle<Scope*> scope);
    145 
    146  bool hasInitialEnvironment() const { return hasInitialEnv_; }
    147  CallObject& callObj() const;
    148 
    149  bool hasArgsObj() const { return !!argsObj_; }
    150  ArgumentsObject& argsObj() const {
    151    MOZ_ASSERT(hasArgsObj());
    152    MOZ_ASSERT(script()->needsArgsObj());
    153    return *argsObj_;
    154  }
    155 
    156  bool isFunctionFrame() const { return script_->isFunction(); }
    157  bool isGlobalFrame() const { return script_->isGlobalCode(); }
    158  bool isModuleFrame() const { return script_->isModule(); }
    159 
    160  JSScript* script() const { return script_; }
    161  JSFunction* callee() const {
    162    MOZ_ASSERT(isFunctionFrame());
    163    MOZ_ASSERT(callee_);
    164    return callee_;
    165  }
    166  Value calleev() const { return ObjectValue(*callee()); }
    167  Value& thisArgument() { return thisArgument_; }
    168 
    169  bool isConstructing() const { return isConstructing_; }
    170 
    171  bool hasCachedSavedFrame() const { return hasCachedSavedFrame_; }
    172 
    173  void setHasCachedSavedFrame() { hasCachedSavedFrame_ = true; }
    174 
    175  void clearHasCachedSavedFrame() { hasCachedSavedFrame_ = false; }
    176 
    177  unsigned numFormalArgs() const {
    178    return isFunctionFrame() ? callee()->nargs() : 0;
    179  }
    180  unsigned numActualArgs() const { return numActualArgs_; }
    181  unsigned numArgSlots() const {
    182    return (std::max)(numFormalArgs(), numActualArgs());
    183  }
    184 
    185  Value* argv() { return slots_; }
    186  Value* locals() { return slots_ + numArgSlots(); }
    187 
    188  Value& unaliasedLocal(unsigned i) {
    189    MOZ_ASSERT(i < script()->nfixed());
    190    return locals()[i];
    191  }
    192  Value& unaliasedFormal(unsigned i,
    193                         MaybeCheckAliasing checkAliasing = CHECK_ALIASING) {
    194    MOZ_ASSERT(i < numFormalArgs());
    195    MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals() &&
    196                                     !script()->formalIsAliased(i));
    197    return argv()[i];
    198  }
    199  Value& unaliasedActual(unsigned i,
    200                         MaybeCheckAliasing checkAliasing = CHECK_ALIASING) {
    201    MOZ_ASSERT(i < numActualArgs());
    202    MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
    203    MOZ_ASSERT_IF(checkAliasing && i < numFormalArgs(),
    204                  !script()->formalIsAliased(i));
    205    return argv()[i];
    206  }
    207 
    208  void setReturnValue(const Value& value) { returnValue_ = value; }
    209 
    210  Value& returnValue() {
    211    MOZ_ASSERT(!script()->noScriptRval());
    212    return returnValue_;
    213  }
    214 
    215  void trace(JSTracer* trc);
    216  void dump();
    217 };
    218 
    219 }  // namespace jit
    220 }  // namespace js
    221 
    222 #endif  // jit_RematerializedFrame_h