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 */