mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2025-01-15 07:21:07 +00:00
477 lines
14 KiB
C++
Executable File
477 lines
14 KiB
C++
Executable File
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
|
* 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 jspubtd_h
|
|
#define jspubtd_h
|
|
|
|
/*
|
|
* JS public API typedefs.
|
|
*/
|
|
|
|
#include "mozilla/Assertions.h"
|
|
#include "mozilla/EnumeratedArray.h"
|
|
#include "mozilla/LinkedList.h"
|
|
#include "mozilla/PodOperations.h"
|
|
|
|
#include "jsprototypes.h"
|
|
#include "jstypes.h"
|
|
|
|
#include "js/TraceKind.h"
|
|
#include "js/TypeDecls.h"
|
|
|
|
#if defined(JS_GC_ZEAL) || defined(DEBUG)
|
|
# define JSGC_HASH_TABLE_CHECKS
|
|
#endif
|
|
|
|
namespace JS {
|
|
|
|
class AutoIdVector;
|
|
class CallArgs;
|
|
|
|
template <typename T>
|
|
class Rooted;
|
|
|
|
class JS_FRIEND_API(CompileOptions);
|
|
class JS_FRIEND_API(ReadOnlyCompileOptions);
|
|
class JS_FRIEND_API(OwningCompileOptions);
|
|
class JS_FRIEND_API(TransitiveCompileOptions);
|
|
class JS_PUBLIC_API(CompartmentOptions);
|
|
|
|
struct RootingContext;
|
|
class Value;
|
|
struct Zone;
|
|
|
|
namespace shadow {
|
|
struct Runtime;
|
|
} // namespace shadow
|
|
|
|
} // namespace JS
|
|
|
|
namespace js {
|
|
class RootLists;
|
|
} // namespace js
|
|
|
|
/*
|
|
* Run-time version enumeration. For compile-time version checking, please use
|
|
* the JS_HAS_* macros in jsversion.h, or use MOZJS_MAJOR_VERSION,
|
|
* MOZJS_MINOR_VERSION, MOZJS_PATCH_VERSION, and MOZJS_ALPHA definitions.
|
|
*/
|
|
enum JSVersion {
|
|
JSVERSION_ECMA_3 = 148,
|
|
JSVERSION_1_6 = 160,
|
|
JSVERSION_1_7 = 170,
|
|
JSVERSION_1_8 = 180,
|
|
JSVERSION_ECMA_5 = 185,
|
|
JSVERSION_DEFAULT = 0,
|
|
JSVERSION_UNKNOWN = -1,
|
|
JSVERSION_LATEST = JSVERSION_ECMA_5
|
|
};
|
|
|
|
/* Result of typeof operator enumeration. */
|
|
enum JSType {
|
|
JSTYPE_VOID, /* undefined */
|
|
JSTYPE_OBJECT, /* object */
|
|
JSTYPE_FUNCTION, /* function */
|
|
JSTYPE_STRING, /* string */
|
|
JSTYPE_NUMBER, /* number */
|
|
JSTYPE_BOOLEAN, /* boolean */
|
|
JSTYPE_NULL, /* null */
|
|
JSTYPE_SYMBOL, /* symbol */
|
|
JSTYPE_LIMIT
|
|
};
|
|
|
|
/* Dense index into cached prototypes and class atoms for standard objects. */
|
|
enum JSProtoKey {
|
|
#define PROTOKEY_AND_INITIALIZER(name,code,init,clasp) JSProto_##name = code,
|
|
JS_FOR_EACH_PROTOTYPE(PROTOKEY_AND_INITIALIZER)
|
|
#undef PROTOKEY_AND_INITIALIZER
|
|
JSProto_LIMIT
|
|
};
|
|
|
|
/* Struct forward declarations. */
|
|
struct JSClass;
|
|
struct JSCompartment;
|
|
struct JSCrossCompartmentCall;
|
|
class JSErrorReport;
|
|
struct JSExceptionState;
|
|
struct JSFunctionSpec;
|
|
struct JSLocaleCallbacks;
|
|
struct JSObjectMap;
|
|
struct JSPrincipals;
|
|
struct JSPropertyName;
|
|
struct JSPropertySpec;
|
|
struct JSRuntime;
|
|
struct JSSecurityCallbacks;
|
|
struct JSStructuredCloneCallbacks;
|
|
struct JSStructuredCloneReader;
|
|
struct JSStructuredCloneWriter;
|
|
class JS_PUBLIC_API(JSTracer);
|
|
|
|
class JSFlatString;
|
|
|
|
typedef bool (*JSInitCallback)(void);
|
|
|
|
template<typename T> struct JSConstScalarSpec;
|
|
typedef JSConstScalarSpec<double> JSConstDoubleSpec;
|
|
typedef JSConstScalarSpec<int32_t> JSConstIntegerSpec;
|
|
|
|
/*
|
|
* Generic trace operation that calls JS::TraceEdge on each traceable thing's
|
|
* location reachable from data.
|
|
*/
|
|
typedef void
|
|
(* JSTraceDataOp)(JSTracer* trc, void* data);
|
|
|
|
namespace js {
|
|
namespace gc {
|
|
class AutoTraceSession;
|
|
class StoreBuffer;
|
|
} // namespace gc
|
|
|
|
// Whether the current thread is permitted access to any part of the specified
|
|
// runtime or zone.
|
|
JS_FRIEND_API(bool)
|
|
CurrentThreadCanAccessRuntime(const JSRuntime* rt);
|
|
|
|
#ifdef DEBUG
|
|
JS_FRIEND_API(bool)
|
|
CurrentThreadIsPerformingGC();
|
|
#endif
|
|
|
|
} // namespace js
|
|
|
|
namespace JS {
|
|
|
|
class JS_PUBLIC_API(AutoEnterCycleCollection);
|
|
class JS_PUBLIC_API(AutoAssertOnBarrier);
|
|
struct JS_PUBLIC_API(PropertyDescriptor);
|
|
|
|
typedef void (*OffThreadCompileCallback)(void* token, void* callbackData);
|
|
|
|
enum class HeapState {
|
|
Idle, // doing nothing with the GC heap
|
|
Tracing, // tracing the GC heap without collecting, e.g. IterateCompartments()
|
|
MajorCollecting, // doing a GC of the major heap
|
|
MinorCollecting, // doing a GC of the minor heap (nursery)
|
|
CycleCollecting // in the "Unlink" phase of cycle collection
|
|
};
|
|
|
|
namespace shadow {
|
|
|
|
struct Runtime
|
|
{
|
|
private:
|
|
JS::HeapState heapState_;
|
|
|
|
protected:
|
|
void setHeapState(JS::HeapState newState) {
|
|
MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(asRuntime()));
|
|
MOZ_ASSERT(heapState_ != newState);
|
|
heapState_ = newState;
|
|
}
|
|
|
|
JS::HeapState heapState() const {
|
|
MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(asRuntime()) ||
|
|
js::CurrentThreadIsPerformingGC());
|
|
return heapState_;
|
|
}
|
|
|
|
// In some cases, invoking GC barriers (incremental or otherwise) will break
|
|
// things. These barriers assert if this flag is set.
|
|
bool allowGCBarriers_;
|
|
friend class JS::AutoAssertOnBarrier;
|
|
|
|
js::gc::StoreBuffer* gcStoreBufferPtr_;
|
|
|
|
// The gray bits can become invalid if UnmarkGray overflows the stack. A
|
|
// full GC will reset this bit, since it fills in all the gray bits.
|
|
bool gcGrayBitsValid_;
|
|
|
|
public:
|
|
Runtime()
|
|
: heapState_(JS::HeapState::Idle)
|
|
, allowGCBarriers_(true)
|
|
, gcStoreBufferPtr_(nullptr)
|
|
, gcGrayBitsValid_(false)
|
|
{}
|
|
|
|
bool isHeapBusy() const { return heapState() != JS::HeapState::Idle; }
|
|
bool isHeapTracing() const { return heapState() == JS::HeapState::Tracing; }
|
|
bool isHeapMajorCollecting() const { return heapState() == JS::HeapState::MajorCollecting; }
|
|
bool isHeapMinorCollecting() const { return heapState() == JS::HeapState::MinorCollecting; }
|
|
bool isHeapCollecting() const { return isHeapMinorCollecting() || isHeapMajorCollecting(); }
|
|
bool isCycleCollecting() const {
|
|
return heapState() == JS::HeapState::CycleCollecting;
|
|
}
|
|
|
|
bool allowGCBarriers() const { return allowGCBarriers_; }
|
|
|
|
js::gc::StoreBuffer* gcStoreBufferPtr() { return gcStoreBufferPtr_; }
|
|
|
|
bool areGCGrayBitsValid() const { return gcGrayBitsValid_; }
|
|
void setGCGrayBitsValid(bool valid) { gcGrayBitsValid_ = valid; }
|
|
|
|
const JSRuntime* asRuntime() const {
|
|
return reinterpret_cast<const JSRuntime*>(this);
|
|
}
|
|
|
|
static JS::shadow::Runtime* asShadowRuntime(JSRuntime* rt) {
|
|
return reinterpret_cast<JS::shadow::Runtime*>(rt);
|
|
}
|
|
|
|
protected:
|
|
void setGCStoreBufferPtr(js::gc::StoreBuffer* storeBuffer) {
|
|
gcStoreBufferPtr_ = storeBuffer;
|
|
}
|
|
};
|
|
|
|
} /* namespace shadow */
|
|
|
|
// Decorates the Unlinking phase of CycleCollection so that accidental use
|
|
// of barriered accessors results in assertions instead of leaks.
|
|
class MOZ_STACK_CLASS JS_PUBLIC_API(AutoEnterCycleCollection)
|
|
{
|
|
#ifdef DEBUG
|
|
JSRuntime* runtime;
|
|
|
|
public:
|
|
explicit AutoEnterCycleCollection(JSContext* cx);
|
|
~AutoEnterCycleCollection();
|
|
#else
|
|
public:
|
|
explicit AutoEnterCycleCollection(JSContext* cx) {}
|
|
~AutoEnterCycleCollection() {}
|
|
#endif
|
|
};
|
|
|
|
class JS_PUBLIC_API(AutoGCRooter)
|
|
{
|
|
public:
|
|
AutoGCRooter(JSContext* cx, ptrdiff_t tag);
|
|
AutoGCRooter(JS::RootingContext* cx, ptrdiff_t tag);
|
|
|
|
~AutoGCRooter() {
|
|
MOZ_ASSERT(this == *stackTop);
|
|
*stackTop = down;
|
|
}
|
|
|
|
/* Implemented in gc/RootMarking.cpp. */
|
|
inline void trace(JSTracer* trc);
|
|
static void traceAll(JSTracer* trc);
|
|
static void traceAllWrappers(JSTracer* trc);
|
|
|
|
protected:
|
|
AutoGCRooter * const down;
|
|
|
|
/*
|
|
* Discriminates actual subclass of this being used. If non-negative, the
|
|
* subclass roots an array of values of the length stored in this field.
|
|
* If negative, meaning is indicated by the corresponding value in the enum
|
|
* below. Any other negative value indicates some deeper problem such as
|
|
* memory corruption.
|
|
*/
|
|
ptrdiff_t tag_;
|
|
|
|
enum {
|
|
VALARRAY = -2, /* js::AutoValueArray */
|
|
PARSER = -3, /* js::frontend::Parser */
|
|
VALVECTOR = -10, /* js::AutoValueVector */
|
|
IDVECTOR = -11, /* js::AutoIdVector */
|
|
OBJVECTOR = -14, /* js::AutoObjectVector */
|
|
IONMASM = -19, /* js::jit::MacroAssembler */
|
|
WRAPVECTOR = -20, /* js::AutoWrapperVector */
|
|
WRAPPER = -21, /* js::AutoWrapperRooter */
|
|
CUSTOM = -26 /* js::CustomAutoRooter */
|
|
};
|
|
|
|
static ptrdiff_t GetTag(const Value& value) { return VALVECTOR; }
|
|
static ptrdiff_t GetTag(const jsid& id) { return IDVECTOR; }
|
|
static ptrdiff_t GetTag(JSObject* obj) { return OBJVECTOR; }
|
|
|
|
private:
|
|
AutoGCRooter ** const stackTop;
|
|
|
|
/* No copy or assignment semantics. */
|
|
AutoGCRooter(AutoGCRooter& ida) = delete;
|
|
void operator=(AutoGCRooter& ida) = delete;
|
|
};
|
|
|
|
// Our instantiations of Rooted<void*> and PersistentRooted<void*> require an
|
|
// instantiation of MapTypeToRootKind.
|
|
template <>
|
|
struct MapTypeToRootKind<void*> {
|
|
static const RootKind kind = RootKind::Traceable;
|
|
};
|
|
|
|
} /* namespace JS */
|
|
|
|
namespace js {
|
|
|
|
class ExclusiveContext;
|
|
|
|
/*
|
|
* This list enumerates the different types of conceptual stacks we have in
|
|
* SpiderMonkey. In reality, they all share the C stack, but we allow different
|
|
* stack limits depending on the type of code running.
|
|
*/
|
|
enum StackKind
|
|
{
|
|
StackForSystemCode, // C++, such as the GC, running on behalf of the VM.
|
|
StackForTrustedScript, // Script running with trusted principals.
|
|
StackForUntrustedScript, // Script running with untrusted principals.
|
|
StackKindCount
|
|
};
|
|
|
|
using RootedListHeads = mozilla::EnumeratedArray<JS::RootKind, JS::RootKind::Limit,
|
|
JS::Rooted<void*>*>;
|
|
|
|
// Abstracts JS rooting mechanisms so they can be shared between the JSContext
|
|
// and JSRuntime.
|
|
class RootLists
|
|
{
|
|
// Stack GC roots for Rooted GC heap pointers.
|
|
RootedListHeads stackRoots_;
|
|
template <typename T> friend class JS::Rooted;
|
|
|
|
// Stack GC roots for AutoFooRooter classes.
|
|
JS::AutoGCRooter* autoGCRooters_;
|
|
friend class JS::AutoGCRooter;
|
|
|
|
// Heap GC roots for PersistentRooted pointers.
|
|
mozilla::EnumeratedArray<JS::RootKind, JS::RootKind::Limit,
|
|
mozilla::LinkedList<JS::PersistentRooted<void*>>> heapRoots_;
|
|
template <typename T> friend class JS::PersistentRooted;
|
|
|
|
public:
|
|
RootLists() : autoGCRooters_(nullptr) {
|
|
for (auto& stackRootPtr : stackRoots_)
|
|
stackRootPtr = nullptr;
|
|
}
|
|
|
|
~RootLists() {
|
|
// The semantics of PersistentRooted containing pointers and tagged
|
|
// pointers are somewhat different from those of PersistentRooted
|
|
// containing a structure with a trace method. PersistentRooted
|
|
// containing pointers are allowed to outlive the owning RootLists,
|
|
// whereas those containing a traceable structure are not.
|
|
//
|
|
// The purpose of this feature is to support lazy initialization of
|
|
// global references for the several places in Gecko that do not have
|
|
// access to a tighter context, but that still need to refer to GC
|
|
// pointers. For such pointers, FinishPersistentRootedChains ensures
|
|
// that the contained references are nulled out when the owning
|
|
// RootLists dies to prevent UAF errors.
|
|
//
|
|
// However, for RootKind::Traceable, we do not know the concrete type
|
|
// of the held thing, so we simply cannot do this without accruing
|
|
// extra overhead and complexity for all users for a case that is
|
|
// unlikely to ever be used in practice. For this reason, the following
|
|
// assertion disallows usage of PersistentRooted<Traceable> that
|
|
// outlives the RootLists.
|
|
MOZ_ASSERT(heapRoots_[JS::RootKind::Traceable].isEmpty());
|
|
}
|
|
|
|
void traceStackRoots(JSTracer* trc);
|
|
void checkNoGCRooters();
|
|
|
|
void tracePersistentRoots(JSTracer* trc);
|
|
void finishPersistentRoots();
|
|
};
|
|
|
|
} // namespace js
|
|
|
|
namespace JS {
|
|
|
|
/*
|
|
* JS::RootingContext is a base class of ContextFriendFields and JSContext.
|
|
* This class can be used to let code construct a Rooted<> or PersistentRooted<>
|
|
* instance, without giving it full access to the JSContext.
|
|
*/
|
|
struct RootingContext
|
|
{
|
|
js::RootLists roots;
|
|
|
|
#ifdef DEBUG
|
|
// Whether the derived class is a JSContext or an ExclusiveContext.
|
|
bool isJSContext;
|
|
#endif
|
|
|
|
explicit RootingContext(bool isJSContextArg)
|
|
#ifdef DEBUG
|
|
: isJSContext(isJSContextArg)
|
|
#endif
|
|
{}
|
|
|
|
static RootingContext* get(JSContext* cx) {
|
|
return reinterpret_cast<RootingContext*>(cx);
|
|
}
|
|
};
|
|
|
|
} // namespace JS
|
|
|
|
namespace js {
|
|
|
|
struct ContextFriendFields : public JS::RootingContext
|
|
{
|
|
protected:
|
|
/* The current compartment. */
|
|
JSCompartment* compartment_;
|
|
|
|
/* The current zone. */
|
|
JS::Zone* zone_;
|
|
|
|
public:
|
|
/* Limit pointer for checking native stack consumption. */
|
|
uintptr_t nativeStackLimit[js::StackKindCount];
|
|
|
|
explicit ContextFriendFields(bool isJSContext);
|
|
|
|
static const ContextFriendFields* get(const JSContext* cx) {
|
|
return reinterpret_cast<const ContextFriendFields*>(cx);
|
|
}
|
|
|
|
static ContextFriendFields* get(JSContext* cx) {
|
|
return reinterpret_cast<ContextFriendFields*>(cx);
|
|
}
|
|
|
|
friend JSCompartment* GetContextCompartment(const JSContext* cx);
|
|
friend JS::Zone* GetContextZone(const JSContext* cx);
|
|
template <typename T> friend class JS::Rooted;
|
|
};
|
|
|
|
/*
|
|
* Inlinable accessors for JSContext.
|
|
*
|
|
* - These must not be available on the more restricted superclasses of
|
|
* JSContext, so we can't simply define them on ContextFriendFields.
|
|
*
|
|
* - They're perfectly ordinary JSContext functionality, so ought to be
|
|
* usable without resorting to jsfriendapi.h, and when JSContext is an
|
|
* incomplete type.
|
|
*/
|
|
inline JSCompartment*
|
|
GetContextCompartment(const JSContext* cx)
|
|
{
|
|
return ContextFriendFields::get(cx)->compartment_;
|
|
}
|
|
|
|
inline JS::Zone*
|
|
GetContextZone(const JSContext* cx)
|
|
{
|
|
return ContextFriendFields::get(cx)->zone_;
|
|
}
|
|
|
|
} /* namespace js */
|
|
|
|
MOZ_BEGIN_EXTERN_C
|
|
|
|
// Defined in NSPR prio.h.
|
|
typedef struct PRFileDesc PRFileDesc;
|
|
|
|
MOZ_END_EXTERN_C
|
|
|
|
#endif /* jspubtd_h */
|