1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sw=4 et tw=78:
3 : *
4 : * ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is Mozilla Communicator client code, released
18 : * March 31, 1998.
19 : *
20 : * The Initial Developer of the Original Code is
21 : * Netscape Communications Corporation.
22 : * Portions created by the Initial Developer are Copyright (C) 1998
23 : * the Initial Developer. All Rights Reserved.
24 : *
25 : * Contributor(s):
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either of the GNU General Public License Version 2 or later (the "GPL"),
29 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : /* JS execution context. */
42 :
43 : #ifndef jscntxt_h___
44 : #define jscntxt_h___
45 :
46 : #include "mozilla/Attributes.h"
47 :
48 : #include <string.h>
49 :
50 : #include "jsapi.h"
51 : #include "jsfriendapi.h"
52 : #include "jsprvtd.h"
53 : #include "jsatom.h"
54 : #include "jsclist.h"
55 : #include "jsdhash.h"
56 : #include "jsgc.h"
57 : #include "jspropertycache.h"
58 : #include "jspropertytree.h"
59 : #include "jsutil.h"
60 : #include "prmjtime.h"
61 :
62 : #include "ds/LifoAlloc.h"
63 : #include "gc/Statistics.h"
64 : #include "js/HashTable.h"
65 : #include "js/Vector.h"
66 : #include "vm/Stack.h"
67 :
68 : #ifdef _MSC_VER
69 : #pragma warning(push)
70 : #pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
71 : #pragma warning(push)
72 : #pragma warning(disable:4355) /* Silence warning about "this" used in base member initializer list */
73 : #endif
74 :
75 : JS_BEGIN_EXTERN_C
76 : struct DtoaState;
77 : JS_END_EXTERN_C
78 :
79 : struct JSSharpInfo {
80 : bool hasGen;
81 : bool isSharp;
82 :
83 874063 : JSSharpInfo() : hasGen(false), isSharp(false) {}
84 : };
85 :
86 : typedef js::HashMap<JSObject *, JSSharpInfo> JSSharpTable;
87 :
88 26228 : struct JSSharpObjectMap {
89 : unsigned depth;
90 : uint32_t sharpgen;
91 : JSSharpTable table;
92 :
93 26231 : JSSharpObjectMap(JSContext *cx) : depth(0), sharpgen(0), table(js::TempAllocPolicy(cx)) {
94 26231 : table.init();
95 26231 : }
96 : };
97 :
98 : namespace js {
99 :
100 : namespace mjit {
101 : class JaegerCompartment;
102 : }
103 :
104 : class WeakMapBase;
105 : class InterpreterFrames;
106 :
107 : class ScriptOpcodeCounts;
108 : struct ScriptOpcodeCountsPair;
109 :
110 : /*
111 : * GetSrcNote cache to avoid O(n^2) growth in finding a source note for a
112 : * given pc in a script. We use the script->code pointer to tag the cache,
113 : * instead of the script address itself, so that source notes are always found
114 : * by offset from the bytecode with which they were generated.
115 : */
116 19908 : struct GSNCache {
117 : typedef HashMap<jsbytecode *,
118 : jssrcnote *,
119 : PointerHasher<jsbytecode *, 0>,
120 : SystemAllocPolicy> Map;
121 :
122 : jsbytecode *code;
123 : Map map;
124 :
125 19910 : GSNCache() : code(NULL) { }
126 :
127 : void purge();
128 : };
129 :
130 : inline GSNCache *
131 : GetGSNCache(JSContext *cx);
132 :
133 : struct PendingProxyOperation {
134 : PendingProxyOperation *next;
135 : JSObject *object;
136 : };
137 :
138 : typedef Vector<ScriptOpcodeCountsPair, 0, SystemAllocPolicy> ScriptOpcodeCountsVector;
139 :
140 : struct ConservativeGCData
141 : {
142 : /*
143 : * The GC scans conservatively between ThreadData::nativeStackBase and
144 : * nativeStackTop unless the latter is NULL.
145 : */
146 : uintptr_t *nativeStackTop;
147 :
148 : union {
149 : jmp_buf jmpbuf;
150 : uintptr_t words[JS_HOWMANY(sizeof(jmp_buf), sizeof(uintptr_t))];
151 : } registerSnapshot;
152 :
153 : /*
154 : * Cycle collector uses this to communicate that the native stack of the
155 : * GC thread should be scanned only if the thread have more than the given
156 : * threshold of requests.
157 : */
158 : unsigned requestThreshold;
159 :
160 19910 : ConservativeGCData()
161 19910 : : nativeStackTop(NULL), requestThreshold(0)
162 19910 : {}
163 :
164 19908 : ~ConservativeGCData() {
165 : #ifdef JS_THREADSAFE
166 : /*
167 : * The conservative GC scanner should be disabled when the thread leaves
168 : * the last request.
169 : */
170 19908 : JS_ASSERT(!hasStackToScan());
171 : #endif
172 19908 : }
173 :
174 : JS_NEVER_INLINE void recordStackTop();
175 :
176 : #ifdef JS_THREADSAFE
177 424548 : void updateForRequestEnd(unsigned suspendCount) {
178 424548 : if (suspendCount)
179 356267 : recordStackTop();
180 : else
181 68281 : nativeStackTop = NULL;
182 424548 : }
183 : #endif
184 :
185 53058 : bool hasStackToScan() const {
186 53058 : return !!nativeStackTop;
187 : }
188 : };
189 :
190 : } /* namespace js */
191 :
192 : struct JSRuntime : js::RuntimeFriendFields
193 : {
194 : /* Default compartment. */
195 : JSCompartment *atomsCompartment;
196 :
197 : /* List of compartments (protected by the GC lock). */
198 : js::CompartmentVector compartments;
199 :
200 : /* See comment for JS_AbortIfWrongThread in jsapi.h. */
201 : #ifdef JS_THREADSAFE
202 : public:
203 27226744 : void *ownerThread() const { return ownerThread_; }
204 : void clearOwnerThread();
205 : void setOwnerThread();
206 : JS_FRIEND_API(bool) onOwnerThread() const;
207 : private:
208 : void *ownerThread_;
209 : public:
210 : #else
211 : public:
212 : bool onOwnerThread() const { return true; }
213 : #endif
214 :
215 : /* Keeper of the contiguous stack used by all contexts in this thread. */
216 : js::StackSpace stackSpace;
217 :
218 : /* Temporary arena pool used while compiling and decompiling. */
219 : static const size_t TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 1 << 12;
220 : js::LifoAlloc tempLifoAlloc;
221 :
222 : private:
223 : /*
224 : * Both of these allocators are used for regular expression code which is shared at the
225 : * thread-data level.
226 : */
227 : JSC::ExecutableAllocator *execAlloc_;
228 : WTF::BumpPointerAllocator *bumpAlloc_;
229 :
230 : JSC::ExecutableAllocator *createExecutableAllocator(JSContext *cx);
231 : WTF::BumpPointerAllocator *createBumpPointerAllocator(JSContext *cx);
232 :
233 : public:
234 58226 : JSC::ExecutableAllocator *getExecutableAllocator(JSContext *cx) {
235 58226 : return execAlloc_ ? execAlloc_ : createExecutableAllocator(cx);
236 : }
237 2975 : WTF::BumpPointerAllocator *getBumpPointerAllocator(JSContext *cx) {
238 2975 : return bumpAlloc_ ? bumpAlloc_ : createBumpPointerAllocator(cx);
239 : }
240 :
241 : /* Base address of the native stack for the current thread. */
242 : uintptr_t nativeStackBase;
243 :
244 : /* The native stack size limit that runtime should not exceed. */
245 : size_t nativeStackQuota;
246 :
247 : /*
248 : * Frames currently running in js::Interpret. See InterpreterFrames for
249 : * details.
250 : */
251 : js::InterpreterFrames *interpreterFrames;
252 :
253 : /* Context create/destroy callback. */
254 : JSContextCallback cxCallback;
255 :
256 : /* Compartment create/destroy callback. */
257 : JSCompartmentCallback compartmentCallback;
258 :
259 : js::ActivityCallback activityCallback;
260 : void *activityCallbackArg;
261 :
262 : #ifdef JS_THREADSAFE
263 : /* Number of JS_SuspendRequest calls withot JS_ResumeRequest. */
264 : unsigned suspendCount;
265 :
266 : /* The request depth for this thread. */
267 : unsigned requestDepth;
268 :
269 : # ifdef DEBUG
270 : unsigned checkRequestDepth;
271 : # endif
272 : #endif
273 :
274 : /* Garbage collector state, used by jsgc.c. */
275 :
276 : /*
277 : * Set of all GC chunks with at least one allocated thing. The
278 : * conservative GC uses it to quickly check if a possible GC thing points
279 : * into an allocated chunk.
280 : */
281 : js::GCChunkSet gcChunkSet;
282 :
283 : /*
284 : * Doubly-linked lists of chunks from user and system compartments. The GC
285 : * allocates its arenas from the corresponding list and when all arenas
286 : * in the list head are taken, then the chunk is removed from the list.
287 : * During the GC when all arenas in a chunk become free, that chunk is
288 : * removed from the list and scheduled for release.
289 : */
290 : js::gc::Chunk *gcSystemAvailableChunkListHead;
291 : js::gc::Chunk *gcUserAvailableChunkListHead;
292 : js::gc::ChunkPool gcChunkPool;
293 :
294 : js::RootedValueMap gcRootsHash;
295 : js::GCLocks gcLocksHash;
296 : unsigned gcKeepAtoms;
297 : size_t gcBytes;
298 : size_t gcMaxBytes;
299 : size_t gcMaxMallocBytes;
300 :
301 : /*
302 : * Number of the committed arenas in all GC chunks including empty chunks.
303 : * The counter is volatile as it is read without the GC lock, see comments
304 : * in MaybeGC.
305 : */
306 : volatile uint32_t gcNumArenasFreeCommitted;
307 : js::GCMarker gcMarker;
308 : void *gcVerifyData;
309 : bool gcChunkAllocationSinceLastGC;
310 : int64_t gcNextFullGCTime;
311 : int64_t gcJitReleaseTime;
312 : JSGCMode gcMode;
313 : volatile uintptr_t gcIsNeeded;
314 : js::WeakMapBase *gcWeakMapList;
315 : js::gcstats::Statistics gcStats;
316 :
317 : /* Incremented on every GC slice. */
318 : uint64_t gcNumber;
319 :
320 : /* The gcNumber at the time of the most recent GC's first slice. */
321 : uint64_t gcStartNumber;
322 :
323 : /* The reason that an interrupt-triggered GC should be called. */
324 : js::gcreason::Reason gcTriggerReason;
325 :
326 : /*
327 : * Compartment that triggered GC. If more than one Compatment need GC,
328 : * gcTriggerCompartment is reset to NULL and a global GC is performed.
329 : */
330 : JSCompartment *gcTriggerCompartment;
331 :
332 : /* Compartment that is currently involved in per-compartment GC */
333 : JSCompartment *gcCurrentCompartment;
334 :
335 : /*
336 : * If this is non-NULL, all marked objects must belong to this compartment.
337 : * This is used to look for compartment bugs.
338 : */
339 : JSCompartment *gcCheckCompartment;
340 :
341 : /*
342 : * The current incremental GC phase. During non-incremental GC, this is
343 : * always NO_INCREMENTAL.
344 : */
345 : js::gc::State gcIncrementalState;
346 :
347 : /* Indicates that a new compartment was created during incremental GC. */
348 : bool gcCompartmentCreated;
349 :
350 : /* Indicates that the last incremental slice exhausted the mark stack. */
351 : bool gcLastMarkSlice;
352 :
353 : /*
354 : * Indicates that a GC slice has taken place in the middle of an animation
355 : * frame, rather than at the beginning. In this case, the next slice will be
356 : * delayed so that we don't get back-to-back slices.
357 : */
358 : volatile uintptr_t gcInterFrameGC;
359 :
360 : /* Default budget for incremental GC slice. See SliceBudget in jsgc.h. */
361 : int64_t gcSliceBudget;
362 :
363 : /*
364 : * We disable incremental GC if we encounter a js::Class with a trace hook
365 : * that does not implement write barriers.
366 : */
367 : bool gcIncrementalEnabled;
368 :
369 : /* Compartment that is undergoing an incremental GC. */
370 : JSCompartment *gcIncrementalCompartment;
371 :
372 : /*
373 : * We save all conservative scanned roots in this vector so that
374 : * conservative scanning can be "replayed" deterministically. In DEBUG mode,
375 : * this allows us to run a non-incremental GC after every incremental GC to
376 : * ensure that no objects were missed.
377 : */
378 : #ifdef DEBUG
379 425210 : struct SavedGCRoot {
380 : void *thing;
381 : JSGCTraceKind kind;
382 :
383 175857 : SavedGCRoot(void *thing, JSGCTraceKind kind) : thing(thing), kind(kind) {}
384 : };
385 : js::Vector<SavedGCRoot, 0, js::SystemAllocPolicy> gcSavedRoots;
386 : #endif
387 :
388 : /*
389 : * We can pack these flags as only the GC thread writes to them. Atomic
390 : * updates to packed bytes are not guaranteed, so stores issued by one
391 : * thread may be lost due to unsynchronized read-modify-write cycles on
392 : * other threads.
393 : */
394 : bool gcPoke;
395 : bool gcRunning;
396 :
397 : /*
398 : * These options control the zealousness of the GC. The fundamental values
399 : * are gcNextScheduled and gcDebugCompartmentGC. At every allocation,
400 : * gcNextScheduled is decremented. When it reaches zero, we do either a
401 : * full or a compartmental GC, based on gcDebugCompartmentGC.
402 : *
403 : * At this point, if gcZeal_ == 2 then gcNextScheduled is reset to the
404 : * value of gcZealFrequency. Otherwise, no additional GCs take place.
405 : *
406 : * You can control these values in several ways:
407 : * - Pass the -Z flag to the shell (see the usage info for details)
408 : * - Call gczeal() or schedulegc() from inside shell-executed JS code
409 : * (see the help for details)
410 : *
411 : * If gzZeal_ == 1 then we perform GCs in select places (during MaybeGC and
412 : * whenever a GC poke happens). This option is mainly useful to embedders.
413 : *
414 : * We use gcZeal_ == 4 to enable write barrier verification. See the comment
415 : * in jsgc.cpp for more information about this.
416 : */
417 : #ifdef JS_GC_ZEAL
418 : int gcZeal_;
419 : int gcZealFrequency;
420 : int gcNextScheduled;
421 : bool gcDebugCompartmentGC;
422 : bool gcDeterministicOnly;
423 :
424 -1793318227 : int gcZeal() { return gcZeal_; }
425 :
426 270394255 : bool needZealousGC() {
427 270394255 : if (gcNextScheduled > 0 && --gcNextScheduled == 0) {
428 10570 : if (gcZeal() == js::gc::ZealAllocValue)
429 10500 : gcNextScheduled = gcZealFrequency;
430 10570 : return true;
431 : }
432 270383685 : return false;
433 : }
434 : #else
435 : int gcZeal() { return 0; }
436 : bool needZealousGC() { return false; }
437 : #endif
438 :
439 : JSGCCallback gcCallback;
440 : js::GCSliceCallback gcSliceCallback;
441 : JSFinalizeCallback gcFinalizeCallback;
442 :
443 : private:
444 : /*
445 : * Malloc counter to measure memory pressure for GC scheduling. It runs
446 : * from gcMaxMallocBytes down to zero.
447 : */
448 : volatile ptrdiff_t gcMallocBytes;
449 :
450 : public:
451 : /*
452 : * The trace operations to trace embedding-specific GC roots. One is for
453 : * tracing through black roots and the other is for tracing through gray
454 : * roots. The black/gray distinction is only relevant to the cycle
455 : * collector.
456 : */
457 : JSTraceDataOp gcBlackRootsTraceOp;
458 : void *gcBlackRootsData;
459 : JSTraceDataOp gcGrayRootsTraceOp;
460 : void *gcGrayRootsData;
461 :
462 : /* Stack of thread-stack-allocated GC roots. */
463 : js::AutoGCRooter *autoGCRooters;
464 :
465 : /* Strong references on scripts held for PCCount profiling API. */
466 : js::ScriptOpcodeCountsVector *scriptPCCounters;
467 :
468 : /* Well-known numbers held for use by this runtime's contexts. */
469 : js::Value NaNValue;
470 : js::Value negativeInfinityValue;
471 : js::Value positiveInfinityValue;
472 :
473 : JSAtom *emptyString;
474 :
475 : /* List of active contexts sharing this runtime. */
476 : JSCList contextList;
477 :
478 1736329 : bool hasContexts() const {
479 1736329 : return !JS_CLIST_IS_EMPTY(&contextList);
480 : }
481 :
482 : /* Per runtime debug hooks -- see jsprvtd.h and jsdbgapi.h. */
483 : JSDebugHooks debugHooks;
484 :
485 : /* If true, new compartments are initially in debug mode. */
486 : bool debugMode;
487 :
488 : /* If true, new scripts must be created with PC counter information. */
489 : bool profilingScripts;
490 :
491 : /* Had an out-of-memory error which did not populate an exception. */
492 : JSBool hadOutOfMemory;
493 :
494 : /*
495 : * Linked list of all js::Debugger objects. This may be accessed by the GC
496 : * thread, if any, or a thread that is in a request and holds gcLock.
497 : */
498 : JSCList debuggerList;
499 :
500 : /* Client opaque pointers */
501 : void *data;
502 :
503 : #ifdef JS_THREADSAFE
504 : /* These combine to interlock the GC and new requests. */
505 : PRLock *gcLock;
506 :
507 : js::GCHelperThread gcHelperThread;
508 : #endif /* JS_THREADSAFE */
509 :
510 : uint32_t debuggerMutations;
511 :
512 : const JSSecurityCallbacks *securityCallbacks;
513 : JSDestroyPrincipalsOp destroyPrincipals;
514 :
515 : /* Structured data callbacks are runtime-wide. */
516 : const JSStructuredCloneCallbacks *structuredCloneCallbacks;
517 :
518 : /* Call this to accumulate telemetry data. */
519 : JSAccumulateTelemetryDataCallback telemetryCallback;
520 :
521 : /*
522 : * The propertyRemovals counter is incremented for every JSObject::clear,
523 : * and for each JSObject::remove method call that frees a slot in the given
524 : * object. See js_NativeGet and js_NativeSet in jsobj.cpp.
525 : */
526 : int32_t propertyRemovals;
527 :
528 : /* Number localization, used by jsnum.c */
529 : const char *thousandsSeparator;
530 : const char *decimalSeparator;
531 : const char *numGrouping;
532 :
533 : /*
534 : * Weak references to lazily-created, well-known XML singletons.
535 : *
536 : * NB: Singleton objects must be carefully disconnected from the rest of
537 : * the object graph usually associated with a JSContext's global object,
538 : * including the set of standard class objects. See jsxml.c for details.
539 : */
540 : JSObject *anynameObject;
541 : JSObject *functionNamespaceObject;
542 :
543 : /*
544 : * Flag indicating that we are waiving any soft limits on the GC heap
545 : * because we want allocations to be infallible (except when we hit OOM).
546 : */
547 : bool waiveGCQuota;
548 :
549 : /*
550 : * The GSN cache is per thread since even multi-cx-per-thread embeddings
551 : * do not interleave js_GetSrcNote calls.
552 : */
553 : js::GSNCache gsnCache;
554 :
555 : /* Property cache for faster call/get/set invocation. */
556 : js::PropertyCache propertyCache;
557 :
558 : /* State used by jsdtoa.cpp. */
559 : DtoaState *dtoaState;
560 :
561 : /* List of currently pending operations on proxies. */
562 : js::PendingProxyOperation *pendingProxyOperation;
563 :
564 : js::ConservativeGCData conservativeGC;
565 :
566 : private:
567 : JSPrincipals *trustedPrincipals_;
568 : public:
569 21214 : void setTrustedPrincipals(JSPrincipals *p) { trustedPrincipals_ = p; }
570 9481962 : JSPrincipals *trustedPrincipals() const { return trustedPrincipals_; }
571 :
572 : /* Literal table maintained by jsatom.c functions. */
573 : JSAtomState atomState;
574 :
575 : /* Tables of strings that are pre-allocated in the atomsCompartment. */
576 : js::StaticStrings staticStrings;
577 :
578 : JSWrapObjectCallback wrapObjectCallback;
579 : JSPreWrapCallback preWrapObjectCallback;
580 : js::PreserveWrapperCallback preserveWrapperCallback;
581 :
582 : #ifdef DEBUG
583 : size_t noGCOrAllocationCheck;
584 : #endif
585 :
586 : /*
587 : * To ensure that cx->malloc does not cause a GC, we set this flag during
588 : * OOM reporting (in js_ReportOutOfMemory). If a GC is requested while
589 : * reporting the OOM, we ignore it.
590 : */
591 : int32_t inOOMReport;
592 :
593 : bool jitHardening;
594 :
595 : JSRuntime();
596 : ~JSRuntime();
597 :
598 : bool init(uint32_t maxbytes);
599 :
600 39820 : JSRuntime *thisFromCtor() { return this; }
601 :
602 : /*
603 : * Call the system malloc while checking for GC memory pressure and
604 : * reporting OOM error when cx is not null. We will not GC from here.
605 : */
606 29049063 : void* malloc_(size_t bytes, JSContext *cx = NULL) {
607 29049063 : updateMallocCounter(cx, bytes);
608 29049063 : void *p = ::js_malloc(bytes);
609 29049063 : return JS_LIKELY(!!p) ? p : onOutOfMemory(NULL, bytes, cx);
610 : }
611 :
612 : /*
613 : * Call the system calloc while checking for GC memory pressure and
614 : * reporting OOM error when cx is not null. We will not GC from here.
615 : */
616 2263540 : void* calloc_(size_t bytes, JSContext *cx = NULL) {
617 2263540 : updateMallocCounter(cx, bytes);
618 2263540 : void *p = ::js_calloc(bytes);
619 2263540 : return JS_LIKELY(!!p) ? p : onOutOfMemory(reinterpret_cast<void *>(1), bytes, cx);
620 : }
621 :
622 907136 : void* realloc_(void* p, size_t oldBytes, size_t newBytes, JSContext *cx = NULL) {
623 907136 : JS_ASSERT(oldBytes < newBytes);
624 907136 : updateMallocCounter(cx, newBytes - oldBytes);
625 907136 : void *p2 = ::js_realloc(p, newBytes);
626 907136 : return JS_LIKELY(!!p2) ? p2 : onOutOfMemory(p, newBytes, cx);
627 : }
628 :
629 274243 : void* realloc_(void* p, size_t bytes, JSContext *cx = NULL) {
630 : /*
631 : * For compatibility we do not account for realloc that increases
632 : * previously allocated memory.
633 : */
634 274243 : if (!p)
635 37 : updateMallocCounter(cx, bytes);
636 274243 : void *p2 = ::js_realloc(p, bytes);
637 274243 : return JS_LIKELY(!!p2) ? p2 : onOutOfMemory(p, bytes, cx);
638 : }
639 :
640 38033960 : inline void free_(void* p) {
641 : /* FIXME: Making this free in the background is buggy. Can it work? */
642 38033960 : js::Foreground::free_(p);
643 38033960 : }
644 :
645 435261 : JS_DECLARE_NEW_METHODS(malloc_, JS_ALWAYS_INLINE)
646 42287 : JS_DECLARE_DELETE_METHODS(free_, JS_ALWAYS_INLINE)
647 :
648 : bool isGCMallocLimitReached() const { return gcMallocBytes <= 0; }
649 :
650 71052 : void resetGCMallocBytes() { gcMallocBytes = ptrdiff_t(gcMaxMallocBytes); }
651 :
652 19960 : void setGCMaxMallocBytes(size_t value) {
653 : /*
654 : * For compatibility treat any value that exceeds PTRDIFF_T_MAX to
655 : * mean that value.
656 : */
657 19960 : gcMaxMallocBytes = (ptrdiff_t(value) >= 0) ? value : size_t(-1) >> 1;
658 19960 : resetGCMallocBytes();
659 19960 : }
660 :
661 : /*
662 : * Call this after allocating memory held by GC things, to update memory
663 : * pressure counters or report the OOM error if necessary. If oomError and
664 : * cx is not null the function also reports OOM error.
665 : *
666 : * The function must be called outside the GC lock and in case of OOM error
667 : * the caller must ensure that no deadlock possible during OOM reporting.
668 : */
669 : void updateMallocCounter(JSContext *cx, size_t nbytes);
670 :
671 : /*
672 : * The function must be called outside the GC lock.
673 : */
674 : JS_FRIEND_API(void) onTooMuchMalloc();
675 :
676 : /*
677 : * This should be called after system malloc/realloc returns NULL to try
678 : * to recove some memory or to report an error. Failures in malloc and
679 : * calloc are signaled by p == null and p == reinterpret_cast<void *>(1).
680 : * Other values of p mean a realloc failure.
681 : *
682 : * The function must be called outside the GC lock.
683 : */
684 : JS_FRIEND_API(void *) onOutOfMemory(void *p, size_t nbytes, JSContext *cx);
685 :
686 : void triggerOperationCallback();
687 :
688 : void setJitHardening(bool enabled);
689 1775528 : bool getJitHardening() const {
690 1775528 : return jitHardening;
691 : }
692 :
693 : void sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *normal, size_t *temporary,
694 : size_t *regexpCode, size_t *stackCommitted, size_t *gcMarker);
695 : };
696 :
697 : /* Common macros to access thread-local caches in JSRuntime. */
698 : #define JS_PROPERTY_CACHE(cx) (cx->runtime->propertyCache)
699 :
700 : #define JS_KEEP_ATOMS(rt) (rt)->gcKeepAtoms++;
701 : #define JS_UNKEEP_ATOMS(rt) (rt)->gcKeepAtoms--;
702 :
703 : #ifdef JS_ARGUMENT_FORMATTER_DEFINED
704 : /*
705 : * Linked list mapping format strings for JS_{Convert,Push}Arguments{,VA} to
706 : * formatter functions. Elements are sorted in non-increasing format string
707 : * length order.
708 : */
709 : struct JSArgumentFormatMap {
710 : const char *format;
711 : size_t length;
712 : JSArgumentFormatter formatter;
713 : JSArgumentFormatMap *next;
714 : };
715 : #endif
716 :
717 : namespace js {
718 :
719 : template <typename T> class Root;
720 : class CheckRoot;
721 :
722 : struct AutoResolving;
723 :
724 : static inline bool
725 972 : OptionsHasXML(uint32_t options)
726 : {
727 972 : return !!(options & JSOPTION_XML);
728 : }
729 :
730 : static inline bool
731 : OptionsSameVersionFlags(uint32_t self, uint32_t other)
732 : {
733 : static const uint32_t mask = JSOPTION_XML;
734 : return !((self & mask) ^ (other & mask));
735 : }
736 :
737 : /*
738 : * Flags accompany script version data so that a) dynamically created scripts
739 : * can inherit their caller's compile-time properties and b) scripts can be
740 : * appropriately compared in the eval cache across global option changes. An
741 : * example of the latter is enabling the top-level-anonymous-function-is-error
742 : * option: subsequent evals of the same, previously-valid script text may have
743 : * become invalid.
744 : */
745 : namespace VersionFlags {
746 : static const unsigned MASK = 0x0FFF; /* see JSVersion in jspubtd.h */
747 : static const unsigned HAS_XML = 0x1000; /* flag induced by XML option */
748 : static const unsigned FULL_MASK = 0x3FFF;
749 : }
750 :
751 : static inline JSVersion
752 7884730 : VersionNumber(JSVersion version)
753 : {
754 7884730 : return JSVersion(uint32_t(version) & VersionFlags::MASK);
755 : }
756 :
757 : static inline bool
758 5151897 : VersionHasXML(JSVersion version)
759 : {
760 5151897 : return !!(version & VersionFlags::HAS_XML);
761 : }
762 :
763 : /* @warning This is a distinct condition from having the XML flag set. */
764 : static inline bool
765 1880 : VersionShouldParseXML(JSVersion version)
766 : {
767 1880 : return VersionHasXML(version) || VersionNumber(version) >= JSVERSION_1_6;
768 : }
769 :
770 : static inline JSVersion
771 50870 : VersionExtractFlags(JSVersion version)
772 : {
773 50870 : return JSVersion(uint32_t(version) & ~VersionFlags::MASK);
774 : }
775 :
776 : static inline void
777 24833 : VersionCopyFlags(JSVersion *version, JSVersion from)
778 : {
779 24833 : *version = JSVersion(VersionNumber(*version) | VersionExtractFlags(from));
780 24833 : }
781 :
782 : static inline bool
783 26037 : VersionHasFlags(JSVersion version)
784 : {
785 26037 : return !!VersionExtractFlags(version);
786 : }
787 :
788 : static inline unsigned
789 5011016 : VersionFlagsToOptions(JSVersion version)
790 : {
791 5011016 : unsigned copts = VersionHasXML(version) ? JSOPTION_XML : 0;
792 5011016 : JS_ASSERT((copts & JSCOMPILEOPTION_MASK) == copts);
793 5011016 : return copts;
794 : }
795 :
796 : static inline JSVersion
797 968 : OptionFlagsToVersion(unsigned options, JSVersion version)
798 : {
799 968 : return VersionSetXML(version, OptionsHasXML(options));
800 : }
801 :
802 : static inline bool
803 26037 : VersionIsKnown(JSVersion version)
804 : {
805 26037 : return VersionNumber(version) != JSVERSION_UNKNOWN;
806 : }
807 :
808 : typedef HashSet<JSObject *,
809 : DefaultHasher<JSObject *>,
810 : SystemAllocPolicy> BusyArraysSet;
811 :
812 : } /* namespace js */
813 :
814 : struct JSContext : js::ContextFriendFields
815 : {
816 : explicit JSContext(JSRuntime *rt);
817 52462 : JSContext *thisDuringConstruction() { return this; }
818 : ~JSContext();
819 :
820 : /* JSRuntime contextList linkage. */
821 : JSCList link;
822 :
823 : private:
824 : /* See JSContext::findVersion. */
825 : JSVersion defaultVersion; /* script compilation version */
826 : JSVersion versionOverride; /* supercedes defaultVersion when valid */
827 : bool hasVersionOverride;
828 :
829 : /* Exception state -- the exception member is a GC root by definition. */
830 : JSBool throwing; /* is there a pending exception? */
831 : js::Value exception; /* most-recently-thrown exception */
832 :
833 : /* Per-context run options. */
834 : unsigned runOptions; /* see jsapi.h for JSOPTION_* */
835 :
836 : public:
837 : int32_t reportGranularity; /* see jsprobes.h */
838 :
839 : /* Locale specific callbacks for string conversion. */
840 : JSLocaleCallbacks *localeCallbacks;
841 :
842 : js::AutoResolving *resolvingList;
843 :
844 : /*
845 : * True if generating an error, to prevent runaway recursion.
846 : * NB: generatingError packs with throwing below.
847 : */
848 : bool generatingError;
849 :
850 : /* GC heap compartment. */
851 : JSCompartment *compartment;
852 :
853 : inline void setCompartment(JSCompartment *compartment);
854 :
855 : /* Current execution stack. */
856 : js::ContextStack stack;
857 :
858 : /* ContextStack convenience functions */
859 1856072004 : inline bool hasfp() const { return stack.hasfp(); }
860 1045535751 : inline js::StackFrame* fp() const { return stack.fp(); }
861 3625099 : inline js::StackFrame* maybefp() const { return stack.maybefp(); }
862 55876901 : inline js::FrameRegs& regs() const { return stack.regs(); }
863 63767098 : inline js::FrameRegs* maybeRegs() const { return stack.maybeRegs(); }
864 :
865 : /* Set cx->compartment based on the current scope chain. */
866 : void resetCompartment();
867 :
868 : /* Wrap cx->exception for the current compartment. */
869 : void wrapPendingException();
870 :
871 : private:
872 : /* Lazily initialized pool of maps used during parse/emit. */
873 : js::ParseMapPool *parseMapPool_;
874 :
875 : public:
876 : /* Top-level object and pointer to top stack frame's scope chain. */
877 : JSObject *globalObject;
878 :
879 : /* State for object and array toSource conversion. */
880 : JSSharpObjectMap sharpObjectMap;
881 : js::BusyArraysSet busyArrays;
882 :
883 : /* Argument formatter support for JS_{Convert,Push}Arguments{,VA}. */
884 : JSArgumentFormatMap *argumentFormatMap;
885 :
886 : /* Last message string and log file for debugging. */
887 : char *lastMessage;
888 :
889 : /* Per-context optional error reporter. */
890 : JSErrorReporter errorReporter;
891 :
892 : /* Branch callback. */
893 : JSOperationCallback operationCallback;
894 :
895 : /* Client opaque pointers. */
896 : void *data;
897 : void *data2;
898 :
899 : inline js::RegExpStatics *regExpStatics();
900 :
901 : public:
902 6872290 : js::ParseMapPool &parseMapPool() {
903 6872290 : JS_ASSERT(parseMapPool_);
904 6872290 : return *parseMapPool_;
905 : }
906 :
907 : inline bool ensureParseMapPool();
908 :
909 : /*
910 : * The default script compilation version can be set iff there is no code running.
911 : * This typically occurs via the JSAPI right after a context is constructed.
912 : */
913 : inline bool canSetDefaultVersion() const;
914 :
915 : /* Force a version for future script compilation. */
916 : inline void overrideVersion(JSVersion newVersion);
917 :
918 : /* Set the default script compilation version. */
919 73313 : void setDefaultVersion(JSVersion version) {
920 73313 : defaultVersion = version;
921 73313 : }
922 :
923 47629 : void clearVersionOverride() { hasVersionOverride = false; }
924 23786 : JSVersion getDefaultVersion() const { return defaultVersion; }
925 267388 : bool isVersionOverridden() const { return hasVersionOverride; }
926 :
927 : JSVersion getVersionOverride() const {
928 : JS_ASSERT(isVersionOverridden());
929 : return versionOverride;
930 : }
931 :
932 : /*
933 : * Set the default version if possible; otherwise, force the version.
934 : * Return whether an override occurred.
935 : */
936 : inline bool maybeOverrideVersion(JSVersion newVersion);
937 :
938 : /*
939 : * If there is no code on the stack, turn the override version into the
940 : * default version.
941 : */
942 243593 : void maybeMigrateVersionOverride() {
943 243593 : JS_ASSERT(stack.empty());
944 243593 : if (JS_UNLIKELY(isVersionOverridden())) {
945 22 : defaultVersion = versionOverride;
946 22 : clearVersionOverride();
947 : }
948 243593 : }
949 :
950 : /*
951 : * Return:
952 : * - The override version, if there is an override version.
953 : * - The newest scripted frame's version, if there is such a frame.
954 : * - The default version.
955 : *
956 : * Note: if this ever shows up in a profile, just add caching!
957 : */
958 : inline JSVersion findVersion() const;
959 :
960 1329240 : void setRunOptions(unsigned ropts) {
961 1329240 : JS_ASSERT((ropts & JSRUNOPTION_MASK) == ropts);
962 1329240 : runOptions = ropts;
963 1329240 : }
964 :
965 : /* Note: may override the version. */
966 : inline void setCompileOptions(unsigned newcopts);
967 :
968 3609000 : unsigned getRunOptions() const { return runOptions; }
969 : inline unsigned getCompileOptions() const;
970 : inline unsigned allOptions() const;
971 :
972 42050102 : bool hasRunOption(unsigned ropt) const {
973 42050102 : JS_ASSERT((ropt & JSRUNOPTION_MASK) == ropt);
974 42050102 : return !!(runOptions & ropt);
975 : }
976 :
977 8873992 : bool hasStrictOption() const { return hasRunOption(JSOPTION_STRICT); }
978 7337 : bool hasWErrorOption() const { return hasRunOption(JSOPTION_WERROR); }
979 637462 : bool hasAtLineOption() const { return hasRunOption(JSOPTION_ATLINE); }
980 :
981 71322898 : js::LifoAlloc &tempLifoAlloc() { return runtime->tempLifoAlloc; }
982 : inline js::LifoAlloc &typeLifoAlloc();
983 :
984 : #ifdef JS_THREADSAFE
985 : unsigned outstandingRequests;/* number of JS_BeginRequest calls
986 : without the corresponding
987 : JS_EndRequest. */
988 : #endif
989 :
990 :
991 : #ifdef JSGC_ROOT_ANALYSIS
992 :
993 : /*
994 : * Stack allocated GC roots for stack GC heap pointers, which may be
995 : * overwritten if moved during a GC.
996 : */
997 : js::Root<js::gc::Cell*> *thingGCRooters[js::THING_ROOT_COUNT];
998 :
999 : #ifdef DEBUG
1000 : /*
1001 : * Stack allocated list of stack locations which hold non-relocatable
1002 : * GC heap pointers (where the target is rooted somewhere else) or integer
1003 : * values which may be confused for GC heap pointers. These are used to
1004 : * suppress false positives which occur when a rooting analysis treats the
1005 : * location as holding a relocatable pointer, but have no other effect on
1006 : * GC behavior.
1007 : */
1008 : js::CheckRoot *checkGCRooters;
1009 : #endif
1010 :
1011 : #endif /* JSGC_ROOT_ANALYSIS */
1012 :
1013 : /* Stored here to avoid passing it around as a parameter. */
1014 : unsigned resolveFlags;
1015 :
1016 : /* Random number generator state, used by jsmath.cpp. */
1017 : int64_t rngSeed;
1018 :
1019 : /* Location to stash the iteration value between JSOP_MOREITER and JSOP_ITERNEXT. */
1020 : js::Value iterValue;
1021 :
1022 : #ifdef JS_METHODJIT
1023 : bool methodJitEnabled;
1024 :
1025 : inline js::mjit::JaegerCompartment *jaegerCompartment();
1026 : #endif
1027 :
1028 : bool inferenceEnabled;
1029 :
1030 -1378315075 : bool typeInferenceEnabled() { return inferenceEnabled; }
1031 :
1032 : /* Caller must be holding runtime->gcLock. */
1033 : void updateJITEnabled();
1034 :
1035 : #ifdef MOZ_TRACE_JSCALLS
1036 : /* Function entry/exit debugging callback. */
1037 : JSFunctionCallback functionCallback;
1038 :
1039 : void doFunctionCallback(const JSFunction *fun,
1040 : const JSScript *scr,
1041 : int entering) const
1042 : {
1043 : if (functionCallback)
1044 : functionCallback(fun, scr, this, entering);
1045 : }
1046 : #endif
1047 :
1048 : DSTOffsetCache dstOffsetCache;
1049 :
1050 : /* List of currently active non-escaping enumerators (for-in). */
1051 : JSObject *enumerators;
1052 :
1053 : private:
1054 : /*
1055 : * To go from a live generator frame (on the stack) to its generator object
1056 : * (see comment js_FloatingFrameIfGenerator), we maintain a stack of active
1057 : * generators, pushing and popping when entering and leaving generator
1058 : * frames, respectively.
1059 : */
1060 : js::Vector<JSGenerator *, 2, js::SystemAllocPolicy> genStack;
1061 :
1062 : public:
1063 : /* Return the generator object for the given generator frame. */
1064 : JSGenerator *generatorFor(js::StackFrame *fp) const;
1065 :
1066 : /* Early OOM-check. */
1067 : inline bool ensureGeneratorStackSpace();
1068 :
1069 30834 : bool enterGenerator(JSGenerator *gen) {
1070 30834 : return genStack.append(gen);
1071 : }
1072 :
1073 30834 : void leaveGenerator(JSGenerator *gen) {
1074 30834 : JS_ASSERT(genStack.back() == gen);
1075 30834 : genStack.popBack();
1076 30834 : }
1077 :
1078 : #ifdef JS_THREADSAFE
1079 : /*
1080 : * When non-null JSContext::free_ delegates the job to the background
1081 : * thread.
1082 : */
1083 : js::GCHelperThread *gcBackgroundFree;
1084 : #endif
1085 :
1086 28535192 : inline void* malloc_(size_t bytes) {
1087 28535192 : return runtime->malloc_(bytes, this);
1088 : }
1089 :
1090 : inline void* mallocNoReport(size_t bytes) {
1091 : JS_ASSERT(bytes != 0);
1092 : return runtime->malloc_(bytes, NULL);
1093 : }
1094 :
1095 1911865 : inline void* calloc_(size_t bytes) {
1096 1911865 : JS_ASSERT(bytes != 0);
1097 1911865 : return runtime->calloc_(bytes, this);
1098 : }
1099 :
1100 274243 : inline void* realloc_(void* p, size_t bytes) {
1101 274243 : return runtime->realloc_(p, bytes, this);
1102 : }
1103 :
1104 907136 : inline void* realloc_(void* p, size_t oldBytes, size_t newBytes) {
1105 907136 : return runtime->realloc_(p, oldBytes, newBytes, this);
1106 : }
1107 :
1108 25240467 : inline void free_(void* p) {
1109 : #ifdef JS_THREADSAFE
1110 25240467 : if (gcBackgroundFree) {
1111 2829189 : gcBackgroundFree->freeLater(p);
1112 2829189 : return;
1113 : }
1114 : #endif
1115 22411278 : runtime->free_(p);
1116 : }
1117 :
1118 1727382 : JS_DECLARE_NEW_METHODS(malloc_, inline)
1119 2896400 : JS_DECLARE_DELETE_METHODS(free_, inline)
1120 :
1121 : void purge();
1122 :
1123 : /* For DEBUG. */
1124 : inline void assertValidStackDepth(unsigned depth);
1125 :
1126 65510927 : bool isExceptionPending() {
1127 65510927 : return throwing;
1128 : }
1129 :
1130 2256122 : js::Value getPendingException() {
1131 2256122 : JS_ASSERT(throwing);
1132 2256122 : return exception;
1133 : }
1134 :
1135 : void setPendingException(js::Value v);
1136 :
1137 2901326 : void clearPendingException() {
1138 2901326 : this->throwing = false;
1139 2901326 : this->exception.setUndefined();
1140 2901326 : }
1141 :
1142 : /*
1143 : * Count of currently active compilations.
1144 : * When there are compilations active for the context, the GC must not
1145 : * purge the ParseMapPool.
1146 : */
1147 : unsigned activeCompilations;
1148 :
1149 : #ifdef DEBUG
1150 : /*
1151 : * Controls whether a quadratic-complexity assertion is performed during
1152 : * stack iteration, defaults to true.
1153 : */
1154 : bool stackIterAssertionEnabled;
1155 : #endif
1156 :
1157 : /*
1158 : * See JS_SetTrustedPrincipals in jsapi.h.
1159 : * Note: !cx->compartment is treated as trusted.
1160 : */
1161 : bool runningWithTrustedPrincipals() const;
1162 :
1163 : JS_FRIEND_API(size_t) sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const;
1164 :
1165 198404 : static inline JSContext *fromLinkField(JSCList *link) {
1166 198404 : JS_ASSERT(link);
1167 198404 : return reinterpret_cast<JSContext *>(uintptr_t(link) - offsetof(JSContext, link));
1168 : }
1169 :
1170 : void mark(JSTracer *trc);
1171 :
1172 : private:
1173 : /*
1174 : * The allocation code calls the function to indicate either OOM failure
1175 : * when p is null or that a memory pressure counter has reached some
1176 : * threshold when p is not null. The function takes the pointer and not
1177 : * a boolean flag to minimize the amount of code in its inlined callers.
1178 : */
1179 : JS_FRIEND_API(void) checkMallocGCPressure(void *p);
1180 : }; /* struct JSContext */
1181 :
1182 : namespace js {
1183 :
1184 : struct AutoResolving {
1185 : public:
1186 : enum Kind {
1187 : LOOKUP,
1188 : WATCH
1189 : };
1190 :
1191 10001934 : AutoResolving(JSContext *cx, JSObject *obj, jsid id, Kind kind = LOOKUP
1192 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
1193 10001934 : : context(cx), object(obj), id(id), kind(kind), link(cx->resolvingList)
1194 : {
1195 10001934 : JS_GUARD_OBJECT_NOTIFIER_INIT;
1196 10001934 : JS_ASSERT(obj);
1197 10001934 : cx->resolvingList = this;
1198 10001934 : }
1199 :
1200 20003868 : ~AutoResolving() {
1201 10001934 : JS_ASSERT(context->resolvingList == this);
1202 10001934 : context->resolvingList = link;
1203 10001934 : }
1204 :
1205 10001934 : bool alreadyStarted() const {
1206 10001934 : return link && alreadyStartedSlow();
1207 : }
1208 :
1209 : private:
1210 : bool alreadyStartedSlow() const;
1211 :
1212 : JSContext *const context;
1213 : JSObject *const object;
1214 : jsid const id;
1215 : Kind const kind;
1216 : AutoResolving *const link;
1217 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
1218 : };
1219 :
1220 : #ifdef JS_HAS_XML_SUPPORT
1221 6733 : class AutoXMLRooter : private AutoGCRooter {
1222 : public:
1223 6733 : AutoXMLRooter(JSContext *cx, JSXML *xml
1224 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
1225 6733 : : AutoGCRooter(cx, XML), xml(xml)
1226 : {
1227 6733 : JS_GUARD_OBJECT_NOTIFIER_INIT;
1228 6733 : JS_ASSERT(xml);
1229 6733 : }
1230 :
1231 : friend void AutoGCRooter::trace(JSTracer *trc);
1232 :
1233 : private:
1234 : JSXML * const xml;
1235 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
1236 : };
1237 : #endif /* JS_HAS_XML_SUPPORT */
1238 :
1239 : #ifdef JS_THREADSAFE
1240 : # define JS_LOCK_GC(rt) PR_Lock((rt)->gcLock)
1241 : # define JS_UNLOCK_GC(rt) PR_Unlock((rt)->gcLock)
1242 : #else
1243 : # define JS_LOCK_GC(rt)
1244 : # define JS_UNLOCK_GC(rt)
1245 : #endif
1246 :
1247 : class AutoLockGC
1248 : {
1249 : public:
1250 4810912 : explicit AutoLockGC(JSRuntime *rt = NULL
1251 : MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
1252 4810912 : : runtime(rt)
1253 : {
1254 4810885 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
1255 : // Avoid MSVC warning C4390 for non-threadsafe builds.
1256 : #ifdef JS_THREADSAFE
1257 4810870 : if (rt)
1258 403673 : JS_LOCK_GC(rt);
1259 : #endif
1260 4810878 : }
1261 :
1262 4810925 : ~AutoLockGC()
1263 4810924 : {
1264 : #ifdef JS_THREADSAFE
1265 4810925 : if (runtime)
1266 2910581 : JS_UNLOCK_GC(runtime);
1267 : #endif
1268 4810929 : }
1269 :
1270 2047018 : bool locked() const {
1271 2047018 : return !!runtime;
1272 : }
1273 :
1274 2506901 : void lock(JSRuntime *rt) {
1275 2506901 : JS_ASSERT(rt);
1276 2506901 : JS_ASSERT(!runtime);
1277 2506901 : runtime = rt;
1278 2506901 : JS_LOCK_GC(rt);
1279 2506902 : }
1280 :
1281 : private:
1282 : JSRuntime *runtime;
1283 : MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
1284 : };
1285 :
1286 : class AutoUnlockGC {
1287 : private:
1288 : JSRuntime *rt;
1289 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
1290 :
1291 : public:
1292 92750 : explicit AutoUnlockGC(JSRuntime *rt
1293 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
1294 92750 : : rt(rt)
1295 : {
1296 92750 : JS_GUARD_OBJECT_NOTIFIER_INIT;
1297 92750 : JS_UNLOCK_GC(rt);
1298 92750 : }
1299 92750 : ~AutoUnlockGC() { JS_LOCK_GC(rt); }
1300 : };
1301 :
1302 : class AutoKeepAtoms {
1303 : JSRuntime *rt;
1304 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
1305 :
1306 : public:
1307 353716 : explicit AutoKeepAtoms(JSRuntime *rt
1308 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
1309 353716 : : rt(rt)
1310 : {
1311 353716 : JS_GUARD_OBJECT_NOTIFIER_INIT;
1312 353716 : JS_KEEP_ATOMS(rt);
1313 353716 : }
1314 353716 : ~AutoKeepAtoms() { JS_UNKEEP_ATOMS(rt); }
1315 : };
1316 :
1317 : class AutoReleasePtr {
1318 : JSContext *cx;
1319 : void *ptr;
1320 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
1321 :
1322 : AutoReleasePtr(const AutoReleasePtr &other) MOZ_DELETE;
1323 : AutoReleasePtr operator=(const AutoReleasePtr &other) MOZ_DELETE;
1324 :
1325 : public:
1326 4085 : explicit AutoReleasePtr(JSContext *cx, void *ptr
1327 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
1328 4085 : : cx(cx), ptr(ptr)
1329 : {
1330 4085 : JS_GUARD_OBJECT_NOTIFIER_INIT;
1331 4085 : }
1332 4085 : ~AutoReleasePtr() { cx->free_(ptr); }
1333 : };
1334 :
1335 : /*
1336 : * FIXME: bug 602774: cleaner API for AutoReleaseNullablePtr
1337 : */
1338 : class AutoReleaseNullablePtr {
1339 : JSContext *cx;
1340 : void *ptr;
1341 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
1342 :
1343 : AutoReleaseNullablePtr(const AutoReleaseNullablePtr &other) MOZ_DELETE;
1344 : AutoReleaseNullablePtr operator=(const AutoReleaseNullablePtr &other) MOZ_DELETE;
1345 :
1346 : public:
1347 2278 : explicit AutoReleaseNullablePtr(JSContext *cx, void *ptr
1348 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
1349 2278 : : cx(cx), ptr(ptr)
1350 : {
1351 2278 : JS_GUARD_OBJECT_NOTIFIER_INIT;
1352 2278 : }
1353 0 : void reset(void *ptr2) {
1354 0 : if (ptr)
1355 0 : cx->free_(ptr);
1356 0 : ptr = ptr2;
1357 0 : }
1358 2278 : ~AutoReleaseNullablePtr() { if (ptr) cx->free_(ptr); }
1359 : };
1360 :
1361 : } /* namespace js */
1362 :
1363 : class JSAutoResolveFlags
1364 : {
1365 : public:
1366 53651317 : JSAutoResolveFlags(JSContext *cx, unsigned flags
1367 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
1368 53651317 : : mContext(cx), mSaved(cx->resolveFlags)
1369 : {
1370 53651317 : JS_GUARD_OBJECT_NOTIFIER_INIT;
1371 53651317 : cx->resolveFlags = flags;
1372 53651317 : }
1373 :
1374 53651317 : ~JSAutoResolveFlags() { mContext->resolveFlags = mSaved; }
1375 :
1376 : private:
1377 : JSContext *mContext;
1378 : unsigned mSaved;
1379 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
1380 : };
1381 :
1382 : namespace js {
1383 :
1384 : /*
1385 : * Enumerate all contexts in a runtime.
1386 : */
1387 : class ContextIter {
1388 : JSCList *begin;
1389 : JSCList *end;
1390 :
1391 : public:
1392 118264 : explicit ContextIter(JSRuntime *rt) {
1393 118264 : end = &rt->contextList;
1394 118264 : begin = end->next;
1395 118264 : }
1396 :
1397 479794 : bool done() const {
1398 479794 : return begin == end;
1399 : }
1400 :
1401 117454 : void next() {
1402 117454 : JS_ASSERT(!done());
1403 117454 : begin = begin->next;
1404 117454 : }
1405 :
1406 126622 : JSContext *get() const {
1407 126622 : JS_ASSERT(!done());
1408 126622 : return JSContext::fromLinkField(begin);
1409 : }
1410 :
1411 : operator JSContext *() const {
1412 : return get();
1413 : }
1414 :
1415 126622 : JSContext *operator ->() const {
1416 126622 : return get();
1417 : }
1418 : };
1419 :
1420 : } /* namespace js */
1421 :
1422 : /*
1423 : * Create and destroy functions for JSContext, which is manually allocated
1424 : * and exclusively owned.
1425 : */
1426 : extern JSContext *
1427 : js_NewContext(JSRuntime *rt, size_t stackChunkSize);
1428 :
1429 : typedef enum JSDestroyContextMode {
1430 : JSDCM_NO_GC,
1431 : JSDCM_MAYBE_GC,
1432 : JSDCM_FORCE_GC,
1433 : JSDCM_NEW_FAILED
1434 : } JSDestroyContextMode;
1435 :
1436 : extern void
1437 : js_DestroyContext(JSContext *cx, JSDestroyContextMode mode);
1438 :
1439 : #ifdef va_start
1440 : extern JSBool
1441 : js_ReportErrorVA(JSContext *cx, unsigned flags, const char *format, va_list ap);
1442 :
1443 : extern JSBool
1444 : js_ReportErrorNumberVA(JSContext *cx, unsigned flags, JSErrorCallback callback,
1445 : void *userRef, const unsigned errorNumber,
1446 : JSBool charArgs, va_list ap);
1447 :
1448 : extern JSBool
1449 : js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
1450 : void *userRef, const unsigned errorNumber,
1451 : char **message, JSErrorReport *reportp,
1452 : bool charArgs, va_list ap);
1453 : #endif
1454 :
1455 : namespace js {
1456 :
1457 : /* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */
1458 : extern void
1459 : ReportUsageError(JSContext *cx, JSObject *callee, const char *msg);
1460 :
1461 : } /* namespace js */
1462 :
1463 : extern void
1464 : js_ReportOutOfMemory(JSContext *cx);
1465 :
1466 : extern JS_FRIEND_API(void)
1467 : js_ReportAllocationOverflow(JSContext *cx);
1468 :
1469 : /*
1470 : * Report an exception using a previously composed JSErrorReport.
1471 : * XXXbe remove from "friend" API
1472 : */
1473 : extern JS_FRIEND_API(void)
1474 : js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *report);
1475 :
1476 : extern void
1477 : js_ReportIsNotDefined(JSContext *cx, const char *name);
1478 :
1479 : /*
1480 : * Report an attempt to access the property of a null or undefined value (v).
1481 : */
1482 : extern JSBool
1483 : js_ReportIsNullOrUndefined(JSContext *cx, int spindex, const js::Value &v,
1484 : JSString *fallback);
1485 :
1486 : extern void
1487 : js_ReportMissingArg(JSContext *cx, const js::Value &v, unsigned arg);
1488 :
1489 : /*
1490 : * Report error using js_DecompileValueGenerator(cx, spindex, v, fallback) as
1491 : * the first argument for the error message. If the error message has less
1492 : * then 3 arguments, use null for arg1 or arg2.
1493 : */
1494 : extern JSBool
1495 : js_ReportValueErrorFlags(JSContext *cx, unsigned flags, const unsigned errorNumber,
1496 : int spindex, const js::Value &v, JSString *fallback,
1497 : const char *arg1, const char *arg2);
1498 :
1499 : #define js_ReportValueError(cx,errorNumber,spindex,v,fallback) \
1500 : ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \
1501 : spindex, v, fallback, NULL, NULL))
1502 :
1503 : #define js_ReportValueError2(cx,errorNumber,spindex,v,fallback,arg1) \
1504 : ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \
1505 : spindex, v, fallback, arg1, NULL))
1506 :
1507 : #define js_ReportValueError3(cx,errorNumber,spindex,v,fallback,arg1,arg2) \
1508 : ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \
1509 : spindex, v, fallback, arg1, arg2))
1510 :
1511 : extern JSErrorFormatString js_ErrorFormatString[JSErr_Limit];
1512 :
1513 : #ifdef JS_THREADSAFE
1514 : # define JS_ASSERT_REQUEST_DEPTH(cx) JS_ASSERT((cx)->runtime->requestDepth >= 1)
1515 : #else
1516 : # define JS_ASSERT_REQUEST_DEPTH(cx) ((void) 0)
1517 : #endif
1518 :
1519 : /*
1520 : * If the operation callback flag was set, call the operation callback.
1521 : * This macro can run the full GC. Return true if it is OK to continue and
1522 : * false otherwise.
1523 : */
1524 : #define JS_CHECK_OPERATION_LIMIT(cx) \
1525 : (JS_ASSERT_REQUEST_DEPTH(cx), \
1526 : (!cx->runtime->interrupt || js_InvokeOperationCallback(cx)))
1527 :
1528 : /*
1529 : * Invoke the operation callback and return false if the current execution
1530 : * is to be terminated.
1531 : */
1532 : extern JSBool
1533 : js_InvokeOperationCallback(JSContext *cx);
1534 :
1535 : extern JSBool
1536 : js_HandleExecutionInterrupt(JSContext *cx);
1537 :
1538 : extern jsbytecode*
1539 : js_GetCurrentBytecodePC(JSContext* cx);
1540 :
1541 : extern JSScript *
1542 : js_GetCurrentScript(JSContext* cx);
1543 :
1544 : namespace js {
1545 :
1546 : #ifdef JS_METHODJIT
1547 : namespace mjit {
1548 : void ExpandInlineFrames(JSCompartment *compartment);
1549 : }
1550 : #endif
1551 :
1552 : } /* namespace js */
1553 :
1554 : /* How much expansion of inlined frames to do when inspecting the stack. */
1555 : enum FrameExpandKind {
1556 : FRAME_EXPAND_NONE = 0,
1557 : FRAME_EXPAND_ALL = 1
1558 : };
1559 :
1560 : namespace js {
1561 :
1562 : /************************************************************************/
1563 :
1564 : static JS_ALWAYS_INLINE void
1565 6101043 : MakeRangeGCSafe(Value *vec, size_t len)
1566 : {
1567 6101043 : PodZero(vec, len);
1568 6101043 : }
1569 :
1570 : static JS_ALWAYS_INLINE void
1571 : MakeRangeGCSafe(Value *beg, Value *end)
1572 : {
1573 : PodZero(beg, end - beg);
1574 : }
1575 :
1576 : static JS_ALWAYS_INLINE void
1577 : MakeRangeGCSafe(jsid *beg, jsid *end)
1578 : {
1579 : for (jsid *id = beg; id != end; ++id)
1580 : *id = INT_TO_JSID(0);
1581 : }
1582 :
1583 : static JS_ALWAYS_INLINE void
1584 : MakeRangeGCSafe(jsid *vec, size_t len)
1585 : {
1586 : MakeRangeGCSafe(vec, vec + len);
1587 : }
1588 :
1589 : static JS_ALWAYS_INLINE void
1590 : MakeRangeGCSafe(const Shape **beg, const Shape **end)
1591 : {
1592 : PodZero(beg, end - beg);
1593 : }
1594 :
1595 : static JS_ALWAYS_INLINE void
1596 : MakeRangeGCSafe(const Shape **vec, size_t len)
1597 : {
1598 : PodZero(vec, len);
1599 : }
1600 :
1601 : static JS_ALWAYS_INLINE void
1602 30149853 : SetValueRangeToUndefined(Value *beg, Value *end)
1603 : {
1604 57824728 : for (Value *v = beg; v != end; ++v)
1605 27674875 : v->setUndefined();
1606 30149853 : }
1607 :
1608 : static JS_ALWAYS_INLINE void
1609 29593882 : SetValueRangeToUndefined(Value *vec, size_t len)
1610 : {
1611 29593882 : SetValueRangeToUndefined(vec, vec + len);
1612 29593882 : }
1613 :
1614 : static JS_ALWAYS_INLINE void
1615 : SetValueRangeToNull(Value *beg, Value *end)
1616 : {
1617 : for (Value *v = beg; v != end; ++v)
1618 : v->setNull();
1619 : }
1620 :
1621 : static JS_ALWAYS_INLINE void
1622 : SetValueRangeToNull(Value *vec, size_t len)
1623 : {
1624 : SetValueRangeToNull(vec, vec + len);
1625 : }
1626 :
1627 : class AutoObjectVector : public AutoVectorRooter<JSObject *>
1628 33844 : {
1629 : public:
1630 33844 : explicit AutoObjectVector(JSContext *cx
1631 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
1632 33844 : : AutoVectorRooter<JSObject *>(cx, OBJVECTOR)
1633 : {
1634 33844 : JS_GUARD_OBJECT_NOTIFIER_INIT;
1635 33844 : }
1636 :
1637 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
1638 : };
1639 :
1640 : class AutoShapeVector : public AutoVectorRooter<const Shape *>
1641 1456589 : {
1642 : public:
1643 1456589 : explicit AutoShapeVector(JSContext *cx
1644 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
1645 1456589 : : AutoVectorRooter<const Shape *>(cx, SHAPEVECTOR)
1646 : {
1647 1456589 : JS_GUARD_OBJECT_NOTIFIER_INIT;
1648 1456589 : }
1649 :
1650 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
1651 : };
1652 :
1653 : class AutoValueArray : public AutoGCRooter
1654 10038 : {
1655 : js::Value *start_;
1656 : unsigned length_;
1657 :
1658 : public:
1659 10038 : AutoValueArray(JSContext *cx, js::Value *start, unsigned length
1660 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
1661 10038 : : AutoGCRooter(cx, VALARRAY), start_(start), length_(length)
1662 : {
1663 10038 : JS_GUARD_OBJECT_NOTIFIER_INIT;
1664 10038 : }
1665 :
1666 0 : Value *start() { return start_; }
1667 0 : unsigned length() const { return length_; }
1668 :
1669 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
1670 : };
1671 :
1672 : /*
1673 : * Allocation policy that uses JSRuntime::malloc_ and friends, so that
1674 : * memory pressure is properly accounted for. This is suitable for
1675 : * long-lived objects owned by the JSRuntime.
1676 : *
1677 : * Since it doesn't hold a JSContext (those may not live long enough), it
1678 : * can't report out-of-memory conditions itself; the caller must check for
1679 : * OOM and take the appropriate action.
1680 : *
1681 : * FIXME bug 647103 - replace these *AllocPolicy names.
1682 : */
1683 : class RuntimeAllocPolicy
1684 : {
1685 : JSRuntime *const runtime;
1686 :
1687 : public:
1688 47052 : RuntimeAllocPolicy(JSRuntime *rt) : runtime(rt) {}
1689 17050 : RuntimeAllocPolicy(JSContext *cx) : runtime(cx->runtime) {}
1690 78610 : void *malloc_(size_t bytes) { return runtime->malloc_(bytes); }
1691 : void *realloc_(void *p, size_t bytes) { return runtime->realloc_(p, bytes); }
1692 78605 : void free_(void *p) { runtime->free_(p); }
1693 0 : void reportAllocOverflow() const {}
1694 : };
1695 :
1696 : /*
1697 : * FIXME bug 647103 - replace these *AllocPolicy names.
1698 : */
1699 : class ContextAllocPolicy
1700 : {
1701 : JSContext *const cx;
1702 :
1703 : public:
1704 860701 : ContextAllocPolicy(JSContext *cx) : cx(cx) {}
1705 7662743 : JSContext *context() const { return cx; }
1706 272156 : void *malloc_(size_t bytes) { return cx->malloc_(bytes); }
1707 79350 : void *realloc_(void *p, size_t oldBytes, size_t bytes) { return cx->realloc_(p, oldBytes, bytes); }
1708 549 : void free_(void *p) { cx->free_(p); }
1709 0 : void reportAllocOverflow() const { js_ReportAllocationOverflow(cx); }
1710 : };
1711 :
1712 : } /* namespace js */
1713 :
1714 : #ifdef _MSC_VER
1715 : #pragma warning(pop)
1716 : #pragma warning(pop)
1717 : #endif
1718 :
1719 : #endif /* jscntxt_h___ */
|