Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/js/src/jit/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 18 kB image not shown  

Quelle  WarpSnapshot.h   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: set ts=8 sts=2 et sw=2 tw=80:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#ifndef jit_WarpSnapshot_h
#define jit_WarpSnapshot_h

#include "mozilla/LinkedList.h"
#include "mozilla/Variant.h"

#include "builtin/ModuleObject.h"
#include "jit/JitAllocPolicy.h"
#include "jit/JitContext.h"
#include "jit/JitZone.h"
#include "jit/OffthreadSnapshot.h"
#include "jit/TypeData.h"
#include "vm/EnvironmentObject.h"
#include "vm/FunctionFlags.h"  // js::FunctionFlags

namespace js {

class ArgumentsObject;
class CallObject;
class GlobalLexicalEnvironmentObject;
class LexicalEnvironmentObject;
class ModuleEnvironmentObject;
class NamedLambdaObject;

namespace jit {

class CacheIRStubInfo;
class CompileInfo;
class WarpScriptSnapshot;

#define WARP_OP_SNAPSHOT_LIST(_) \
  _(WarpArguments)               \
  _(WarpRegExp)                  \
  _(WarpBuiltinObject)           \
  _(WarpGetIntrinsic)            \
  _(WarpGetImport)               \
  _(WarpRest)                    \
  _(WarpBindUnqualifiedGName)    \
  _(WarpVarEnvironment)          \
  _(WarpLexicalEnvironment)      \
  _(WarpClassBodyEnvironment)    \
  _(WarpBailout)                 \
  _(WarpCacheIR)                 \
  _(WarpInlinedCall)             \
  _(WarpPolymorphicTypes)

// WarpOpSnapshot is the base class for data attached to a single bytecode op by
// WarpOracle. This is typically data that WarpBuilder can't read off-thread
// without racing.
class WarpOpSnapshot : public TempObject,
                       public mozilla::LinkedListElement<WarpOpSnapshot> {
 public:
  enum class Kind : uint16_t {
#define DEF_KIND(KIND) KIND,
    WARP_OP_SNAPSHOT_LIST(DEF_KIND)
#undef DEF_KIND
  };

 private:
  // Bytecode offset.
  uint32_t offset_ = 0;

  Kind kind_;

 protected:
  WarpOpSnapshot(Kind kind, uint32_t offset) : offset_(offset), kind_(kind) {}

 public:
  uint32_t offset() const { return offset_; }
  Kind kind() const { return kind_; }

  template <typename T>
  const T* as() const {
    MOZ_ASSERT(kind_ == T::ThisKind);
    return static_cast<const T*>(this);
  }

  template <typename T>
  T* as() {
    MOZ_ASSERT(kind_ == T::ThisKind);
    return static_cast<T*>(this);
  }

  void trace(JSTracer* trc);

#ifdef JS_JITSPEW
  void dump(GenericPrinter& out, JSScript* script) const;
#endif
};

using WarpOpSnapshotList = mozilla::LinkedList<WarpOpSnapshot>;

// Template object for JSOp::Arguments.
class WarpArguments : public WarpOpSnapshot {
  // Note: this can be nullptr if the realm has no template object yet.
  OffthreadGCPtr<ArgumentsObject*> templateObj_;

 public:
  static constexpr Kind ThisKind = Kind::WarpArguments;

  WarpArguments(uint32_t offset, ArgumentsObject* templateObj)
      : WarpOpSnapshot(ThisKind, offset), templateObj_(templateObj) {}
  ArgumentsObject* templateObj() const { return templateObj_; }

  void traceData(JSTracer* trc);

#ifdef JS_JITSPEW
  void dumpData(GenericPrinter& out) const;
#endif
};

// The "has RegExpShared" state for JSOp::RegExp's template object.
class WarpRegExp : public WarpOpSnapshot {
  bool hasShared_;

 public:
  static constexpr Kind ThisKind = Kind::WarpRegExp;

  WarpRegExp(uint32_t offset, bool hasShared)
      : WarpOpSnapshot(ThisKind, offset), hasShared_(hasShared) {}
  bool hasShared() const { return hasShared_; }

  void traceData(JSTracer* trc);

#ifdef JS_JITSPEW
  void dumpData(GenericPrinter& out) const;
#endif
};

// The object for JSOp::BuiltinObject if it exists at compile-time.
class WarpBuiltinObject : public WarpOpSnapshot {
  OffthreadGCPtr<JSObject*> builtin_;

 public:
  static constexpr Kind ThisKind = Kind::WarpBuiltinObject;

  WarpBuiltinObject(uint32_t offset, JSObject* builtin)
      : WarpOpSnapshot(ThisKind, offset), builtin_(builtin) {
    MOZ_ASSERT(builtin);
  }
  JSObject* builtin() const { return builtin_; }

  void traceData(JSTracer* trc);

#ifdef JS_JITSPEW
  void dumpData(GenericPrinter& out) const;
#endif
};

// The intrinsic for JSOp::GetIntrinsic if it exists at compile-time.
class WarpGetIntrinsic : public WarpOpSnapshot {
  OffthreadGCPtr<Value> intrinsic_;

 public:
  static constexpr Kind ThisKind = Kind::WarpGetIntrinsic;

  WarpGetIntrinsic(uint32_t offset, const Value& intrinsic)
      : WarpOpSnapshot(ThisKind, offset), intrinsic_(intrinsic) {}
  Value intrinsic() const { return intrinsic_; }

  void traceData(JSTracer* trc);

#ifdef JS_JITSPEW
  void dumpData(GenericPrinter& out) const;
#endif
};

// Target module environment and slot information for JSOp::GetImport.
class WarpGetImport : public WarpOpSnapshot {
  OffthreadGCPtr<ModuleEnvironmentObject*> targetEnv_;
  uint32_t numFixedSlots_;
  uint32_t slot_;
  bool needsLexicalCheck_;

 public:
  static constexpr Kind ThisKind = Kind::WarpGetImport;

  WarpGetImport(uint32_t offset, ModuleEnvironmentObject* targetEnv,
                uint32_t numFixedSlots, uint32_t slot, bool needsLexicalCheck)
      : WarpOpSnapshot(ThisKind, offset),
        targetEnv_(targetEnv),
        numFixedSlots_(numFixedSlots),
        slot_(slot),
        needsLexicalCheck_(needsLexicalCheck) {}
  ModuleEnvironmentObject* targetEnv() const { return targetEnv_; }
  uint32_t numFixedSlots() const { return numFixedSlots_; }
  uint32_t slot() const { return slot_; }
  bool needsLexicalCheck() const { return needsLexicalCheck_; }

  void traceData(JSTracer* trc);

#ifdef JS_JITSPEW
  void dumpData(GenericPrinter& out) const;
#endif
};

// Informs WarpBuilder that an IC site is cold and execution should bail out.
class WarpBailout : public WarpOpSnapshot {
 public:
  static constexpr Kind ThisKind = Kind::WarpBailout;

  explicit WarpBailout(uint32_t offset) : WarpOpSnapshot(ThisKind, offset) {}

  void traceData(JSTracer* trc);

#ifdef JS_JITSPEW
  void dumpData(GenericPrinter& out) const;
#endif
};

// Information from a Baseline IC stub.
class WarpCacheIR : public WarpOpSnapshot {
  // Baseline stub code. Stored here to keep the CacheIRStubInfo alive.
  OffthreadGCPtr<JitCode*> stubCode_;
  const CacheIRStubInfo* stubInfo_;

  // Copied Baseline stub data. Allocated in the same LifoAlloc.
  const uint8_t* stubData_;

 public:
  static constexpr Kind ThisKind = Kind::WarpCacheIR;

  WarpCacheIR(uint32_t offset, JitCode* stubCode,
              const CacheIRStubInfo* stubInfo, const uint8_t* stubData)
      : WarpOpSnapshot(ThisKind, offset),
        stubCode_(stubCode),
        stubInfo_(stubInfo),
        stubData_(stubData) {}

  const CacheIRStubInfo* stubInfo() const { return stubInfo_; }
  const uint8_t* stubData() const { return stubData_; }

  void traceData(JSTracer* trc);

#ifdef JS_JITSPEW
  void dumpData(GenericPrinter& out) const;
#endif
};

// [SMDOC] Warp Nursery Object support
//
// CacheIR stub data can contain nursery allocated objects. This can happen for
// example for GuardSpecificObject/GuardSpecificFunction or GuardProto.
//
// To support nursery GCs in parallel with off-thread compilation, we use the
// following mechanism:
//
// * When WarpOracle copies stub data, it builds a Vector of nursery objects.
//   The nursery object pointers in the stub data are replaced with the
//   corresponding index into this Vector.
//   See WarpScriptOracle::replaceNurseryPointers.
//
// * The Vector is copied to the snapshot and, at the end of compilation, to
//   the IonScript. The Vector is only accessed on the main thread.
//
// * The MIR backend never accesses the raw JSObject*. Instead, it uses
//   MNurseryObject which will load the object at runtime from the IonScript.
//
// WarpObjectField is a helper class to encode/decode a stub data field that
// either stores an object or a nursery index.
class WarpObjectField {
  // This is a nursery index if the low bit is set. Else it's a JSObject*.
  static constexpr uintptr_t NurseryIndexTag = 0x1;
  static constexpr uintptr_t NurseryIndexShift = 1;

  uintptr_t data_;

  explicit WarpObjectField(uintptr_t data) : data_(data) {}

 public:
  static WarpObjectField fromData(uintptr_t data) {
    return WarpObjectField(data);
  }
  static WarpObjectField fromObject(JSObject* obj) {
    return WarpObjectField(uintptr_t(obj));
  }
  static WarpObjectField fromNurseryIndex(uint32_t index) {
    uintptr_t data = (uintptr_t(index) << NurseryIndexShift) | NurseryIndexTag;
    return WarpObjectField(data);
  }

  uintptr_t rawData() const { return data_; }

  bool isNurseryIndex() const { return (data_ & NurseryIndexTag) != 0; }

  uint32_t toNurseryIndex() const {
    MOZ_ASSERT(isNurseryIndex());
    return data_ >> NurseryIndexShift;
  }

  JSObject* toObject() const {
    MOZ_ASSERT(!isNurseryIndex());
    return reinterpret_cast<JSObject*>(data_);
  }
};

// Information for inlining a scripted call IC.
class WarpInlinedCall : public WarpOpSnapshot {
  // Used for generating the correct guards.
  WarpCacheIR* cacheIRSnapshot_;

  // Used for generating the inlined code.
  WarpScriptSnapshot* scriptSnapshot_;
  CompileInfo* info_;

 public:
  static constexpr Kind ThisKind = Kind::WarpInlinedCall;

  WarpInlinedCall(uint32_t offset, WarpCacheIR* cacheIRSnapshot,
                  WarpScriptSnapshot* scriptSnapshot, CompileInfo* info)
      : WarpOpSnapshot(ThisKind, offset),
        cacheIRSnapshot_(cacheIRSnapshot),
        scriptSnapshot_(scriptSnapshot),
        info_(info) {}

  WarpCacheIR* cacheIRSnapshot() const { return cacheIRSnapshot_; }
  WarpScriptSnapshot* scriptSnapshot() const { return scriptSnapshot_; }
  CompileInfo* info() const { return info_; }

  void traceData(JSTracer* trc);

#ifdef JS_JITSPEW
  void dumpData(GenericPrinter& out) const;
#endif
};

// Information for inlining an ordered set of types
class WarpPolymorphicTypes : public WarpOpSnapshot {
  TypeDataList list_;

 public:
  static constexpr Kind ThisKind = Kind::WarpPolymorphicTypes;

  WarpPolymorphicTypes(uint32_t offset, TypeDataList list)
      : WarpOpSnapshot(ThisKind, offset), list_(list) {}

  const TypeDataList& list() const { return list_; }

  void traceData(JSTracer* trc);

#ifdef JS_JITSPEW
  void dumpData(GenericPrinter& out) const;
#endif
};

// Shape for JSOp::Rest.
class WarpRest : public WarpOpSnapshot {
  OffthreadGCPtr<Shape*> shape_;

 public:
  static constexpr Kind ThisKind = Kind::WarpRest;

  WarpRest(uint32_t offset, Shape* shape)
      : WarpOpSnapshot(ThisKind, offset), shape_(shape) {}

  Shape* shape() const { return shape_; }

  void traceData(JSTracer* trc);

#ifdef JS_JITSPEW
  void dumpData(GenericPrinter& out) const;
#endif
};

// Global environment for BindUnqualifiedGName
class WarpBindUnqualifiedGName : public WarpOpSnapshot {
  OffthreadGCPtr<JSObject*> globalEnv_;

 public:
  static constexpr Kind ThisKind = Kind::WarpBindUnqualifiedGName;

  WarpBindUnqualifiedGName(uint32_t offset, JSObject* globalEnv)
      : WarpOpSnapshot(ThisKind, offset), globalEnv_(globalEnv) {}

  JSObject* globalEnv() const { return globalEnv_; }

  void traceData(JSTracer* trc);

#ifdef JS_JITSPEW
  void dumpData(GenericPrinter& out) const;
#endif
};

// Block environment for PushVarEnv
class WarpVarEnvironment : public WarpOpSnapshot {
  OffthreadGCPtr<VarEnvironmentObject*> templateObj_;

 public:
  static constexpr Kind ThisKind = Kind::WarpVarEnvironment;

  WarpVarEnvironment(uint32_t offset, VarEnvironmentObject* templateObj)
      : WarpOpSnapshot(ThisKind, offset), templateObj_(templateObj) {}

  VarEnvironmentObject* templateObj() const { return templateObj_; }

  void traceData(JSTracer* trc);

#ifdef JS_JITSPEW
  void dumpData(GenericPrinter& out) const;
#endif
};

// Block environment for PushLexicalEnv, FreshenLexicalEnv, RecreateLexicalEnv
class WarpLexicalEnvironment : public WarpOpSnapshot {
  OffthreadGCPtr<BlockLexicalEnvironmentObject*> templateObj_;

 public:
  static constexpr Kind ThisKind = Kind::WarpLexicalEnvironment;

  WarpLexicalEnvironment(uint32_t offset,
                         BlockLexicalEnvironmentObject* templateObj)
      : WarpOpSnapshot(ThisKind, offset), templateObj_(templateObj) {}

  BlockLexicalEnvironmentObject* templateObj() const { return templateObj_; }

  void traceData(JSTracer* trc);

#ifdef JS_JITSPEW
  void dumpData(GenericPrinter& out) const;
#endif
};

// Class body lexical environment for PushClassBodyEnv
class WarpClassBodyEnvironment : public WarpOpSnapshot {
  OffthreadGCPtr<ClassBodyLexicalEnvironmentObject*> templateObj_;

 public:
  static constexpr Kind ThisKind = Kind::WarpClassBodyEnvironment;

  WarpClassBodyEnvironment(uint32_t offset,
                           ClassBodyLexicalEnvironmentObject* templateObj)
      : WarpOpSnapshot(ThisKind, offset), templateObj_(templateObj) {}

  ClassBodyLexicalEnvironmentObject* templateObj() const {
    return templateObj_;
  }

  void traceData(JSTracer* trc);

#ifdef JS_JITSPEW
  void dumpData(GenericPrinter& out) const;
#endif
};

struct NoEnvironment {};
using ConstantObjectEnvironment = OffthreadGCPtr<JSObject*>;
struct FunctionEnvironment {
  OffthreadGCPtr<CallObject*> callObjectTemplate;
  OffthreadGCPtr<NamedLambdaObject*> namedLambdaTemplate;

 public:
  FunctionEnvironment(CallObject* callObjectTemplate,
                      NamedLambdaObject* namedLambdaTemplate)
      : callObjectTemplate(callObjectTemplate),
        namedLambdaTemplate(namedLambdaTemplate) {}
};

// Snapshot data for the environment object(s) created in the script's prologue.
//
// One of:
//
// * NoEnvironment: No environment object should be set. Leave the slot
//   initialized to |undefined|.
//
// * ConstantObjectEnvironment: Use this JSObject* as environment object.
//
// * FunctionEnvironment: Use the callee's environment chain. Optionally
//   allocate a new NamedLambdaObject and/or CallObject based on
//   namedLambdaTemplate and callObjectTemplate.
using WarpEnvironment =
    mozilla::Variant<NoEnvironment, ConstantObjectEnvironment,
                     FunctionEnvironment>;

// Snapshot data for a single JSScript.
class WarpScriptSnapshot
    : public TempObject,
      public mozilla::LinkedListElement<WarpScriptSnapshot> {
  OffthreadGCPtr<JSScript*> script_;
  WarpEnvironment environment_;
  WarpOpSnapshotList opSnapshots_;

  // If the script has a JSOp::ImportMeta op, this is the module to bake in.
  OffthreadGCPtr<ModuleObject*> moduleObject_;

  // Whether this script is for an arrow function.
  bool isArrowFunction_;

 public:
  WarpScriptSnapshot(JSScript* script, const WarpEnvironment& env,
                     WarpOpSnapshotList&& opSnapshots,
                     ModuleObject* moduleObject);

  JSScript* script() const { return script_; }
  const WarpEnvironment& environment() const { return environment_; }
  const WarpOpSnapshotList& opSnapshots() const { return opSnapshots_; }
  ModuleObject* moduleObject() const { return moduleObject_; }

  bool isArrowFunction() const { return isArrowFunction_; }

  void trace(JSTracer* trc);

#ifdef JS_JITSPEW
  void dump(GenericPrinter& out) const;
#endif
};

// Captures information from previous bailouts to prevent bailout/recompile
// loops.
class WarpBailoutInfo {
  // True if any script in the compilation has the failedBoundsCheck flag. In
  // this case mark bounds checks as non-movable to prevent hoisting them in
  // TryEliminateBoundsCheck.
  bool failedBoundsCheck_ = false;

  // True if any script in the compilation has the failedLexicalCheck flag. In
  // this case mark lexical checks as non-movable.
  bool failedLexicalCheck_ = false;

 public:
  bool failedBoundsCheck() const { return failedBoundsCheck_; }
  void setFailedBoundsCheck() { failedBoundsCheck_ = true; }

  bool failedLexicalCheck() const { return failedLexicalCheck_; }
  void setFailedLexicalCheck() { failedLexicalCheck_ = true; }
};

using WarpScriptSnapshotList = mozilla::LinkedList<WarpScriptSnapshot>;

using WarpZoneStubsSnapshot = JitZone::Stubs<JitCode*>;

// Data allocated by WarpOracle on the main thread that's used off-thread by
// WarpBuilder to build the MIR graph.
class WarpSnapshot : public TempObject {
  // The scripts being compiled.
  WarpScriptSnapshotList scriptSnapshots_;

  // JitZone stubs this compilation depends on.
  const WarpZoneStubsSnapshot zoneStubs_;

  // The global lexical environment and its thisObject(). We don't inline
  // cross-realm calls so this can be stored once per snapshot.
  OffthreadGCPtr<GlobalLexicalEnvironmentObject*> globalLexicalEnv_;
  OffthreadGCPtr<JSObject*> globalLexicalEnvThis_;

  const WarpBailoutInfo bailoutInfo_;

  // List of (originally) nursery-allocated objects. Must only be accessed on
  // the main thread. See also WarpObjectField.
  using NurseryObjectVector = Vector<JSObject*, 0, JitAllocPolicy>;
  NurseryObjectVector nurseryObjects_;

#ifdef JS_CACHEIR_SPEW
  bool needsFinalWarmUpCount_ = false;
#endif

#ifdef DEBUG
  // A hash of the stub pointers and entry counts for each of the ICs
  // in this snapshot.
  mozilla::HashNumber icHash_ = 0;
#endif

 public:
  explicit WarpSnapshot(JSContext* cx, TempAllocator& alloc,
                        WarpScriptSnapshotList&& scriptSnapshots,
                        const WarpZoneStubsSnapshot& zoneStubs,
                        const WarpBailoutInfo& bailoutInfo,
                        bool recordWarmUpCount);

  WarpScriptSnapshot* rootScript() { return scriptSnapshots_.getFirst(); }
  const WarpScriptSnapshotList& scripts() const { return scriptSnapshots_; }

  JitCode* getZoneStub(JitZone::StubKind kind) const {
    MOZ_ASSERT(zoneStubs_[kind]);
    return zoneStubs_[kind];
  }

  GlobalLexicalEnvironmentObject* globalLexicalEnv() const {
    return globalLexicalEnv_;
  }
  JSObject* globalLexicalEnvThis() const { return globalLexicalEnvThis_; }

  void trace(JSTracer* trc);

  const WarpBailoutInfo& bailoutInfo() const { return bailoutInfo_; }

  NurseryObjectVector& nurseryObjects() { return nurseryObjects_; }
  const NurseryObjectVector& nurseryObjects() const { return nurseryObjects_; }

#ifdef DEBUG
  mozilla::HashNumber icHash() const { return icHash_; }
  void setICHash(mozilla::HashNumber hash) { icHash_ = hash; }
#endif

#ifdef JS_JITSPEW
  void dump() const;
  void dump(GenericPrinter& out) const;
#endif

#ifdef JS_CACHEIR_SPEW
  bool needsFinalWarmUpCount() const { return needsFinalWarmUpCount_; }
#endif
};

}  // namespace jit
}  // namespace js

#endif /* jit_WarpSnapshot_h */

Messung V0.5
C=96 H=99 G=97

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.