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