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

Quelle  JSContext-inl.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 vm_JSContext_inl_h
#define vm_JSContext_inl_h

#include "vm/JSContext.h"

#include <type_traits>

#include "gc/Marking.h"
#include "gc/Zone.h"
#include "jit/JitFrames.h"
#include "util/DiagnosticAssertions.h"
#include "vm/BigIntType.h"
#include "vm/GlobalObject.h"
#include "vm/Realm.h"

#include "gc/Allocator-inl.h"
#include "vm/Activation-inl.h"  // js::Activation::hasWasmExitFP

namespace js {

class ContextChecks {
  JSContext* cx;

  JS::Realm* realm() const { return cx->realm(); }
  JS::Compartment* compartment() const { return cx->compartment(); }
  JS::Zone* zone() const { return cx->zone(); }

 public:
  explicit ContextChecks(JSContext* cx) : cx(cx) {
#ifdef DEBUG
    if (realm()) {
      GlobalObject* global = realm()->unsafeUnbarrieredMaybeGlobal();
      if (global) {
        checkObject(global);
      }
    }
#endif
  }

  /*
   * Set a breakpoint here (break js::ContextChecks::fail) to debug
   * realm/compartment/zone mismatches.
   */

  static void fail(JS::Realm* r1, JS::Realm* r2, int argIndex) {
    MOZ_CRASH_UNSAFE_PRINTF("*** Realm mismatch %p vs. %p at argument %d", r1,
                            r2, argIndex);
  }
  static void fail(JS::Compartment* c1, JS::Compartment* c2, int argIndex) {
    MOZ_CRASH_UNSAFE_PRINTF("*** Compartment mismatch %p vs. %p at argument %d",
                            c1, c2, argIndex);
  }
  static void fail(JS::Zone* z1, JS::Zone* z2, int argIndex) {
    MOZ_CRASH_UNSAFE_PRINTF("*** Zone mismatch %p vs. %p at argument %d", z1,
                            z2, argIndex);
  }

  void check(JS::Realm* r, int argIndex) {
    if (r && r != realm()) {
      fail(realm(), r, argIndex);
    }
  }

  void check(JS::Compartment* c, int argIndex) {
    if (c && c != compartment()) {
      fail(compartment(), c, argIndex);
    }
  }

  void check(JS::Zone* z, int argIndex) {
    if (zone() && z != zone()) {
      fail(zone(), z, argIndex);
    }
  }

  void check(JSObject* obj, int argIndex) {
    if (obj) {
      checkObject(obj);
      check(obj->compartment(), argIndex);
    }
  }

  void checkObject(JSObject* obj) {
    JS::AssertObjectIsNotGray(obj);
    MOZ_ASSERT(!js::gc::IsAboutToBeFinalizedUnbarriered(obj));
  }

  template <typename T>
  void checkAtom(T* thing, int argIndex) {
    static_assert(std::is_same_v<T, JSAtom> || std::is_same_v<T, JS::Symbol>,
                  "Should only be called with JSAtom* or JS::Symbol* argument");

#ifdef DEBUG
    // Atoms which move across zone boundaries need to be marked in the new
    // zone, see JS_MarkCrossZoneId.
    if (zone()) {
      if (!cx->runtime()->gc.atomMarking.atomIsMarked(zone(), thing)) {
        MOZ_CRASH_UNSAFE_PRINTF(
            "*** Atom not marked for zone %p at argument %d", zone(), argIndex);
      }
    }
#endif
  }

  void check(JSString* str, int argIndex) {
    JS::AssertCellIsNotGray(str);
    if (str->isAtom()) {
      checkAtom(&str->asAtom(), argIndex);
    } else {
      check(str->zone(), argIndex);
    }
  }

  void check(JS::Symbol* symbol, int argIndex) { checkAtom(symbol, argIndex); }

  void check(JS::BigInt* bi, int argIndex) { check(bi->zone(), argIndex); }

  void check(const js::Value& v, int argIndex) {
    if (v.isObject()) {
      check(&v.toObject(), argIndex);
    } else if (v.isString()) {
      check(v.toString(), argIndex);
    } else if (v.isSymbol()) {
      check(v.toSymbol(), argIndex);
    } else if (v.isBigInt()) {
      check(v.toBigInt(), argIndex);
    }
  }

  // Check the contents of any container class that supports the C++
  // iteration protocol, eg GCVector<jsid>.
  template <typename Container>
  std::enable_if_t<std::is_same_v<decltype(std::declval<Container>().begin()),
                                  decltype(std::declval<Container>().end())>>
  check(const Container& container, int argIndex) {
    for (auto i : container) {
      check(i, argIndex);
    }
  }

  void check(const JS::HandleValueArray& arr, int argIndex) {
    for (size_t i = 0; i < arr.length(); i++) {
      check(arr[i], argIndex);
    }
  }

  void check(const CallArgs& args, int argIndex) {
    for (Value* p = args.base(); p != args.end(); ++p) {
      check(*p, argIndex);
    }
  }

  void check(jsid id, int argIndex) {
    if (id.isAtom()) {
      checkAtom(id.toAtom(), argIndex);
    } else if (id.isSymbol()) {
      checkAtom(id.toSymbol(), argIndex);
    } else {
      MOZ_ASSERT(!id.isGCThing());
    }
  }

  void check(JSScript* script, int argIndex) {
    JS::AssertCellIsNotGray(script);
    if (script) {
      check(script->realm(), argIndex);
    }
  }

  void check(AbstractFramePtr frame, int argIndex);

  void check(const PropertyDescriptor& desc, int argIndex) {
    if (desc.hasGetter()) {
      check(desc.getter(), argIndex);
    }
    if (desc.hasSetter()) {
      check(desc.setter(), argIndex);
    }
    if (desc.hasValue()) {
      check(desc.value(), argIndex);
    }
  }

  void check(Handle<mozilla::Maybe<Value>> maybe, int argIndex) {
    if (maybe.get().isSome()) {
      check(maybe.get().ref(), argIndex);
    }
  }

  void check(Handle<mozilla::Maybe<PropertyDescriptor>> maybe, int argIndex) {
    if (maybe.get().isSome()) {
      check(maybe.get().ref(), argIndex);
    }
  }
};

}  // namespace js

template <class... Args>
inline void JSContext::checkImpl(const Args&... args) {
  int argIndex = 0;
  (..., js::ContextChecks(this).check(args, argIndex++));
}

template <class... Args>
inline void JSContext::check(const Args&... args) {
#ifdef JS_CRASH_DIAGNOSTICS
  if (contextChecksEnabled()) {
    checkImpl(args...);
  }
#endif
}

template <class... Args>
inline void JSContext::releaseCheck(const Args&... args) {
  if (contextChecksEnabled()) {
    checkImpl(args...);
  }
}

template <class... Args>
MOZ_ALWAYS_INLINE void JSContext::debugOnlyCheck(const Args&... args) {
#if defined(DEBUG) && defined(JS_CRASH_DIAGNOSTICS)
  if (contextChecksEnabled()) {
    checkImpl(args...);
  }
#endif
}

namespace js {

STATIC_PRECONDITION_ASSUME(ubound(args.argv_) >= argc)
MOZ_ALWAYS_INLINE bool CallNativeImpl(JSContext* cx, NativeImpl impl,
                                      const CallArgs& args) {
#ifdef DEBUG
  bool alreadyThrowing = cx->isExceptionPending();
#endif
  cx->check(args);
  bool ok = impl(cx, args);
  if (ok) {
    cx->check(args.rval());
    MOZ_ASSERT_IF(!alreadyThrowing, !cx->isExceptionPending());
  }
  return ok;
}

MOZ_ALWAYS_INLINE bool CheckForInterrupt(JSContext* cx) {
  MOZ_ASSERT(!cx->isExceptionPending());
  // Add an inline fast-path since we have to check for interrupts in some hot
  // C++ loops of library builtins.
  if (MOZ_UNLIKELY(cx->hasAnyPendingInterrupt())) {
    return cx->handleInterrupt();
  }

  JS_INTERRUPT_POSSIBLY_FAIL();

  return true;
}

/* namespace js */

inline void JSContext::minorGC(JS::GCReason reason) {
  runtime()->gc.minorGC(reason);
}

inline bool JSContext::runningWithTrustedPrincipals() {
  if (!realm()) {
    return true;
  }
  if (!runtime()->trustedPrincipals()) {
    return false;
  }
  return realm()->principals() == runtime()->trustedPrincipals();
}

inline void JSContext::enterRealm(JS::Realm* realm) {
  // We should never enter a realm while in the atoms zone.
  MOZ_ASSERT_IF(zone(), !zone()->isAtomsZone());

  realm->enter();
  setRealm(realm);
}

inline void JSContext::enterAtomsZone() {
  realm_ = nullptr;
  setZone(runtime_->unsafeAtomsZone());
}

inline void JSContext::setZone(js::Zone* zone) { zone_ = zone; }

inline void JSContext::enterRealmOf(JSObject* target) {
  JS::AssertCellIsNotGray(target);
  enterRealm(target->nonCCWRealm());
}

inline void JSContext::enterRealmOf(JSScript* target) {
  JS::AssertCellIsNotGray(target);
  enterRealm(target->realm());
}

inline void JSContext::enterRealmOf(js::Shape* target) {
  JS::AssertCellIsNotGray(target);
  enterRealm(target->realm());
}

inline void JSContext::enterNullRealm() {
  // We should never enter a realm while in the atoms zone.
  MOZ_ASSERT_IF(zone(), !zone()->isAtomsZone());

  setRealm(nullptr);
}

inline void JSContext::leaveRealm(JS::Realm* oldRealm) {
  // Only call leave() after we've setRealm()-ed away from the current realm.
  JS::Realm* startingRealm = realm_;

  // The current realm should be marked as entered-from-C++ at this point.
  MOZ_ASSERT_IF(startingRealm, startingRealm->hasBeenEnteredIgnoringJit());

  setRealm(oldRealm);

  if (startingRealm) {
    startingRealm->leave();
  }
}

inline void JSContext::leaveAtomsZone(JS::Realm* oldRealm) {
  setRealm(oldRealm);
}

inline void JSContext::setRealm(JS::Realm* realm) {
  realm_ = realm;
  if (realm) {
    // This thread must have exclusive access to the zone.
    MOZ_ASSERT(CurrentThreadCanAccessZone(realm->zone()));
    MOZ_ASSERT(!realm->zone()->isAtomsZone());
    setZone(realm->zone());
  } else {
    setZone(nullptr);
  }
}

inline void JSContext::setRealmForJitExceptionHandler(JS::Realm* realm) {
  // JIT code enters (same-compartment) realms without calling realm->enter()
  // so we don't call realm->leave() here.
  MOZ_ASSERT(realm->compartment() == compartment());
  realm_ = realm;
}

inline js::RuntimeCaches& JSContext::caches() { return runtime()->caches(); }

template <typename T, js::AllowGC allowGC, typename... Args>
T* JSContext::newCell(Args&&... args) {
  return js::gc::CellAllocator::template NewCell<T, allowGC>(
      this, std::forward<Args>(args)...);
}

#endif /* vm_JSContext_inl_h */

Messung V0.5
C=95 H=97 G=95

¤ Dauer der Verarbeitung: 0.20 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.