mozjs_sys 0.67.1

System crate for the Mozilla SpiderMonkey JavaScript engine.
/* -*- 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 gc_FreeOp_h
#define gc_FreeOp_h

#include "mozilla/Assertions.h"  // MOZ_ASSERT

#include "jit/ExecutableAllocator.h"  // jit::JitPoisonRangeVector
#include "js/AllocPolicy.h"           // SystemAllocPolicy
#include "js/MemoryFunctions.h"       // JSFreeOp
#include "js/Utility.h"               // AutoEnterOOMUnsafeRegion, js_free
#include "js/Vector.h"                // js::Vector

struct JSRuntime;

namespace js {

/*
 * A FreeOp can do one thing: free memory. For convenience, it has delete_
 * convenience methods that also call destructors.
 *
 * FreeOp is passed to finalizers and other sweep-phase hooks so that we do not
 * need to pass a JSContext to those hooks.
 */
class FreeOp : public JSFreeOp {
  Vector<void*, 0, SystemAllocPolicy> freeLaterList;
  jit::JitPoisonRangeVector jitPoisonRanges;

 public:
  static FreeOp* get(JSFreeOp* fop) { return static_cast<FreeOp*>(fop); }

  explicit FreeOp(JSRuntime* maybeRuntime);
  ~FreeOp();

  bool onMainThread() const { return runtime_ != nullptr; }

  bool maybeOnHelperThread() const {
    // Sometimes background finalization happens on the main thread so
    // runtime_ being null doesn't always mean we are off thread.
    return !runtime_;
  }

  bool isDefaultFreeOp() const;

  void free_(void* p) { js_free(p); }

  void freeLater(void* p) {
    // FreeOps other than the defaultFreeOp() are constructed on the stack,
    // and won't hold onto the pointers to free indefinitely.
    MOZ_ASSERT(!isDefaultFreeOp());

    AutoEnterOOMUnsafeRegion oomUnsafe;
    if (!freeLaterList.append(p)) {
      oomUnsafe.crash("FreeOp::freeLater");
    }
  }

  bool appendJitPoisonRange(const jit::JitPoisonRange& range) {
    // FreeOps other than the defaultFreeOp() are constructed on the stack,
    // and won't hold onto the pointers to free indefinitely.
    MOZ_ASSERT(!isDefaultFreeOp());

    return jitPoisonRanges.append(range);
  }

  template <class T>
  void delete_(T* p) {
    if (p) {
      p->~T();
      free_(p);
    }
  }
};

}  // namespace js

#endif  // gc_FreeOp_h