js/src/jscntxt.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/jscntxt.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1094 @@
     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 +/* JS execution context. */
    1.11 +
    1.12 +#ifndef jscntxt_h
    1.13 +#define jscntxt_h
    1.14 +
    1.15 +#include "mozilla/MemoryReporting.h"
    1.16 +
    1.17 +#include "js/Vector.h"
    1.18 +#include "vm/Runtime.h"
    1.19 +
    1.20 +#ifdef _MSC_VER
    1.21 +#pragma warning(push)
    1.22 +#pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
    1.23 +#endif
    1.24 +
    1.25 +struct DtoaState;
    1.26 +
    1.27 +extern void
    1.28 +js_ReportOutOfMemory(js::ThreadSafeContext *cx);
    1.29 +
    1.30 +extern void
    1.31 +js_ReportAllocationOverflow(js::ThreadSafeContext *cx);
    1.32 +
    1.33 +extern void
    1.34 +js_ReportOverRecursed(js::ThreadSafeContext *cx);
    1.35 +
    1.36 +namespace js {
    1.37 +
    1.38 +namespace jit {
    1.39 +class IonContext;
    1.40 +class CompileCompartment;
    1.41 +}
    1.42 +
    1.43 +struct CallsiteCloneKey {
    1.44 +    /* The original function that we are cloning. */
    1.45 +    JSFunction *original;
    1.46 +
    1.47 +    /* The script of the call. */
    1.48 +    JSScript *script;
    1.49 +
    1.50 +    /* The offset of the call. */
    1.51 +    uint32_t offset;
    1.52 +
    1.53 +    CallsiteCloneKey(JSFunction *f, JSScript *s, uint32_t o) : original(f), script(s), offset(o) {}
    1.54 +
    1.55 +    typedef CallsiteCloneKey Lookup;
    1.56 +
    1.57 +    static inline uint32_t hash(CallsiteCloneKey key) {
    1.58 +        return uint32_t(size_t(key.script->offsetToPC(key.offset)) ^ size_t(key.original));
    1.59 +    }
    1.60 +
    1.61 +    static inline bool match(const CallsiteCloneKey &a, const CallsiteCloneKey &b) {
    1.62 +        return a.script == b.script && a.offset == b.offset && a.original == b.original;
    1.63 +    }
    1.64 +};
    1.65 +
    1.66 +typedef HashMap<CallsiteCloneKey,
    1.67 +                ReadBarriered<JSFunction>,
    1.68 +                CallsiteCloneKey,
    1.69 +                SystemAllocPolicy> CallsiteCloneTable;
    1.70 +
    1.71 +JSFunction *
    1.72 +ExistingCloneFunctionAtCallsite(const CallsiteCloneTable &table, JSFunction *fun,
    1.73 +                                JSScript *script, jsbytecode *pc);
    1.74 +
    1.75 +JSFunction *CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun,
    1.76 +                                    HandleScript script, jsbytecode *pc);
    1.77 +
    1.78 +typedef HashSet<JSObject *> ObjectSet;
    1.79 +typedef HashSet<Shape *> ShapeSet;
    1.80 +
    1.81 +/* Detects cycles when traversing an object graph. */
    1.82 +class AutoCycleDetector
    1.83 +{
    1.84 +    JSContext *cx;
    1.85 +    RootedObject obj;
    1.86 +    bool cyclic;
    1.87 +    uint32_t hashsetGenerationAtInit;
    1.88 +    ObjectSet::AddPtr hashsetAddPointer;
    1.89 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
    1.90 +
    1.91 +  public:
    1.92 +    AutoCycleDetector(JSContext *cx, HandleObject objArg
    1.93 +                      MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
    1.94 +      : cx(cx), obj(cx, objArg), cyclic(true)
    1.95 +    {
    1.96 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
    1.97 +    }
    1.98 +
    1.99 +    ~AutoCycleDetector();
   1.100 +
   1.101 +    bool init();
   1.102 +
   1.103 +    bool foundCycle() { return cyclic; }
   1.104 +};
   1.105 +
   1.106 +/* Updates references in the cycle detection set if the GC moves them. */
   1.107 +extern void
   1.108 +TraceCycleDetectionSet(JSTracer *trc, ObjectSet &set);
   1.109 +
   1.110 +struct AutoResolving;
   1.111 +class DtoaCache;
   1.112 +class ForkJoinContext;
   1.113 +class RegExpCompartment;
   1.114 +class RegExpStatics;
   1.115 +
   1.116 +namespace frontend { struct CompileError; }
   1.117 +
   1.118 +/*
   1.119 + * Execution Context Overview:
   1.120 + *
   1.121 + * Several different structures may be used to provide a context for operations
   1.122 + * on the VM. Each context is thread local, but varies in what data it can
   1.123 + * access and what other threads may be running.
   1.124 + *
   1.125 + * - ThreadSafeContext is used by threads operating in one compartment which
   1.126 + * may run in parallel with other threads operating on the same or other
   1.127 + * compartments.
   1.128 + *
   1.129 + * - ExclusiveContext is used by threads operating in one compartment/zone,
   1.130 + * where other threads may operate in other compartments, but *not* the same
   1.131 + * compartment or zone which the ExclusiveContext is in. A thread with an
   1.132 + * ExclusiveContext may enter the atoms compartment and atomize strings, in
   1.133 + * which case a lock is used.
   1.134 + *
   1.135 + * - JSContext is used only by the runtime's main thread. The context may
   1.136 + * operate in any compartment or zone which is not used by an ExclusiveContext
   1.137 + * or ThreadSafeContext, and will only run in parallel with threads using such
   1.138 + * contexts.
   1.139 + *
   1.140 + * An ExclusiveContext coerces to a ThreadSafeContext, and a JSContext coerces
   1.141 + * to an ExclusiveContext or ThreadSafeContext.
   1.142 + *
   1.143 + * Contexts which are a ThreadSafeContext but not an ExclusiveContext are used
   1.144 + * to represent a ForkJoinContext, the per-thread parallel context used in PJS.
   1.145 + */
   1.146 +
   1.147 +struct ThreadSafeContext : ContextFriendFields,
   1.148 +                           public MallocProvider<ThreadSafeContext>
   1.149 +{
   1.150 +    friend struct StackBaseShape;
   1.151 +    friend UnownedBaseShape *BaseShape::lookupUnowned(ThreadSafeContext *cx,
   1.152 +                                                      const StackBaseShape &base);
   1.153 +    friend Shape *JSObject::lookupChildProperty(ThreadSafeContext *cx,
   1.154 +                                                JS::HandleObject obj, js::HandleShape parent,
   1.155 +                                                js::StackShape &child);
   1.156 +
   1.157 +  public:
   1.158 +    enum ContextKind {
   1.159 +        Context_JS,
   1.160 +        Context_Exclusive,
   1.161 +        Context_ForkJoin
   1.162 +    };
   1.163 +
   1.164 +  private:
   1.165 +    ContextKind contextKind_;
   1.166 +
   1.167 +  public:
   1.168 +    PerThreadData *perThreadData;
   1.169 +
   1.170 +    ThreadSafeContext(JSRuntime *rt, PerThreadData *pt, ContextKind kind);
   1.171 +
   1.172 +    bool isJSContext() const {
   1.173 +        return contextKind_ == Context_JS;
   1.174 +    }
   1.175 +
   1.176 +    JSContext *maybeJSContext() const {
   1.177 +        if (isJSContext())
   1.178 +            return (JSContext *) this;
   1.179 +        return nullptr;
   1.180 +    }
   1.181 +
   1.182 +    JSContext *asJSContext() const {
   1.183 +        // Note: there is no way to perform an unchecked coercion from a
   1.184 +        // ThreadSafeContext to a JSContext. This ensures that trying to use
   1.185 +        // the context as a JSContext off the main thread will nullptr crash
   1.186 +        // rather than race.
   1.187 +        JS_ASSERT(isJSContext());
   1.188 +        return maybeJSContext();
   1.189 +    }
   1.190 +
   1.191 +    // In some cases we could potentially want to do operations that require a
   1.192 +    // JSContext while running off the main thread. While this should never
   1.193 +    // actually happen, the wide enough API for working off the main thread
   1.194 +    // makes such operations impossible to rule out. Rather than blindly using
   1.195 +    // asJSContext() and crashing afterwards, this method may be used to watch
   1.196 +    // for such cases and produce either a soft failure in release builds or
   1.197 +    // an assertion failure in debug builds.
   1.198 +    bool shouldBeJSContext() const {
   1.199 +        JS_ASSERT(isJSContext());
   1.200 +        return isJSContext();
   1.201 +    }
   1.202 +
   1.203 +    bool isExclusiveContext() const {
   1.204 +        return contextKind_ == Context_JS || contextKind_ == Context_Exclusive;
   1.205 +    }
   1.206 +
   1.207 +    ExclusiveContext *maybeExclusiveContext() const {
   1.208 +        if (isExclusiveContext())
   1.209 +            return (ExclusiveContext *) this;
   1.210 +        return nullptr;
   1.211 +    }
   1.212 +
   1.213 +    ExclusiveContext *asExclusiveContext() const {
   1.214 +        JS_ASSERT(isExclusiveContext());
   1.215 +        return maybeExclusiveContext();
   1.216 +    }
   1.217 +
   1.218 +    bool isForkJoinContext() const;
   1.219 +    ForkJoinContext *asForkJoinContext();
   1.220 +
   1.221 +    // The generational GC nursery may only be used on the main thread.
   1.222 +#ifdef JSGC_GENERATIONAL
   1.223 +    inline bool hasNursery() const {
   1.224 +        return isJSContext();
   1.225 +    }
   1.226 +
   1.227 +    inline js::Nursery &nursery() {
   1.228 +        JS_ASSERT(hasNursery());
   1.229 +        return runtime_->gcNursery;
   1.230 +    }
   1.231 +#endif
   1.232 +
   1.233 +    /*
   1.234 +     * Allocator used when allocating GCThings on this context. If we are a
   1.235 +     * JSContext, this is the Zone allocator of the JSContext's zone.
   1.236 +     * Otherwise, this is a per-thread allocator.
   1.237 +     *
   1.238 +     * This does not live in PerThreadData because the notion of an allocator
   1.239 +     * is only per-thread when off the main thread. The runtime (and the main
   1.240 +     * thread) can have more than one zone, each with its own allocator, and
   1.241 +     * it's up to the context to specify what compartment and zone we are
   1.242 +     * operating in.
   1.243 +     */
   1.244 +  protected:
   1.245 +    Allocator *allocator_;
   1.246 +
   1.247 +  public:
   1.248 +    static size_t offsetOfAllocator() { return offsetof(ThreadSafeContext, allocator_); }
   1.249 +
   1.250 +    inline Allocator *const allocator();
   1.251 +
   1.252 +    // Allocations can only trigger GC when running on the main thread.
   1.253 +    inline AllowGC allowGC() const { return isJSContext() ? CanGC : NoGC; }
   1.254 +
   1.255 +    template <typename T>
   1.256 +    bool isInsideCurrentZone(T thing) const {
   1.257 +        return thing->zoneFromAnyThread() == zone_;
   1.258 +    }
   1.259 +
   1.260 +    template <typename T>
   1.261 +    inline bool isInsideCurrentCompartment(T thing) const {
   1.262 +        return thing->compartment() == compartment_;
   1.263 +    }
   1.264 +
   1.265 +    template <typename T>
   1.266 +    inline bool isThreadLocal(T thing) const;
   1.267 +
   1.268 +    void *onOutOfMemory(void *p, size_t nbytes) {
   1.269 +        return runtime_->onOutOfMemory(p, nbytes, maybeJSContext());
   1.270 +    }
   1.271 +
   1.272 +    /* Clear the pending exception (if any) due to OOM. */
   1.273 +    void recoverFromOutOfMemory();
   1.274 +
   1.275 +    inline void updateMallocCounter(size_t nbytes) {
   1.276 +        // Note: this is racy.
   1.277 +        runtime_->updateMallocCounter(zone_, nbytes);
   1.278 +    }
   1.279 +
   1.280 +    void reportAllocationOverflow() {
   1.281 +        js_ReportAllocationOverflow(this);
   1.282 +    }
   1.283 +
   1.284 +    // Accessors for immutable runtime data.
   1.285 +    JSAtomState &names() { return *runtime_->commonNames; }
   1.286 +    StaticStrings &staticStrings() { return *runtime_->staticStrings; }
   1.287 +    AtomSet &permanentAtoms() { return *runtime_->permanentAtoms; }
   1.288 +    const JS::AsmJSCacheOps &asmJSCacheOps() { return runtime_->asmJSCacheOps; }
   1.289 +    PropertyName *emptyString() { return runtime_->emptyString; }
   1.290 +    FreeOp *defaultFreeOp() { return runtime_->defaultFreeOp(); }
   1.291 +    bool useHelperThreads() { return runtime_->useHelperThreads(); }
   1.292 +    void *runtimeAddressForJit() { return runtime_; }
   1.293 +    void *stackLimitAddress(StackKind kind) { return &runtime_->mainThread.nativeStackLimit[kind]; }
   1.294 +    void *stackLimitAddressForJitCode(StackKind kind);
   1.295 +    size_t gcSystemPageSize() { return runtime_->gcSystemPageSize; }
   1.296 +    bool signalHandlersInstalled() const { return runtime_->signalHandlersInstalled(); }
   1.297 +    bool jitSupportsFloatingPoint() const { return runtime_->jitSupportsFloatingPoint; }
   1.298 +
   1.299 +    // Thread local data that may be accessed freely.
   1.300 +    DtoaState *dtoaState() {
   1.301 +        return perThreadData->dtoaState;
   1.302 +    }
   1.303 +};
   1.304 +
   1.305 +struct WorkerThread;
   1.306 +
   1.307 +class ExclusiveContext : public ThreadSafeContext
   1.308 +{
   1.309 +    friend class gc::ArenaLists;
   1.310 +    friend class AutoCompartment;
   1.311 +    friend class AutoLockForExclusiveAccess;
   1.312 +    friend struct StackBaseShape;
   1.313 +    friend void JSScript::initCompartment(ExclusiveContext *cx);
   1.314 +    friend class jit::IonContext;
   1.315 +
   1.316 +    // The worker on which this context is running, if this is not a JSContext.
   1.317 +    WorkerThread *workerThread_;
   1.318 +
   1.319 +  public:
   1.320 +
   1.321 +    ExclusiveContext(JSRuntime *rt, PerThreadData *pt, ContextKind kind)
   1.322 +      : ThreadSafeContext(rt, pt, kind),
   1.323 +        workerThread_(nullptr),
   1.324 +        enterCompartmentDepth_(0)
   1.325 +    {}
   1.326 +
   1.327 +    /*
   1.328 +     * "Entering" a compartment changes cx->compartment (which changes
   1.329 +     * cx->global). Note that this does not push any InterpreterFrame which means
   1.330 +     * that it is possible for cx->fp()->compartment() != cx->compartment.
   1.331 +     * This is not a problem since, in general, most places in the VM cannot
   1.332 +     * know that they were called from script (e.g., they may have been called
   1.333 +     * through the JSAPI via JS_CallFunction) and thus cannot expect fp.
   1.334 +     *
   1.335 +     * Compartments should be entered/left in a LIFO fasion. The depth of this
   1.336 +     * enter/leave stack is maintained by enterCompartmentDepth_ and queried by
   1.337 +     * hasEnteredCompartment.
   1.338 +     *
   1.339 +     * To enter a compartment, code should prefer using AutoCompartment over
   1.340 +     * manually calling cx->enterCompartment/leaveCompartment.
   1.341 +     */
   1.342 +  protected:
   1.343 +    unsigned            enterCompartmentDepth_;
   1.344 +    inline void setCompartment(JSCompartment *comp);
   1.345 +  public:
   1.346 +    bool hasEnteredCompartment() const {
   1.347 +        return enterCompartmentDepth_ > 0;
   1.348 +    }
   1.349 +#ifdef DEBUG
   1.350 +    unsigned getEnterCompartmentDepth() const {
   1.351 +        return enterCompartmentDepth_;
   1.352 +    }
   1.353 +#endif
   1.354 +
   1.355 +    inline void enterCompartment(JSCompartment *c);
   1.356 +    inline void enterNullCompartment();
   1.357 +    inline void leaveCompartment(JSCompartment *oldCompartment);
   1.358 +
   1.359 +    void setWorkerThread(WorkerThread *workerThread);
   1.360 +    WorkerThread *workerThread() const { return workerThread_; }
   1.361 +
   1.362 +    // Threads with an ExclusiveContext may freely access any data in their
   1.363 +    // compartment and zone.
   1.364 +    JSCompartment *compartment() const {
   1.365 +        JS_ASSERT_IF(runtime_->isAtomsCompartment(compartment_),
   1.366 +                     runtime_->currentThreadHasExclusiveAccess());
   1.367 +        return compartment_;
   1.368 +    }
   1.369 +    JS::Zone *zone() const {
   1.370 +        JS_ASSERT_IF(!compartment(), !zone_);
   1.371 +        JS_ASSERT_IF(compartment(), js::GetCompartmentZone(compartment()) == zone_);
   1.372 +        return zone_;
   1.373 +    }
   1.374 +
   1.375 +    // Zone local methods that can be used freely from an ExclusiveContext.
   1.376 +    types::TypeObject *getNewType(const Class *clasp, TaggedProto proto, JSFunction *fun = nullptr);
   1.377 +    types::TypeObject *getSingletonType(const Class *clasp, TaggedProto proto);
   1.378 +    inline js::LifoAlloc &typeLifoAlloc();
   1.379 +
   1.380 +    // Current global. This is only safe to use within the scope of the
   1.381 +    // AutoCompartment from which it's called.
   1.382 +    inline js::Handle<js::GlobalObject*> global() const;
   1.383 +
   1.384 +    // Methods to access runtime data that must be protected by locks.
   1.385 +    frontend::ParseMapPool &parseMapPool() {
   1.386 +        return runtime_->parseMapPool();
   1.387 +    }
   1.388 +    AtomSet &atoms() {
   1.389 +        return runtime_->atoms();
   1.390 +    }
   1.391 +    JSCompartment *atomsCompartment() {
   1.392 +        return runtime_->atomsCompartment();
   1.393 +    }
   1.394 +    ScriptDataTable &scriptDataTable() {
   1.395 +        return runtime_->scriptDataTable();
   1.396 +    }
   1.397 +
   1.398 +    // Methods specific to any WorkerThread for the context.
   1.399 +    frontend::CompileError &addPendingCompileError();
   1.400 +    void addPendingOverRecursed();
   1.401 +};
   1.402 +
   1.403 +} /* namespace js */
   1.404 +
   1.405 +struct JSContext : public js::ExclusiveContext,
   1.406 +                   public mozilla::LinkedListElement<JSContext>
   1.407 +{
   1.408 +    explicit JSContext(JSRuntime *rt);
   1.409 +    ~JSContext();
   1.410 +
   1.411 +    JSRuntime *runtime() const { return runtime_; }
   1.412 +    js::PerThreadData &mainThread() const { return runtime()->mainThread; }
   1.413 +
   1.414 +    static size_t offsetOfRuntime() {
   1.415 +        return offsetof(JSContext, runtime_);
   1.416 +    }
   1.417 +
   1.418 +    friend class js::ExclusiveContext;
   1.419 +    friend class JS::AutoSaveExceptionState;
   1.420 +
   1.421 +  private:
   1.422 +    /* Exception state -- the exception member is a GC root by definition. */
   1.423 +    bool                throwing;            /* is there a pending exception? */
   1.424 +    js::Value           unwrappedException_; /* most-recently-thrown exception */
   1.425 +
   1.426 +    /* Per-context options. */
   1.427 +    JS::ContextOptions  options_;
   1.428 +
   1.429 +  public:
   1.430 +    int32_t             reportGranularity;  /* see vm/Probes.h */
   1.431 +
   1.432 +    js::AutoResolving   *resolvingList;
   1.433 +
   1.434 +    /* True if generating an error, to prevent runaway recursion. */
   1.435 +    bool                generatingError;
   1.436 +
   1.437 +    /* See JS_SaveFrameChain/JS_RestoreFrameChain. */
   1.438 +  private:
   1.439 +    struct SavedFrameChain {
   1.440 +        SavedFrameChain(JSCompartment *comp, unsigned count)
   1.441 +          : compartment(comp), enterCompartmentCount(count) {}
   1.442 +        JSCompartment *compartment;
   1.443 +        unsigned enterCompartmentCount;
   1.444 +    };
   1.445 +    typedef js::Vector<SavedFrameChain, 1, js::SystemAllocPolicy> SaveStack;
   1.446 +    SaveStack           savedFrameChains_;
   1.447 +  public:
   1.448 +    bool saveFrameChain();
   1.449 +    void restoreFrameChain();
   1.450 +
   1.451 +    /*
   1.452 +     * When no compartments have been explicitly entered, the context's
   1.453 +     * compartment will be set to the compartment of the "default compartment
   1.454 +     * object".
   1.455 +     */
   1.456 +  private:
   1.457 +    JSObject *defaultCompartmentObject_;
   1.458 +  public:
   1.459 +    inline void setDefaultCompartmentObject(JSObject *obj);
   1.460 +    inline void setDefaultCompartmentObjectIfUnset(JSObject *obj);
   1.461 +    JSObject *maybeDefaultCompartmentObject() const {
   1.462 +        JS_ASSERT(!options().noDefaultCompartmentObject());
   1.463 +        return defaultCompartmentObject_;
   1.464 +    }
   1.465 +
   1.466 +    /* State for object and array toSource conversion. */
   1.467 +    js::ObjectSet       cycleDetectorSet;
   1.468 +
   1.469 +    /* Per-context optional error reporter. */
   1.470 +    JSErrorReporter     errorReporter;
   1.471 +
   1.472 +    /* Client opaque pointers. */
   1.473 +    void                *data;
   1.474 +    void                *data2;
   1.475 +
   1.476 +  public:
   1.477 +
   1.478 +    /*
   1.479 +     * Return:
   1.480 +     * - The newest scripted frame's version, if there is such a frame.
   1.481 +     * - The version from the compartment.
   1.482 +     * - The default version.
   1.483 +     *
   1.484 +     * Note: if this ever shows up in a profile, just add caching!
   1.485 +     */
   1.486 +    JSVersion findVersion() const;
   1.487 +
   1.488 +    const JS::ContextOptions &options() const {
   1.489 +        return options_;
   1.490 +    }
   1.491 +
   1.492 +    JS::ContextOptions &options() {
   1.493 +        return options_;
   1.494 +    }
   1.495 +
   1.496 +    js::LifoAlloc &tempLifoAlloc() { return runtime()->tempLifoAlloc; }
   1.497 +
   1.498 +#ifdef JS_THREADSAFE
   1.499 +    unsigned            outstandingRequests;/* number of JS_BeginRequest calls
   1.500 +                                               without the corresponding
   1.501 +                                               JS_EndRequest. */
   1.502 +#endif
   1.503 +
   1.504 +    /* Location to stash the iteration value between JSOP_MOREITER and JSOP_ITERNEXT. */
   1.505 +    js::Value           iterValue;
   1.506 +
   1.507 +    bool jitIsBroken;
   1.508 +
   1.509 +    void updateJITEnabled();
   1.510 +
   1.511 +    /* Whether this context has JS frames on the stack. */
   1.512 +    bool currentlyRunning() const;
   1.513 +
   1.514 +    bool currentlyRunningInInterpreter() const {
   1.515 +        return mainThread().activation()->isInterpreter();
   1.516 +    }
   1.517 +    bool currentlyRunningInJit() const {
   1.518 +        return mainThread().activation()->isJit();
   1.519 +    }
   1.520 +    js::InterpreterFrame *interpreterFrame() const {
   1.521 +        return mainThread().activation()->asInterpreter()->current();
   1.522 +    }
   1.523 +    js::InterpreterRegs &interpreterRegs() const {
   1.524 +        return mainThread().activation()->asInterpreter()->regs();
   1.525 +    }
   1.526 +
   1.527 +    /*
   1.528 +     * Get the topmost script and optional pc on the stack. By default, this
   1.529 +     * function only returns a JSScript in the current compartment, returning
   1.530 +     * nullptr if the current script is in a different compartment. This
   1.531 +     * behavior can be overridden by passing ALLOW_CROSS_COMPARTMENT.
   1.532 +     */
   1.533 +    enum MaybeAllowCrossCompartment {
   1.534 +        DONT_ALLOW_CROSS_COMPARTMENT = false,
   1.535 +        ALLOW_CROSS_COMPARTMENT = true
   1.536 +    };
   1.537 +    inline JSScript *currentScript(jsbytecode **pc = nullptr,
   1.538 +                                   MaybeAllowCrossCompartment = DONT_ALLOW_CROSS_COMPARTMENT) const;
   1.539 +
   1.540 +#ifdef MOZ_TRACE_JSCALLS
   1.541 +    /* Function entry/exit debugging callback. */
   1.542 +    JSFunctionCallback    functionCallback;
   1.543 +
   1.544 +    void doFunctionCallback(const JSFunction *fun,
   1.545 +                            const JSScript *scr,
   1.546 +                            int entering) const
   1.547 +    {
   1.548 +        if (functionCallback)
   1.549 +            functionCallback(fun, scr, this, entering);
   1.550 +    }
   1.551 +#endif
   1.552 +
   1.553 +  private:
   1.554 +    /* Innermost-executing generator or null if no generator are executing. */
   1.555 +    JSGenerator *innermostGenerator_;
   1.556 +  public:
   1.557 +    JSGenerator *innermostGenerator() const { return innermostGenerator_; }
   1.558 +    void enterGenerator(JSGenerator *gen);
   1.559 +    void leaveGenerator(JSGenerator *gen);
   1.560 +
   1.561 +    bool isExceptionPending() {
   1.562 +        return throwing;
   1.563 +    }
   1.564 +
   1.565 +    MOZ_WARN_UNUSED_RESULT
   1.566 +    bool getPendingException(JS::MutableHandleValue rval);
   1.567 +
   1.568 +    bool isThrowingOutOfMemory();
   1.569 +
   1.570 +    void setPendingException(js::Value v);
   1.571 +
   1.572 +    void clearPendingException() {
   1.573 +        throwing = false;
   1.574 +        unwrappedException_.setUndefined();
   1.575 +    }
   1.576 +
   1.577 +#ifdef DEBUG
   1.578 +    /*
   1.579 +     * Controls whether a quadratic-complexity assertion is performed during
   1.580 +     * stack iteration; defaults to true.
   1.581 +     */
   1.582 +    bool stackIterAssertionEnabled;
   1.583 +#endif
   1.584 +
   1.585 +    /*
   1.586 +     * See JS_SetTrustedPrincipals in jsapi.h.
   1.587 +     * Note: !cx->compartment is treated as trusted.
   1.588 +     */
   1.589 +    bool runningWithTrustedPrincipals() const;
   1.590 +
   1.591 +    JS_FRIEND_API(size_t) sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
   1.592 +
   1.593 +    void mark(JSTracer *trc);
   1.594 +
   1.595 +  private:
   1.596 +    /*
   1.597 +     * The allocation code calls the function to indicate either OOM failure
   1.598 +     * when p is null or that a memory pressure counter has reached some
   1.599 +     * threshold when p is not null. The function takes the pointer and not
   1.600 +     * a boolean flag to minimize the amount of code in its inlined callers.
   1.601 +     */
   1.602 +    JS_FRIEND_API(void) checkMallocGCPressure(void *p);
   1.603 +}; /* struct JSContext */
   1.604 +
   1.605 +namespace js {
   1.606 +
   1.607 +struct AutoResolving {
   1.608 +  public:
   1.609 +    enum Kind {
   1.610 +        LOOKUP,
   1.611 +        WATCH
   1.612 +    };
   1.613 +
   1.614 +    AutoResolving(JSContext *cx, HandleObject obj, HandleId id, Kind kind = LOOKUP
   1.615 +                  MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   1.616 +      : context(cx), object(obj), id(id), kind(kind), link(cx->resolvingList)
   1.617 +    {
   1.618 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   1.619 +        JS_ASSERT(obj);
   1.620 +        cx->resolvingList = this;
   1.621 +    }
   1.622 +
   1.623 +    ~AutoResolving() {
   1.624 +        JS_ASSERT(context->resolvingList == this);
   1.625 +        context->resolvingList = link;
   1.626 +    }
   1.627 +
   1.628 +    bool alreadyStarted() const {
   1.629 +        return link && alreadyStartedSlow();
   1.630 +    }
   1.631 +
   1.632 +  private:
   1.633 +    bool alreadyStartedSlow() const;
   1.634 +
   1.635 +    JSContext           *const context;
   1.636 +    HandleObject        object;
   1.637 +    HandleId            id;
   1.638 +    Kind                const kind;
   1.639 +    AutoResolving       *const link;
   1.640 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   1.641 +};
   1.642 +
   1.643 +/*
   1.644 + * Enumerate all contexts in a runtime.
   1.645 + */
   1.646 +class ContextIter {
   1.647 +    JSContext *iter;
   1.648 +
   1.649 +public:
   1.650 +    explicit ContextIter(JSRuntime *rt) {
   1.651 +        iter = rt->contextList.getFirst();
   1.652 +    }
   1.653 +
   1.654 +    bool done() const {
   1.655 +        return !iter;
   1.656 +    }
   1.657 +
   1.658 +    void next() {
   1.659 +        JS_ASSERT(!done());
   1.660 +        iter = iter->getNext();
   1.661 +    }
   1.662 +
   1.663 +    JSContext *get() const {
   1.664 +        JS_ASSERT(!done());
   1.665 +        return iter;
   1.666 +    }
   1.667 +
   1.668 +    operator JSContext *() const {
   1.669 +        return get();
   1.670 +    }
   1.671 +
   1.672 +    JSContext *operator ->() const {
   1.673 +        return get();
   1.674 +    }
   1.675 +};
   1.676 +
   1.677 +/*
   1.678 + * Create and destroy functions for JSContext, which is manually allocated
   1.679 + * and exclusively owned.
   1.680 + */
   1.681 +extern JSContext *
   1.682 +NewContext(JSRuntime *rt, size_t stackChunkSize);
   1.683 +
   1.684 +enum DestroyContextMode {
   1.685 +    DCM_NO_GC,
   1.686 +    DCM_FORCE_GC,
   1.687 +    DCM_NEW_FAILED
   1.688 +};
   1.689 +
   1.690 +extern void
   1.691 +DestroyContext(JSContext *cx, DestroyContextMode mode);
   1.692 +
   1.693 +enum ErrorArgumentsType {
   1.694 +    ArgumentsAreUnicode,
   1.695 +    ArgumentsAreASCII
   1.696 +};
   1.697 +
   1.698 +
   1.699 +/*
   1.700 + * Loads and returns a self-hosted function by name. For performance, define
   1.701 + * the property name in vm/CommonPropertyNames.h.
   1.702 + *
   1.703 + * Defined in SelfHosting.cpp.
   1.704 + */
   1.705 +JSFunction *
   1.706 +SelfHostedFunction(JSContext *cx, HandlePropertyName propName);
   1.707 +
   1.708 +} /* namespace js */
   1.709 +
   1.710 +#ifdef va_start
   1.711 +extern bool
   1.712 +js_ReportErrorVA(JSContext *cx, unsigned flags, const char *format, va_list ap);
   1.713 +
   1.714 +extern bool
   1.715 +js_ReportErrorNumberVA(JSContext *cx, unsigned flags, JSErrorCallback callback,
   1.716 +                       void *userRef, const unsigned errorNumber,
   1.717 +                       js::ErrorArgumentsType argumentsType, va_list ap);
   1.718 +
   1.719 +extern bool
   1.720 +js_ReportErrorNumberUCArray(JSContext *cx, unsigned flags, JSErrorCallback callback,
   1.721 +                            void *userRef, const unsigned errorNumber,
   1.722 +                            const jschar **args);
   1.723 +#endif
   1.724 +
   1.725 +extern bool
   1.726 +js_ExpandErrorArguments(js::ExclusiveContext *cx, JSErrorCallback callback,
   1.727 +                        void *userRef, const unsigned errorNumber,
   1.728 +                        char **message, JSErrorReport *reportp,
   1.729 +                        js::ErrorArgumentsType argumentsType, va_list ap);
   1.730 +
   1.731 +namespace js {
   1.732 +
   1.733 +/* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */
   1.734 +extern void
   1.735 +ReportUsageError(JSContext *cx, HandleObject callee, const char *msg);
   1.736 +
   1.737 +/*
   1.738 + * Prints a full report and returns true if the given report is non-nullptr
   1.739 + * and the report doesn't have the JSREPORT_WARNING flag set or reportWarnings
   1.740 + * is true.
   1.741 + * Returns false otherwise, printing just the message if the report is nullptr.
   1.742 + */
   1.743 +extern bool
   1.744 +PrintError(JSContext *cx, FILE *file, const char *message, JSErrorReport *report,
   1.745 +           bool reportWarnings);
   1.746 +
   1.747 +/*
   1.748 + * Send a JSErrorReport to the errorReporter callback.
   1.749 + */
   1.750 +void
   1.751 +CallErrorReporter(JSContext *cx, const char *message, JSErrorReport *report);
   1.752 +
   1.753 +} /* namespace js */
   1.754 +
   1.755 +extern void
   1.756 +js_ReportIsNotDefined(JSContext *cx, const char *name);
   1.757 +
   1.758 +/*
   1.759 + * Report an attempt to access the property of a null or undefined value (v).
   1.760 + */
   1.761 +extern bool
   1.762 +js_ReportIsNullOrUndefined(JSContext *cx, int spindex, js::HandleValue v,
   1.763 +                           js::HandleString fallback);
   1.764 +
   1.765 +extern void
   1.766 +js_ReportMissingArg(JSContext *cx, js::HandleValue v, unsigned arg);
   1.767 +
   1.768 +/*
   1.769 + * Report error using js_DecompileValueGenerator(cx, spindex, v, fallback) as
   1.770 + * the first argument for the error message. If the error message has less
   1.771 + * then 3 arguments, use null for arg1 or arg2.
   1.772 + */
   1.773 +extern bool
   1.774 +js_ReportValueErrorFlags(JSContext *cx, unsigned flags, const unsigned errorNumber,
   1.775 +                         int spindex, js::HandleValue v, js::HandleString fallback,
   1.776 +                         const char *arg1, const char *arg2);
   1.777 +
   1.778 +#define js_ReportValueError(cx,errorNumber,spindex,v,fallback)                \
   1.779 +    ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber,          \
   1.780 +                                    spindex, v, fallback, nullptr, nullptr))
   1.781 +
   1.782 +#define js_ReportValueError2(cx,errorNumber,spindex,v,fallback,arg1)          \
   1.783 +    ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber,          \
   1.784 +                                    spindex, v, fallback, arg1, nullptr))
   1.785 +
   1.786 +#define js_ReportValueError3(cx,errorNumber,spindex,v,fallback,arg1,arg2)     \
   1.787 +    ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber,          \
   1.788 +                                    spindex, v, fallback, arg1, arg2))
   1.789 +
   1.790 +extern const JSErrorFormatString js_ErrorFormatString[JSErr_Limit];
   1.791 +
   1.792 +char *
   1.793 +js_strdup(js::ExclusiveContext *cx, const char *s);
   1.794 +
   1.795 +#ifdef JS_THREADSAFE
   1.796 +# define JS_ASSERT_REQUEST_DEPTH(cx)  JS_ASSERT((cx)->runtime()->requestDepth >= 1)
   1.797 +#else
   1.798 +# define JS_ASSERT_REQUEST_DEPTH(cx)  ((void) 0)
   1.799 +#endif
   1.800 +
   1.801 +namespace js {
   1.802 +
   1.803 +/*
   1.804 + * Invoke the interrupt callback and return false if the current execution
   1.805 + * is to be terminated.
   1.806 + */
   1.807 +bool
   1.808 +InvokeInterruptCallback(JSContext *cx);
   1.809 +
   1.810 +bool
   1.811 +HandleExecutionInterrupt(JSContext *cx);
   1.812 +
   1.813 +/*
   1.814 + * Process any pending interrupt requests. Long-running inner loops in C++ must
   1.815 + * call this periodically to make sure they are interruptible --- that is, to
   1.816 + * make sure they do not prevent the slow script dialog from appearing.
   1.817 + *
   1.818 + * This can run a full GC or call the interrupt callback, which could do
   1.819 + * anything. In the browser, it displays the slow script dialog.
   1.820 + *
   1.821 + * If this returns true, the caller can continue; if false, the caller must
   1.822 + * break out of its loop. This happens if, for example, the user clicks "Stop
   1.823 + * script" on the slow script dialog; treat it as an uncatchable error.
   1.824 + */
   1.825 +inline bool
   1.826 +CheckForInterrupt(JSContext *cx)
   1.827 +{
   1.828 +    JS_ASSERT_REQUEST_DEPTH(cx);
   1.829 +    return !cx->runtime()->interrupt || InvokeInterruptCallback(cx);
   1.830 +}
   1.831 +
   1.832 +/************************************************************************/
   1.833 +
   1.834 +class AutoStringVector : public AutoVectorRooter<JSString *>
   1.835 +{
   1.836 +  public:
   1.837 +    explicit AutoStringVector(JSContext *cx
   1.838 +                              MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   1.839 +        : AutoVectorRooter<JSString *>(cx, STRINGVECTOR)
   1.840 +    {
   1.841 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   1.842 +    }
   1.843 +
   1.844 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   1.845 +};
   1.846 +
   1.847 +class AutoPropertyNameVector : public AutoVectorRooter<PropertyName *>
   1.848 +{
   1.849 +  public:
   1.850 +    explicit AutoPropertyNameVector(JSContext *cx
   1.851 +                                    MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   1.852 +        : AutoVectorRooter<PropertyName *>(cx, STRINGVECTOR)
   1.853 +    {
   1.854 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   1.855 +    }
   1.856 +
   1.857 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   1.858 +};
   1.859 +
   1.860 +class AutoShapeVector : public AutoVectorRooter<Shape *>
   1.861 +{
   1.862 +  public:
   1.863 +    explicit AutoShapeVector(JSContext *cx
   1.864 +                             MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   1.865 +        : AutoVectorRooter<Shape *>(cx, SHAPEVECTOR)
   1.866 +    {
   1.867 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   1.868 +    }
   1.869 +
   1.870 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   1.871 +};
   1.872 +
   1.873 +class AutoObjectObjectHashMap : public AutoHashMapRooter<JSObject *, JSObject *>
   1.874 +{
   1.875 +  public:
   1.876 +    explicit AutoObjectObjectHashMap(JSContext *cx
   1.877 +                                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   1.878 +      : AutoHashMapRooter<JSObject *, JSObject *>(cx, OBJOBJHASHMAP)
   1.879 +    {
   1.880 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   1.881 +    }
   1.882 +
   1.883 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   1.884 +};
   1.885 +
   1.886 +class AutoObjectUnsigned32HashMap : public AutoHashMapRooter<JSObject *, uint32_t>
   1.887 +{
   1.888 +  public:
   1.889 +    explicit AutoObjectUnsigned32HashMap(JSContext *cx
   1.890 +                                         MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   1.891 +      : AutoHashMapRooter<JSObject *, uint32_t>(cx, OBJU32HASHMAP)
   1.892 +    {
   1.893 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   1.894 +    }
   1.895 +
   1.896 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   1.897 +};
   1.898 +
   1.899 +class AutoObjectHashSet : public AutoHashSetRooter<JSObject *>
   1.900 +{
   1.901 +  public:
   1.902 +    explicit AutoObjectHashSet(JSContext *cx
   1.903 +                               MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   1.904 +      : AutoHashSetRooter<JSObject *>(cx, OBJHASHSET)
   1.905 +    {
   1.906 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   1.907 +    }
   1.908 +
   1.909 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   1.910 +};
   1.911 +
   1.912 +/* AutoArrayRooter roots an external array of Values. */
   1.913 +class AutoArrayRooter : private AutoGCRooter
   1.914 +{
   1.915 +  public:
   1.916 +    AutoArrayRooter(JSContext *cx, size_t len, Value *vec
   1.917 +                    MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   1.918 +      : AutoGCRooter(cx, len), array(vec)
   1.919 +    {
   1.920 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   1.921 +        JS_ASSERT(tag_ >= 0);
   1.922 +    }
   1.923 +
   1.924 +    void changeLength(size_t newLength) {
   1.925 +        tag_ = ptrdiff_t(newLength);
   1.926 +        JS_ASSERT(tag_ >= 0);
   1.927 +    }
   1.928 +
   1.929 +    void changeArray(Value *newArray, size_t newLength) {
   1.930 +        changeLength(newLength);
   1.931 +        array = newArray;
   1.932 +    }
   1.933 +
   1.934 +    Value *start() {
   1.935 +        return array;
   1.936 +    }
   1.937 +
   1.938 +    size_t length() {
   1.939 +        JS_ASSERT(tag_ >= 0);
   1.940 +        return size_t(tag_);
   1.941 +    }
   1.942 +
   1.943 +    MutableHandleValue handleAt(size_t i) {
   1.944 +        JS_ASSERT(i < size_t(tag_));
   1.945 +        return MutableHandleValue::fromMarkedLocation(&array[i]);
   1.946 +    }
   1.947 +    HandleValue handleAt(size_t i) const {
   1.948 +        JS_ASSERT(i < size_t(tag_));
   1.949 +        return HandleValue::fromMarkedLocation(&array[i]);
   1.950 +    }
   1.951 +    MutableHandleValue operator[](size_t i) {
   1.952 +        JS_ASSERT(i < size_t(tag_));
   1.953 +        return MutableHandleValue::fromMarkedLocation(&array[i]);
   1.954 +    }
   1.955 +    HandleValue operator[](size_t i) const {
   1.956 +        JS_ASSERT(i < size_t(tag_));
   1.957 +        return HandleValue::fromMarkedLocation(&array[i]);
   1.958 +    }
   1.959 +
   1.960 +    friend void AutoGCRooter::trace(JSTracer *trc);
   1.961 +
   1.962 +  private:
   1.963 +    Value *array;
   1.964 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   1.965 +};
   1.966 +
   1.967 +class AutoAssertNoException
   1.968 +{
   1.969 +#ifdef DEBUG
   1.970 +    JSContext *cx;
   1.971 +    bool hadException;
   1.972 +#endif
   1.973 +
   1.974 +  public:
   1.975 +    AutoAssertNoException(JSContext *cx)
   1.976 +#ifdef DEBUG
   1.977 +      : cx(cx),
   1.978 +        hadException(cx->isExceptionPending())
   1.979 +#endif
   1.980 +    {
   1.981 +    }
   1.982 +
   1.983 +    ~AutoAssertNoException()
   1.984 +    {
   1.985 +        JS_ASSERT_IF(!hadException, !cx->isExceptionPending());
   1.986 +    }
   1.987 +};
   1.988 +
   1.989 +/*
   1.990 + * FIXME bug 647103 - replace these *AllocPolicy names.
   1.991 + */
   1.992 +class ContextAllocPolicy
   1.993 +{
   1.994 +    ThreadSafeContext *const cx_;
   1.995 +
   1.996 +  public:
   1.997 +    ContextAllocPolicy(ThreadSafeContext *cx) : cx_(cx) {}
   1.998 +    ThreadSafeContext *context() const { return cx_; }
   1.999 +    void *malloc_(size_t bytes) { return cx_->malloc_(bytes); }
  1.1000 +    void *calloc_(size_t bytes) { return cx_->calloc_(bytes); }
  1.1001 +    void *realloc_(void *p, size_t oldBytes, size_t bytes) { return cx_->realloc_(p, oldBytes, bytes); }
  1.1002 +    void free_(void *p) { js_free(p); }
  1.1003 +    void reportAllocOverflow() const { js_ReportAllocationOverflow(cx_); }
  1.1004 +};
  1.1005 +
  1.1006 +/* Exposed intrinsics so that Ion may inline them. */
  1.1007 +bool intrinsic_ToObject(JSContext *cx, unsigned argc, Value *vp);
  1.1008 +bool intrinsic_IsCallable(JSContext *cx, unsigned argc, Value *vp);
  1.1009 +bool intrinsic_ThrowError(JSContext *cx, unsigned argc, Value *vp);
  1.1010 +bool intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp);
  1.1011 +
  1.1012 +bool intrinsic_UnsafePutElements(JSContext *cx, unsigned argc, Value *vp);
  1.1013 +bool intrinsic_DefineValueProperty(JSContext *cx, unsigned argc, Value *vp);
  1.1014 +bool intrinsic_UnsafeSetReservedSlot(JSContext *cx, unsigned argc, Value *vp);
  1.1015 +bool intrinsic_UnsafeGetReservedSlot(JSContext *cx, unsigned argc, Value *vp);
  1.1016 +bool intrinsic_HaveSameClass(JSContext *cx, unsigned argc, Value *vp);
  1.1017 +bool intrinsic_IsPackedArray(JSContext *cx, unsigned argc, Value *vp);
  1.1018 +
  1.1019 +bool intrinsic_ShouldForceSequential(JSContext *cx, unsigned argc, Value *vp);
  1.1020 +bool intrinsic_NewParallelArray(JSContext *cx, unsigned argc, Value *vp);
  1.1021 +bool intrinsic_ForkJoinGetSlice(JSContext *cx, unsigned argc, Value *vp);
  1.1022 +bool intrinsic_InParallelSection(JSContext *cx, unsigned argc, Value *vp);
  1.1023 +
  1.1024 +bool intrinsic_ObjectIsTypedObject(JSContext *cx, unsigned argc, Value *vp);
  1.1025 +bool intrinsic_ObjectIsTransparentTypedObject(JSContext *cx, unsigned argc, Value *vp);
  1.1026 +bool intrinsic_ObjectIsOpaqueTypedObject(JSContext *cx, unsigned argc, Value *vp);
  1.1027 +bool intrinsic_ObjectIsTypeDescr(JSContext *cx, unsigned argc, Value *vp);
  1.1028 +bool intrinsic_TypeDescrIsSimpleType(JSContext *cx, unsigned argc, Value *vp);
  1.1029 +bool intrinsic_TypeDescrIsArrayType(JSContext *cx, unsigned argc, Value *vp);
  1.1030 +bool intrinsic_TypeDescrIsUnsizedArrayType(JSContext *cx, unsigned argc, Value *vp);
  1.1031 +bool intrinsic_TypeDescrIsSizedArrayType(JSContext *cx, unsigned argc, Value *vp);
  1.1032 +
  1.1033 +class AutoLockForExclusiveAccess
  1.1034 +{
  1.1035 +#ifdef JS_THREADSAFE
  1.1036 +    JSRuntime *runtime;
  1.1037 +
  1.1038 +    void init(JSRuntime *rt) {
  1.1039 +        runtime = rt;
  1.1040 +        if (runtime->numExclusiveThreads) {
  1.1041 +            runtime->assertCanLock(ExclusiveAccessLock);
  1.1042 +            PR_Lock(runtime->exclusiveAccessLock);
  1.1043 +#ifdef DEBUG
  1.1044 +            runtime->exclusiveAccessOwner = PR_GetCurrentThread();
  1.1045 +#endif
  1.1046 +        } else {
  1.1047 +            JS_ASSERT(!runtime->mainThreadHasExclusiveAccess);
  1.1048 +            runtime->mainThreadHasExclusiveAccess = true;
  1.1049 +        }
  1.1050 +    }
  1.1051 +
  1.1052 +  public:
  1.1053 +    AutoLockForExclusiveAccess(ExclusiveContext *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
  1.1054 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  1.1055 +        init(cx->runtime_);
  1.1056 +    }
  1.1057 +    AutoLockForExclusiveAccess(JSRuntime *rt MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
  1.1058 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  1.1059 +        init(rt);
  1.1060 +    }
  1.1061 +    ~AutoLockForExclusiveAccess() {
  1.1062 +        if (runtime->numExclusiveThreads) {
  1.1063 +            JS_ASSERT(runtime->exclusiveAccessOwner == PR_GetCurrentThread());
  1.1064 +            runtime->exclusiveAccessOwner = nullptr;
  1.1065 +            PR_Unlock(runtime->exclusiveAccessLock);
  1.1066 +        } else {
  1.1067 +            JS_ASSERT(runtime->mainThreadHasExclusiveAccess);
  1.1068 +            runtime->mainThreadHasExclusiveAccess = false;
  1.1069 +        }
  1.1070 +    }
  1.1071 +#else // JS_THREADSAFE
  1.1072 +  public:
  1.1073 +    AutoLockForExclusiveAccess(ExclusiveContext *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
  1.1074 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  1.1075 +    }
  1.1076 +    AutoLockForExclusiveAccess(JSRuntime *rt MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
  1.1077 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  1.1078 +    }
  1.1079 +    ~AutoLockForExclusiveAccess() {
  1.1080 +        // An empty destructor is needed to avoid warnings from clang about
  1.1081 +        // unused local variables of this type.
  1.1082 +    }
  1.1083 +#endif // JS_THREADSAFE
  1.1084 +
  1.1085 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
  1.1086 +};
  1.1087 +
  1.1088 +void
  1.1089 +CrashAtUnhandlableOOM(const char *reason);
  1.1090 +
  1.1091 +} /* namespace js */
  1.1092 +
  1.1093 +#ifdef _MSC_VER
  1.1094 +#pragma warning(pop)
  1.1095 +#endif
  1.1096 +
  1.1097 +#endif /* jscntxt_h */

mercurial