js/src/jscntxt.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /* JS execution context. */
     9 #ifndef jscntxt_h
    10 #define jscntxt_h
    12 #include "mozilla/MemoryReporting.h"
    14 #include "js/Vector.h"
    15 #include "vm/Runtime.h"
    17 #ifdef _MSC_VER
    18 #pragma warning(push)
    19 #pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
    20 #endif
    22 struct DtoaState;
    24 extern void
    25 js_ReportOutOfMemory(js::ThreadSafeContext *cx);
    27 extern void
    28 js_ReportAllocationOverflow(js::ThreadSafeContext *cx);
    30 extern void
    31 js_ReportOverRecursed(js::ThreadSafeContext *cx);
    33 namespace js {
    35 namespace jit {
    36 class IonContext;
    37 class CompileCompartment;
    38 }
    40 struct CallsiteCloneKey {
    41     /* The original function that we are cloning. */
    42     JSFunction *original;
    44     /* The script of the call. */
    45     JSScript *script;
    47     /* The offset of the call. */
    48     uint32_t offset;
    50     CallsiteCloneKey(JSFunction *f, JSScript *s, uint32_t o) : original(f), script(s), offset(o) {}
    52     typedef CallsiteCloneKey Lookup;
    54     static inline uint32_t hash(CallsiteCloneKey key) {
    55         return uint32_t(size_t(key.script->offsetToPC(key.offset)) ^ size_t(key.original));
    56     }
    58     static inline bool match(const CallsiteCloneKey &a, const CallsiteCloneKey &b) {
    59         return a.script == b.script && a.offset == b.offset && a.original == b.original;
    60     }
    61 };
    63 typedef HashMap<CallsiteCloneKey,
    64                 ReadBarriered<JSFunction>,
    65                 CallsiteCloneKey,
    66                 SystemAllocPolicy> CallsiteCloneTable;
    68 JSFunction *
    69 ExistingCloneFunctionAtCallsite(const CallsiteCloneTable &table, JSFunction *fun,
    70                                 JSScript *script, jsbytecode *pc);
    72 JSFunction *CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun,
    73                                     HandleScript script, jsbytecode *pc);
    75 typedef HashSet<JSObject *> ObjectSet;
    76 typedef HashSet<Shape *> ShapeSet;
    78 /* Detects cycles when traversing an object graph. */
    79 class AutoCycleDetector
    80 {
    81     JSContext *cx;
    82     RootedObject obj;
    83     bool cyclic;
    84     uint32_t hashsetGenerationAtInit;
    85     ObjectSet::AddPtr hashsetAddPointer;
    86     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
    88   public:
    89     AutoCycleDetector(JSContext *cx, HandleObject objArg
    90                       MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
    91       : cx(cx), obj(cx, objArg), cyclic(true)
    92     {
    93         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
    94     }
    96     ~AutoCycleDetector();
    98     bool init();
   100     bool foundCycle() { return cyclic; }
   101 };
   103 /* Updates references in the cycle detection set if the GC moves them. */
   104 extern void
   105 TraceCycleDetectionSet(JSTracer *trc, ObjectSet &set);
   107 struct AutoResolving;
   108 class DtoaCache;
   109 class ForkJoinContext;
   110 class RegExpCompartment;
   111 class RegExpStatics;
   113 namespace frontend { struct CompileError; }
   115 /*
   116  * Execution Context Overview:
   117  *
   118  * Several different structures may be used to provide a context for operations
   119  * on the VM. Each context is thread local, but varies in what data it can
   120  * access and what other threads may be running.
   121  *
   122  * - ThreadSafeContext is used by threads operating in one compartment which
   123  * may run in parallel with other threads operating on the same or other
   124  * compartments.
   125  *
   126  * - ExclusiveContext is used by threads operating in one compartment/zone,
   127  * where other threads may operate in other compartments, but *not* the same
   128  * compartment or zone which the ExclusiveContext is in. A thread with an
   129  * ExclusiveContext may enter the atoms compartment and atomize strings, in
   130  * which case a lock is used.
   131  *
   132  * - JSContext is used only by the runtime's main thread. The context may
   133  * operate in any compartment or zone which is not used by an ExclusiveContext
   134  * or ThreadSafeContext, and will only run in parallel with threads using such
   135  * contexts.
   136  *
   137  * An ExclusiveContext coerces to a ThreadSafeContext, and a JSContext coerces
   138  * to an ExclusiveContext or ThreadSafeContext.
   139  *
   140  * Contexts which are a ThreadSafeContext but not an ExclusiveContext are used
   141  * to represent a ForkJoinContext, the per-thread parallel context used in PJS.
   142  */
   144 struct ThreadSafeContext : ContextFriendFields,
   145                            public MallocProvider<ThreadSafeContext>
   146 {
   147     friend struct StackBaseShape;
   148     friend UnownedBaseShape *BaseShape::lookupUnowned(ThreadSafeContext *cx,
   149                                                       const StackBaseShape &base);
   150     friend Shape *JSObject::lookupChildProperty(ThreadSafeContext *cx,
   151                                                 JS::HandleObject obj, js::HandleShape parent,
   152                                                 js::StackShape &child);
   154   public:
   155     enum ContextKind {
   156         Context_JS,
   157         Context_Exclusive,
   158         Context_ForkJoin
   159     };
   161   private:
   162     ContextKind contextKind_;
   164   public:
   165     PerThreadData *perThreadData;
   167     ThreadSafeContext(JSRuntime *rt, PerThreadData *pt, ContextKind kind);
   169     bool isJSContext() const {
   170         return contextKind_ == Context_JS;
   171     }
   173     JSContext *maybeJSContext() const {
   174         if (isJSContext())
   175             return (JSContext *) this;
   176         return nullptr;
   177     }
   179     JSContext *asJSContext() const {
   180         // Note: there is no way to perform an unchecked coercion from a
   181         // ThreadSafeContext to a JSContext. This ensures that trying to use
   182         // the context as a JSContext off the main thread will nullptr crash
   183         // rather than race.
   184         JS_ASSERT(isJSContext());
   185         return maybeJSContext();
   186     }
   188     // In some cases we could potentially want to do operations that require a
   189     // JSContext while running off the main thread. While this should never
   190     // actually happen, the wide enough API for working off the main thread
   191     // makes such operations impossible to rule out. Rather than blindly using
   192     // asJSContext() and crashing afterwards, this method may be used to watch
   193     // for such cases and produce either a soft failure in release builds or
   194     // an assertion failure in debug builds.
   195     bool shouldBeJSContext() const {
   196         JS_ASSERT(isJSContext());
   197         return isJSContext();
   198     }
   200     bool isExclusiveContext() const {
   201         return contextKind_ == Context_JS || contextKind_ == Context_Exclusive;
   202     }
   204     ExclusiveContext *maybeExclusiveContext() const {
   205         if (isExclusiveContext())
   206             return (ExclusiveContext *) this;
   207         return nullptr;
   208     }
   210     ExclusiveContext *asExclusiveContext() const {
   211         JS_ASSERT(isExclusiveContext());
   212         return maybeExclusiveContext();
   213     }
   215     bool isForkJoinContext() const;
   216     ForkJoinContext *asForkJoinContext();
   218     // The generational GC nursery may only be used on the main thread.
   219 #ifdef JSGC_GENERATIONAL
   220     inline bool hasNursery() const {
   221         return isJSContext();
   222     }
   224     inline js::Nursery &nursery() {
   225         JS_ASSERT(hasNursery());
   226         return runtime_->gcNursery;
   227     }
   228 #endif
   230     /*
   231      * Allocator used when allocating GCThings on this context. If we are a
   232      * JSContext, this is the Zone allocator of the JSContext's zone.
   233      * Otherwise, this is a per-thread allocator.
   234      *
   235      * This does not live in PerThreadData because the notion of an allocator
   236      * is only per-thread when off the main thread. The runtime (and the main
   237      * thread) can have more than one zone, each with its own allocator, and
   238      * it's up to the context to specify what compartment and zone we are
   239      * operating in.
   240      */
   241   protected:
   242     Allocator *allocator_;
   244   public:
   245     static size_t offsetOfAllocator() { return offsetof(ThreadSafeContext, allocator_); }
   247     inline Allocator *const allocator();
   249     // Allocations can only trigger GC when running on the main thread.
   250     inline AllowGC allowGC() const { return isJSContext() ? CanGC : NoGC; }
   252     template <typename T>
   253     bool isInsideCurrentZone(T thing) const {
   254         return thing->zoneFromAnyThread() == zone_;
   255     }
   257     template <typename T>
   258     inline bool isInsideCurrentCompartment(T thing) const {
   259         return thing->compartment() == compartment_;
   260     }
   262     template <typename T>
   263     inline bool isThreadLocal(T thing) const;
   265     void *onOutOfMemory(void *p, size_t nbytes) {
   266         return runtime_->onOutOfMemory(p, nbytes, maybeJSContext());
   267     }
   269     /* Clear the pending exception (if any) due to OOM. */
   270     void recoverFromOutOfMemory();
   272     inline void updateMallocCounter(size_t nbytes) {
   273         // Note: this is racy.
   274         runtime_->updateMallocCounter(zone_, nbytes);
   275     }
   277     void reportAllocationOverflow() {
   278         js_ReportAllocationOverflow(this);
   279     }
   281     // Accessors for immutable runtime data.
   282     JSAtomState &names() { return *runtime_->commonNames; }
   283     StaticStrings &staticStrings() { return *runtime_->staticStrings; }
   284     AtomSet &permanentAtoms() { return *runtime_->permanentAtoms; }
   285     const JS::AsmJSCacheOps &asmJSCacheOps() { return runtime_->asmJSCacheOps; }
   286     PropertyName *emptyString() { return runtime_->emptyString; }
   287     FreeOp *defaultFreeOp() { return runtime_->defaultFreeOp(); }
   288     bool useHelperThreads() { return runtime_->useHelperThreads(); }
   289     void *runtimeAddressForJit() { return runtime_; }
   290     void *stackLimitAddress(StackKind kind) { return &runtime_->mainThread.nativeStackLimit[kind]; }
   291     void *stackLimitAddressForJitCode(StackKind kind);
   292     size_t gcSystemPageSize() { return runtime_->gcSystemPageSize; }
   293     bool signalHandlersInstalled() const { return runtime_->signalHandlersInstalled(); }
   294     bool jitSupportsFloatingPoint() const { return runtime_->jitSupportsFloatingPoint; }
   296     // Thread local data that may be accessed freely.
   297     DtoaState *dtoaState() {
   298         return perThreadData->dtoaState;
   299     }
   300 };
   302 struct WorkerThread;
   304 class ExclusiveContext : public ThreadSafeContext
   305 {
   306     friend class gc::ArenaLists;
   307     friend class AutoCompartment;
   308     friend class AutoLockForExclusiveAccess;
   309     friend struct StackBaseShape;
   310     friend void JSScript::initCompartment(ExclusiveContext *cx);
   311     friend class jit::IonContext;
   313     // The worker on which this context is running, if this is not a JSContext.
   314     WorkerThread *workerThread_;
   316   public:
   318     ExclusiveContext(JSRuntime *rt, PerThreadData *pt, ContextKind kind)
   319       : ThreadSafeContext(rt, pt, kind),
   320         workerThread_(nullptr),
   321         enterCompartmentDepth_(0)
   322     {}
   324     /*
   325      * "Entering" a compartment changes cx->compartment (which changes
   326      * cx->global). Note that this does not push any InterpreterFrame which means
   327      * that it is possible for cx->fp()->compartment() != cx->compartment.
   328      * This is not a problem since, in general, most places in the VM cannot
   329      * know that they were called from script (e.g., they may have been called
   330      * through the JSAPI via JS_CallFunction) and thus cannot expect fp.
   331      *
   332      * Compartments should be entered/left in a LIFO fasion. The depth of this
   333      * enter/leave stack is maintained by enterCompartmentDepth_ and queried by
   334      * hasEnteredCompartment.
   335      *
   336      * To enter a compartment, code should prefer using AutoCompartment over
   337      * manually calling cx->enterCompartment/leaveCompartment.
   338      */
   339   protected:
   340     unsigned            enterCompartmentDepth_;
   341     inline void setCompartment(JSCompartment *comp);
   342   public:
   343     bool hasEnteredCompartment() const {
   344         return enterCompartmentDepth_ > 0;
   345     }
   346 #ifdef DEBUG
   347     unsigned getEnterCompartmentDepth() const {
   348         return enterCompartmentDepth_;
   349     }
   350 #endif
   352     inline void enterCompartment(JSCompartment *c);
   353     inline void enterNullCompartment();
   354     inline void leaveCompartment(JSCompartment *oldCompartment);
   356     void setWorkerThread(WorkerThread *workerThread);
   357     WorkerThread *workerThread() const { return workerThread_; }
   359     // Threads with an ExclusiveContext may freely access any data in their
   360     // compartment and zone.
   361     JSCompartment *compartment() const {
   362         JS_ASSERT_IF(runtime_->isAtomsCompartment(compartment_),
   363                      runtime_->currentThreadHasExclusiveAccess());
   364         return compartment_;
   365     }
   366     JS::Zone *zone() const {
   367         JS_ASSERT_IF(!compartment(), !zone_);
   368         JS_ASSERT_IF(compartment(), js::GetCompartmentZone(compartment()) == zone_);
   369         return zone_;
   370     }
   372     // Zone local methods that can be used freely from an ExclusiveContext.
   373     types::TypeObject *getNewType(const Class *clasp, TaggedProto proto, JSFunction *fun = nullptr);
   374     types::TypeObject *getSingletonType(const Class *clasp, TaggedProto proto);
   375     inline js::LifoAlloc &typeLifoAlloc();
   377     // Current global. This is only safe to use within the scope of the
   378     // AutoCompartment from which it's called.
   379     inline js::Handle<js::GlobalObject*> global() const;
   381     // Methods to access runtime data that must be protected by locks.
   382     frontend::ParseMapPool &parseMapPool() {
   383         return runtime_->parseMapPool();
   384     }
   385     AtomSet &atoms() {
   386         return runtime_->atoms();
   387     }
   388     JSCompartment *atomsCompartment() {
   389         return runtime_->atomsCompartment();
   390     }
   391     ScriptDataTable &scriptDataTable() {
   392         return runtime_->scriptDataTable();
   393     }
   395     // Methods specific to any WorkerThread for the context.
   396     frontend::CompileError &addPendingCompileError();
   397     void addPendingOverRecursed();
   398 };
   400 } /* namespace js */
   402 struct JSContext : public js::ExclusiveContext,
   403                    public mozilla::LinkedListElement<JSContext>
   404 {
   405     explicit JSContext(JSRuntime *rt);
   406     ~JSContext();
   408     JSRuntime *runtime() const { return runtime_; }
   409     js::PerThreadData &mainThread() const { return runtime()->mainThread; }
   411     static size_t offsetOfRuntime() {
   412         return offsetof(JSContext, runtime_);
   413     }
   415     friend class js::ExclusiveContext;
   416     friend class JS::AutoSaveExceptionState;
   418   private:
   419     /* Exception state -- the exception member is a GC root by definition. */
   420     bool                throwing;            /* is there a pending exception? */
   421     js::Value           unwrappedException_; /* most-recently-thrown exception */
   423     /* Per-context options. */
   424     JS::ContextOptions  options_;
   426   public:
   427     int32_t             reportGranularity;  /* see vm/Probes.h */
   429     js::AutoResolving   *resolvingList;
   431     /* True if generating an error, to prevent runaway recursion. */
   432     bool                generatingError;
   434     /* See JS_SaveFrameChain/JS_RestoreFrameChain. */
   435   private:
   436     struct SavedFrameChain {
   437         SavedFrameChain(JSCompartment *comp, unsigned count)
   438           : compartment(comp), enterCompartmentCount(count) {}
   439         JSCompartment *compartment;
   440         unsigned enterCompartmentCount;
   441     };
   442     typedef js::Vector<SavedFrameChain, 1, js::SystemAllocPolicy> SaveStack;
   443     SaveStack           savedFrameChains_;
   444   public:
   445     bool saveFrameChain();
   446     void restoreFrameChain();
   448     /*
   449      * When no compartments have been explicitly entered, the context's
   450      * compartment will be set to the compartment of the "default compartment
   451      * object".
   452      */
   453   private:
   454     JSObject *defaultCompartmentObject_;
   455   public:
   456     inline void setDefaultCompartmentObject(JSObject *obj);
   457     inline void setDefaultCompartmentObjectIfUnset(JSObject *obj);
   458     JSObject *maybeDefaultCompartmentObject() const {
   459         JS_ASSERT(!options().noDefaultCompartmentObject());
   460         return defaultCompartmentObject_;
   461     }
   463     /* State for object and array toSource conversion. */
   464     js::ObjectSet       cycleDetectorSet;
   466     /* Per-context optional error reporter. */
   467     JSErrorReporter     errorReporter;
   469     /* Client opaque pointers. */
   470     void                *data;
   471     void                *data2;
   473   public:
   475     /*
   476      * Return:
   477      * - The newest scripted frame's version, if there is such a frame.
   478      * - The version from the compartment.
   479      * - The default version.
   480      *
   481      * Note: if this ever shows up in a profile, just add caching!
   482      */
   483     JSVersion findVersion() const;
   485     const JS::ContextOptions &options() const {
   486         return options_;
   487     }
   489     JS::ContextOptions &options() {
   490         return options_;
   491     }
   493     js::LifoAlloc &tempLifoAlloc() { return runtime()->tempLifoAlloc; }
   495 #ifdef JS_THREADSAFE
   496     unsigned            outstandingRequests;/* number of JS_BeginRequest calls
   497                                                without the corresponding
   498                                                JS_EndRequest. */
   499 #endif
   501     /* Location to stash the iteration value between JSOP_MOREITER and JSOP_ITERNEXT. */
   502     js::Value           iterValue;
   504     bool jitIsBroken;
   506     void updateJITEnabled();
   508     /* Whether this context has JS frames on the stack. */
   509     bool currentlyRunning() const;
   511     bool currentlyRunningInInterpreter() const {
   512         return mainThread().activation()->isInterpreter();
   513     }
   514     bool currentlyRunningInJit() const {
   515         return mainThread().activation()->isJit();
   516     }
   517     js::InterpreterFrame *interpreterFrame() const {
   518         return mainThread().activation()->asInterpreter()->current();
   519     }
   520     js::InterpreterRegs &interpreterRegs() const {
   521         return mainThread().activation()->asInterpreter()->regs();
   522     }
   524     /*
   525      * Get the topmost script and optional pc on the stack. By default, this
   526      * function only returns a JSScript in the current compartment, returning
   527      * nullptr if the current script is in a different compartment. This
   528      * behavior can be overridden by passing ALLOW_CROSS_COMPARTMENT.
   529      */
   530     enum MaybeAllowCrossCompartment {
   531         DONT_ALLOW_CROSS_COMPARTMENT = false,
   532         ALLOW_CROSS_COMPARTMENT = true
   533     };
   534     inline JSScript *currentScript(jsbytecode **pc = nullptr,
   535                                    MaybeAllowCrossCompartment = DONT_ALLOW_CROSS_COMPARTMENT) const;
   537 #ifdef MOZ_TRACE_JSCALLS
   538     /* Function entry/exit debugging callback. */
   539     JSFunctionCallback    functionCallback;
   541     void doFunctionCallback(const JSFunction *fun,
   542                             const JSScript *scr,
   543                             int entering) const
   544     {
   545         if (functionCallback)
   546             functionCallback(fun, scr, this, entering);
   547     }
   548 #endif
   550   private:
   551     /* Innermost-executing generator or null if no generator are executing. */
   552     JSGenerator *innermostGenerator_;
   553   public:
   554     JSGenerator *innermostGenerator() const { return innermostGenerator_; }
   555     void enterGenerator(JSGenerator *gen);
   556     void leaveGenerator(JSGenerator *gen);
   558     bool isExceptionPending() {
   559         return throwing;
   560     }
   562     MOZ_WARN_UNUSED_RESULT
   563     bool getPendingException(JS::MutableHandleValue rval);
   565     bool isThrowingOutOfMemory();
   567     void setPendingException(js::Value v);
   569     void clearPendingException() {
   570         throwing = false;
   571         unwrappedException_.setUndefined();
   572     }
   574 #ifdef DEBUG
   575     /*
   576      * Controls whether a quadratic-complexity assertion is performed during
   577      * stack iteration; defaults to true.
   578      */
   579     bool stackIterAssertionEnabled;
   580 #endif
   582     /*
   583      * See JS_SetTrustedPrincipals in jsapi.h.
   584      * Note: !cx->compartment is treated as trusted.
   585      */
   586     bool runningWithTrustedPrincipals() const;
   588     JS_FRIEND_API(size_t) sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
   590     void mark(JSTracer *trc);
   592   private:
   593     /*
   594      * The allocation code calls the function to indicate either OOM failure
   595      * when p is null or that a memory pressure counter has reached some
   596      * threshold when p is not null. The function takes the pointer and not
   597      * a boolean flag to minimize the amount of code in its inlined callers.
   598      */
   599     JS_FRIEND_API(void) checkMallocGCPressure(void *p);
   600 }; /* struct JSContext */
   602 namespace js {
   604 struct AutoResolving {
   605   public:
   606     enum Kind {
   607         LOOKUP,
   608         WATCH
   609     };
   611     AutoResolving(JSContext *cx, HandleObject obj, HandleId id, Kind kind = LOOKUP
   612                   MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   613       : context(cx), object(obj), id(id), kind(kind), link(cx->resolvingList)
   614     {
   615         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   616         JS_ASSERT(obj);
   617         cx->resolvingList = this;
   618     }
   620     ~AutoResolving() {
   621         JS_ASSERT(context->resolvingList == this);
   622         context->resolvingList = link;
   623     }
   625     bool alreadyStarted() const {
   626         return link && alreadyStartedSlow();
   627     }
   629   private:
   630     bool alreadyStartedSlow() const;
   632     JSContext           *const context;
   633     HandleObject        object;
   634     HandleId            id;
   635     Kind                const kind;
   636     AutoResolving       *const link;
   637     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   638 };
   640 /*
   641  * Enumerate all contexts in a runtime.
   642  */
   643 class ContextIter {
   644     JSContext *iter;
   646 public:
   647     explicit ContextIter(JSRuntime *rt) {
   648         iter = rt->contextList.getFirst();
   649     }
   651     bool done() const {
   652         return !iter;
   653     }
   655     void next() {
   656         JS_ASSERT(!done());
   657         iter = iter->getNext();
   658     }
   660     JSContext *get() const {
   661         JS_ASSERT(!done());
   662         return iter;
   663     }
   665     operator JSContext *() const {
   666         return get();
   667     }
   669     JSContext *operator ->() const {
   670         return get();
   671     }
   672 };
   674 /*
   675  * Create and destroy functions for JSContext, which is manually allocated
   676  * and exclusively owned.
   677  */
   678 extern JSContext *
   679 NewContext(JSRuntime *rt, size_t stackChunkSize);
   681 enum DestroyContextMode {
   682     DCM_NO_GC,
   683     DCM_FORCE_GC,
   684     DCM_NEW_FAILED
   685 };
   687 extern void
   688 DestroyContext(JSContext *cx, DestroyContextMode mode);
   690 enum ErrorArgumentsType {
   691     ArgumentsAreUnicode,
   692     ArgumentsAreASCII
   693 };
   696 /*
   697  * Loads and returns a self-hosted function by name. For performance, define
   698  * the property name in vm/CommonPropertyNames.h.
   699  *
   700  * Defined in SelfHosting.cpp.
   701  */
   702 JSFunction *
   703 SelfHostedFunction(JSContext *cx, HandlePropertyName propName);
   705 } /* namespace js */
   707 #ifdef va_start
   708 extern bool
   709 js_ReportErrorVA(JSContext *cx, unsigned flags, const char *format, va_list ap);
   711 extern bool
   712 js_ReportErrorNumberVA(JSContext *cx, unsigned flags, JSErrorCallback callback,
   713                        void *userRef, const unsigned errorNumber,
   714                        js::ErrorArgumentsType argumentsType, va_list ap);
   716 extern bool
   717 js_ReportErrorNumberUCArray(JSContext *cx, unsigned flags, JSErrorCallback callback,
   718                             void *userRef, const unsigned errorNumber,
   719                             const jschar **args);
   720 #endif
   722 extern bool
   723 js_ExpandErrorArguments(js::ExclusiveContext *cx, JSErrorCallback callback,
   724                         void *userRef, const unsigned errorNumber,
   725                         char **message, JSErrorReport *reportp,
   726                         js::ErrorArgumentsType argumentsType, va_list ap);
   728 namespace js {
   730 /* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */
   731 extern void
   732 ReportUsageError(JSContext *cx, HandleObject callee, const char *msg);
   734 /*
   735  * Prints a full report and returns true if the given report is non-nullptr
   736  * and the report doesn't have the JSREPORT_WARNING flag set or reportWarnings
   737  * is true.
   738  * Returns false otherwise, printing just the message if the report is nullptr.
   739  */
   740 extern bool
   741 PrintError(JSContext *cx, FILE *file, const char *message, JSErrorReport *report,
   742            bool reportWarnings);
   744 /*
   745  * Send a JSErrorReport to the errorReporter callback.
   746  */
   747 void
   748 CallErrorReporter(JSContext *cx, const char *message, JSErrorReport *report);
   750 } /* namespace js */
   752 extern void
   753 js_ReportIsNotDefined(JSContext *cx, const char *name);
   755 /*
   756  * Report an attempt to access the property of a null or undefined value (v).
   757  */
   758 extern bool
   759 js_ReportIsNullOrUndefined(JSContext *cx, int spindex, js::HandleValue v,
   760                            js::HandleString fallback);
   762 extern void
   763 js_ReportMissingArg(JSContext *cx, js::HandleValue v, unsigned arg);
   765 /*
   766  * Report error using js_DecompileValueGenerator(cx, spindex, v, fallback) as
   767  * the first argument for the error message. If the error message has less
   768  * then 3 arguments, use null for arg1 or arg2.
   769  */
   770 extern bool
   771 js_ReportValueErrorFlags(JSContext *cx, unsigned flags, const unsigned errorNumber,
   772                          int spindex, js::HandleValue v, js::HandleString fallback,
   773                          const char *arg1, const char *arg2);
   775 #define js_ReportValueError(cx,errorNumber,spindex,v,fallback)                \
   776     ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber,          \
   777                                     spindex, v, fallback, nullptr, nullptr))
   779 #define js_ReportValueError2(cx,errorNumber,spindex,v,fallback,arg1)          \
   780     ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber,          \
   781                                     spindex, v, fallback, arg1, nullptr))
   783 #define js_ReportValueError3(cx,errorNumber,spindex,v,fallback,arg1,arg2)     \
   784     ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber,          \
   785                                     spindex, v, fallback, arg1, arg2))
   787 extern const JSErrorFormatString js_ErrorFormatString[JSErr_Limit];
   789 char *
   790 js_strdup(js::ExclusiveContext *cx, const char *s);
   792 #ifdef JS_THREADSAFE
   793 # define JS_ASSERT_REQUEST_DEPTH(cx)  JS_ASSERT((cx)->runtime()->requestDepth >= 1)
   794 #else
   795 # define JS_ASSERT_REQUEST_DEPTH(cx)  ((void) 0)
   796 #endif
   798 namespace js {
   800 /*
   801  * Invoke the interrupt callback and return false if the current execution
   802  * is to be terminated.
   803  */
   804 bool
   805 InvokeInterruptCallback(JSContext *cx);
   807 bool
   808 HandleExecutionInterrupt(JSContext *cx);
   810 /*
   811  * Process any pending interrupt requests. Long-running inner loops in C++ must
   812  * call this periodically to make sure they are interruptible --- that is, to
   813  * make sure they do not prevent the slow script dialog from appearing.
   814  *
   815  * This can run a full GC or call the interrupt callback, which could do
   816  * anything. In the browser, it displays the slow script dialog.
   817  *
   818  * If this returns true, the caller can continue; if false, the caller must
   819  * break out of its loop. This happens if, for example, the user clicks "Stop
   820  * script" on the slow script dialog; treat it as an uncatchable error.
   821  */
   822 inline bool
   823 CheckForInterrupt(JSContext *cx)
   824 {
   825     JS_ASSERT_REQUEST_DEPTH(cx);
   826     return !cx->runtime()->interrupt || InvokeInterruptCallback(cx);
   827 }
   829 /************************************************************************/
   831 class AutoStringVector : public AutoVectorRooter<JSString *>
   832 {
   833   public:
   834     explicit AutoStringVector(JSContext *cx
   835                               MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   836         : AutoVectorRooter<JSString *>(cx, STRINGVECTOR)
   837     {
   838         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   839     }
   841     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   842 };
   844 class AutoPropertyNameVector : public AutoVectorRooter<PropertyName *>
   845 {
   846   public:
   847     explicit AutoPropertyNameVector(JSContext *cx
   848                                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   849         : AutoVectorRooter<PropertyName *>(cx, STRINGVECTOR)
   850     {
   851         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   852     }
   854     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   855 };
   857 class AutoShapeVector : public AutoVectorRooter<Shape *>
   858 {
   859   public:
   860     explicit AutoShapeVector(JSContext *cx
   861                              MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   862         : AutoVectorRooter<Shape *>(cx, SHAPEVECTOR)
   863     {
   864         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   865     }
   867     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   868 };
   870 class AutoObjectObjectHashMap : public AutoHashMapRooter<JSObject *, JSObject *>
   871 {
   872   public:
   873     explicit AutoObjectObjectHashMap(JSContext *cx
   874                                      MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   875       : AutoHashMapRooter<JSObject *, JSObject *>(cx, OBJOBJHASHMAP)
   876     {
   877         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   878     }
   880     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   881 };
   883 class AutoObjectUnsigned32HashMap : public AutoHashMapRooter<JSObject *, uint32_t>
   884 {
   885   public:
   886     explicit AutoObjectUnsigned32HashMap(JSContext *cx
   887                                          MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   888       : AutoHashMapRooter<JSObject *, uint32_t>(cx, OBJU32HASHMAP)
   889     {
   890         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   891     }
   893     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   894 };
   896 class AutoObjectHashSet : public AutoHashSetRooter<JSObject *>
   897 {
   898   public:
   899     explicit AutoObjectHashSet(JSContext *cx
   900                                MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   901       : AutoHashSetRooter<JSObject *>(cx, OBJHASHSET)
   902     {
   903         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   904     }
   906     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   907 };
   909 /* AutoArrayRooter roots an external array of Values. */
   910 class AutoArrayRooter : private AutoGCRooter
   911 {
   912   public:
   913     AutoArrayRooter(JSContext *cx, size_t len, Value *vec
   914                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   915       : AutoGCRooter(cx, len), array(vec)
   916     {
   917         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   918         JS_ASSERT(tag_ >= 0);
   919     }
   921     void changeLength(size_t newLength) {
   922         tag_ = ptrdiff_t(newLength);
   923         JS_ASSERT(tag_ >= 0);
   924     }
   926     void changeArray(Value *newArray, size_t newLength) {
   927         changeLength(newLength);
   928         array = newArray;
   929     }
   931     Value *start() {
   932         return array;
   933     }
   935     size_t length() {
   936         JS_ASSERT(tag_ >= 0);
   937         return size_t(tag_);
   938     }
   940     MutableHandleValue handleAt(size_t i) {
   941         JS_ASSERT(i < size_t(tag_));
   942         return MutableHandleValue::fromMarkedLocation(&array[i]);
   943     }
   944     HandleValue handleAt(size_t i) const {
   945         JS_ASSERT(i < size_t(tag_));
   946         return HandleValue::fromMarkedLocation(&array[i]);
   947     }
   948     MutableHandleValue operator[](size_t i) {
   949         JS_ASSERT(i < size_t(tag_));
   950         return MutableHandleValue::fromMarkedLocation(&array[i]);
   951     }
   952     HandleValue operator[](size_t i) const {
   953         JS_ASSERT(i < size_t(tag_));
   954         return HandleValue::fromMarkedLocation(&array[i]);
   955     }
   957     friend void AutoGCRooter::trace(JSTracer *trc);
   959   private:
   960     Value *array;
   961     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   962 };
   964 class AutoAssertNoException
   965 {
   966 #ifdef DEBUG
   967     JSContext *cx;
   968     bool hadException;
   969 #endif
   971   public:
   972     AutoAssertNoException(JSContext *cx)
   973 #ifdef DEBUG
   974       : cx(cx),
   975         hadException(cx->isExceptionPending())
   976 #endif
   977     {
   978     }
   980     ~AutoAssertNoException()
   981     {
   982         JS_ASSERT_IF(!hadException, !cx->isExceptionPending());
   983     }
   984 };
   986 /*
   987  * FIXME bug 647103 - replace these *AllocPolicy names.
   988  */
   989 class ContextAllocPolicy
   990 {
   991     ThreadSafeContext *const cx_;
   993   public:
   994     ContextAllocPolicy(ThreadSafeContext *cx) : cx_(cx) {}
   995     ThreadSafeContext *context() const { return cx_; }
   996     void *malloc_(size_t bytes) { return cx_->malloc_(bytes); }
   997     void *calloc_(size_t bytes) { return cx_->calloc_(bytes); }
   998     void *realloc_(void *p, size_t oldBytes, size_t bytes) { return cx_->realloc_(p, oldBytes, bytes); }
   999     void free_(void *p) { js_free(p); }
  1000     void reportAllocOverflow() const { js_ReportAllocationOverflow(cx_); }
  1001 };
  1003 /* Exposed intrinsics so that Ion may inline them. */
  1004 bool intrinsic_ToObject(JSContext *cx, unsigned argc, Value *vp);
  1005 bool intrinsic_IsCallable(JSContext *cx, unsigned argc, Value *vp);
  1006 bool intrinsic_ThrowError(JSContext *cx, unsigned argc, Value *vp);
  1007 bool intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp);
  1009 bool intrinsic_UnsafePutElements(JSContext *cx, unsigned argc, Value *vp);
  1010 bool intrinsic_DefineValueProperty(JSContext *cx, unsigned argc, Value *vp);
  1011 bool intrinsic_UnsafeSetReservedSlot(JSContext *cx, unsigned argc, Value *vp);
  1012 bool intrinsic_UnsafeGetReservedSlot(JSContext *cx, unsigned argc, Value *vp);
  1013 bool intrinsic_HaveSameClass(JSContext *cx, unsigned argc, Value *vp);
  1014 bool intrinsic_IsPackedArray(JSContext *cx, unsigned argc, Value *vp);
  1016 bool intrinsic_ShouldForceSequential(JSContext *cx, unsigned argc, Value *vp);
  1017 bool intrinsic_NewParallelArray(JSContext *cx, unsigned argc, Value *vp);
  1018 bool intrinsic_ForkJoinGetSlice(JSContext *cx, unsigned argc, Value *vp);
  1019 bool intrinsic_InParallelSection(JSContext *cx, unsigned argc, Value *vp);
  1021 bool intrinsic_ObjectIsTypedObject(JSContext *cx, unsigned argc, Value *vp);
  1022 bool intrinsic_ObjectIsTransparentTypedObject(JSContext *cx, unsigned argc, Value *vp);
  1023 bool intrinsic_ObjectIsOpaqueTypedObject(JSContext *cx, unsigned argc, Value *vp);
  1024 bool intrinsic_ObjectIsTypeDescr(JSContext *cx, unsigned argc, Value *vp);
  1025 bool intrinsic_TypeDescrIsSimpleType(JSContext *cx, unsigned argc, Value *vp);
  1026 bool intrinsic_TypeDescrIsArrayType(JSContext *cx, unsigned argc, Value *vp);
  1027 bool intrinsic_TypeDescrIsUnsizedArrayType(JSContext *cx, unsigned argc, Value *vp);
  1028 bool intrinsic_TypeDescrIsSizedArrayType(JSContext *cx, unsigned argc, Value *vp);
  1030 class AutoLockForExclusiveAccess
  1032 #ifdef JS_THREADSAFE
  1033     JSRuntime *runtime;
  1035     void init(JSRuntime *rt) {
  1036         runtime = rt;
  1037         if (runtime->numExclusiveThreads) {
  1038             runtime->assertCanLock(ExclusiveAccessLock);
  1039             PR_Lock(runtime->exclusiveAccessLock);
  1040 #ifdef DEBUG
  1041             runtime->exclusiveAccessOwner = PR_GetCurrentThread();
  1042 #endif
  1043         } else {
  1044             JS_ASSERT(!runtime->mainThreadHasExclusiveAccess);
  1045             runtime->mainThreadHasExclusiveAccess = true;
  1049   public:
  1050     AutoLockForExclusiveAccess(ExclusiveContext *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
  1051         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  1052         init(cx->runtime_);
  1054     AutoLockForExclusiveAccess(JSRuntime *rt MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
  1055         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  1056         init(rt);
  1058     ~AutoLockForExclusiveAccess() {
  1059         if (runtime->numExclusiveThreads) {
  1060             JS_ASSERT(runtime->exclusiveAccessOwner == PR_GetCurrentThread());
  1061             runtime->exclusiveAccessOwner = nullptr;
  1062             PR_Unlock(runtime->exclusiveAccessLock);
  1063         } else {
  1064             JS_ASSERT(runtime->mainThreadHasExclusiveAccess);
  1065             runtime->mainThreadHasExclusiveAccess = false;
  1068 #else // JS_THREADSAFE
  1069   public:
  1070     AutoLockForExclusiveAccess(ExclusiveContext *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
  1071         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  1073     AutoLockForExclusiveAccess(JSRuntime *rt MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
  1074         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  1076     ~AutoLockForExclusiveAccess() {
  1077         // An empty destructor is needed to avoid warnings from clang about
  1078         // unused local variables of this type.
  1080 #endif // JS_THREADSAFE
  1082     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
  1083 };
  1085 void
  1086 CrashAtUnhandlableOOM(const char *reason);
  1088 } /* namespace js */
  1090 #ifdef _MSC_VER
  1091 #pragma warning(pop)
  1092 #endif
  1094 #endif /* jscntxt_h */

mercurial