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