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.

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

mercurial