js/src/vm/Runtime.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/vm/Runtime.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2089 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef vm_Runtime_h
    1.11 +#define vm_Runtime_h
    1.12 +
    1.13 +#include "mozilla/Atomics.h"
    1.14 +#include "mozilla/Attributes.h"
    1.15 +#include "mozilla/LinkedList.h"
    1.16 +#include "mozilla/MemoryReporting.h"
    1.17 +#include "mozilla/PodOperations.h"
    1.18 +#include "mozilla/Scoped.h"
    1.19 +#include "mozilla/ThreadLocal.h"
    1.20 +
    1.21 +#include <setjmp.h>
    1.22 +
    1.23 +#include "jsatom.h"
    1.24 +#include "jsclist.h"
    1.25 +#include "jsgc.h"
    1.26 +#ifdef DEBUG
    1.27 +# include "jsproxy.h"
    1.28 +#endif
    1.29 +#include "jsscript.h"
    1.30 +
    1.31 +#include "ds/FixedSizeHash.h"
    1.32 +#include "frontend/ParseMaps.h"
    1.33 +#ifdef JSGC_GENERATIONAL
    1.34 +# include "gc/Nursery.h"
    1.35 +#endif
    1.36 +#include "gc/Statistics.h"
    1.37 +#ifdef JSGC_GENERATIONAL
    1.38 +# include "gc/StoreBuffer.h"
    1.39 +#endif
    1.40 +#include "gc/Tracer.h"
    1.41 +#ifdef XP_MACOSX
    1.42 +# include "jit/AsmJSSignalHandlers.h"
    1.43 +#endif
    1.44 +#include "js/HashTable.h"
    1.45 +#include "js/Vector.h"
    1.46 +#include "vm/CommonPropertyNames.h"
    1.47 +#include "vm/DateTime.h"
    1.48 +#include "vm/MallocProvider.h"
    1.49 +#include "vm/SPSProfiler.h"
    1.50 +#include "vm/Stack.h"
    1.51 +#include "vm/ThreadPool.h"
    1.52 +
    1.53 +#ifdef _MSC_VER
    1.54 +#pragma warning(push)
    1.55 +#pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
    1.56 +#endif
    1.57 +
    1.58 +namespace js {
    1.59 +
    1.60 +class PerThreadData;
    1.61 +class ThreadSafeContext;
    1.62 +class AutoKeepAtoms;
    1.63 +#ifdef JS_TRACE_LOGGING
    1.64 +class TraceLogger;
    1.65 +#endif
    1.66 +
    1.67 +/* Thread Local Storage slot for storing the runtime for a thread. */
    1.68 +extern mozilla::ThreadLocal<PerThreadData*> TlsPerThreadData;
    1.69 +
    1.70 +} // namespace js
    1.71 +
    1.72 +struct DtoaState;
    1.73 +
    1.74 +extern void
    1.75 +js_ReportOutOfMemory(js::ThreadSafeContext *cx);
    1.76 +
    1.77 +extern void
    1.78 +js_ReportAllocationOverflow(js::ThreadSafeContext *cx);
    1.79 +
    1.80 +extern void
    1.81 +js_ReportOverRecursed(js::ThreadSafeContext *cx);
    1.82 +
    1.83 +namespace JSC { class ExecutableAllocator; }
    1.84 +
    1.85 +namespace WTF { class BumpPointerAllocator; }
    1.86 +
    1.87 +namespace js {
    1.88 +
    1.89 +typedef Rooted<JSLinearString*> RootedLinearString;
    1.90 +
    1.91 +class Activation;
    1.92 +class ActivationIterator;
    1.93 +class AsmJSActivation;
    1.94 +class MathCache;
    1.95 +
    1.96 +namespace jit {
    1.97 +class JitRuntime;
    1.98 +class JitActivation;
    1.99 +struct PcScriptCache;
   1.100 +class Simulator;
   1.101 +class SimulatorRuntime;
   1.102 +class AutoFlushICache;
   1.103 +}
   1.104 +
   1.105 +/*
   1.106 + * GetSrcNote cache to avoid O(n^2) growth in finding a source note for a
   1.107 + * given pc in a script. We use the script->code pointer to tag the cache,
   1.108 + * instead of the script address itself, so that source notes are always found
   1.109 + * by offset from the bytecode with which they were generated.
   1.110 + */
   1.111 +struct GSNCache {
   1.112 +    typedef HashMap<jsbytecode *,
   1.113 +                    jssrcnote *,
   1.114 +                    PointerHasher<jsbytecode *, 0>,
   1.115 +                    SystemAllocPolicy> Map;
   1.116 +
   1.117 +    jsbytecode      *code;
   1.118 +    Map             map;
   1.119 +
   1.120 +    GSNCache() : code(nullptr) { }
   1.121 +
   1.122 +    void purge();
   1.123 +};
   1.124 +
   1.125 +/*
   1.126 + * ScopeCoordinateName cache to avoid O(n^2) growth in finding the name
   1.127 + * associated with a given aliasedvar operation.
   1.128 + */
   1.129 +struct ScopeCoordinateNameCache {
   1.130 +    typedef HashMap<uint32_t,
   1.131 +                    jsid,
   1.132 +                    DefaultHasher<uint32_t>,
   1.133 +                    SystemAllocPolicy> Map;
   1.134 +
   1.135 +    Shape *shape;
   1.136 +    Map map;
   1.137 +
   1.138 +    ScopeCoordinateNameCache() : shape(nullptr) {}
   1.139 +    void purge();
   1.140 +};
   1.141 +
   1.142 +typedef Vector<ScriptAndCounts, 0, SystemAllocPolicy> ScriptAndCountsVector;
   1.143 +
   1.144 +struct ConservativeGCData
   1.145 +{
   1.146 +    /*
   1.147 +     * The GC scans conservatively between ThreadData::nativeStackBase and
   1.148 +     * nativeStackTop unless the latter is nullptr.
   1.149 +     */
   1.150 +    uintptr_t           *nativeStackTop;
   1.151 +
   1.152 +    union {
   1.153 +        jmp_buf         jmpbuf;
   1.154 +        uintptr_t       words[JS_HOWMANY(sizeof(jmp_buf), sizeof(uintptr_t))];
   1.155 +    } registerSnapshot;
   1.156 +
   1.157 +    ConservativeGCData() {
   1.158 +        mozilla::PodZero(this);
   1.159 +    }
   1.160 +
   1.161 +    ~ConservativeGCData() {
   1.162 +#ifdef JS_THREADSAFE
   1.163 +        /*
   1.164 +         * The conservative GC scanner should be disabled when the thread leaves
   1.165 +         * the last request.
   1.166 +         */
   1.167 +        JS_ASSERT(!hasStackToScan());
   1.168 +#endif
   1.169 +    }
   1.170 +
   1.171 +    MOZ_NEVER_INLINE void recordStackTop();
   1.172 +
   1.173 +#ifdef JS_THREADSAFE
   1.174 +    void updateForRequestEnd() {
   1.175 +        nativeStackTop = nullptr;
   1.176 +    }
   1.177 +#endif
   1.178 +
   1.179 +    bool hasStackToScan() const {
   1.180 +        return !!nativeStackTop;
   1.181 +    }
   1.182 +};
   1.183 +
   1.184 +struct EvalCacheEntry
   1.185 +{
   1.186 +    JSScript *script;
   1.187 +    JSScript *callerScript;
   1.188 +    jsbytecode *pc;
   1.189 +};
   1.190 +
   1.191 +struct EvalCacheLookup
   1.192 +{
   1.193 +    EvalCacheLookup(JSContext *cx) : str(cx), callerScript(cx) {}
   1.194 +    RootedLinearString str;
   1.195 +    RootedScript callerScript;
   1.196 +    JSVersion version;
   1.197 +    jsbytecode *pc;
   1.198 +};
   1.199 +
   1.200 +struct EvalCacheHashPolicy
   1.201 +{
   1.202 +    typedef EvalCacheLookup Lookup;
   1.203 +
   1.204 +    static HashNumber hash(const Lookup &l);
   1.205 +    static bool match(const EvalCacheEntry &entry, const EvalCacheLookup &l);
   1.206 +};
   1.207 +
   1.208 +typedef HashSet<EvalCacheEntry, EvalCacheHashPolicy, SystemAllocPolicy> EvalCache;
   1.209 +
   1.210 +struct LazyScriptHashPolicy
   1.211 +{
   1.212 +    struct Lookup {
   1.213 +        JSContext *cx;
   1.214 +        LazyScript *lazy;
   1.215 +
   1.216 +        Lookup(JSContext *cx, LazyScript *lazy)
   1.217 +          : cx(cx), lazy(lazy)
   1.218 +        {}
   1.219 +    };
   1.220 +
   1.221 +    static const size_t NumHashes = 3;
   1.222 +
   1.223 +    static void hash(const Lookup &lookup, HashNumber hashes[NumHashes]);
   1.224 +    static bool match(JSScript *script, const Lookup &lookup);
   1.225 +
   1.226 +    // Alternate methods for use when removing scripts from the hash without an
   1.227 +    // explicit LazyScript lookup.
   1.228 +    static void hash(JSScript *script, HashNumber hashes[NumHashes]);
   1.229 +    static bool match(JSScript *script, JSScript *lookup) { return script == lookup; }
   1.230 +
   1.231 +    static void clear(JSScript **pscript) { *pscript = nullptr; }
   1.232 +    static bool isCleared(JSScript *script) { return !script; }
   1.233 +};
   1.234 +
   1.235 +typedef FixedSizeHashSet<JSScript *, LazyScriptHashPolicy, 769> LazyScriptCache;
   1.236 +
   1.237 +class PropertyIteratorObject;
   1.238 +
   1.239 +class NativeIterCache
   1.240 +{
   1.241 +    static const size_t SIZE = size_t(1) << 8;
   1.242 +
   1.243 +    /* Cached native iterators. */
   1.244 +    PropertyIteratorObject *data[SIZE];
   1.245 +
   1.246 +    static size_t getIndex(uint32_t key) {
   1.247 +        return size_t(key) % SIZE;
   1.248 +    }
   1.249 +
   1.250 +  public:
   1.251 +    /* Native iterator most recently started. */
   1.252 +    PropertyIteratorObject *last;
   1.253 +
   1.254 +    NativeIterCache()
   1.255 +      : last(nullptr)
   1.256 +    {
   1.257 +        mozilla::PodArrayZero(data);
   1.258 +    }
   1.259 +
   1.260 +    void purge() {
   1.261 +        last = nullptr;
   1.262 +        mozilla::PodArrayZero(data);
   1.263 +    }
   1.264 +
   1.265 +    PropertyIteratorObject *get(uint32_t key) const {
   1.266 +        return data[getIndex(key)];
   1.267 +    }
   1.268 +
   1.269 +    void set(uint32_t key, PropertyIteratorObject *iterobj) {
   1.270 +        data[getIndex(key)] = iterobj;
   1.271 +    }
   1.272 +};
   1.273 +
   1.274 +/*
   1.275 + * Cache for speeding up repetitive creation of objects in the VM.
   1.276 + * When an object is created which matches the criteria in the 'key' section
   1.277 + * below, an entry is filled with the resulting object.
   1.278 + */
   1.279 +class NewObjectCache
   1.280 +{
   1.281 +    /* Statically asserted to be equal to sizeof(JSObject_Slots16) */
   1.282 +    static const unsigned MAX_OBJ_SIZE = 4 * sizeof(void*) + 16 * sizeof(Value);
   1.283 +
   1.284 +    static void staticAsserts() {
   1.285 +        JS_STATIC_ASSERT(NewObjectCache::MAX_OBJ_SIZE == sizeof(JSObject_Slots16));
   1.286 +        JS_STATIC_ASSERT(gc::FINALIZE_OBJECT_LAST == gc::FINALIZE_OBJECT16_BACKGROUND);
   1.287 +    }
   1.288 +
   1.289 +    struct Entry
   1.290 +    {
   1.291 +        /* Class of the constructed object. */
   1.292 +        const Class *clasp;
   1.293 +
   1.294 +        /*
   1.295 +         * Key with one of three possible values:
   1.296 +         *
   1.297 +         * - Global for the object. The object must have a standard class for
   1.298 +         *   which the global's prototype can be determined, and the object's
   1.299 +         *   parent will be the global.
   1.300 +         *
   1.301 +         * - Prototype for the object (cannot be global). The object's parent
   1.302 +         *   will be the prototype's parent.
   1.303 +         *
   1.304 +         * - Type for the object. The object's parent will be the type's
   1.305 +         *   prototype's parent.
   1.306 +         */
   1.307 +        gc::Cell *key;
   1.308 +
   1.309 +        /* Allocation kind for the constructed object. */
   1.310 +        gc::AllocKind kind;
   1.311 +
   1.312 +        /* Number of bytes to copy from the template object. */
   1.313 +        uint32_t nbytes;
   1.314 +
   1.315 +        /*
   1.316 +         * Template object to copy from, with the initial values of fields,
   1.317 +         * fixed slots (undefined) and private data (nullptr).
   1.318 +         */
   1.319 +        char templateObject[MAX_OBJ_SIZE];
   1.320 +    };
   1.321 +
   1.322 +    Entry entries[41];  // TODO: reconsider size
   1.323 +
   1.324 +  public:
   1.325 +
   1.326 +    typedef int EntryIndex;
   1.327 +
   1.328 +    NewObjectCache() { mozilla::PodZero(this); }
   1.329 +    void purge() { mozilla::PodZero(this); }
   1.330 +
   1.331 +    /* Remove any cached items keyed on moved objects. */
   1.332 +    void clearNurseryObjects(JSRuntime *rt);
   1.333 +
   1.334 +    /*
   1.335 +     * Get the entry index for the given lookup, return whether there was a hit
   1.336 +     * on an existing entry.
   1.337 +     */
   1.338 +    inline bool lookupProto(const Class *clasp, JSObject *proto, gc::AllocKind kind, EntryIndex *pentry);
   1.339 +    inline bool lookupGlobal(const Class *clasp, js::GlobalObject *global, gc::AllocKind kind,
   1.340 +                             EntryIndex *pentry);
   1.341 +
   1.342 +    bool lookupType(js::types::TypeObject *type, gc::AllocKind kind, EntryIndex *pentry) {
   1.343 +        return lookup(type->clasp(), type, kind, pentry);
   1.344 +    }
   1.345 +
   1.346 +    /*
   1.347 +     * Return a new object from a cache hit produced by a lookup method, or
   1.348 +     * nullptr if returning the object could possibly trigger GC (does not
   1.349 +     * indicate failure).
   1.350 +     */
   1.351 +    template <AllowGC allowGC>
   1.352 +    inline JSObject *newObjectFromHit(JSContext *cx, EntryIndex entry, js::gc::InitialHeap heap);
   1.353 +
   1.354 +    /* Fill an entry after a cache miss. */
   1.355 +    void fillProto(EntryIndex entry, const Class *clasp, js::TaggedProto proto, gc::AllocKind kind, JSObject *obj);
   1.356 +
   1.357 +    inline void fillGlobal(EntryIndex entry, const Class *clasp, js::GlobalObject *global,
   1.358 +                           gc::AllocKind kind, JSObject *obj);
   1.359 +
   1.360 +    void fillType(EntryIndex entry, js::types::TypeObject *type, gc::AllocKind kind,
   1.361 +                  JSObject *obj)
   1.362 +    {
   1.363 +        JS_ASSERT(obj->type() == type);
   1.364 +        return fill(entry, type->clasp(), type, kind, obj);
   1.365 +    }
   1.366 +
   1.367 +    /* Invalidate any entries which might produce an object with shape/proto. */
   1.368 +    void invalidateEntriesForShape(JSContext *cx, HandleShape shape, HandleObject proto);
   1.369 +
   1.370 +  private:
   1.371 +    bool lookup(const Class *clasp, gc::Cell *key, gc::AllocKind kind, EntryIndex *pentry) {
   1.372 +        uintptr_t hash = (uintptr_t(clasp) ^ uintptr_t(key)) + kind;
   1.373 +        *pentry = hash % mozilla::ArrayLength(entries);
   1.374 +
   1.375 +        Entry *entry = &entries[*pentry];
   1.376 +
   1.377 +        /* N.B. Lookups with the same clasp/key but different kinds map to different entries. */
   1.378 +        return entry->clasp == clasp && entry->key == key;
   1.379 +    }
   1.380 +
   1.381 +    void fill(EntryIndex entry_, const Class *clasp, gc::Cell *key, gc::AllocKind kind, JSObject *obj) {
   1.382 +        JS_ASSERT(unsigned(entry_) < mozilla::ArrayLength(entries));
   1.383 +        Entry *entry = &entries[entry_];
   1.384 +
   1.385 +        JS_ASSERT(!obj->hasDynamicSlots() && !obj->hasDynamicElements());
   1.386 +
   1.387 +        entry->clasp = clasp;
   1.388 +        entry->key = key;
   1.389 +        entry->kind = kind;
   1.390 +
   1.391 +        entry->nbytes = gc::Arena::thingSize(kind);
   1.392 +        js_memcpy(&entry->templateObject, obj, entry->nbytes);
   1.393 +    }
   1.394 +
   1.395 +    static void copyCachedToObject(JSObject *dst, JSObject *src, gc::AllocKind kind) {
   1.396 +        js_memcpy(dst, src, gc::Arena::thingSize(kind));
   1.397 +#ifdef JSGC_GENERATIONAL
   1.398 +        Shape::writeBarrierPost(dst->shape_, &dst->shape_);
   1.399 +        types::TypeObject::writeBarrierPost(dst->type_, &dst->type_);
   1.400 +#endif
   1.401 +    }
   1.402 +};
   1.403 +
   1.404 +/*
   1.405 + * A FreeOp can do one thing: free memory. For convenience, it has delete_
   1.406 + * convenience methods that also call destructors.
   1.407 + *
   1.408 + * FreeOp is passed to finalizers and other sweep-phase hooks so that we do not
   1.409 + * need to pass a JSContext to those hooks.
   1.410 + */
   1.411 +class FreeOp : public JSFreeOp {
   1.412 +    bool        shouldFreeLater_;
   1.413 +
   1.414 +  public:
   1.415 +    static FreeOp *get(JSFreeOp *fop) {
   1.416 +        return static_cast<FreeOp *>(fop);
   1.417 +    }
   1.418 +
   1.419 +    FreeOp(JSRuntime *rt, bool shouldFreeLater)
   1.420 +      : JSFreeOp(rt),
   1.421 +        shouldFreeLater_(shouldFreeLater)
   1.422 +    {
   1.423 +    }
   1.424 +
   1.425 +    bool shouldFreeLater() const {
   1.426 +        return shouldFreeLater_;
   1.427 +    }
   1.428 +
   1.429 +    inline void free_(void *p);
   1.430 +
   1.431 +    template <class T>
   1.432 +    inline void delete_(T *p) {
   1.433 +        if (p) {
   1.434 +            p->~T();
   1.435 +            free_(p);
   1.436 +        }
   1.437 +    }
   1.438 +
   1.439 +    static void staticAsserts() {
   1.440 +        /*
   1.441 +         * Check that JSFreeOp is the first base class for FreeOp and we can
   1.442 +         * reinterpret a pointer to JSFreeOp as a pointer to FreeOp without
   1.443 +         * any offset adjustments. JSClass::finalize <-> Class::finalize depends
   1.444 +         * on this.
   1.445 +         */
   1.446 +        JS_STATIC_ASSERT(offsetof(FreeOp, shouldFreeLater_) == sizeof(JSFreeOp));
   1.447 +    }
   1.448 +};
   1.449 +
   1.450 +} /* namespace js */
   1.451 +
   1.452 +namespace JS {
   1.453 +struct RuntimeSizes;
   1.454 +}
   1.455 +
   1.456 +/* Various built-in or commonly-used names pinned on first context. */
   1.457 +struct JSAtomState
   1.458 +{
   1.459 +#define PROPERTYNAME_FIELD(idpart, id, text) js::FixedHeapPtr<js::PropertyName> id;
   1.460 +    FOR_EACH_COMMON_PROPERTYNAME(PROPERTYNAME_FIELD)
   1.461 +#undef PROPERTYNAME_FIELD
   1.462 +#define PROPERTYNAME_FIELD(name, code, init, clasp) js::FixedHeapPtr<js::PropertyName> name;
   1.463 +    JS_FOR_EACH_PROTOTYPE(PROPERTYNAME_FIELD)
   1.464 +#undef PROPERTYNAME_FIELD
   1.465 +};
   1.466 +
   1.467 +namespace js {
   1.468 +
   1.469 +#define NAME_OFFSET(name)       offsetof(JSAtomState, name)
   1.470 +
   1.471 +inline HandlePropertyName
   1.472 +AtomStateOffsetToName(const JSAtomState &atomState, size_t offset)
   1.473 +{
   1.474 +    return *(js::FixedHeapPtr<js::PropertyName>*)((char*)&atomState + offset);
   1.475 +}
   1.476 +
   1.477 +// There are several coarse locks in the enum below. These may be either
   1.478 +// per-runtime or per-process. When acquiring more than one of these locks,
   1.479 +// the acquisition must be done in the order below to avoid deadlocks.
   1.480 +enum RuntimeLock {
   1.481 +    ExclusiveAccessLock,
   1.482 +    WorkerThreadStateLock,
   1.483 +    InterruptLock,
   1.484 +    GCLock
   1.485 +};
   1.486 +
   1.487 +#ifdef DEBUG
   1.488 +void AssertCurrentThreadCanLock(RuntimeLock which);
   1.489 +#else
   1.490 +inline void AssertCurrentThreadCanLock(RuntimeLock which) {}
   1.491 +#endif
   1.492 +
   1.493 +/*
   1.494 + * Encapsulates portions of the runtime/context that are tied to a
   1.495 + * single active thread.  Instances of this structure can occur for
   1.496 + * the main thread as |JSRuntime::mainThread|, for select operations
   1.497 + * performed off thread, such as parsing, and for Parallel JS worker
   1.498 + * threads.
   1.499 + */
   1.500 +class PerThreadData : public PerThreadDataFriendFields
   1.501 +{
   1.502 +    /*
   1.503 +     * Backpointer to the full shared JSRuntime* with which this
   1.504 +     * thread is associated.  This is private because accessing the
   1.505 +     * fields of this runtime can provoke race conditions, so the
   1.506 +     * intention is that access will be mediated through safe
   1.507 +     * functions like |runtimeFromMainThread| and |associatedWith()| below.
   1.508 +     */
   1.509 +    JSRuntime *runtime_;
   1.510 +
   1.511 +  public:
   1.512 +    /*
   1.513 +     * We save all conservative scanned roots in this vector so that
   1.514 +     * conservative scanning can be "replayed" deterministically. In DEBUG mode,
   1.515 +     * this allows us to run a non-incremental GC after every incremental GC to
   1.516 +     * ensure that no objects were missed.
   1.517 +     */
   1.518 +#ifdef DEBUG
   1.519 +    struct SavedGCRoot {
   1.520 +        void *thing;
   1.521 +        JSGCTraceKind kind;
   1.522 +
   1.523 +        SavedGCRoot(void *thing, JSGCTraceKind kind) : thing(thing), kind(kind) {}
   1.524 +    };
   1.525 +    js::Vector<SavedGCRoot, 0, js::SystemAllocPolicy> gcSavedRoots;
   1.526 +#endif
   1.527 +
   1.528 +    /*
   1.529 +     * If Ion code is on the stack, and has called into C++, this will be
   1.530 +     * aligned to an Ion exit frame.
   1.531 +     */
   1.532 +    uint8_t             *ionTop;
   1.533 +
   1.534 +    /*
   1.535 +     * The current JSContext when entering JIT code. This field may only be used
   1.536 +     * from JIT code and C++ directly called by JIT code (otherwise it may refer
   1.537 +     * to the wrong JSContext).
   1.538 +     */
   1.539 +    JSContext           *jitJSContext;
   1.540 +
   1.541 +    /*
   1.542 +     * The stack limit checked by JIT code. This stack limit may be temporarily
   1.543 +     * set to null to force JIT code to exit (e.g., for the operation callback).
   1.544 +     */
   1.545 +    uintptr_t            jitStackLimit;
   1.546 +
   1.547 +    inline void setJitStackLimit(uintptr_t limit);
   1.548 +
   1.549 +#ifdef JS_TRACE_LOGGING
   1.550 +    TraceLogger         *traceLogger;
   1.551 +#endif
   1.552 +
   1.553 +    /*
   1.554 +     * asm.js maintains a stack of AsmJSModule activations (see AsmJS.h). This
   1.555 +     * stack is used by JSRuntime::requestInterrupt to stop long-running asm.js
   1.556 +     * without requiring dynamic polling operations in the generated
   1.557 +     * code. Since requestInterrupt may run on a separate thread than the
   1.558 +     * JSRuntime's owner thread all reads/writes must be synchronized (by
   1.559 +     * rt->interruptLock).
   1.560 +     */
   1.561 +  private:
   1.562 +    friend class js::Activation;
   1.563 +    friend class js::ActivationIterator;
   1.564 +    friend class js::jit::JitActivation;
   1.565 +    friend class js::AsmJSActivation;
   1.566 +#ifdef DEBUG
   1.567 +    friend void js::AssertCurrentThreadCanLock(RuntimeLock which);
   1.568 +#endif
   1.569 +
   1.570 +    /*
   1.571 +     * Points to the most recent activation running on the thread.
   1.572 +     * See Activation comment in vm/Stack.h.
   1.573 +     */
   1.574 +    js::Activation *activation_;
   1.575 +
   1.576 +    /* See AsmJSActivation comment. Protected by rt->interruptLock. */
   1.577 +    js::AsmJSActivation *asmJSActivationStack_;
   1.578 +
   1.579 +    /* Pointer to the current AutoFlushICache. */
   1.580 +    js::jit::AutoFlushICache *autoFlushICache_;
   1.581 +
   1.582 +#ifdef JS_ARM_SIMULATOR
   1.583 +    js::jit::Simulator *simulator_;
   1.584 +    uintptr_t simulatorStackLimit_;
   1.585 +#endif
   1.586 +
   1.587 +  public:
   1.588 +    js::Activation *const *addressOfActivation() const {
   1.589 +        return &activation_;
   1.590 +    }
   1.591 +    static unsigned offsetOfAsmJSActivationStackReadOnly() {
   1.592 +        return offsetof(PerThreadData, asmJSActivationStack_);
   1.593 +    }
   1.594 +    static unsigned offsetOfActivation() {
   1.595 +        return offsetof(PerThreadData, activation_);
   1.596 +    }
   1.597 +
   1.598 +    js::AsmJSActivation *asmJSActivationStackFromAnyThread() const {
   1.599 +        return asmJSActivationStack_;
   1.600 +    }
   1.601 +    js::AsmJSActivation *asmJSActivationStackFromOwnerThread() const {
   1.602 +        return asmJSActivationStack_;
   1.603 +    }
   1.604 +
   1.605 +    js::Activation *activation() const {
   1.606 +        return activation_;
   1.607 +    }
   1.608 +
   1.609 +    /* State used by jsdtoa.cpp. */
   1.610 +    DtoaState           *dtoaState;
   1.611 +
   1.612 +    /*
   1.613 +     * When this flag is non-zero, any attempt to GC will be skipped. It is used
   1.614 +     * to suppress GC when reporting an OOM (see js_ReportOutOfMemory) and in
   1.615 +     * debugging facilities that cannot tolerate a GC and would rather OOM
   1.616 +     * immediately, such as utilities exposed to GDB. Setting this flag is
   1.617 +     * extremely dangerous and should only be used when in an OOM situation or
   1.618 +     * in non-exposed debugging facilities.
   1.619 +     */
   1.620 +    int32_t suppressGC;
   1.621 +
   1.622 +    // Number of active bytecode compilation on this thread.
   1.623 +    unsigned activeCompilations;
   1.624 +
   1.625 +    PerThreadData(JSRuntime *runtime);
   1.626 +    ~PerThreadData();
   1.627 +
   1.628 +    bool init();
   1.629 +
   1.630 +    bool associatedWith(const JSRuntime *rt) { return runtime_ == rt; }
   1.631 +    inline JSRuntime *runtimeFromMainThread();
   1.632 +    inline JSRuntime *runtimeIfOnOwnerThread();
   1.633 +
   1.634 +    inline bool exclusiveThreadsPresent();
   1.635 +    inline void addActiveCompilation();
   1.636 +    inline void removeActiveCompilation();
   1.637 +
   1.638 +    // For threads which may be associated with different runtimes, depending
   1.639 +    // on the work they are doing.
   1.640 +    class MOZ_STACK_CLASS AutoEnterRuntime
   1.641 +    {
   1.642 +        PerThreadData *pt;
   1.643 +
   1.644 +      public:
   1.645 +        AutoEnterRuntime(PerThreadData *pt, JSRuntime *rt)
   1.646 +          : pt(pt)
   1.647 +        {
   1.648 +            JS_ASSERT(!pt->runtime_);
   1.649 +            pt->runtime_ = rt;
   1.650 +        }
   1.651 +
   1.652 +        ~AutoEnterRuntime() {
   1.653 +            pt->runtime_ = nullptr;
   1.654 +        }
   1.655 +    };
   1.656 +
   1.657 +    js::jit::AutoFlushICache *autoFlushICache() const;
   1.658 +    void setAutoFlushICache(js::jit::AutoFlushICache *afc);
   1.659 +
   1.660 +#ifdef JS_ARM_SIMULATOR
   1.661 +    js::jit::Simulator *simulator() const;
   1.662 +    void setSimulator(js::jit::Simulator *sim);
   1.663 +    js::jit::SimulatorRuntime *simulatorRuntime() const;
   1.664 +    uintptr_t *addressOfSimulatorStackLimit();
   1.665 +#endif
   1.666 +};
   1.667 +
   1.668 +namespace gc {
   1.669 +class MarkingValidator;
   1.670 +} // namespace gc
   1.671 +
   1.672 +typedef Vector<JS::Zone *, 4, SystemAllocPolicy> ZoneVector;
   1.673 +
   1.674 +class AutoLockForExclusiveAccess;
   1.675 +
   1.676 +void RecomputeStackLimit(JSRuntime *rt, StackKind kind);
   1.677 +
   1.678 +} // namespace js
   1.679 +
   1.680 +struct JSRuntime : public JS::shadow::Runtime,
   1.681 +                   public js::MallocProvider<JSRuntime>
   1.682 +{
   1.683 +    /*
   1.684 +     * Per-thread data for the main thread that is associated with
   1.685 +     * this JSRuntime, as opposed to any worker threads used in
   1.686 +     * parallel sections.  See definition of |PerThreadData| struct
   1.687 +     * above for more details.
   1.688 +     *
   1.689 +     * NB: This field is statically asserted to be at offset
   1.690 +     * sizeof(js::shadow::Runtime). See
   1.691 +     * PerThreadDataFriendFields::getMainThread.
   1.692 +     */
   1.693 +    js::PerThreadData mainThread;
   1.694 +
   1.695 +    /*
   1.696 +     * If non-null, another runtime guaranteed to outlive this one and whose
   1.697 +     * permanent data may be used by this one where possible.
   1.698 +     */
   1.699 +    JSRuntime *parentRuntime;
   1.700 +
   1.701 +    /*
   1.702 +     * If true, we've been asked to call the interrupt callback as soon as
   1.703 +     * possible.
   1.704 +     */
   1.705 +    mozilla::Atomic<bool, mozilla::Relaxed> interrupt;
   1.706 +
   1.707 +#if defined(JS_THREADSAFE) && defined(JS_ION)
   1.708 +    /*
   1.709 +     * If non-zero, ForkJoin should service an interrupt. This is a separate
   1.710 +     * flag from |interrupt| because we cannot use the mprotect trick with PJS
   1.711 +     * code and ignore the TriggerCallbackAnyThreadDontStopIon trigger.
   1.712 +     */
   1.713 +    mozilla::Atomic<bool, mozilla::Relaxed> interruptPar;
   1.714 +#endif
   1.715 +
   1.716 +    /* Set when handling a signal for a thread associated with this runtime. */
   1.717 +    bool handlingSignal;
   1.718 +
   1.719 +    JSInterruptCallback interruptCallback;
   1.720 +
   1.721 +#ifdef DEBUG
   1.722 +    void assertCanLock(js::RuntimeLock which);
   1.723 +#else
   1.724 +    void assertCanLock(js::RuntimeLock which) {}
   1.725 +#endif
   1.726 +
   1.727 +  private:
   1.728 +    /*
   1.729 +     * Lock taken when triggering an interrupt from another thread.
   1.730 +     * Protects all data that is touched in this process.
   1.731 +     */
   1.732 +#ifdef JS_THREADSAFE
   1.733 +    PRLock *interruptLock;
   1.734 +    PRThread *interruptLockOwner;
   1.735 +#else
   1.736 +    bool interruptLockTaken;
   1.737 +#endif // JS_THREADSAFE
   1.738 +  public:
   1.739 +
   1.740 +    class AutoLockForInterrupt {
   1.741 +        JSRuntime *rt;
   1.742 +      public:
   1.743 +        AutoLockForInterrupt(JSRuntime *rt MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : rt(rt) {
   1.744 +            MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   1.745 +            rt->assertCanLock(js::InterruptLock);
   1.746 +#ifdef JS_THREADSAFE
   1.747 +            PR_Lock(rt->interruptLock);
   1.748 +            rt->interruptLockOwner = PR_GetCurrentThread();
   1.749 +#else
   1.750 +            rt->interruptLockTaken = true;
   1.751 +#endif // JS_THREADSAFE
   1.752 +        }
   1.753 +        ~AutoLockForInterrupt() {
   1.754 +            JS_ASSERT(rt->currentThreadOwnsInterruptLock());
   1.755 +#ifdef JS_THREADSAFE
   1.756 +            rt->interruptLockOwner = nullptr;
   1.757 +            PR_Unlock(rt->interruptLock);
   1.758 +#else
   1.759 +            rt->interruptLockTaken = false;
   1.760 +#endif // JS_THREADSAFE
   1.761 +        }
   1.762 +
   1.763 +        MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   1.764 +    };
   1.765 +
   1.766 +    bool currentThreadOwnsInterruptLock() {
   1.767 +#if defined(JS_THREADSAFE)
   1.768 +        return interruptLockOwner == PR_GetCurrentThread();
   1.769 +#else
   1.770 +        return interruptLockTaken;
   1.771 +#endif
   1.772 +    }
   1.773 +
   1.774 +#ifdef JS_THREADSAFE
   1.775 +
   1.776 +  private:
   1.777 +    /*
   1.778 +     * Lock taken when using per-runtime or per-zone data that could otherwise
   1.779 +     * be accessed simultaneously by both the main thread and another thread
   1.780 +     * with an ExclusiveContext.
   1.781 +     *
   1.782 +     * Locking this only occurs if there is actually a thread other than the
   1.783 +     * main thread with an ExclusiveContext which could access such data.
   1.784 +     */
   1.785 +    PRLock *exclusiveAccessLock;
   1.786 +    mozilla::DebugOnly<PRThread *> exclusiveAccessOwner;
   1.787 +    mozilla::DebugOnly<bool> mainThreadHasExclusiveAccess;
   1.788 +
   1.789 +    /* Number of non-main threads with an ExclusiveContext. */
   1.790 +    size_t numExclusiveThreads;
   1.791 +
   1.792 +    friend class js::AutoLockForExclusiveAccess;
   1.793 +
   1.794 +  public:
   1.795 +    void setUsedByExclusiveThread(JS::Zone *zone);
   1.796 +    void clearUsedByExclusiveThread(JS::Zone *zone);
   1.797 +
   1.798 +#endif // JS_THREADSAFE
   1.799 +
   1.800 +#ifdef DEBUG
   1.801 +    bool currentThreadHasExclusiveAccess() {
   1.802 +#ifdef JS_THREADSAFE
   1.803 +        return (!numExclusiveThreads && mainThreadHasExclusiveAccess) ||
   1.804 +               exclusiveAccessOwner == PR_GetCurrentThread();
   1.805 +#else
   1.806 +        return true;
   1.807 +#endif
   1.808 +    }
   1.809 +#endif // DEBUG
   1.810 +
   1.811 +    bool exclusiveThreadsPresent() const {
   1.812 +#ifdef JS_THREADSAFE
   1.813 +        return numExclusiveThreads > 0;
   1.814 +#else
   1.815 +        return false;
   1.816 +#endif
   1.817 +    }
   1.818 +
   1.819 +    /* Embedders can use this zone however they wish. */
   1.820 +    JS::Zone            *systemZone;
   1.821 +
   1.822 +    /* List of compartments and zones (protected by the GC lock). */
   1.823 +    js::ZoneVector      zones;
   1.824 +
   1.825 +    /* How many compartments there are across all zones. */
   1.826 +    size_t              numCompartments;
   1.827 +
   1.828 +    /* Locale-specific callbacks for string conversion. */
   1.829 +    JSLocaleCallbacks *localeCallbacks;
   1.830 +
   1.831 +    /* Default locale for Internationalization API */
   1.832 +    char *defaultLocale;
   1.833 +
   1.834 +    /* Default JSVersion. */
   1.835 +    JSVersion defaultVersion_;
   1.836 +
   1.837 +#ifdef JS_THREADSAFE
   1.838 +  private:
   1.839 +    /* See comment for JS_AbortIfWrongThread in jsapi.h. */
   1.840 +    void *ownerThread_;
   1.841 +    friend bool js::CurrentThreadCanAccessRuntime(JSRuntime *rt);
   1.842 +  public:
   1.843 +#endif
   1.844 +
   1.845 +    /* Temporary arena pool used while compiling and decompiling. */
   1.846 +    static const size_t TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 4 * 1024;
   1.847 +    js::LifoAlloc tempLifoAlloc;
   1.848 +
   1.849 +    /*
   1.850 +     * Free LIFO blocks are transferred to this allocator before being freed on
   1.851 +     * the background GC thread.
   1.852 +     */
   1.853 +    js::LifoAlloc freeLifoAlloc;
   1.854 +
   1.855 +  private:
   1.856 +    /*
   1.857 +     * Both of these allocators are used for regular expression code which is shared at the
   1.858 +     * thread-data level.
   1.859 +     */
   1.860 +    JSC::ExecutableAllocator *execAlloc_;
   1.861 +    WTF::BumpPointerAllocator *bumpAlloc_;
   1.862 +    js::jit::JitRuntime *jitRuntime_;
   1.863 +
   1.864 +    /*
   1.865 +     * Self-hosting state cloned on demand into other compartments. Shared with the parent
   1.866 +     * runtime if there is one.
   1.867 +     */
   1.868 +    JSObject *selfHostingGlobal_;
   1.869 +
   1.870 +    /* Space for interpreter frames. */
   1.871 +    js::InterpreterStack interpreterStack_;
   1.872 +
   1.873 +    JSC::ExecutableAllocator *createExecutableAllocator(JSContext *cx);
   1.874 +    WTF::BumpPointerAllocator *createBumpPointerAllocator(JSContext *cx);
   1.875 +    js::jit::JitRuntime *createJitRuntime(JSContext *cx);
   1.876 +
   1.877 +  public:
   1.878 +    JSC::ExecutableAllocator *getExecAlloc(JSContext *cx) {
   1.879 +        return execAlloc_ ? execAlloc_ : createExecutableAllocator(cx);
   1.880 +    }
   1.881 +    JSC::ExecutableAllocator &execAlloc() {
   1.882 +        JS_ASSERT(execAlloc_);
   1.883 +        return *execAlloc_;
   1.884 +    }
   1.885 +    JSC::ExecutableAllocator *maybeExecAlloc() {
   1.886 +        return execAlloc_;
   1.887 +    }
   1.888 +    WTF::BumpPointerAllocator *getBumpPointerAllocator(JSContext *cx) {
   1.889 +        return bumpAlloc_ ? bumpAlloc_ : createBumpPointerAllocator(cx);
   1.890 +    }
   1.891 +    js::jit::JitRuntime *getJitRuntime(JSContext *cx) {
   1.892 +        return jitRuntime_ ? jitRuntime_ : createJitRuntime(cx);
   1.893 +    }
   1.894 +    js::jit::JitRuntime *jitRuntime() const {
   1.895 +        return jitRuntime_;
   1.896 +    }
   1.897 +    bool hasJitRuntime() const {
   1.898 +        return !!jitRuntime_;
   1.899 +    }
   1.900 +    js::InterpreterStack &interpreterStack() {
   1.901 +        return interpreterStack_;
   1.902 +    }
   1.903 +
   1.904 +    //-------------------------------------------------------------------------
   1.905 +    // Self-hosting support
   1.906 +    //-------------------------------------------------------------------------
   1.907 +
   1.908 +    bool initSelfHosting(JSContext *cx);
   1.909 +    void finishSelfHosting();
   1.910 +    void markSelfHostingGlobal(JSTracer *trc);
   1.911 +    bool isSelfHostingGlobal(JSObject *global) {
   1.912 +        return global == selfHostingGlobal_;
   1.913 +    }
   1.914 +    bool isSelfHostingCompartment(JSCompartment *comp);
   1.915 +    bool cloneSelfHostedFunctionScript(JSContext *cx, js::Handle<js::PropertyName*> name,
   1.916 +                                       js::Handle<JSFunction*> targetFun);
   1.917 +    bool cloneSelfHostedValue(JSContext *cx, js::Handle<js::PropertyName*> name,
   1.918 +                              js::MutableHandleValue vp);
   1.919 +
   1.920 +    //-------------------------------------------------------------------------
   1.921 +    // Locale information
   1.922 +    //-------------------------------------------------------------------------
   1.923 +
   1.924 +    /*
   1.925 +     * Set the default locale for the ECMAScript Internationalization API
   1.926 +     * (Intl.Collator, Intl.NumberFormat, Intl.DateTimeFormat).
   1.927 +     * Note that the Internationalization API encourages clients to
   1.928 +     * specify their own locales.
   1.929 +     * The locale string remains owned by the caller.
   1.930 +     */
   1.931 +    bool setDefaultLocale(const char *locale);
   1.932 +
   1.933 +    /* Reset the default locale to OS defaults. */
   1.934 +    void resetDefaultLocale();
   1.935 +
   1.936 +    /* Gets current default locale. String remains owned by context. */
   1.937 +    const char *getDefaultLocale();
   1.938 +
   1.939 +    JSVersion defaultVersion() { return defaultVersion_; }
   1.940 +    void setDefaultVersion(JSVersion v) { defaultVersion_ = v; }
   1.941 +
   1.942 +    /* Base address of the native stack for the current thread. */
   1.943 +    uintptr_t           nativeStackBase;
   1.944 +
   1.945 +    /* The native stack size limit that runtime should not exceed. */
   1.946 +    size_t              nativeStackQuota[js::StackKindCount];
   1.947 +
   1.948 +    /* Context create/destroy callback. */
   1.949 +    JSContextCallback   cxCallback;
   1.950 +    void               *cxCallbackData;
   1.951 +
   1.952 +    /* Compartment destroy callback. */
   1.953 +    JSDestroyCompartmentCallback destroyCompartmentCallback;
   1.954 +
   1.955 +    /* Zone destroy callback. */
   1.956 +    JSZoneCallback destroyZoneCallback;
   1.957 +
   1.958 +    /* Zone sweep callback. */
   1.959 +    JSZoneCallback sweepZoneCallback;
   1.960 +
   1.961 +    /* Call this to get the name of a compartment. */
   1.962 +    JSCompartmentNameCallback compartmentNameCallback;
   1.963 +
   1.964 +    js::ActivityCallback  activityCallback;
   1.965 +    void                 *activityCallbackArg;
   1.966 +    void triggerActivityCallback(bool active);
   1.967 +
   1.968 +#ifdef JS_THREADSAFE
   1.969 +    /* The request depth for this thread. */
   1.970 +    unsigned            requestDepth;
   1.971 +
   1.972 +# ifdef DEBUG
   1.973 +    unsigned            checkRequestDepth;
   1.974 +# endif
   1.975 +#endif
   1.976 +
   1.977 +#ifdef DEBUG
   1.978 +    /*
   1.979 +     * To help embedders enforce their invariants, we allow them to specify in
   1.980 +     * advance which JSContext should be passed to JSAPI calls. If this is set
   1.981 +     * to a non-null value, the assertSameCompartment machinery does double-
   1.982 +     * duty (in debug builds) to verify that it matches the cx being used.
   1.983 +     */
   1.984 +    JSContext          *activeContext;
   1.985 +#endif
   1.986 +
   1.987 +    /* Garbage collector state, used by jsgc.c. */
   1.988 +
   1.989 +    /* Garbase collector state has been sucessfully initialized. */
   1.990 +    bool                gcInitialized;
   1.991 +
   1.992 +    /*
   1.993 +     * Set of all GC chunks with at least one allocated thing. The
   1.994 +     * conservative GC uses it to quickly check if a possible GC thing points
   1.995 +     * into an allocated chunk.
   1.996 +     */
   1.997 +    js::GCChunkSet      gcChunkSet;
   1.998 +
   1.999 +    /*
  1.1000 +     * Doubly-linked lists of chunks from user and system compartments. The GC
  1.1001 +     * allocates its arenas from the corresponding list and when all arenas
  1.1002 +     * in the list head are taken, then the chunk is removed from the list.
  1.1003 +     * During the GC when all arenas in a chunk become free, that chunk is
  1.1004 +     * removed from the list and scheduled for release.
  1.1005 +     */
  1.1006 +    js::gc::Chunk       *gcSystemAvailableChunkListHead;
  1.1007 +    js::gc::Chunk       *gcUserAvailableChunkListHead;
  1.1008 +    js::gc::ChunkPool   gcChunkPool;
  1.1009 +
  1.1010 +    js::RootedValueMap  gcRootsHash;
  1.1011 +
  1.1012 +    /* This is updated by both the main and GC helper threads. */
  1.1013 +    mozilla::Atomic<size_t, mozilla::ReleaseAcquire> gcBytes;
  1.1014 +
  1.1015 +    size_t              gcMaxBytes;
  1.1016 +    size_t              gcMaxMallocBytes;
  1.1017 +
  1.1018 +    /*
  1.1019 +     * Number of the committed arenas in all GC chunks including empty chunks.
  1.1020 +     */
  1.1021 +    mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> gcNumArenasFreeCommitted;
  1.1022 +    js::GCMarker        gcMarker;
  1.1023 +    void                *gcVerifyPreData;
  1.1024 +    void                *gcVerifyPostData;
  1.1025 +    bool                gcChunkAllocationSinceLastGC;
  1.1026 +    int64_t             gcNextFullGCTime;
  1.1027 +    int64_t             gcLastGCTime;
  1.1028 +    int64_t             gcJitReleaseTime;
  1.1029 +  private:
  1.1030 +    JSGCMode            gcMode_;
  1.1031 +
  1.1032 +  public:
  1.1033 +    JSGCMode gcMode() const { return gcMode_; }
  1.1034 +    void setGCMode(JSGCMode mode) {
  1.1035 +        gcMode_ = mode;
  1.1036 +        gcMarker.setGCMode(mode);
  1.1037 +    }
  1.1038 +
  1.1039 +    size_t              gcAllocationThreshold;
  1.1040 +    bool                gcHighFrequencyGC;
  1.1041 +    uint64_t            gcHighFrequencyTimeThreshold;
  1.1042 +    uint64_t            gcHighFrequencyLowLimitBytes;
  1.1043 +    uint64_t            gcHighFrequencyHighLimitBytes;
  1.1044 +    double              gcHighFrequencyHeapGrowthMax;
  1.1045 +    double              gcHighFrequencyHeapGrowthMin;
  1.1046 +    double              gcLowFrequencyHeapGrowth;
  1.1047 +    bool                gcDynamicHeapGrowth;
  1.1048 +    bool                gcDynamicMarkSlice;
  1.1049 +    uint64_t            gcDecommitThreshold;
  1.1050 +
  1.1051 +    /* During shutdown, the GC needs to clean up every possible object. */
  1.1052 +    bool                gcShouldCleanUpEverything;
  1.1053 +
  1.1054 +    /*
  1.1055 +     * The gray bits can become invalid if UnmarkGray overflows the stack. A
  1.1056 +     * full GC will reset this bit, since it fills in all the gray bits.
  1.1057 +     */
  1.1058 +    bool                gcGrayBitsValid;
  1.1059 +
  1.1060 +    /*
  1.1061 +     * These flags must be kept separate so that a thread requesting a
  1.1062 +     * compartment GC doesn't cancel another thread's concurrent request for a
  1.1063 +     * full GC.
  1.1064 +     */
  1.1065 +    volatile uintptr_t  gcIsNeeded;
  1.1066 +
  1.1067 +    js::gcstats::Statistics gcStats;
  1.1068 +
  1.1069 +    /* Incremented on every GC slice. */
  1.1070 +    uint64_t            gcNumber;
  1.1071 +
  1.1072 +    /* The gcNumber at the time of the most recent GC's first slice. */
  1.1073 +    uint64_t            gcStartNumber;
  1.1074 +
  1.1075 +    /* Whether the currently running GC can finish in multiple slices. */
  1.1076 +    bool                gcIsIncremental;
  1.1077 +
  1.1078 +    /* Whether all compartments are being collected in first GC slice. */
  1.1079 +    bool                gcIsFull;
  1.1080 +
  1.1081 +    /* The reason that an interrupt-triggered GC should be called. */
  1.1082 +    JS::gcreason::Reason gcTriggerReason;
  1.1083 +
  1.1084 +    /*
  1.1085 +     * If this is true, all marked objects must belong to a compartment being
  1.1086 +     * GCed. This is used to look for compartment bugs.
  1.1087 +     */
  1.1088 +    bool                gcStrictCompartmentChecking;
  1.1089 +
  1.1090 +#ifdef DEBUG
  1.1091 +    /*
  1.1092 +     * If this is 0, all cross-compartment proxies must be registered in the
  1.1093 +     * wrapper map. This checking must be disabled temporarily while creating
  1.1094 +     * new wrappers. When non-zero, this records the recursion depth of wrapper
  1.1095 +     * creation.
  1.1096 +     */
  1.1097 +    uintptr_t           gcDisableStrictProxyCheckingCount;
  1.1098 +#else
  1.1099 +    uintptr_t           unused1;
  1.1100 +#endif
  1.1101 +
  1.1102 +    /*
  1.1103 +     * The current incremental GC phase. This is also used internally in
  1.1104 +     * non-incremental GC.
  1.1105 +     */
  1.1106 +    js::gc::State       gcIncrementalState;
  1.1107 +
  1.1108 +    /* Indicates that the last incremental slice exhausted the mark stack. */
  1.1109 +    bool                gcLastMarkSlice;
  1.1110 +
  1.1111 +    /* Whether any sweeping will take place in the separate GC helper thread. */
  1.1112 +    bool                gcSweepOnBackgroundThread;
  1.1113 +
  1.1114 +    /* Whether any black->gray edges were found during marking. */
  1.1115 +    bool                gcFoundBlackGrayEdges;
  1.1116 +
  1.1117 +    /* List head of zones to be swept in the background. */
  1.1118 +    JS::Zone            *gcSweepingZones;
  1.1119 +
  1.1120 +    /* Index of current zone group (for stats). */
  1.1121 +    unsigned            gcZoneGroupIndex;
  1.1122 +
  1.1123 +    /*
  1.1124 +     * Incremental sweep state.
  1.1125 +     */
  1.1126 +    JS::Zone            *gcZoneGroups;
  1.1127 +    JS::Zone            *gcCurrentZoneGroup;
  1.1128 +    int                 gcSweepPhase;
  1.1129 +    JS::Zone            *gcSweepZone;
  1.1130 +    int                 gcSweepKindIndex;
  1.1131 +    bool                gcAbortSweepAfterCurrentGroup;
  1.1132 +
  1.1133 +    /*
  1.1134 +     * List head of arenas allocated during the sweep phase.
  1.1135 +     */
  1.1136 +    js::gc::ArenaHeader *gcArenasAllocatedDuringSweep;
  1.1137 +
  1.1138 +#ifdef DEBUG
  1.1139 +    js::gc::MarkingValidator *gcMarkingValidator;
  1.1140 +#endif
  1.1141 +
  1.1142 +    /*
  1.1143 +     * Indicates that a GC slice has taken place in the middle of an animation
  1.1144 +     * frame, rather than at the beginning. In this case, the next slice will be
  1.1145 +     * delayed so that we don't get back-to-back slices.
  1.1146 +     */
  1.1147 +    volatile uintptr_t  gcInterFrameGC;
  1.1148 +
  1.1149 +    /* Default budget for incremental GC slice. See SliceBudget in jsgc.h. */
  1.1150 +    int64_t             gcSliceBudget;
  1.1151 +
  1.1152 +    /*
  1.1153 +     * We disable incremental GC if we encounter a js::Class with a trace hook
  1.1154 +     * that does not implement write barriers.
  1.1155 +     */
  1.1156 +    bool                gcIncrementalEnabled;
  1.1157 +
  1.1158 +    /*
  1.1159 +     * GGC can be enabled from the command line while testing.
  1.1160 +     */
  1.1161 +    unsigned            gcGenerationalDisabled;
  1.1162 +
  1.1163 +    /*
  1.1164 +     * This is true if we are in the middle of a brain transplant (e.g.,
  1.1165 +     * JS_TransplantObject) or some other operation that can manipulate
  1.1166 +     * dead zones.
  1.1167 +     */
  1.1168 +    bool                gcManipulatingDeadZones;
  1.1169 +
  1.1170 +    /*
  1.1171 +     * This field is incremented each time we mark an object inside a
  1.1172 +     * zone with no incoming cross-compartment pointers. Typically if
  1.1173 +     * this happens it signals that an incremental GC is marking too much
  1.1174 +     * stuff. At various times we check this counter and, if it has changed, we
  1.1175 +     * run an immediate, non-incremental GC to clean up the dead
  1.1176 +     * zones. This should happen very rarely.
  1.1177 +     */
  1.1178 +    unsigned            gcObjectsMarkedInDeadZones;
  1.1179 +
  1.1180 +    bool                gcPoke;
  1.1181 +
  1.1182 +    volatile js::HeapState heapState;
  1.1183 +
  1.1184 +    bool isHeapBusy() { return heapState != js::Idle; }
  1.1185 +    bool isHeapMajorCollecting() { return heapState == js::MajorCollecting; }
  1.1186 +    bool isHeapMinorCollecting() { return heapState == js::MinorCollecting; }
  1.1187 +    bool isHeapCollecting() { return isHeapMajorCollecting() || isHeapMinorCollecting(); }
  1.1188 +
  1.1189 +#ifdef JSGC_GENERATIONAL
  1.1190 +    js::Nursery                  gcNursery;
  1.1191 +    js::gc::StoreBuffer          gcStoreBuffer;
  1.1192 +#endif
  1.1193 +
  1.1194 +    /*
  1.1195 +     * These options control the zealousness of the GC. The fundamental values
  1.1196 +     * are gcNextScheduled and gcDebugCompartmentGC. At every allocation,
  1.1197 +     * gcNextScheduled is decremented. When it reaches zero, we do either a
  1.1198 +     * full or a compartmental GC, based on gcDebugCompartmentGC.
  1.1199 +     *
  1.1200 +     * At this point, if gcZeal_ is one of the types that trigger periodic
  1.1201 +     * collection, then gcNextScheduled is reset to the value of
  1.1202 +     * gcZealFrequency. Otherwise, no additional GCs take place.
  1.1203 +     *
  1.1204 +     * You can control these values in several ways:
  1.1205 +     *   - Pass the -Z flag to the shell (see the usage info for details)
  1.1206 +     *   - Call gczeal() or schedulegc() from inside shell-executed JS code
  1.1207 +     *     (see the help for details)
  1.1208 +     *
  1.1209 +     * If gzZeal_ == 1 then we perform GCs in select places (during MaybeGC and
  1.1210 +     * whenever a GC poke happens). This option is mainly useful to embedders.
  1.1211 +     *
  1.1212 +     * We use gcZeal_ == 4 to enable write barrier verification. See the comment
  1.1213 +     * in jsgc.cpp for more information about this.
  1.1214 +     *
  1.1215 +     * gcZeal_ values from 8 to 10 periodically run different types of
  1.1216 +     * incremental GC.
  1.1217 +     */
  1.1218 +#ifdef JS_GC_ZEAL
  1.1219 +    int                 gcZeal_;
  1.1220 +    int                 gcZealFrequency;
  1.1221 +    int                 gcNextScheduled;
  1.1222 +    bool                gcDeterministicOnly;
  1.1223 +    int                 gcIncrementalLimit;
  1.1224 +
  1.1225 +    js::Vector<JSObject *, 0, js::SystemAllocPolicy> gcSelectedForMarking;
  1.1226 +
  1.1227 +    int gcZeal() { return gcZeal_; }
  1.1228 +
  1.1229 +    bool upcomingZealousGC() {
  1.1230 +        return gcNextScheduled == 1;
  1.1231 +    }
  1.1232 +
  1.1233 +    bool needZealousGC() {
  1.1234 +        if (gcNextScheduled > 0 && --gcNextScheduled == 0) {
  1.1235 +            if (gcZeal() == js::gc::ZealAllocValue ||
  1.1236 +                gcZeal() == js::gc::ZealGenerationalGCValue ||
  1.1237 +                (gcZeal() >= js::gc::ZealIncrementalRootsThenFinish &&
  1.1238 +                 gcZeal() <= js::gc::ZealIncrementalMultipleSlices))
  1.1239 +            {
  1.1240 +                gcNextScheduled = gcZealFrequency;
  1.1241 +            }
  1.1242 +            return true;
  1.1243 +        }
  1.1244 +        return false;
  1.1245 +    }
  1.1246 +#else
  1.1247 +    int gcZeal() { return 0; }
  1.1248 +    bool upcomingZealousGC() { return false; }
  1.1249 +    bool needZealousGC() { return false; }
  1.1250 +#endif
  1.1251 +
  1.1252 +    bool                gcValidate;
  1.1253 +    bool                gcFullCompartmentChecks;
  1.1254 +
  1.1255 +    JSGCCallback        gcCallback;
  1.1256 +    JS::GCSliceCallback gcSliceCallback;
  1.1257 +    JSFinalizeCallback  gcFinalizeCallback;
  1.1258 +
  1.1259 +    void                *gcCallbackData;
  1.1260 +
  1.1261 +  private:
  1.1262 +    /*
  1.1263 +     * Malloc counter to measure memory pressure for GC scheduling. It runs
  1.1264 +     * from gcMaxMallocBytes down to zero.
  1.1265 +     */
  1.1266 +    mozilla::Atomic<ptrdiff_t, mozilla::ReleaseAcquire> gcMallocBytes;
  1.1267 +
  1.1268 +    /*
  1.1269 +     * Whether a GC has been triggered as a result of gcMallocBytes falling
  1.1270 +     * below zero.
  1.1271 +     */
  1.1272 +    mozilla::Atomic<bool, mozilla::ReleaseAcquire> gcMallocGCTriggered;
  1.1273 +
  1.1274 +#ifdef JS_ARM_SIMULATOR
  1.1275 +    js::jit::SimulatorRuntime *simulatorRuntime_;
  1.1276 +#endif
  1.1277 +
  1.1278 +  public:
  1.1279 +    void setNeedsBarrier(bool needs) {
  1.1280 +        needsBarrier_ = needs;
  1.1281 +    }
  1.1282 +
  1.1283 +    struct ExtraTracer {
  1.1284 +        JSTraceDataOp op;
  1.1285 +        void *data;
  1.1286 +
  1.1287 +        ExtraTracer()
  1.1288 +          : op(nullptr), data(nullptr)
  1.1289 +        {}
  1.1290 +        ExtraTracer(JSTraceDataOp op, void *data)
  1.1291 +          : op(op), data(data)
  1.1292 +        {}
  1.1293 +    };
  1.1294 +
  1.1295 +#ifdef JS_ARM_SIMULATOR
  1.1296 +    js::jit::SimulatorRuntime *simulatorRuntime() const;
  1.1297 +    void setSimulatorRuntime(js::jit::SimulatorRuntime *srt);
  1.1298 +#endif
  1.1299 +
  1.1300 +    /*
  1.1301 +     * The trace operations to trace embedding-specific GC roots. One is for
  1.1302 +     * tracing through black roots and the other is for tracing through gray
  1.1303 +     * roots. The black/gray distinction is only relevant to the cycle
  1.1304 +     * collector.
  1.1305 +     */
  1.1306 +    typedef js::Vector<ExtraTracer, 4, js::SystemAllocPolicy> ExtraTracerVector;
  1.1307 +    ExtraTracerVector   gcBlackRootTracers;
  1.1308 +    ExtraTracer         gcGrayRootTracer;
  1.1309 +
  1.1310 +    /*
  1.1311 +     * The GC can only safely decommit memory when the page size of the
  1.1312 +     * running process matches the compiled arena size.
  1.1313 +     */
  1.1314 +    size_t              gcSystemPageSize;
  1.1315 +
  1.1316 +    /* The OS allocation granularity may not match the page size. */
  1.1317 +    size_t              gcSystemAllocGranularity;
  1.1318 +
  1.1319 +    /* Strong references on scripts held for PCCount profiling API. */
  1.1320 +    js::ScriptAndCountsVector *scriptAndCountsVector;
  1.1321 +
  1.1322 +    /* Well-known numbers held for use by this runtime's contexts. */
  1.1323 +    const js::Value     NaNValue;
  1.1324 +    const js::Value     negativeInfinityValue;
  1.1325 +    const js::Value     positiveInfinityValue;
  1.1326 +
  1.1327 +    js::PropertyName    *emptyString;
  1.1328 +
  1.1329 +    /* List of active contexts sharing this runtime. */
  1.1330 +    mozilla::LinkedList<JSContext> contextList;
  1.1331 +
  1.1332 +    bool hasContexts() const {
  1.1333 +        return !contextList.isEmpty();
  1.1334 +    }
  1.1335 +
  1.1336 +    mozilla::ScopedDeletePtr<js::SourceHook> sourceHook;
  1.1337 +
  1.1338 +    /* Per runtime debug hooks -- see js/OldDebugAPI.h. */
  1.1339 +    JSDebugHooks        debugHooks;
  1.1340 +
  1.1341 +    /* If true, new compartments are initially in debug mode. */
  1.1342 +    bool                debugMode;
  1.1343 +
  1.1344 +    /* SPS profiling metadata */
  1.1345 +    js::SPSProfiler     spsProfiler;
  1.1346 +
  1.1347 +    /* If true, new scripts must be created with PC counter information. */
  1.1348 +    bool                profilingScripts;
  1.1349 +
  1.1350 +    /* Always preserve JIT code during GCs, for testing. */
  1.1351 +    bool                alwaysPreserveCode;
  1.1352 +
  1.1353 +    /* Had an out-of-memory error which did not populate an exception. */
  1.1354 +    bool                hadOutOfMemory;
  1.1355 +
  1.1356 +    /* A context has been created on this runtime. */
  1.1357 +    bool                haveCreatedContext;
  1.1358 +
  1.1359 +    /* Linked list of all Debugger objects in the runtime. */
  1.1360 +    mozilla::LinkedList<js::Debugger> debuggerList;
  1.1361 +
  1.1362 +    /*
  1.1363 +     * Head of circular list of all enabled Debuggers that have
  1.1364 +     * onNewGlobalObject handler methods established.
  1.1365 +     */
  1.1366 +    JSCList             onNewGlobalObjectWatchers;
  1.1367 +
  1.1368 +    /* Client opaque pointers */
  1.1369 +    void                *data;
  1.1370 +
  1.1371 +  private:
  1.1372 +    /* Synchronize GC heap access between main thread and GCHelperThread. */
  1.1373 +    PRLock *gcLock;
  1.1374 +    mozilla::DebugOnly<PRThread *> gcLockOwner;
  1.1375 +
  1.1376 +    friend class js::GCHelperThread;
  1.1377 +  public:
  1.1378 +
  1.1379 +    void lockGC() {
  1.1380 +#ifdef JS_THREADSAFE
  1.1381 +        assertCanLock(js::GCLock);
  1.1382 +        PR_Lock(gcLock);
  1.1383 +        JS_ASSERT(!gcLockOwner);
  1.1384 +#ifdef DEBUG
  1.1385 +        gcLockOwner = PR_GetCurrentThread();
  1.1386 +#endif
  1.1387 +#endif
  1.1388 +    }
  1.1389 +
  1.1390 +    void unlockGC() {
  1.1391 +#ifdef JS_THREADSAFE
  1.1392 +        JS_ASSERT(gcLockOwner == PR_GetCurrentThread());
  1.1393 +        gcLockOwner = nullptr;
  1.1394 +        PR_Unlock(gcLock);
  1.1395 +#endif
  1.1396 +    }
  1.1397 +
  1.1398 +    js::GCHelperThread  gcHelperThread;
  1.1399 +
  1.1400 +#if defined(XP_MACOSX) && defined(JS_ION)
  1.1401 +    js::AsmJSMachExceptionHandler asmJSMachExceptionHandler;
  1.1402 +#endif
  1.1403 +
  1.1404 +    // Whether asm.js signal handlers have been installed and can be used for
  1.1405 +    // performing interrupt checks in loops.
  1.1406 +  private:
  1.1407 +    bool signalHandlersInstalled_;
  1.1408 +  public:
  1.1409 +    bool signalHandlersInstalled() const {
  1.1410 +        return signalHandlersInstalled_;
  1.1411 +    }
  1.1412 +
  1.1413 +  private:
  1.1414 +    js::FreeOp          defaultFreeOp_;
  1.1415 +
  1.1416 +  public:
  1.1417 +    js::FreeOp *defaultFreeOp() {
  1.1418 +        return &defaultFreeOp_;
  1.1419 +    }
  1.1420 +
  1.1421 +    uint32_t            debuggerMutations;
  1.1422 +
  1.1423 +    const JSSecurityCallbacks *securityCallbacks;
  1.1424 +    const js::DOMCallbacks *DOMcallbacks;
  1.1425 +    JSDestroyPrincipalsOp destroyPrincipals;
  1.1426 +
  1.1427 +    /* Structured data callbacks are runtime-wide. */
  1.1428 +    const JSStructuredCloneCallbacks *structuredCloneCallbacks;
  1.1429 +
  1.1430 +    /* Call this to accumulate telemetry data. */
  1.1431 +    JSAccumulateTelemetryDataCallback telemetryCallback;
  1.1432 +
  1.1433 +    /* AsmJSCache callbacks are runtime-wide. */
  1.1434 +    JS::AsmJSCacheOps asmJSCacheOps;
  1.1435 +
  1.1436 +    /*
  1.1437 +     * The propertyRemovals counter is incremented for every JSObject::clear,
  1.1438 +     * and for each JSObject::remove method call that frees a slot in the given
  1.1439 +     * object. See js_NativeGet and js_NativeSet in jsobj.cpp.
  1.1440 +     */
  1.1441 +    uint32_t            propertyRemovals;
  1.1442 +
  1.1443 +#if !EXPOSE_INTL_API
  1.1444 +    /* Number localization, used by jsnum.cpp. */
  1.1445 +    const char          *thousandsSeparator;
  1.1446 +    const char          *decimalSeparator;
  1.1447 +    const char          *numGrouping;
  1.1448 +#endif
  1.1449 +
  1.1450 +  private:
  1.1451 +    js::MathCache *mathCache_;
  1.1452 +    js::MathCache *createMathCache(JSContext *cx);
  1.1453 +  public:
  1.1454 +    js::MathCache *getMathCache(JSContext *cx) {
  1.1455 +        return mathCache_ ? mathCache_ : createMathCache(cx);
  1.1456 +    }
  1.1457 +    js::MathCache *maybeGetMathCache() {
  1.1458 +        return mathCache_;
  1.1459 +    }
  1.1460 +
  1.1461 +    js::GSNCache        gsnCache;
  1.1462 +    js::ScopeCoordinateNameCache scopeCoordinateNameCache;
  1.1463 +    js::NewObjectCache  newObjectCache;
  1.1464 +    js::NativeIterCache nativeIterCache;
  1.1465 +    js::SourceDataCache sourceDataCache;
  1.1466 +    js::EvalCache       evalCache;
  1.1467 +    js::LazyScriptCache lazyScriptCache;
  1.1468 +
  1.1469 +    js::DateTimeInfo    dateTimeInfo;
  1.1470 +
  1.1471 +    js::ConservativeGCData conservativeGC;
  1.1472 +
  1.1473 +    // Pool of maps used during parse/emit. This may be modified by threads
  1.1474 +    // with an ExclusiveContext and requires a lock. Active compilations
  1.1475 +    // prevent the pool from being purged during GCs.
  1.1476 +  private:
  1.1477 +    js::frontend::ParseMapPool parseMapPool_;
  1.1478 +    unsigned activeCompilations_;
  1.1479 +  public:
  1.1480 +    js::frontend::ParseMapPool &parseMapPool() {
  1.1481 +        JS_ASSERT(currentThreadHasExclusiveAccess());
  1.1482 +        return parseMapPool_;
  1.1483 +    }
  1.1484 +    bool hasActiveCompilations() {
  1.1485 +        return activeCompilations_ != 0;
  1.1486 +    }
  1.1487 +    void addActiveCompilation() {
  1.1488 +        JS_ASSERT(currentThreadHasExclusiveAccess());
  1.1489 +        activeCompilations_++;
  1.1490 +    }
  1.1491 +    void removeActiveCompilation() {
  1.1492 +        JS_ASSERT(currentThreadHasExclusiveAccess());
  1.1493 +        activeCompilations_--;
  1.1494 +    }
  1.1495 +
  1.1496 +    // Count of AutoKeepAtoms instances on the main thread's stack. When any
  1.1497 +    // instances exist, atoms in the runtime will not be collected. Threads
  1.1498 +    // with an ExclusiveContext do not increment this value, but the presence
  1.1499 +    // of any such threads also inhibits collection of atoms. We don't scan the
  1.1500 +    // stacks of exclusive threads, so we need to avoid collecting their
  1.1501 +    // objects in another way. The only GC thing pointers they have are to
  1.1502 +    // their exclusive compartment (which is not collected) or to the atoms
  1.1503 +    // compartment. Therefore, we avoid collecting the atoms compartment when
  1.1504 +    // exclusive threads are running.
  1.1505 +  private:
  1.1506 +    unsigned keepAtoms_;
  1.1507 +    friend class js::AutoKeepAtoms;
  1.1508 +  public:
  1.1509 +    bool keepAtoms() {
  1.1510 +        JS_ASSERT(CurrentThreadCanAccessRuntime(this));
  1.1511 +        return keepAtoms_ != 0 || exclusiveThreadsPresent();
  1.1512 +    }
  1.1513 +
  1.1514 +  private:
  1.1515 +    const JSPrincipals  *trustedPrincipals_;
  1.1516 +  public:
  1.1517 +    void setTrustedPrincipals(const JSPrincipals *p) { trustedPrincipals_ = p; }
  1.1518 +    const JSPrincipals *trustedPrincipals() const { return trustedPrincipals_; }
  1.1519 +
  1.1520 +  private:
  1.1521 +    bool beingDestroyed_;
  1.1522 +  public:
  1.1523 +    bool isBeingDestroyed() const {
  1.1524 +        return beingDestroyed_;
  1.1525 +    }
  1.1526 +
  1.1527 +  private:
  1.1528 +    // Set of all atoms other than those in permanentAtoms and staticStrings.
  1.1529 +    // This may be modified by threads with an ExclusiveContext and requires
  1.1530 +    // a lock.
  1.1531 +    js::AtomSet *atoms_;
  1.1532 +
  1.1533 +    // Compartment and associated zone containing all atoms in the runtime,
  1.1534 +    // as well as runtime wide IonCode stubs. The contents of this compartment
  1.1535 +    // may be modified by threads with an ExclusiveContext and requires a lock.
  1.1536 +    JSCompartment *atomsCompartment_;
  1.1537 +
  1.1538 +  public:
  1.1539 +    bool initializeAtoms(JSContext *cx);
  1.1540 +    void finishAtoms();
  1.1541 +
  1.1542 +    void sweepAtoms();
  1.1543 +
  1.1544 +    js::AtomSet &atoms() {
  1.1545 +        JS_ASSERT(currentThreadHasExclusiveAccess());
  1.1546 +        return *atoms_;
  1.1547 +    }
  1.1548 +    JSCompartment *atomsCompartment() {
  1.1549 +        JS_ASSERT(currentThreadHasExclusiveAccess());
  1.1550 +        return atomsCompartment_;
  1.1551 +    }
  1.1552 +
  1.1553 +    bool isAtomsCompartment(JSCompartment *comp) {
  1.1554 +        return comp == atomsCompartment_;
  1.1555 +    }
  1.1556 +
  1.1557 +    // The atoms compartment is the only one in its zone.
  1.1558 +    inline bool isAtomsZone(JS::Zone *zone);
  1.1559 +
  1.1560 +    bool activeGCInAtomsZone();
  1.1561 +
  1.1562 +    // Permanent atoms are fixed during initialization of the runtime and are
  1.1563 +    // not modified or collected until the runtime is destroyed. These may be
  1.1564 +    // shared with another, longer living runtime through |parentRuntime| and
  1.1565 +    // can be freely accessed with no locking necessary.
  1.1566 +
  1.1567 +    // Permanent atoms pre-allocated for general use.
  1.1568 +    js::StaticStrings *staticStrings;
  1.1569 +
  1.1570 +    // Cached pointers to various permanent property names.
  1.1571 +    JSAtomState *commonNames;
  1.1572 +
  1.1573 +    // All permanent atoms in the runtime, other than those in staticStrings.
  1.1574 +    js::AtomSet *permanentAtoms;
  1.1575 +
  1.1576 +    bool transformToPermanentAtoms();
  1.1577 +
  1.1578 +    const JSWrapObjectCallbacks            *wrapObjectCallbacks;
  1.1579 +    js::PreserveWrapperCallback            preserveWrapperCallback;
  1.1580 +
  1.1581 +    // Table of bytecode and other data that may be shared across scripts
  1.1582 +    // within the runtime. This may be modified by threads with an
  1.1583 +    // ExclusiveContext and requires a lock.
  1.1584 +  private:
  1.1585 +    js::ScriptDataTable scriptDataTable_;
  1.1586 +  public:
  1.1587 +    js::ScriptDataTable &scriptDataTable() {
  1.1588 +        JS_ASSERT(currentThreadHasExclusiveAccess());
  1.1589 +        return scriptDataTable_;
  1.1590 +    }
  1.1591 +
  1.1592 +#ifdef DEBUG
  1.1593 +    size_t              noGCOrAllocationCheck;
  1.1594 +#endif
  1.1595 +
  1.1596 +    bool                jitSupportsFloatingPoint;
  1.1597 +
  1.1598 +    // Used to reset stack limit after a signaled interrupt (i.e. jitStackLimit_ = -1)
  1.1599 +    // has been noticed by Ion/Baseline.
  1.1600 +    void resetJitStackLimit();
  1.1601 +
  1.1602 +    // Cache for jit::GetPcScript().
  1.1603 +    js::jit::PcScriptCache *ionPcScriptCache;
  1.1604 +
  1.1605 +    js::ThreadPool threadPool;
  1.1606 +
  1.1607 +    js::DefaultJSContextCallback defaultJSContextCallback;
  1.1608 +
  1.1609 +    js::CTypesActivityCallback  ctypesActivityCallback;
  1.1610 +
  1.1611 +    // Non-zero if this is a ForkJoin warmup execution.  See
  1.1612 +    // js::ForkJoin() for more information.
  1.1613 +    uint32_t forkJoinWarmup;
  1.1614 +
  1.1615 +  private:
  1.1616 +    // In certain cases, we want to optimize certain opcodes to typed instructions,
  1.1617 +    // to avoid carrying an extra register to feed into an unbox. Unfortunately,
  1.1618 +    // that's not always possible. For example, a GetPropertyCacheT could return a
  1.1619 +    // typed double, but if it takes its out-of-line path, it could return an
  1.1620 +    // object, and trigger invalidation. The invalidation bailout will consider the
  1.1621 +    // return value to be a double, and create a garbage Value.
  1.1622 +    //
  1.1623 +    // To allow the GetPropertyCacheT optimization, we allow the ability for
  1.1624 +    // GetPropertyCache to override the return value at the top of the stack - the
  1.1625 +    // value that will be temporarily corrupt. This special override value is set
  1.1626 +    // only in callVM() targets that are about to return *and* have invalidated
  1.1627 +    // their callee.
  1.1628 +    js::Value            ionReturnOverride_;
  1.1629 +
  1.1630 +#ifdef JS_THREADSAFE
  1.1631 +    static mozilla::Atomic<size_t> liveRuntimesCount;
  1.1632 +#else
  1.1633 +    static size_t liveRuntimesCount;
  1.1634 +#endif
  1.1635 +
  1.1636 +  public:
  1.1637 +    static bool hasLiveRuntimes() {
  1.1638 +        return liveRuntimesCount > 0;
  1.1639 +    }
  1.1640 +
  1.1641 +    bool hasIonReturnOverride() const {
  1.1642 +        return !ionReturnOverride_.isMagic();
  1.1643 +    }
  1.1644 +    js::Value takeIonReturnOverride() {
  1.1645 +        js::Value v = ionReturnOverride_;
  1.1646 +        ionReturnOverride_ = js::MagicValue(JS_ARG_POISON);
  1.1647 +        return v;
  1.1648 +    }
  1.1649 +    void setIonReturnOverride(const js::Value &v) {
  1.1650 +        JS_ASSERT(!hasIonReturnOverride());
  1.1651 +        ionReturnOverride_ = v;
  1.1652 +    }
  1.1653 +
  1.1654 +    JSRuntime(JSRuntime *parentRuntime, JSUseHelperThreads useHelperThreads);
  1.1655 +    ~JSRuntime();
  1.1656 +
  1.1657 +    bool init(uint32_t maxbytes);
  1.1658 +
  1.1659 +    JSRuntime *thisFromCtor() { return this; }
  1.1660 +
  1.1661 +    void setGCMaxMallocBytes(size_t value);
  1.1662 +
  1.1663 +    void resetGCMallocBytes() {
  1.1664 +        gcMallocBytes = ptrdiff_t(gcMaxMallocBytes);
  1.1665 +        gcMallocGCTriggered = false;
  1.1666 +    }
  1.1667 +
  1.1668 +    /*
  1.1669 +     * Call this after allocating memory held by GC things, to update memory
  1.1670 +     * pressure counters or report the OOM error if necessary. If oomError and
  1.1671 +     * cx is not null the function also reports OOM error.
  1.1672 +     *
  1.1673 +     * The function must be called outside the GC lock and in case of OOM error
  1.1674 +     * the caller must ensure that no deadlock possible during OOM reporting.
  1.1675 +     */
  1.1676 +    void updateMallocCounter(size_t nbytes);
  1.1677 +    void updateMallocCounter(JS::Zone *zone, size_t nbytes);
  1.1678 +
  1.1679 +    void reportAllocationOverflow() { js_ReportAllocationOverflow(nullptr); }
  1.1680 +
  1.1681 +    bool isTooMuchMalloc() const {
  1.1682 +        return gcMallocBytes <= 0;
  1.1683 +    }
  1.1684 +
  1.1685 +    /*
  1.1686 +     * The function must be called outside the GC lock.
  1.1687 +     */
  1.1688 +    JS_FRIEND_API(void) onTooMuchMalloc();
  1.1689 +
  1.1690 +    /*
  1.1691 +     * This should be called after system malloc/realloc returns nullptr to try
  1.1692 +     * to recove some memory or to report an error. Failures in malloc and
  1.1693 +     * calloc are signaled by p == null and p == reinterpret_cast<void *>(1).
  1.1694 +     * Other values of p mean a realloc failure.
  1.1695 +     *
  1.1696 +     * The function must be called outside the GC lock.
  1.1697 +     */
  1.1698 +    JS_FRIEND_API(void *) onOutOfMemory(void *p, size_t nbytes);
  1.1699 +    JS_FRIEND_API(void *) onOutOfMemory(void *p, size_t nbytes, JSContext *cx);
  1.1700 +
  1.1701 +    // Ways in which the interrupt callback on the runtime can be triggered,
  1.1702 +    // varying based on which thread is triggering the callback.
  1.1703 +    enum InterruptMode {
  1.1704 +        RequestInterruptMainThread,
  1.1705 +        RequestInterruptAnyThread,
  1.1706 +        RequestInterruptAnyThreadDontStopIon,
  1.1707 +        RequestInterruptAnyThreadForkJoin
  1.1708 +    };
  1.1709 +
  1.1710 +    void requestInterrupt(InterruptMode mode);
  1.1711 +
  1.1712 +    void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes *runtime);
  1.1713 +
  1.1714 +  private:
  1.1715 +    JS::RuntimeOptions options_;
  1.1716 +
  1.1717 +    JSUseHelperThreads useHelperThreads_;
  1.1718 +
  1.1719 +    // Settings for how helper threads can be used.
  1.1720 +    bool parallelIonCompilationEnabled_;
  1.1721 +    bool parallelParsingEnabled_;
  1.1722 +
  1.1723 +    // True iff this is a DOM Worker runtime.
  1.1724 +    bool isWorkerRuntime_;
  1.1725 +
  1.1726 +  public:
  1.1727 +
  1.1728 +    // This controls whether the JSRuntime is allowed to create any helper
  1.1729 +    // threads at all. This means both specific threads (background GC thread)
  1.1730 +    // and the general JS worker thread pool.
  1.1731 +    bool useHelperThreads() const {
  1.1732 +#ifdef JS_THREADSAFE
  1.1733 +        return useHelperThreads_ == JS_USE_HELPER_THREADS;
  1.1734 +#else
  1.1735 +        return false;
  1.1736 +#endif
  1.1737 +    }
  1.1738 +
  1.1739 +    // Note: these values may be toggled dynamically (in response to about:config
  1.1740 +    // prefs changing).
  1.1741 +    void setParallelIonCompilationEnabled(bool value) {
  1.1742 +        parallelIonCompilationEnabled_ = value;
  1.1743 +    }
  1.1744 +    bool canUseParallelIonCompilation() const {
  1.1745 +        return useHelperThreads() &&
  1.1746 +               parallelIonCompilationEnabled_;
  1.1747 +    }
  1.1748 +    void setParallelParsingEnabled(bool value) {
  1.1749 +        parallelParsingEnabled_ = value;
  1.1750 +    }
  1.1751 +    bool canUseParallelParsing() const {
  1.1752 +        return useHelperThreads() &&
  1.1753 +               parallelParsingEnabled_;
  1.1754 +    }
  1.1755 +
  1.1756 +    void setIsWorkerRuntime() {
  1.1757 +        isWorkerRuntime_ = true;
  1.1758 +    }
  1.1759 +    bool isWorkerRuntime() const {
  1.1760 +        return isWorkerRuntime_;
  1.1761 +    }
  1.1762 +
  1.1763 +    const JS::RuntimeOptions &options() const {
  1.1764 +        return options_;
  1.1765 +    }
  1.1766 +    JS::RuntimeOptions &options() {
  1.1767 +        return options_;
  1.1768 +    }
  1.1769 +
  1.1770 +#ifdef DEBUG
  1.1771 +  public:
  1.1772 +    js::AutoEnterPolicy *enteredPolicy;
  1.1773 +#endif
  1.1774 +
  1.1775 +    /* See comment for JS::SetLargeAllocationFailureCallback in jsapi.h. */
  1.1776 +    JS::LargeAllocationFailureCallback largeAllocationFailureCallback;
  1.1777 +    /* See comment for JS::SetOutOfMemoryCallback in jsapi.h. */
  1.1778 +    JS::OutOfMemoryCallback oomCallback;
  1.1779 +
  1.1780 +    /*
  1.1781 +     * These variations of malloc/calloc/realloc will call the
  1.1782 +     * large-allocation-failure callback on OOM and retry the allocation.
  1.1783 +     */
  1.1784 +
  1.1785 +    static const unsigned LARGE_ALLOCATION = 25 * 1024 * 1024;
  1.1786 +
  1.1787 +    void *callocCanGC(size_t bytes) {
  1.1788 +        void *p = calloc_(bytes);
  1.1789 +        if (MOZ_LIKELY(!!p))
  1.1790 +            return p;
  1.1791 +        if (!largeAllocationFailureCallback || bytes < LARGE_ALLOCATION)
  1.1792 +            return nullptr;
  1.1793 +        largeAllocationFailureCallback();
  1.1794 +        return onOutOfMemory(reinterpret_cast<void *>(1), bytes);
  1.1795 +    }
  1.1796 +
  1.1797 +    void *reallocCanGC(void *p, size_t bytes) {
  1.1798 +        void *p2 = realloc_(p, bytes);
  1.1799 +        if (MOZ_LIKELY(!!p2))
  1.1800 +            return p2;
  1.1801 +        if (!largeAllocationFailureCallback || bytes < LARGE_ALLOCATION)
  1.1802 +            return nullptr;
  1.1803 +        largeAllocationFailureCallback();
  1.1804 +        return onOutOfMemory(p, bytes);
  1.1805 +    }
  1.1806 +};
  1.1807 +
  1.1808 +namespace js {
  1.1809 +
  1.1810 +// When entering JIT code, the calling JSContext* is stored into the thread's
  1.1811 +// PerThreadData. This function retrieves the JSContext with the pre-condition
  1.1812 +// that the caller is JIT code or C++ called directly from JIT code. This
  1.1813 +// function should not be called from arbitrary locations since the JSContext
  1.1814 +// may be the wrong one.
  1.1815 +static inline JSContext *
  1.1816 +GetJSContextFromJitCode()
  1.1817 +{
  1.1818 +    JSContext *cx = TlsPerThreadData.get()->jitJSContext;
  1.1819 +    JS_ASSERT(cx);
  1.1820 +    return cx;
  1.1821 +}
  1.1822 +
  1.1823 +/*
  1.1824 + * Flags accompany script version data so that a) dynamically created scripts
  1.1825 + * can inherit their caller's compile-time properties and b) scripts can be
  1.1826 + * appropriately compared in the eval cache across global option changes. An
  1.1827 + * example of the latter is enabling the top-level-anonymous-function-is-error
  1.1828 + * option: subsequent evals of the same, previously-valid script text may have
  1.1829 + * become invalid.
  1.1830 + */
  1.1831 +namespace VersionFlags {
  1.1832 +static const unsigned MASK      = 0x0FFF; /* see JSVersion in jspubtd.h */
  1.1833 +} /* namespace VersionFlags */
  1.1834 +
  1.1835 +static inline JSVersion
  1.1836 +VersionNumber(JSVersion version)
  1.1837 +{
  1.1838 +    return JSVersion(uint32_t(version) & VersionFlags::MASK);
  1.1839 +}
  1.1840 +
  1.1841 +static inline JSVersion
  1.1842 +VersionExtractFlags(JSVersion version)
  1.1843 +{
  1.1844 +    return JSVersion(uint32_t(version) & ~VersionFlags::MASK);
  1.1845 +}
  1.1846 +
  1.1847 +static inline void
  1.1848 +VersionCopyFlags(JSVersion *version, JSVersion from)
  1.1849 +{
  1.1850 +    *version = JSVersion(VersionNumber(*version) | VersionExtractFlags(from));
  1.1851 +}
  1.1852 +
  1.1853 +static inline bool
  1.1854 +VersionHasFlags(JSVersion version)
  1.1855 +{
  1.1856 +    return !!VersionExtractFlags(version);
  1.1857 +}
  1.1858 +
  1.1859 +static inline bool
  1.1860 +VersionIsKnown(JSVersion version)
  1.1861 +{
  1.1862 +    return VersionNumber(version) != JSVERSION_UNKNOWN;
  1.1863 +}
  1.1864 +
  1.1865 +inline void
  1.1866 +FreeOp::free_(void *p)
  1.1867 +{
  1.1868 +    if (shouldFreeLater()) {
  1.1869 +        runtime()->gcHelperThread.freeLater(p);
  1.1870 +        return;
  1.1871 +    }
  1.1872 +    js_free(p);
  1.1873 +}
  1.1874 +
  1.1875 +class AutoLockGC
  1.1876 +{
  1.1877 +  public:
  1.1878 +    explicit AutoLockGC(JSRuntime *rt = nullptr
  1.1879 +                        MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
  1.1880 +      : runtime(rt)
  1.1881 +    {
  1.1882 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  1.1883 +        // Avoid MSVC warning C4390 for non-threadsafe builds.
  1.1884 +        if (rt)
  1.1885 +            rt->lockGC();
  1.1886 +    }
  1.1887 +
  1.1888 +    ~AutoLockGC()
  1.1889 +    {
  1.1890 +        if (runtime)
  1.1891 +            runtime->unlockGC();
  1.1892 +    }
  1.1893 +
  1.1894 +    bool locked() const {
  1.1895 +        return !!runtime;
  1.1896 +    }
  1.1897 +
  1.1898 +    void lock(JSRuntime *rt) {
  1.1899 +        JS_ASSERT(rt);
  1.1900 +        JS_ASSERT(!runtime);
  1.1901 +        runtime = rt;
  1.1902 +        rt->lockGC();
  1.1903 +    }
  1.1904 +
  1.1905 +  private:
  1.1906 +    JSRuntime *runtime;
  1.1907 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
  1.1908 +};
  1.1909 +
  1.1910 +class AutoUnlockGC
  1.1911 +{
  1.1912 +  private:
  1.1913 +    JSRuntime *rt;
  1.1914 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
  1.1915 +
  1.1916 +  public:
  1.1917 +    explicit AutoUnlockGC(JSRuntime *rt
  1.1918 +                          MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
  1.1919 +      : rt(rt)
  1.1920 +    {
  1.1921 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  1.1922 +        rt->unlockGC();
  1.1923 +    }
  1.1924 +    ~AutoUnlockGC() { rt->lockGC(); }
  1.1925 +};
  1.1926 +
  1.1927 +class MOZ_STACK_CLASS AutoKeepAtoms
  1.1928 +{
  1.1929 +    PerThreadData *pt;
  1.1930 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
  1.1931 +
  1.1932 +  public:
  1.1933 +    explicit AutoKeepAtoms(PerThreadData *pt
  1.1934 +                           MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
  1.1935 +      : pt(pt)
  1.1936 +    {
  1.1937 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  1.1938 +        if (JSRuntime *rt = pt->runtimeIfOnOwnerThread()) {
  1.1939 +            rt->keepAtoms_++;
  1.1940 +        } else {
  1.1941 +            // This should be a thread with an exclusive context, which will
  1.1942 +            // always inhibit collection of atoms.
  1.1943 +            JS_ASSERT(pt->exclusiveThreadsPresent());
  1.1944 +        }
  1.1945 +    }
  1.1946 +    ~AutoKeepAtoms() {
  1.1947 +        if (JSRuntime *rt = pt->runtimeIfOnOwnerThread()) {
  1.1948 +            JS_ASSERT(rt->keepAtoms_);
  1.1949 +            rt->keepAtoms_--;
  1.1950 +        }
  1.1951 +    }
  1.1952 +};
  1.1953 +
  1.1954 +inline void
  1.1955 +PerThreadData::setJitStackLimit(uintptr_t limit)
  1.1956 +{
  1.1957 +    JS_ASSERT(runtime_->currentThreadOwnsInterruptLock());
  1.1958 +    jitStackLimit = limit;
  1.1959 +}
  1.1960 +
  1.1961 +inline JSRuntime *
  1.1962 +PerThreadData::runtimeFromMainThread()
  1.1963 +{
  1.1964 +    JS_ASSERT(CurrentThreadCanAccessRuntime(runtime_));
  1.1965 +    return runtime_;
  1.1966 +}
  1.1967 +
  1.1968 +inline JSRuntime *
  1.1969 +PerThreadData::runtimeIfOnOwnerThread()
  1.1970 +{
  1.1971 +    return CurrentThreadCanAccessRuntime(runtime_) ? runtime_ : nullptr;
  1.1972 +}
  1.1973 +
  1.1974 +inline bool
  1.1975 +PerThreadData::exclusiveThreadsPresent()
  1.1976 +{
  1.1977 +    return runtime_->exclusiveThreadsPresent();
  1.1978 +}
  1.1979 +
  1.1980 +inline void
  1.1981 +PerThreadData::addActiveCompilation()
  1.1982 +{
  1.1983 +    activeCompilations++;
  1.1984 +    runtime_->addActiveCompilation();
  1.1985 +}
  1.1986 +
  1.1987 +inline void
  1.1988 +PerThreadData::removeActiveCompilation()
  1.1989 +{
  1.1990 +    JS_ASSERT(activeCompilations);
  1.1991 +    activeCompilations--;
  1.1992 +    runtime_->removeActiveCompilation();
  1.1993 +}
  1.1994 +
  1.1995 +/************************************************************************/
  1.1996 +
  1.1997 +static MOZ_ALWAYS_INLINE void
  1.1998 +MakeRangeGCSafe(Value *vec, size_t len)
  1.1999 +{
  1.2000 +    mozilla::PodZero(vec, len);
  1.2001 +}
  1.2002 +
  1.2003 +static MOZ_ALWAYS_INLINE void
  1.2004 +MakeRangeGCSafe(Value *beg, Value *end)
  1.2005 +{
  1.2006 +    mozilla::PodZero(beg, end - beg);
  1.2007 +}
  1.2008 +
  1.2009 +static MOZ_ALWAYS_INLINE void
  1.2010 +MakeRangeGCSafe(jsid *beg, jsid *end)
  1.2011 +{
  1.2012 +    for (jsid *id = beg; id != end; ++id)
  1.2013 +        *id = INT_TO_JSID(0);
  1.2014 +}
  1.2015 +
  1.2016 +static MOZ_ALWAYS_INLINE void
  1.2017 +MakeRangeGCSafe(jsid *vec, size_t len)
  1.2018 +{
  1.2019 +    MakeRangeGCSafe(vec, vec + len);
  1.2020 +}
  1.2021 +
  1.2022 +static MOZ_ALWAYS_INLINE void
  1.2023 +MakeRangeGCSafe(Shape **beg, Shape **end)
  1.2024 +{
  1.2025 +    mozilla::PodZero(beg, end - beg);
  1.2026 +}
  1.2027 +
  1.2028 +static MOZ_ALWAYS_INLINE void
  1.2029 +MakeRangeGCSafe(Shape **vec, size_t len)
  1.2030 +{
  1.2031 +    mozilla::PodZero(vec, len);
  1.2032 +}
  1.2033 +
  1.2034 +static MOZ_ALWAYS_INLINE void
  1.2035 +SetValueRangeToUndefined(Value *beg, Value *end)
  1.2036 +{
  1.2037 +    for (Value *v = beg; v != end; ++v)
  1.2038 +        v->setUndefined();
  1.2039 +}
  1.2040 +
  1.2041 +static MOZ_ALWAYS_INLINE void
  1.2042 +SetValueRangeToUndefined(Value *vec, size_t len)
  1.2043 +{
  1.2044 +    SetValueRangeToUndefined(vec, vec + len);
  1.2045 +}
  1.2046 +
  1.2047 +static MOZ_ALWAYS_INLINE void
  1.2048 +SetValueRangeToNull(Value *beg, Value *end)
  1.2049 +{
  1.2050 +    for (Value *v = beg; v != end; ++v)
  1.2051 +        v->setNull();
  1.2052 +}
  1.2053 +
  1.2054 +static MOZ_ALWAYS_INLINE void
  1.2055 +SetValueRangeToNull(Value *vec, size_t len)
  1.2056 +{
  1.2057 +    SetValueRangeToNull(vec, vec + len);
  1.2058 +}
  1.2059 +
  1.2060 +/*
  1.2061 + * Allocation policy that uses JSRuntime::malloc_ and friends, so that
  1.2062 + * memory pressure is properly accounted for. This is suitable for
  1.2063 + * long-lived objects owned by the JSRuntime.
  1.2064 + *
  1.2065 + * Since it doesn't hold a JSContext (those may not live long enough), it
  1.2066 + * can't report out-of-memory conditions itself; the caller must check for
  1.2067 + * OOM and take the appropriate action.
  1.2068 + *
  1.2069 + * FIXME bug 647103 - replace these *AllocPolicy names.
  1.2070 + */
  1.2071 +class RuntimeAllocPolicy
  1.2072 +{
  1.2073 +    JSRuntime *const runtime;
  1.2074 +
  1.2075 +  public:
  1.2076 +    RuntimeAllocPolicy(JSRuntime *rt) : runtime(rt) {}
  1.2077 +    void *malloc_(size_t bytes) { return runtime->malloc_(bytes); }
  1.2078 +    void *calloc_(size_t bytes) { return runtime->calloc_(bytes); }
  1.2079 +    void *realloc_(void *p, size_t bytes) { return runtime->realloc_(p, bytes); }
  1.2080 +    void free_(void *p) { js_free(p); }
  1.2081 +    void reportAllocOverflow() const {}
  1.2082 +};
  1.2083 +
  1.2084 +extern const JSSecurityCallbacks NullSecurityCallbacks;
  1.2085 +
  1.2086 +} /* namespace js */
  1.2087 +
  1.2088 +#ifdef _MSC_VER
  1.2089 +#pragma warning(pop)
  1.2090 +#endif
  1.2091 +
  1.2092 +#endif /* vm_Runtime_h */

mercurial