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 |
#ifndef jscntxt_h___ |
42 |
#define jscntxt_h___ |
43 |
/* |
44 |
* JS execution context. |
45 |
*/ |
46 |
#include "jsarena.h" /* Added by JSIFY */ |
47 |
#include "jsclist.h" |
48 |
#include "jslong.h" |
49 |
#include "jsatom.h" |
50 |
#include "jsversion.h" |
51 |
#include "jsdhash.h" |
52 |
#include "jsgc.h" |
53 |
#include "jsinterp.h" |
54 |
#include "jsobj.h" |
55 |
#include "jsprvtd.h" |
56 |
#include "jspubtd.h" |
57 |
#include "jsregexp.h" |
58 |
#include "jsutil.h" |
59 |
#include "jsarray.h" |
60 |
#include "jstask.h" |
61 |
|
62 |
/* |
63 |
* js_GetSrcNote cache to avoid O(n^2) growth in finding a source note for a |
64 |
* given pc in a script. We use the script->code pointer to tag the cache, |
65 |
* instead of the script address itself, so that source notes are always found |
66 |
* by offset from the bytecode with which they were generated. |
67 |
*/ |
68 |
typedef struct JSGSNCache { |
69 |
jsbytecode *code; |
70 |
JSDHashTable table; |
71 |
#ifdef JS_GSNMETER |
72 |
uint32 hits; |
73 |
uint32 misses; |
74 |
uint32 fills; |
75 |
uint32 purges; |
76 |
# define GSN_CACHE_METER(cache,cnt) (++(cache)->cnt) |
77 |
#else |
78 |
# define GSN_CACHE_METER(cache,cnt) /* nothing */ |
79 |
#endif |
80 |
} JSGSNCache; |
81 |
|
82 |
#define js_FinishGSNCache(cache) js_PurgeGSNCache(cache) |
83 |
|
84 |
extern void |
85 |
js_PurgeGSNCache(JSGSNCache *cache); |
86 |
|
87 |
/* These helper macros take a cx as parameter and operate on its GSN cache. */ |
88 |
#define JS_PURGE_GSN_CACHE(cx) js_PurgeGSNCache(&JS_GSN_CACHE(cx)) |
89 |
#define JS_METER_GSN_CACHE(cx,cnt) GSN_CACHE_METER(&JS_GSN_CACHE(cx), cnt) |
90 |
|
91 |
typedef struct InterpState InterpState; |
92 |
typedef struct VMSideExit VMSideExit; |
93 |
|
94 |
#ifdef __cplusplus |
95 |
namespace nanojit { |
96 |
class Assembler; |
97 |
class CodeAlloc; |
98 |
class Fragment; |
99 |
class LirBuffer; |
100 |
#ifdef DEBUG |
101 |
class LabelMap; |
102 |
#endif |
103 |
extern "C++" { |
104 |
template<typename K> class DefaultHash; |
105 |
template<typename K, typename V, typename H> class HashMap; |
106 |
template<typename T> class Seq; |
107 |
} |
108 |
} |
109 |
#if defined(JS_JIT_SPEW) || defined(DEBUG) |
110 |
struct FragPI; |
111 |
typedef nanojit::HashMap<uint32, FragPI, nanojit::DefaultHash<uint32> > FragStatsMap; |
112 |
#endif |
113 |
class TraceRecorder; |
114 |
class VMAllocator; |
115 |
extern "C++" { template<typename T> class Queue; } |
116 |
typedef Queue<uint16> SlotList; |
117 |
|
118 |
# define CLS(T) T* |
119 |
#else |
120 |
# define CLS(T) void* |
121 |
#endif |
122 |
|
123 |
#define FRAGMENT_TABLE_SIZE 512 |
124 |
struct VMFragment; |
125 |
|
126 |
#ifdef __cplusplus |
127 |
struct REHashKey; |
128 |
struct REHashFn; |
129 |
typedef nanojit::HashMap<REHashKey, nanojit::Fragment*, REHashFn> REHashMap; |
130 |
#endif |
131 |
|
132 |
#define MONITOR_N_GLOBAL_STATES 4 |
133 |
struct GlobalState { |
134 |
JSObject* globalObj; |
135 |
uint32 globalShape; |
136 |
CLS(SlotList) globalSlots; |
137 |
}; |
138 |
|
139 |
/* |
140 |
* Trace monitor. Every JSThread (if JS_THREADSAFE) or JSRuntime (if not |
141 |
* JS_THREADSAFE) has an associated trace monitor that keeps track of loop |
142 |
* frequencies for all JavaScript code loaded into that runtime. |
143 |
*/ |
144 |
struct JSTraceMonitor { |
145 |
/* |
146 |
* The context currently executing JIT-compiled code on this thread, or |
147 |
* NULL if none. Among other things, this can in certain cases prevent |
148 |
* last-ditch GC and suppress calls to JS_ReportOutOfMemory. |
149 |
* |
150 |
* !tracecx && !recorder: not on trace |
151 |
* !tracecx && recorder: recording |
152 |
* tracecx && !recorder: executing a trace |
153 |
* tracecx && recorder: executing inner loop, recording outer loop |
154 |
*/ |
155 |
JSContext *tracecx; |
156 |
|
157 |
CLS(VMAllocator) dataAlloc; /* A chunk allocator for LIR. */ |
158 |
CLS(VMAllocator) tempAlloc; /* A temporary chunk allocator. */ |
159 |
CLS(nanojit::CodeAlloc) codeAlloc; /* An allocator for native code. */ |
160 |
CLS(nanojit::Assembler) assembler; |
161 |
CLS(nanojit::LirBuffer) lirbuf; |
162 |
CLS(nanojit::LirBuffer) reLirBuf; |
163 |
#ifdef DEBUG |
164 |
CLS(nanojit::LabelMap) labels; |
165 |
#endif |
166 |
|
167 |
CLS(TraceRecorder) recorder; |
168 |
jsval *reservedDoublePool; |
169 |
jsval *reservedDoublePoolPtr; |
170 |
|
171 |
struct GlobalState globalStates[MONITOR_N_GLOBAL_STATES]; |
172 |
struct VMFragment* vmfragments[FRAGMENT_TABLE_SIZE]; |
173 |
JSDHashTable recordAttempts; |
174 |
|
175 |
/* |
176 |
* Maximum size of the code cache before we start flushing. 1/16 of this |
177 |
* size is used as threshold for the regular expression code cache. |
178 |
*/ |
179 |
uint32 maxCodeCacheBytes; |
180 |
|
181 |
/* |
182 |
* If nonzero, do not flush the JIT cache after a deep bail. That would |
183 |
* free JITted code pages that we will later return to. Instead, set the |
184 |
* needFlush flag so that it can be flushed later. |
185 |
*/ |
186 |
JSBool needFlush; |
187 |
|
188 |
/* |
189 |
* reservedObjects is a linked list (via fslots[0]) of preallocated JSObjects. |
190 |
* The JIT uses this to ensure that leaving a trace tree can't fail. |
191 |
*/ |
192 |
JSBool useReservedObjects; |
193 |
JSObject *reservedObjects; |
194 |
|
195 |
/* |
196 |
* Fragment map for the regular expression compiler. |
197 |
*/ |
198 |
CLS(REHashMap) reFragments; |
199 |
|
200 |
/* |
201 |
* A temporary allocator for RE recording. |
202 |
*/ |
203 |
CLS(VMAllocator) reTempAlloc; |
204 |
|
205 |
#ifdef __cplusplus /* Allow inclusion from LiveConnect C files. */ |
206 |
|
207 |
#ifdef DEBUG |
208 |
/* Fields needed for fragment/guard profiling. */ |
209 |
CLS(nanojit::Seq<nanojit::Fragment*>) branches; |
210 |
uint32 lastFragID; |
211 |
/* |
212 |
* profAlloc has a lifetime which spans exactly from js_InitJIT to |
213 |
* js_FinishJIT. |
214 |
*/ |
215 |
CLS(VMAllocator) profAlloc; |
216 |
CLS(FragStatsMap) profTab; |
217 |
#endif |
218 |
|
219 |
/* Flush the JIT cache. */ |
220 |
void flush(); |
221 |
|
222 |
/* Mark all objects baked into native code in the code cache. */ |
223 |
void mark(JSTracer *trc); |
224 |
|
225 |
#endif |
226 |
}; |
227 |
|
228 |
typedef struct InterpStruct InterpStruct; |
229 |
|
230 |
/* |
231 |
* N.B. JS_ON_TRACE(cx) is true if JIT code is on the stack in the current |
232 |
* thread, regardless of whether cx is the context in which that trace is |
233 |
* executing. cx must be a context on the current thread. |
234 |
*/ |
235 |
#ifdef JS_TRACER |
236 |
# define JS_ON_TRACE(cx) (JS_TRACE_MONITOR(cx).tracecx != NULL) |
237 |
#else |
238 |
# define JS_ON_TRACE(cx) JS_FALSE |
239 |
#endif |
240 |
|
241 |
#ifdef DEBUG |
242 |
# define JS_EVAL_CACHE_METERING 1 |
243 |
# define JS_FUNCTION_METERING 1 |
244 |
#endif |
245 |
|
246 |
/* Number of potentially reusable scriptsToGC to search for the eval cache. */ |
247 |
#ifndef JS_EVAL_CACHE_SHIFT |
248 |
# define JS_EVAL_CACHE_SHIFT 6 |
249 |
#endif |
250 |
#define JS_EVAL_CACHE_SIZE JS_BIT(JS_EVAL_CACHE_SHIFT) |
251 |
|
252 |
#ifdef JS_EVAL_CACHE_METERING |
253 |
# define EVAL_CACHE_METER_LIST(_) _(probe), _(hit), _(step), _(noscope) |
254 |
# define identity(x) x |
255 |
|
256 |
/* Have to typedef this for LiveConnect C code, which includes us. */ |
257 |
typedef struct JSEvalCacheMeter { |
258 |
uint64 EVAL_CACHE_METER_LIST(identity); |
259 |
} JSEvalCacheMeter; |
260 |
|
261 |
# undef identity |
262 |
#endif |
263 |
|
264 |
#ifdef JS_FUNCTION_METERING |
265 |
# define FUNCTION_KIND_METER_LIST(_) \ |
266 |
_(allfun), _(heavy), _(nofreeupvar), _(onlyfreevar), \ |
267 |
_(display), _(flat), _(setupvar), _(badfunarg) |
268 |
# define identity(x) x |
269 |
|
270 |
typedef struct JSFunctionMeter { |
271 |
int32 FUNCTION_KIND_METER_LIST(identity); |
272 |
} JSFunctionMeter; |
273 |
|
274 |
# undef identity |
275 |
#endif |
276 |
|
277 |
struct JSThreadData { |
278 |
/* |
279 |
* The GSN cache is per thread since even multi-cx-per-thread embeddings |
280 |
* do not interleave js_GetSrcNote calls. |
281 |
*/ |
282 |
JSGSNCache gsnCache; |
283 |
|
284 |
/* Property cache for faster call/get/set invocation. */ |
285 |
JSPropertyCache propertyCache; |
286 |
|
287 |
/* Random number generator state, used by jsmath.cpp. */ |
288 |
int64 rngSeed; |
289 |
|
290 |
#ifdef JS_TRACER |
291 |
/* Trace-tree JIT recorder/interpreter state. */ |
292 |
JSTraceMonitor traceMonitor; |
293 |
#endif |
294 |
|
295 |
/* Lock-free hashed lists of scripts created by eval to garbage-collect. */ |
296 |
JSScript *scriptsToGC[JS_EVAL_CACHE_SIZE]; |
297 |
|
298 |
#ifdef JS_EVAL_CACHE_METERING |
299 |
JSEvalCacheMeter evalCacheMeter; |
300 |
#endif |
301 |
|
302 |
/* |
303 |
* Thread-local version of JSRuntime.gcMallocBytes to avoid taking |
304 |
* locks on each JS_malloc. |
305 |
*/ |
306 |
size_t gcMallocBytes; |
307 |
|
308 |
#ifdef __cplusplus /* Allow inclusion from LiveConnect C files. */ |
309 |
|
310 |
/* |
311 |
* Cache of reusable JSNativeEnumerators mapped by shape identifiers (as |
312 |
* stored in scope->shape). This cache is nulled by the GC and protected |
313 |
* by gcLock. |
314 |
*/ |
315 |
#define NATIVE_ENUM_CACHE_LOG2 8 |
316 |
#define NATIVE_ENUM_CACHE_MASK JS_BITMASK(NATIVE_ENUM_CACHE_LOG2) |
317 |
#define NATIVE_ENUM_CACHE_SIZE JS_BIT(NATIVE_ENUM_CACHE_LOG2) |
318 |
|
319 |
#define NATIVE_ENUM_CACHE_HASH(shape) \ |
320 |
((((shape) >> NATIVE_ENUM_CACHE_LOG2) ^ (shape)) & NATIVE_ENUM_CACHE_MASK) |
321 |
|
322 |
jsuword nativeEnumCache[NATIVE_ENUM_CACHE_SIZE]; |
323 |
|
324 |
#ifdef JS_THREADSAFE |
325 |
/* |
326 |
* Deallocator task for this thread. |
327 |
*/ |
328 |
JSFreePointerListTask *deallocatorTask; |
329 |
#endif |
330 |
|
331 |
void mark(JSTracer *trc) { |
332 |
#ifdef JS_TRACER |
333 |
traceMonitor.mark(trc); |
334 |
#endif |
335 |
} |
336 |
|
337 |
#endif /* __cplusplus */ |
338 |
}; |
339 |
|
340 |
#ifdef JS_THREADSAFE |
341 |
|
342 |
/* |
343 |
* Structure uniquely representing a thread. It holds thread-private data |
344 |
* that can be accessed without a global lock. |
345 |
*/ |
346 |
struct JSThread { |
347 |
/* Linked list of all contexts in use on this thread. */ |
348 |
JSCList contextList; |
349 |
|
350 |
/* Opaque thread-id, from NSPR's PR_GetCurrentThread(). */ |
351 |
jsword id; |
352 |
|
353 |
/* Indicates that the thread is waiting in ClaimTitle from jslock.cpp. */ |
354 |
JSTitle *titleToShare; |
355 |
|
356 |
JSGCThing *gcFreeLists[GC_NUM_FREELISTS]; |
357 |
|
358 |
/* Factored out of JSThread for !JS_THREADSAFE embedding in JSRuntime. */ |
359 |
JSThreadData data; |
360 |
}; |
361 |
|
362 |
#define JS_THREAD_DATA(cx) (&(cx)->thread->data) |
363 |
|
364 |
struct JSThreadsHashEntry { |
365 |
JSDHashEntryHdr base; |
366 |
JSThread *thread; |
367 |
}; |
368 |
|
369 |
extern JSThread * |
370 |
js_CurrentThread(JSRuntime *rt); |
371 |
|
372 |
/* |
373 |
* The function takes the GC lock and does not release in successful return. |
374 |
* On error (out of memory) the function releases the lock but delegates |
375 |
* the error reporting to the caller. |
376 |
*/ |
377 |
extern JSBool |
378 |
js_InitContextThread(JSContext *cx); |
379 |
|
380 |
/* |
381 |
* On entrance the GC lock must be held and it will be held on exit. |
382 |
*/ |
383 |
extern void |
384 |
js_ClearContextThread(JSContext *cx); |
385 |
|
386 |
#endif /* JS_THREADSAFE */ |
387 |
|
388 |
typedef enum JSDestroyContextMode { |
389 |
JSDCM_NO_GC, |
390 |
JSDCM_MAYBE_GC, |
391 |
JSDCM_FORCE_GC, |
392 |
JSDCM_NEW_FAILED |
393 |
} JSDestroyContextMode; |
394 |
|
395 |
typedef enum JSRuntimeState { |
396 |
JSRTS_DOWN, |
397 |
JSRTS_LAUNCHING, |
398 |
JSRTS_UP, |
399 |
JSRTS_LANDING |
400 |
} JSRuntimeState; |
401 |
|
402 |
typedef enum JSBuiltinFunctionId { |
403 |
JSBUILTIN_ObjectToIterator, |
404 |
JSBUILTIN_CallIteratorNext, |
405 |
JSBUILTIN_LIMIT |
406 |
} JSBuiltinFunctionId; |
407 |
|
408 |
typedef struct JSPropertyTreeEntry { |
409 |
JSDHashEntryHdr hdr; |
410 |
JSScopeProperty *child; |
411 |
} JSPropertyTreeEntry; |
412 |
|
413 |
typedef struct JSSetSlotRequest JSSetSlotRequest; |
414 |
|
415 |
struct JSSetSlotRequest { |
416 |
JSObject *obj; /* object containing slot to set */ |
417 |
JSObject *pobj; /* new proto or parent reference */ |
418 |
uint16 slot; /* which to set, proto or parent */ |
419 |
JSPackedBool cycle; /* true if a cycle was detected */ |
420 |
JSSetSlotRequest *next; /* next request in GC worklist */ |
421 |
}; |
422 |
|
423 |
struct JSRuntime { |
424 |
/* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */ |
425 |
JSRuntimeState state; |
426 |
|
427 |
/* Context create/destroy callback. */ |
428 |
JSContextCallback cxCallback; |
429 |
|
430 |
/* |
431 |
* Shape regenerated whenever a prototype implicated by an "add property" |
432 |
* property cache fill and induced trace guard has a readonly property or a |
433 |
* setter defined on it. This number proxies for the shapes of all objects |
434 |
* along the prototype chain of all objects in the runtime on which such an |
435 |
* add-property result has been cached/traced. |
436 |
* |
437 |
* See bug 492355 for more details. |
438 |
* |
439 |
* This comes early in JSRuntime to minimize the immediate format used by |
440 |
* trace-JITted code that reads it. |
441 |
*/ |
442 |
uint32 protoHazardShape; |
443 |
|
444 |
/* Garbage collector state, used by jsgc.c. */ |
445 |
JSGCChunkInfo *gcChunkList; |
446 |
JSGCArenaList gcArenaList[GC_NUM_FREELISTS]; |
447 |
JSGCDoubleArenaList gcDoubleArenaList; |
448 |
JSDHashTable gcRootsHash; |
449 |
JSDHashTable *gcLocksHash; |
450 |
jsrefcount gcKeepAtoms; |
451 |
size_t gcBytes; |
452 |
size_t gcLastBytes; |
453 |
size_t gcMaxBytes; |
454 |
size_t gcMaxMallocBytes; |
455 |
uint32 gcEmptyArenaPoolLifespan; |
456 |
uint32 gcLevel; |
457 |
uint32 gcNumber; |
458 |
JSTracer *gcMarkingTracer; |
459 |
uint32 gcTriggerFactor; |
460 |
size_t gcTriggerBytes; |
461 |
volatile JSBool gcIsNeeded; |
462 |
volatile JSBool gcFlushCodeCaches; |
463 |
|
464 |
/* |
465 |
* NB: do not pack another flag here by claiming gcPadding unless the new |
466 |
* flag is written only by the GC thread. Atomic updates to packed bytes |
467 |
* are not guaranteed, so stores issued by one thread may be lost due to |
468 |
* unsynchronized read-modify-write cycles on other threads. |
469 |
*/ |
470 |
JSPackedBool gcPoke; |
471 |
JSPackedBool gcRunning; |
472 |
JSPackedBool gcRegenShapes; |
473 |
|
474 |
/* |
475 |
* During gc, if rt->gcRegenShapes && |
476 |
* (scope->flags & JSScope::SHAPE_REGEN) == rt->gcRegenShapesScopeFlag, |
477 |
* then the scope's shape has already been regenerated during this GC. |
478 |
* To avoid having to sweep JSScopes, the bit's meaning toggles with each |
479 |
* shape-regenerating GC. |
480 |
* |
481 |
* FIXME Once scopes are GC'd (bug 505004), this will be obsolete. |
482 |
*/ |
483 |
uint8 gcRegenShapesScopeFlag; |
484 |
|
485 |
#ifdef JS_GC_ZEAL |
486 |
jsrefcount gcZeal; |
487 |
#endif |
488 |
|
489 |
JSGCCallback gcCallback; |
490 |
size_t gcMallocBytes; |
491 |
JSGCArenaInfo *gcUntracedArenaStackTop; |
492 |
#ifdef DEBUG |
493 |
size_t gcTraceLaterCount; |
494 |
#endif |
495 |
|
496 |
/* |
497 |
* Table for tracking iterators to ensure that we close iterator's state |
498 |
* before finalizing the iterable object. |
499 |
*/ |
500 |
JSPtrTable gcIteratorTable; |
501 |
|
502 |
/* |
503 |
* The trace operation and its data argument to trace embedding-specific |
504 |
* GC roots. |
505 |
*/ |
506 |
JSTraceDataOp gcExtraRootsTraceOp; |
507 |
void *gcExtraRootsData; |
508 |
|
509 |
/* |
510 |
* Used to serialize cycle checks when setting __proto__ or __parent__ by |
511 |
* requesting the GC handle the required cycle detection. If the GC hasn't |
512 |
* been poked, it won't scan for garbage. This member is protected by |
513 |
* rt->gcLock. |
514 |
*/ |
515 |
JSSetSlotRequest *setSlotRequests; |
516 |
|
517 |
/* Well-known numbers held for use by this runtime's contexts. */ |
518 |
jsdouble *jsNaN; |
519 |
jsdouble *jsNegativeInfinity; |
520 |
jsdouble *jsPositiveInfinity; |
521 |
|
522 |
#ifdef JS_THREADSAFE |
523 |
JSLock *deflatedStringCacheLock; |
524 |
#endif |
525 |
JSHashTable *deflatedStringCache; |
526 |
#ifdef DEBUG |
527 |
uint32 deflatedStringCacheBytes; |
528 |
#endif |
529 |
|
530 |
JSString *emptyString; |
531 |
|
532 |
/* |
533 |
* Builtin functions, lazily created and held for use by the trace recorder. |
534 |
* |
535 |
* This field would be #ifdef JS_TRACER, but XPConnect is compiled without |
536 |
* -DJS_TRACER and includes this header. |
537 |
*/ |
538 |
JSObject *builtinFunctions[JSBUILTIN_LIMIT]; |
539 |
|
540 |
/* List of active contexts sharing this runtime; protected by gcLock. */ |
541 |
JSCList contextList; |
542 |
|
543 |
/* Per runtime debug hooks -- see jsprvtd.h and jsdbgapi.h. */ |
544 |
JSDebugHooks globalDebugHooks; |
545 |
|
546 |
#ifdef JS_TRACER |
547 |
/* True if any debug hooks not supported by the JIT are enabled. */ |
548 |
bool debuggerInhibitsJIT() const { |
549 |
return (globalDebugHooks.interruptHandler || |
550 |
globalDebugHooks.callHook || |
551 |
globalDebugHooks.objectHook); |
552 |
} |
553 |
#endif |
554 |
|
555 |
/* More debugging state, see jsdbgapi.c. */ |
556 |
JSCList trapList; |
557 |
JSCList watchPointList; |
558 |
|
559 |
/* Client opaque pointers */ |
560 |
void *data; |
561 |
|
562 |
#ifdef JS_THREADSAFE |
563 |
/* These combine to interlock the GC and new requests. */ |
564 |
PRLock *gcLock; |
565 |
PRCondVar *gcDone; |
566 |
PRCondVar *requestDone; |
567 |
uint32 requestCount; |
568 |
JSThread *gcThread; |
569 |
|
570 |
/* Lock and owning thread pointer for JS_LOCK_RUNTIME. */ |
571 |
PRLock *rtLock; |
572 |
#ifdef DEBUG |
573 |
jsword rtLockOwner; |
574 |
#endif |
575 |
|
576 |
/* Used to synchronize down/up state change; protected by gcLock. */ |
577 |
PRCondVar *stateChange; |
578 |
|
579 |
/* |
580 |
* State for sharing single-threaded titles, once a second thread tries to |
581 |
* lock a title. The titleSharingDone condvar is protected by rt->gcLock |
582 |
* to minimize number of locks taken in JS_EndRequest. |
583 |
* |
584 |
* The titleSharingTodo linked list is likewise "global" per runtime, not |
585 |
* one-list-per-context, to conserve space over all contexts, optimizing |
586 |
* for the likely case that titles become shared rarely, and among a very |
587 |
* small set of threads (contexts). |
588 |
*/ |
589 |
PRCondVar *titleSharingDone; |
590 |
JSTitle *titleSharingTodo; |
591 |
|
592 |
/* |
593 |
* Magic terminator for the rt->titleSharingTodo linked list, threaded through |
594 |
* title->u.link. This hack allows us to test whether a title is on the list |
595 |
* by asking whether title->u.link is non-null. We use a large, likely bogus |
596 |
* pointer here to distinguish this value from any valid u.count (small int) |
597 |
* value. |
598 |
*/ |
599 |
#define NO_TITLE_SHARING_TODO ((JSTitle *) 0xfeedbeef) |
600 |
|
601 |
/* |
602 |
* Lock serializing trapList and watchPointList accesses, and count of all |
603 |
* mutations to trapList and watchPointList made by debugger threads. To |
604 |
* keep the code simple, we define debuggerMutations for the thread-unsafe |
605 |
* case too. |
606 |
*/ |
607 |
PRLock *debuggerLock; |
608 |
|
609 |
JSDHashTable threads; |
610 |
#endif /* JS_THREADSAFE */ |
611 |
uint32 debuggerMutations; |
612 |
|
613 |
/* |
614 |
* Security callbacks set on the runtime are used by each context unless |
615 |
* an override is set on the context. |
616 |
*/ |
617 |
JSSecurityCallbacks *securityCallbacks; |
618 |
|
619 |
/* |
620 |
* Shared scope property tree, and arena-pool for allocating its nodes. |
621 |
* The propertyRemovals counter is incremented for every JSScope::clear, |
622 |
* and for each JSScope::remove method call that frees a slot in an object. |
623 |
* See js_NativeGet and js_NativeSet in jsobj.c. |
624 |
*/ |
625 |
JSDHashTable propertyTreeHash; |
626 |
JSScopeProperty *propertyFreeList; |
627 |
JSArenaPool propertyArenaPool; |
628 |
int32 propertyRemovals; |
629 |
|
630 |
/* Script filename table. */ |
631 |
struct JSHashTable *scriptFilenameTable; |
632 |
JSCList scriptFilenamePrefixes; |
633 |
#ifdef JS_THREADSAFE |
634 |
PRLock *scriptFilenameTableLock; |
635 |
#endif |
636 |
|
637 |
/* Number localization, used by jsnum.c */ |
638 |
const char *thousandsSeparator; |
639 |
const char *decimalSeparator; |
640 |
const char *numGrouping; |
641 |
|
642 |
/* |
643 |
* Weak references to lazily-created, well-known XML singletons. |
644 |
* |
645 |
* NB: Singleton objects must be carefully disconnected from the rest of |
646 |
* the object graph usually associated with a JSContext's global object, |
647 |
* including the set of standard class objects. See jsxml.c for details. |
648 |
*/ |
649 |
JSObject *anynameObject; |
650 |
JSObject *functionNamespaceObject; |
651 |
|
652 |
#ifndef JS_THREADSAFE |
653 |
JSThreadData threadData; |
654 |
|
655 |
#define JS_THREAD_DATA(cx) (&(cx)->runtime->threadData) |
656 |
#endif |
657 |
|
658 |
/* |
659 |
* Object shape (property cache structural type) identifier generator. |
660 |
* |
661 |
* Type 0 stands for the empty scope, and must not be regenerated due to |
662 |
* uint32 wrap-around. Since js_GenerateShape (in jsinterp.cpp) uses |
663 |
* atomic pre-increment, the initial value for the first typed non-empty |
664 |
* scope will be 1. |
665 |
* |
666 |
* If this counter overflows into SHAPE_OVERFLOW_BIT (in jsinterp.h), the |
667 |
* cache is disabled, to avoid aliasing two different types. It stays |
668 |
* disabled until a triggered GC at some later moment compresses live |
669 |
* types, minimizing rt->shapeGen in the process. |
670 |
*/ |
671 |
volatile uint32 shapeGen; |
672 |
|
673 |
/* Literal table maintained by jsatom.c functions. */ |
674 |
JSAtomState atomState; |
675 |
|
676 |
/* |
677 |
* Various metering fields are defined at the end of JSRuntime. In this |
678 |
* way there is no need to recompile all the code that refers to other |
679 |
* fields of JSRuntime after enabling the corresponding metering macro. |
680 |
*/ |
681 |
#ifdef JS_DUMP_ENUM_CACHE_STATS |
682 |
int32 nativeEnumProbes; |
683 |
int32 nativeEnumMisses; |
684 |
# define ENUM_CACHE_METER(name) JS_ATOMIC_INCREMENT(&cx->runtime->name) |
685 |
#else |
686 |
# define ENUM_CACHE_METER(name) ((void) 0) |
687 |
#endif |
688 |
|
689 |
#ifdef JS_DUMP_LOOP_STATS |
690 |
/* Loop statistics, to trigger trace recording and compiling. */ |
691 |
JSBasicStats loopStats; |
692 |
#endif |
693 |
|
694 |
#if defined DEBUG || defined JS_DUMP_PROPTREE_STATS |
695 |
/* Function invocation metering. */ |
696 |
jsrefcount inlineCalls; |
697 |
jsrefcount nativeCalls; |
698 |
jsrefcount nonInlineCalls; |
699 |
jsrefcount constructs; |
700 |
|
701 |
/* Title lock and scope property metering. */ |
702 |
jsrefcount claimAttempts; |
703 |
jsrefcount claimedTitles; |
704 |
jsrefcount deadContexts; |
705 |
jsrefcount deadlocksAvoided; |
706 |
jsrefcount liveScopes; |
707 |
jsrefcount sharedTitles; |
708 |
jsrefcount totalScopes; |
709 |
jsrefcount liveScopeProps; |
710 |
jsrefcount liveScopePropsPreSweep; |
711 |
jsrefcount totalScopeProps; |
712 |
jsrefcount livePropTreeNodes; |
713 |
jsrefcount duplicatePropTreeNodes; |
714 |
jsrefcount totalPropTreeNodes; |
715 |
jsrefcount propTreeKidsChunks; |
716 |
jsrefcount middleDeleteFixups; |
717 |
|
718 |
/* String instrumentation. */ |
719 |
jsrefcount liveStrings; |
720 |
jsrefcount totalStrings; |
721 |
jsrefcount liveDependentStrings; |
722 |
jsrefcount totalDependentStrings; |
723 |
jsrefcount badUndependStrings; |
724 |
double lengthSum; |
725 |
double lengthSquaredSum; |
726 |
double strdepLengthSum; |
727 |
double strdepLengthSquaredSum; |
728 |
#endif /* DEBUG || JS_DUMP_PROPTREE_STATS */ |
729 |
|
730 |
#ifdef JS_SCOPE_DEPTH_METER |
731 |
/* |
732 |
* Stats on runtime prototype chain lookups and scope chain depths, i.e., |
733 |
* counts of objects traversed on a chain until the wanted id is found. |
734 |
*/ |
735 |
JSBasicStats protoLookupDepthStats; |
736 |
JSBasicStats scopeSearchDepthStats; |
737 |
|
738 |
/* |
739 |
* Stats on compile-time host environment and lexical scope chain lengths |
740 |
* (maximum depths). |
741 |
*/ |
742 |
JSBasicStats hostenvScopeDepthStats; |
743 |
JSBasicStats lexicalScopeDepthStats; |
744 |
#endif |
745 |
|
746 |
#ifdef JS_GCMETER |
747 |
JSGCStats gcStats; |
748 |
#endif |
749 |
|
750 |
#ifdef JS_FUNCTION_METERING |
751 |
JSFunctionMeter functionMeter; |
752 |
char lastScriptFilename[1024]; |
753 |
#endif |
754 |
|
755 |
#ifdef __cplusplus /* Allow inclusion from LiveConnect C files. */ |
756 |
|
757 |
void setGCTriggerFactor(uint32 factor); |
758 |
void setGCLastBytes(size_t lastBytes); |
759 |
|
760 |
inline void* malloc(size_t bytes) { |
761 |
return ::js_malloc(bytes); |
762 |
} |
763 |
|
764 |
inline void* calloc(size_t bytes) { |
765 |
return ::js_calloc(bytes); |
766 |
} |
767 |
|
768 |
inline void* realloc(void* p, size_t bytes) { |
769 |
return ::js_realloc(p, bytes); |
770 |
} |
771 |
|
772 |
inline void free(void* p) { |
773 |
::js_free(p); |
774 |
} |
775 |
|
776 |
#ifdef JS_THREADSAFE |
777 |
JSBackgroundThread *deallocatorThread; |
778 |
#endif |
779 |
|
780 |
#endif /* __cplusplus */ |
781 |
}; |
782 |
|
783 |
/* Common macros to access thread-local caches in JSThread or JSRuntime. */ |
784 |
#define JS_GSN_CACHE(cx) (JS_THREAD_DATA(cx)->gsnCache) |
785 |
#define JS_PROPERTY_CACHE(cx) (JS_THREAD_DATA(cx)->propertyCache) |
786 |
#define JS_TRACE_MONITOR(cx) (JS_THREAD_DATA(cx)->traceMonitor) |
787 |
#define JS_SCRIPTS_TO_GC(cx) (JS_THREAD_DATA(cx)->scriptsToGC) |
788 |
|
789 |
#ifdef JS_EVAL_CACHE_METERING |
790 |
# define EVAL_CACHE_METER(x) (JS_THREAD_DATA(cx)->evalCacheMeter.x++) |
791 |
#else |
792 |
# define EVAL_CACHE_METER(x) ((void) 0) |
793 |
#endif |
794 |
|
795 |
#ifdef DEBUG |
796 |
# define JS_RUNTIME_METER(rt, which) JS_ATOMIC_INCREMENT(&(rt)->which) |
797 |
# define JS_RUNTIME_UNMETER(rt, which) JS_ATOMIC_DECREMENT(&(rt)->which) |
798 |
#else |
799 |
# define JS_RUNTIME_METER(rt, which) /* nothing */ |
800 |
# define JS_RUNTIME_UNMETER(rt, which) /* nothing */ |
801 |
#endif |
802 |
|
803 |
#define JS_KEEP_ATOMS(rt) JS_ATOMIC_INCREMENT(&(rt)->gcKeepAtoms); |
804 |
#define JS_UNKEEP_ATOMS(rt) JS_ATOMIC_DECREMENT(&(rt)->gcKeepAtoms); |
805 |
|
806 |
#ifdef JS_ARGUMENT_FORMATTER_DEFINED |
807 |
/* |
808 |
* Linked list mapping format strings for JS_{Convert,Push}Arguments{,VA} to |
809 |
* formatter functions. Elements are sorted in non-increasing format string |
810 |
* length order. |
811 |
*/ |
812 |
struct JSArgumentFormatMap { |
813 |
const char *format; |
814 |
size_t length; |
815 |
JSArgumentFormatter formatter; |
816 |
JSArgumentFormatMap *next; |
817 |
}; |
818 |
#endif |
819 |
|
820 |
struct JSStackHeader { |
821 |
uintN nslots; |
822 |
JSStackHeader *down; |
823 |
}; |
824 |
|
825 |
#define JS_STACK_SEGMENT(sh) ((jsval *)(sh) + 2) |
826 |
|
827 |
/* |
828 |
* Key and entry types for the JSContext.resolvingTable hash table, typedef'd |
829 |
* here because all consumers need to see these declarations (and not just the |
830 |
* typedef names, as would be the case for an opaque pointer-to-typedef'd-type |
831 |
* declaration), along with cx->resolvingTable. |
832 |
*/ |
833 |
typedef struct JSResolvingKey { |
834 |
JSObject *obj; |
835 |
jsid id; |
836 |
} JSResolvingKey; |
837 |
|
838 |
typedef struct JSResolvingEntry { |
839 |
JSDHashEntryHdr hdr; |
840 |
JSResolvingKey key; |
841 |
uint32 flags; |
842 |
} JSResolvingEntry; |
843 |
|
844 |
#define JSRESFLAG_LOOKUP 0x1 /* resolving id from lookup */ |
845 |
#define JSRESFLAG_WATCH 0x2 /* resolving id from watch */ |
846 |
|
847 |
typedef struct JSLocalRootChunk JSLocalRootChunk; |
848 |
|
849 |
#define JSLRS_CHUNK_SHIFT 8 |
850 |
#define JSLRS_CHUNK_SIZE JS_BIT(JSLRS_CHUNK_SHIFT) |
851 |
#define JSLRS_CHUNK_MASK JS_BITMASK(JSLRS_CHUNK_SHIFT) |
852 |
|
853 |
struct JSLocalRootChunk { |
854 |
jsval roots[JSLRS_CHUNK_SIZE]; |
855 |
JSLocalRootChunk *down; |
856 |
}; |
857 |
|
858 |
typedef struct JSLocalRootStack { |
859 |
uint32 scopeMark; |
860 |
uint32 rootCount; |
861 |
JSLocalRootChunk *topChunk; |
862 |
JSLocalRootChunk firstChunk; |
863 |
} JSLocalRootStack; |
864 |
|
865 |
#define JSLRS_NULL_MARK ((uint32) -1) |
866 |
|
867 |
/* |
868 |
* Macros to push/pop JSTempValueRooter instances to context-linked stack of |
869 |
* temporary GC roots. If you need to protect a result value that flows out of |
870 |
* a C function across several layers of other functions, use the |
871 |
* js_LeaveLocalRootScopeWithResult internal API (see further below) instead. |
872 |
* |
873 |
* The macros also provide a simple way to get a single rooted pointer via |
874 |
* JS_PUSH_TEMP_ROOT_<KIND>(cx, NULL, &tvr). Then &tvr.u.<kind> gives the |
875 |
* necessary pointer. |
876 |
* |
877 |
* JSTempValueRooter.count defines the type of the rooted value referenced by |
878 |
* JSTempValueRooter.u union of type JSTempValueUnion. When count is positive |
879 |
* or zero, u.array points to a vector of jsvals. Otherwise it must be one of |
880 |
* the following constants: |
881 |
*/ |
882 |
#define JSTVU_SINGLE (-1) /* u.value or u.<gcthing> is single jsval |
883 |
or non-JSString GC-thing pointer */ |
884 |
#define JSTVU_TRACE (-2) /* u.trace is a hook to trace a custom |
885 |
* structure */ |
886 |
#define JSTVU_SPROP (-3) /* u.sprop roots property tree node */ |
887 |
#define JSTVU_WEAK_ROOTS (-4) /* u.weakRoots points to saved weak roots */ |
888 |
#define JSTVU_COMPILER (-5) /* u.compiler roots JSCompiler* */ |
889 |
#define JSTVU_SCRIPT (-6) /* u.script roots JSScript* */ |
890 |
#define JSTVU_ENUMERATOR (-7) /* a pointer to JSTempValueRooter points |
891 |
to an instance of JSAutoEnumStateRooter |
892 |
with u.object storing the enumeration |
893 |
object */ |
894 |
|
895 |
/* |
896 |
* Here single JSTVU_SINGLE covers both jsval and pointers to almost (see note |
897 |
* below) any GC-thing via reinterpreting the thing as JSVAL_OBJECT. This works |
898 |
* because the GC-thing is aligned on a 0 mod 8 boundary, and object has the 0 |
899 |
* jsval tag. So any GC-heap-allocated thing pointer may be tagged as if it |
900 |
* were an object and untagged, if it's then used only as an opaque pointer |
901 |
* until discriminated by other means than tag bits. This is how, for example, |
902 |
* js_GetGCThingTraceKind uses its |thing| parameter -- it consults GC-thing |
903 |
* flags stored separately from the thing to decide the kind of thing. |
904 |
* |
905 |
* Note well that JSStrings may be statically allocated (see the intStringTable |
906 |
* and unitStringTable static arrays), so this hack does not work for arbitrary |
907 |
* GC-thing pointers. |
908 |
*/ |
909 |
#define JS_PUSH_TEMP_ROOT_COMMON(cx,x,tvr,cnt,kind) \ |
910 |
JS_BEGIN_MACRO \ |
911 |
JS_ASSERT((cx)->tempValueRooters != (tvr)); \ |
912 |
(tvr)->count = (cnt); \ |
913 |
(tvr)->u.kind = (x); \ |
914 |
(tvr)->down = (cx)->tempValueRooters; \ |
915 |
(cx)->tempValueRooters = (tvr); \ |
916 |
JS_END_MACRO |
917 |
|
918 |
#define JS_POP_TEMP_ROOT(cx,tvr) \ |
919 |
JS_BEGIN_MACRO \ |
920 |
JS_ASSERT((cx)->tempValueRooters == (tvr)); \ |
921 |
(cx)->tempValueRooters = (tvr)->down; \ |
922 |
JS_END_MACRO |
923 |
|
924 |
#define JS_PUSH_TEMP_ROOT(cx,cnt,arr,tvr) \ |
925 |
JS_BEGIN_MACRO \ |
926 |
JS_ASSERT((int)(cnt) >= 0); \ |
927 |
JS_PUSH_TEMP_ROOT_COMMON(cx, arr, tvr, (ptrdiff_t) (cnt), array); \ |
928 |
JS_END_MACRO |
929 |
|
930 |
#define JS_PUSH_SINGLE_TEMP_ROOT(cx,val,tvr) \ |
931 |
JS_PUSH_TEMP_ROOT_COMMON(cx, val, tvr, JSTVU_SINGLE, value) |
932 |
|
933 |
#define JS_PUSH_TEMP_ROOT_OBJECT(cx,obj,tvr) \ |
934 |
JS_PUSH_TEMP_ROOT_COMMON(cx, obj, tvr, JSTVU_SINGLE, object) |
935 |
|
936 |
#define JS_PUSH_TEMP_ROOT_STRING(cx,str,tvr) \ |
937 |
JS_PUSH_SINGLE_TEMP_ROOT(cx, str ? STRING_TO_JSVAL(str) : JSVAL_NULL, tvr) |
938 |
|
939 |
#define JS_PUSH_TEMP_ROOT_XML(cx,xml_,tvr) \ |
940 |
JS_PUSH_TEMP_ROOT_COMMON(cx, xml_, tvr, JSTVU_SINGLE, xml) |
941 |
|
942 |
#define JS_PUSH_TEMP_ROOT_TRACE(cx,trace_,tvr) \ |
943 |
JS_PUSH_TEMP_ROOT_COMMON(cx, trace_, tvr, JSTVU_TRACE, trace) |
944 |
|
945 |
#define JS_PUSH_TEMP_ROOT_SPROP(cx,sprop_,tvr) \ |
946 |
JS_PUSH_TEMP_ROOT_COMMON(cx, sprop_, tvr, JSTVU_SPROP, sprop) |
947 |
|
948 |
#define JS_PUSH_TEMP_ROOT_WEAK_COPY(cx,weakRoots_,tvr) \ |
949 |
JS_PUSH_TEMP_ROOT_COMMON(cx, weakRoots_, tvr, JSTVU_WEAK_ROOTS, weakRoots) |
950 |
|
951 |
#define JS_PUSH_TEMP_ROOT_COMPILER(cx,pc,tvr) \ |
952 |
JS_PUSH_TEMP_ROOT_COMMON(cx, pc, tvr, JSTVU_COMPILER, compiler) |
953 |
|
954 |
#define JS_PUSH_TEMP_ROOT_SCRIPT(cx,script_,tvr) \ |
955 |
JS_PUSH_TEMP_ROOT_COMMON(cx, script_, tvr, JSTVU_SCRIPT, script) |
956 |
|
957 |
#define JSRESOLVE_INFER 0xffff /* infer bits from current bytecode */ |
958 |
|
959 |
struct JSContext { |
960 |
/* |
961 |
* If this flag is set, we were asked to call back the operation callback |
962 |
* as soon as possible. |
963 |
*/ |
964 |
volatile jsint operationCallbackFlag; |
965 |
|
966 |
/* JSRuntime contextList linkage. */ |
967 |
JSCList link; |
968 |
|
969 |
#if JS_HAS_XML_SUPPORT |
970 |
/* |
971 |
* Bit-set formed from binary exponentials of the XML_* tiny-ids defined |
972 |
* for boolean settings in jsxml.c, plus an XSF_CACHE_VALID bit. Together |
973 |
* these act as a cache of the boolean XML.ignore* and XML.prettyPrinting |
974 |
* property values associated with this context's global object. |
975 |
*/ |
976 |
uint8 xmlSettingFlags; |
977 |
uint8 padding; |
978 |
#else |
979 |
uint16 padding; |
980 |
#endif |
981 |
|
982 |
/* |
983 |
* Classic Algol "display" static link optimization. |
984 |
*/ |
985 |
#define JS_DISPLAY_SIZE 16U |
986 |
|
987 |
JSStackFrame *display[JS_DISPLAY_SIZE]; |
988 |
|
989 |
/* Runtime version control identifier. */ |
990 |
uint16 version; |
991 |
|
992 |
/* Per-context options. */ |
993 |
uint32 options; /* see jsapi.h for JSOPTION_* */ |
994 |
|
995 |
/* Locale specific callbacks for string conversion. */ |
996 |
JSLocaleCallbacks *localeCallbacks; |
997 |
|
998 |
/* |
999 |
* cx->resolvingTable is non-null and non-empty if we are initializing |
1000 |
* standard classes lazily, or if we are otherwise recursing indirectly |
1001 |
* from js_LookupProperty through a JSClass.resolve hook. It is used to |
1002 |
* limit runaway recursion (see jsapi.c and jsobj.c). |
1003 |
*/ |
1004 |
JSDHashTable *resolvingTable; |
1005 |
|
1006 |
#if JS_HAS_LVALUE_RETURN |
1007 |
/* |
1008 |
* Secondary return value from native method called on the left-hand side |
1009 |
* of an assignment operator. The native should store the object in which |
1010 |
* to set a property in *rval, and return the property's id expressed as a |
1011 |
* jsval by calling JS_SetCallReturnValue2(cx, idval). |
1012 |
*/ |
1013 |
jsval rval2; |
1014 |
JSPackedBool rval2set; |
1015 |
#endif |
1016 |
|
1017 |
/* |
1018 |
* True if generating an error, to prevent runaway recursion. |
1019 |
* NB: generatingError packs with rval2set, #if JS_HAS_LVALUE_RETURN; |
1020 |
* with insideGCMarkCallback and with throwing below. |
1021 |
*/ |
1022 |
JSPackedBool generatingError; |
1023 |
|
1024 |
/* Flag to indicate that we run inside gcCallback(cx, JSGC_MARK_END). */ |
1025 |
JSPackedBool insideGCMarkCallback; |
1026 |
|
1027 |
/* Exception state -- the exception member is a GC root by definition. */ |
1028 |
JSPackedBool throwing; /* is there a pending exception? */ |
1029 |
jsval exception; /* most-recently-thrown exception */ |
1030 |
|
1031 |
/* Limit pointer for checking native stack consumption during recursion. */ |
1032 |
jsuword stackLimit; |
1033 |
|
1034 |
/* Quota on the size of arenas used to compile and execute scripts. */ |
1035 |
size_t scriptStackQuota; |
1036 |
|
1037 |
/* Data shared by threads in an address space. */ |
1038 |
JSRuntime * const runtime; |
1039 |
|
1040 |
explicit JSContext(JSRuntime *rt) : runtime(rt) {} |
1041 |
|
1042 |
/* Stack arena pool and frame pointer register. */ |
1043 |
JS_REQUIRES_STACK |
1044 |
JSArenaPool stackPool; |
1045 |
|
1046 |
JS_REQUIRES_STACK |
1047 |
JSStackFrame *fp; |
1048 |
|
1049 |
/* Temporary arena pool used while compiling and decompiling. */ |
1050 |
JSArenaPool tempPool; |
1051 |
|
1052 |
/* Top-level object and pointer to top stack frame's scope chain. */ |
1053 |
JSObject *globalObject; |
1054 |
|
1055 |
/* Storage to root recently allocated GC things and script result. */ |
1056 |
JSWeakRoots weakRoots; |
1057 |
|
1058 |
/* Regular expression class statics (XXX not shared globally). */ |
1059 |
JSRegExpStatics regExpStatics; |
1060 |
|
1061 |
/* State for object and array toSource conversion. */ |
1062 |
JSSharpObjectMap sharpObjectMap; |
1063 |
JSHashTable *busyArrayTable; |
1064 |
|
1065 |
/* Argument formatter support for JS_{Convert,Push}Arguments{,VA}. */ |
1066 |
JSArgumentFormatMap *argumentFormatMap; |
1067 |
|
1068 |
/* Last message string and trace file for debugging. */ |
1069 |
char *lastMessage; |
1070 |
#ifdef DEBUG |
1071 |
void *tracefp; |
1072 |
jsbytecode *tracePrevPc; |
1073 |
#endif |
1074 |
|
1075 |
/* Per-context optional error reporter. */ |
1076 |
JSErrorReporter errorReporter; |
1077 |
|
1078 |
/* Branch callback. */ |
1079 |
JSOperationCallback operationCallback; |
1080 |
|
1081 |
/* Interpreter activation count. */ |
1082 |
uintN interpLevel; |
1083 |
|
1084 |
/* Client opaque pointers. */ |
1085 |
void *data; |
1086 |
void *data2; |
1087 |
|
1088 |
/* GC and thread-safe state. */ |
1089 |
JSStackFrame *dormantFrameChain; /* dormant stack frame to scan */ |
1090 |
#ifdef JS_THREADSAFE |
1091 |
JSThread *thread; |
1092 |
jsrefcount requestDepth; |
1093 |
/* Same as requestDepth but ignoring JS_SuspendRequest/JS_ResumeRequest */ |
1094 |
jsrefcount outstandingRequests; |
1095 |
JSTitle *lockedSealedTitle; /* weak ref, for low-cost sealed |
1096 |
title locking */ |
1097 |
JSCList threadLinks; /* JSThread contextList linkage */ |
1098 |
|
1099 |
#define CX_FROM_THREAD_LINKS(tl) \ |
1100 |
((JSContext *)((char *)(tl) - offsetof(JSContext, threadLinks))) |
1101 |
#endif |
1102 |
|
1103 |
/* PDL of stack headers describing stack slots not rooted by argv, etc. */ |
1104 |
JSStackHeader *stackHeaders; |
1105 |
|
1106 |
/* Optional stack of heap-allocated scoped local GC roots. */ |
1107 |
JSLocalRootStack *localRootStack; |
1108 |
|
1109 |
/* Stack of thread-stack-allocated temporary GC roots. */ |
1110 |
JSTempValueRooter *tempValueRooters; |
1111 |
|
1112 |
/* List of pre-allocated doubles. */ |
1113 |
JSGCDoubleCell *doubleFreeList; |
1114 |
|
1115 |
/* Debug hooks associated with the current context. */ |
1116 |
const JSDebugHooks *debugHooks; |
1117 |
|
1118 |
/* Security callbacks that override any defined on the runtime. */ |
1119 |
JSSecurityCallbacks *securityCallbacks; |
1120 |
|
1121 |
/* Pinned regexp pool used for regular expressions. */ |
1122 |
JSArenaPool regexpPool; |
1123 |
|
1124 |
/* Stored here to avoid passing it around as a parameter. */ |
1125 |
uintN resolveFlags; |
1126 |
|
1127 |
#ifdef JS_TRACER |
1128 |
/* |
1129 |
* State for the current tree execution. bailExit is valid if the tree has |
1130 |
* called back into native code via a _FAIL builtin and has not yet bailed, |
1131 |
* else garbage (NULL in debug builds). |
1132 |
*/ |
1133 |
InterpState *interpState; |
1134 |
VMSideExit *bailExit; |
1135 |
|
1136 |
/* |
1137 |
* True if traces may be executed. Invariant: The value of jitEnabled is |
1138 |
* always equal to the expression in updateJITEnabled below. |
1139 |
* |
1140 |
* This flag and the fields accessed by updateJITEnabled are written only |
1141 |
* in runtime->gcLock, to avoid race conditions that would leave the wrong |
1142 |
* value in jitEnabled. (But the interpreter reads this without |
1143 |
* locking. That can race against another thread setting debug hooks, but |
1144 |
* we always read cx->debugHooks without locking anyway.) |
1145 |
*/ |
1146 |
bool jitEnabled; |
1147 |
#endif |
1148 |
|
1149 |
#ifdef __cplusplus /* Allow inclusion from LiveConnect C files, */ |
1150 |
|
1151 |
/* Caller must be holding runtime->gcLock. */ |
1152 |
void updateJITEnabled() { |
1153 |
#ifdef JS_TRACER |
1154 |
jitEnabled = ((options & JSOPTION_JIT) && |
1155 |
!runtime->debuggerInhibitsJIT() && |
1156 |
debugHooks == &runtime->globalDebugHooks); |
1157 |
#endif |
1158 |
} |
1159 |
|
1160 |
|
1161 |
#ifdef JS_THREADSAFE |
1162 |
inline void createDeallocatorTask() { |
1163 |
JSThreadData* tls = JS_THREAD_DATA(this); |
1164 |
JS_ASSERT(!tls->deallocatorTask); |
1165 |
if (runtime->deallocatorThread && !runtime->deallocatorThread->busy()) |
1166 |
tls->deallocatorTask = new JSFreePointerListTask(); |
1167 |
} |
1168 |
|
1169 |
inline void submitDeallocatorTask() { |
1170 |
JSThreadData* tls = JS_THREAD_DATA(this); |
1171 |
if (tls->deallocatorTask) { |
1172 |
runtime->deallocatorThread->schedule(tls->deallocatorTask); |
1173 |
tls->deallocatorTask = NULL; |
1174 |
} |
1175 |
} |
1176 |
#endif |
1177 |
|
1178 |
/* Call this after succesful malloc of memory for GC-related things. */ |
1179 |
inline void updateMallocCounter(size_t nbytes) { |
1180 |
size_t *pbytes, bytes; |
1181 |
|
1182 |
pbytes = &JS_THREAD_DATA(this)->gcMallocBytes; |
1183 |
bytes = *pbytes; |
1184 |
*pbytes = (size_t(-1) - bytes <= nbytes) ? size_t(-1) : bytes + nbytes; |
1185 |
} |
1186 |
|
1187 |
inline void* malloc(size_t bytes) { |
1188 |
JS_ASSERT(bytes != 0); |
1189 |
void *p = runtime->malloc(bytes); |
1190 |
if (!p) { |
1191 |
JS_ReportOutOfMemory(this); |
1192 |
return NULL; |
1193 |
} |
1194 |
updateMallocCounter(bytes); |
1195 |
return p; |
1196 |
} |
1197 |
|
1198 |
inline void* mallocNoReport(size_t bytes) { |
1199 |
JS_ASSERT(bytes != 0); |
1200 |
void *p = runtime->malloc(bytes); |
1201 |
if (!p) |
1202 |
return NULL; |
1203 |
updateMallocCounter(bytes); |
1204 |
return p; |
1205 |
} |
1206 |
|
1207 |
inline void* calloc(size_t bytes) { |
1208 |
JS_ASSERT(bytes != 0); |
1209 |
void *p = runtime->calloc(bytes); |
1210 |
if (!p) { |
1211 |
JS_ReportOutOfMemory(this); |
1212 |
return NULL; |
1213 |
} |
1214 |
updateMallocCounter(bytes); |
1215 |
return p; |
1216 |
} |
1217 |
|
1218 |
inline void* realloc(void* p, size_t bytes) { |
1219 |
void *orig = p; |
1220 |
p = runtime->realloc(p, bytes); |
1221 |
if (!p) { |
1222 |
JS_ReportOutOfMemory(this); |
1223 |
return NULL; |
1224 |
} |
1225 |
if (!orig) |
1226 |
updateMallocCounter(bytes); |
1227 |
return p; |
1228 |
} |
1229 |
|
1230 |
#ifdef JS_THREADSAFE |
1231 |
inline void free(void* p) { |
1232 |
if (!p) |
1233 |
return; |
1234 |
if (thread) { |
1235 |
JSFreePointerListTask* task = JS_THREAD_DATA(this)->deallocatorTask; |
1236 |
if (task) { |
1237 |
task->add(p); |
1238 |
return; |
1239 |
} |
1240 |
} |
1241 |
runtime->free(p); |
1242 |
} |
1243 |
#else |
1244 |
inline void free(void* p) { |
1245 |
if (!p) |
1246 |
return; |
1247 |
runtime->free(p); |
1248 |
} |
1249 |
#endif |
1250 |
|
1251 |
/* |
1252 |
* In the common case that we'd like to allocate the memory for an object |
1253 |
* with cx->malloc/free, we cannot use overloaded C++ operators (no |
1254 |
* placement delete). Factor the common workaround into one place. |
1255 |
*/ |
1256 |
#define CREATE_BODY(parms) \ |
1257 |
void *memory = this->malloc(sizeof(T)); \ |
1258 |
if (!memory) { \ |
1259 |
JS_ReportOutOfMemory(this); \ |
1260 |
return NULL; \ |
1261 |
} \ |
1262 |
return new(memory) T parms; |
1263 |
|
1264 |
template <class T> |
1265 |
JS_ALWAYS_INLINE T *create() { |
1266 |
CREATE_BODY(()) |
1267 |
} |
1268 |
|
1269 |
template <class T, class P1> |
1270 |
JS_ALWAYS_INLINE T *create(const P1 &p1) { |
1271 |
CREATE_BODY((p1)) |
1272 |
} |
1273 |
|
1274 |
template <class T, class P1, class P2> |
1275 |
JS_ALWAYS_INLINE T *create(const P1 &p1, const P2 &p2) { |
1276 |
CREATE_BODY((p1, p2)) |
1277 |
} |
1278 |
|
1279 |
template <class T, class P1, class P2, class P3> |
1280 |
JS_ALWAYS_INLINE T *create(const P1 &p1, const P2 &p2, const P3 &p3) { |
1281 |
CREATE_BODY((p1, p2, p3)) |
1282 |
} |
1283 |
#undef CREATE_BODY |
1284 |
|
1285 |
template <class T> |
1286 |
JS_ALWAYS_INLINE void destroy(T *p) { |
1287 |
p->~T(); |
1288 |
this->free(p); |
1289 |
} |
1290 |
|
1291 |
#endif /* __cplusplus */ |
1292 |
}; |
1293 |
|
1294 |
#ifdef JS_THREADSAFE |
1295 |
# define JS_THREAD_ID(cx) ((cx)->thread ? (cx)->thread->id : 0) |
1296 |
#endif |
1297 |
|
1298 |
#ifdef __cplusplus |
1299 |
|
1300 |
static inline JSAtom ** |
1301 |
FrameAtomBase(JSContext *cx, JSStackFrame *fp) |
1302 |
{ |
1303 |
return fp->imacpc |
1304 |
? COMMON_ATOMS_START(&cx->runtime->atomState) |
1305 |
: fp->script->atomMap.vector; |
1306 |
} |
1307 |
|
1308 |
/* FIXME(bug 332648): Move this into a public header. */ |
1309 |
class JSAutoTempValueRooter |
1310 |
{ |
1311 |
public: |
1312 |
JSAutoTempValueRooter(JSContext *cx, size_t len, jsval *vec |
1313 |
JS_GUARD_OBJECT_NOTIFIER_PARAM) |
1314 |
: mContext(cx) { |
1315 |
JS_GUARD_OBJECT_NOTIFIER_INIT; |
1316 |
JS_PUSH_TEMP_ROOT(mContext, len, vec, &mTvr); |
1317 |
} |
1318 |
explicit JSAutoTempValueRooter(JSContext *cx, jsval v = JSVAL_NULL |
1319 |
JS_GUARD_OBJECT_NOTIFIER_PARAM) |
1320 |
: mContext(cx) { |
1321 |
JS_GUARD_OBJECT_NOTIFIER_INIT; |
1322 |
JS_PUSH_SINGLE_TEMP_ROOT(mContext, v, &mTvr); |
1323 |
} |
1324 |
JSAutoTempValueRooter(JSContext *cx, JSString *str |
1325 |
JS_GUARD_OBJECT_NOTIFIER_PARAM) |
1326 |
: mContext(cx) { |
1327 |
JS_GUARD_OBJECT_NOTIFIER_INIT; |
1328 |
JS_PUSH_TEMP_ROOT_STRING(mContext, str, &mTvr); |
1329 |
} |
1330 |
JSAutoTempValueRooter(JSContext *cx, JSObject *obj |
1331 |
JS_GUARD_OBJECT_NOTIFIER_PARAM) |
1332 |
: mContext(cx) { |
1333 |
JS_GUARD_OBJECT_NOTIFIER_INIT; |
1334 |
JS_PUSH_TEMP_ROOT_OBJECT(mContext, obj, &mTvr); |
1335 |
} |
1336 |
|
1337 |
~JSAutoTempValueRooter() { |
1338 |
JS_POP_TEMP_ROOT(mContext, &mTvr); |
1339 |
} |
1340 |
|
1341 |
jsval value() { return mTvr.u.value; } |
1342 |
jsval *addr() { return &mTvr.u.value; } |
1343 |
|
1344 |
protected: |
1345 |
JSContext *mContext; |
1346 |
|
1347 |
private: |
1348 |
#ifndef AIX |
1349 |
static void *operator new(size_t); |
1350 |
static void operator delete(void *, size_t); |
1351 |
#endif |
1352 |
|
1353 |
JSTempValueRooter mTvr; |
1354 |
JS_DECL_USE_GUARD_OBJECT_NOTIFIER |
1355 |
}; |
1356 |
|
1357 |
class JSAutoTempIdRooter |
1358 |
{ |
1359 |
public: |
1360 |
explicit JSAutoTempIdRooter(JSContext *cx, jsid id = INT_TO_JSID(0) |
1361 |
JS_GUARD_OBJECT_NOTIFIER_PARAM) |
1362 |
: mContext(cx) { |
1363 |
JS_GUARD_OBJECT_NOTIFIER_INIT; |
1364 |
JS_PUSH_SINGLE_TEMP_ROOT(mContext, ID_TO_VALUE(id), &mTvr); |
1365 |
} |
1366 |
|
1367 |
~JSAutoTempIdRooter() { |
1368 |
JS_POP_TEMP_ROOT(mContext, &mTvr); |
1369 |
} |
1370 |
|
1371 |
jsid id() { return (jsid) mTvr.u.value; } |
1372 |
jsid * addr() { return (jsid *) &mTvr.u.value; } |
1373 |
|
1374 |
private: |
1375 |
JSContext *mContext; |
1376 |
JSTempValueRooter mTvr; |
1377 |
JS_DECL_USE_GUARD_OBJECT_NOTIFIER |
1378 |
}; |
1379 |
|
1380 |
/* The auto-root for enumeration object and its state. */ |
1381 |
class JSAutoEnumStateRooter : public JSTempValueRooter |
1382 |
{ |
1383 |
public: |
1384 |
JSAutoEnumStateRooter(JSContext *cx, JSObject *obj, jsval *statep |
1385 |
JS_GUARD_OBJECT_NOTIFIER_PARAM) |
1386 |
: mContext(cx), mStatep(statep) |
1387 |
{ |
1388 |
JS_GUARD_OBJECT_NOTIFIER_INIT; |
1389 |
JS_ASSERT(obj); |
1390 |
JS_ASSERT(statep); |
1391 |
JS_PUSH_TEMP_ROOT_COMMON(cx, obj, this, JSTVU_ENUMERATOR, object); |
1392 |
} |
1393 |
|
1394 |
~JSAutoEnumStateRooter() { |
1395 |
JS_POP_TEMP_ROOT(mContext, this); |
1396 |
} |
1397 |
|
1398 |
void mark(JSTracer *trc) { |
1399 |
JS_CALL_OBJECT_TRACER(trc, u.object, "enumerator_obj"); |
1400 |
js_MarkEnumeratorState(trc, u.object, *mStatep); |
1401 |
} |
1402 |
|
1403 |
private: |
1404 |
JSContext *mContext; |
1405 |
jsval *mStatep; |
1406 |
JS_DECL_USE_GUARD_OBJECT_NOTIFIER |
1407 |
}; |
1408 |
|
1409 |
class JSAutoResolveFlags |
1410 |
{ |
1411 |
public: |
1412 |
JSAutoResolveFlags(JSContext *cx, uintN flags |
1413 |
JS_GUARD_OBJECT_NOTIFIER_PARAM) |
1414 |
: mContext(cx), mSaved(cx->resolveFlags) { |
1415 |
JS_GUARD_OBJECT_NOTIFIER_INIT; |
1416 |
cx->resolveFlags = flags; |
1417 |
} |
1418 |
|
1419 |
~JSAutoResolveFlags() { mContext->resolveFlags = mSaved; } |
1420 |
|
1421 |
private: |
1422 |
JSContext *mContext; |
1423 |
uintN mSaved; |
1424 |
JS_DECL_USE_GUARD_OBJECT_NOTIFIER |
1425 |
}; |
1426 |
|
1427 |
#endif /* __cplusplus */ |
1428 |
|
1429 |
/* |
1430 |
* Slightly more readable macros for testing per-context option settings (also |
1431 |
* to hide bitset implementation detail). |
1432 |
* |
1433 |
* JSOPTION_XML must be handled specially in order to propagate from compile- |
1434 |
* to run-time (from cx->options to script->version/cx->version). To do that, |
1435 |
* we copy JSOPTION_XML from cx->options into cx->version as JSVERSION_HAS_XML |
1436 |
* whenever options are set, and preserve this XML flag across version number |
1437 |
* changes done via the JS_SetVersion API. |
1438 |
* |
1439 |
* But when executing a script or scripted function, the interpreter changes |
1440 |
* cx->version, including the XML flag, to script->version. Thus JSOPTION_XML |
1441 |
* is a compile-time option that causes a run-time version change during each |
1442 |
* activation of the compiled script. That version change has the effect of |
1443 |
* changing JS_HAS_XML_OPTION, so that any compiling done via eval enables XML |
1444 |
* support. If an XML-enabled script or function calls a non-XML function, |
1445 |
* the flag bit will be cleared during the callee's activation. |
1446 |
* |
1447 |
* Note that JS_SetVersion API calls never pass JSVERSION_HAS_XML or'd into |
1448 |
* that API's version parameter. |
1449 |
* |
1450 |
* Note also that script->version must contain this XML option flag in order |
1451 |
* for XDR'ed scripts to serialize and deserialize with that option preserved |
1452 |
* for detection at run-time. We can't copy other compile-time options into |
1453 |
* script->version because that would break backward compatibility (certain |
1454 |
* other options, e.g. JSOPTION_VAROBJFIX, are analogous to JSOPTION_XML). |
1455 |
*/ |
1456 |
#define JS_HAS_OPTION(cx,option) (((cx)->options & (option)) != 0) |
1457 |
#define JS_HAS_STRICT_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_STRICT) |
1458 |
#define JS_HAS_WERROR_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_WERROR) |
1459 |
#define JS_HAS_COMPILE_N_GO_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_COMPILE_N_GO) |
1460 |
#define JS_HAS_ATLINE_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_ATLINE) |
1461 |
|
1462 |
#define JSVERSION_MASK 0x0FFF /* see JSVersion in jspubtd.h */ |
1463 |
#define JSVERSION_HAS_XML 0x1000 /* flag induced by XML option */ |
1464 |
#define JSVERSION_ANONFUNFIX 0x2000 /* see jsapi.h, the comments |
1465 |
for JSOPTION_ANONFUNFIX */ |
1466 |
|
1467 |
#define JSVERSION_NUMBER(cx) ((JSVersion)((cx)->version & \ |
1468 |
JSVERSION_MASK)) |
1469 |
#define JS_HAS_XML_OPTION(cx) ((cx)->version & JSVERSION_HAS_XML || \ |
1470 |
JSVERSION_NUMBER(cx) >= JSVERSION_1_6) |
1471 |
|
1472 |
extern JSThreadData * |
1473 |
js_CurrentThreadData(JSRuntime *rt); |
1474 |
|
1475 |
extern JSBool |
1476 |
js_InitThreads(JSRuntime *rt); |
1477 |
|
1478 |
extern void |
1479 |
js_FinishThreads(JSRuntime *rt); |
1480 |
|
1481 |
extern void |
1482 |
js_PurgeThreads(JSContext *cx); |
1483 |
|
1484 |
extern void |
1485 |
js_TraceThreads(JSRuntime *rt, JSTracer *trc); |
1486 |
|
1487 |
/* |
1488 |
* Ensures the JSOPTION_XML and JSOPTION_ANONFUNFIX bits of cx->options are |
1489 |
* reflected in cx->version, since each bit must travel with a script that has |
1490 |
* it set. |
1491 |
*/ |
1492 |
extern void |
1493 |
js_SyncOptionsToVersion(JSContext *cx); |
1494 |
|
1495 |
/* |
1496 |
* Common subroutine of JS_SetVersion and js_SetVersion, to update per-context |
1497 |
* data that depends on version. |
1498 |
*/ |
1499 |
extern void |
1500 |
js_OnVersionChange(JSContext *cx); |
1501 |
|
1502 |
/* |
1503 |
* Unlike the JS_SetVersion API, this function stores JSVERSION_HAS_XML and |
1504 |
* any future non-version-number flags induced by compiler options. |
1505 |
*/ |
1506 |
extern void |
1507 |
js_SetVersion(JSContext *cx, JSVersion version); |
1508 |
|
1509 |
/* |
1510 |
* Create and destroy functions for JSContext, which is manually allocated |
1511 |
* and exclusively owned. |
1512 |
*/ |
1513 |
extern JSContext * |
1514 |
js_NewContext(JSRuntime *rt, size_t stackChunkSize); |
1515 |
|
1516 |
extern void |
1517 |
js_DestroyContext(JSContext *cx, JSDestroyContextMode mode); |
1518 |
|
1519 |
/* |
1520 |
* Return true if cx points to a context in rt->contextList, else return false. |
1521 |
* NB: the caller (see jslock.c:ClaimTitle) must hold rt->gcLock. |
1522 |
*/ |
1523 |
extern JSBool |
1524 |
js_ValidContextPointer(JSRuntime *rt, JSContext *cx); |
1525 |
|
1526 |
static JS_INLINE JSContext * |
1527 |
js_ContextFromLinkField(JSCList *link) |
1528 |
{ |
1529 |
JS_ASSERT(link); |
1530 |
return (JSContext *) ((uint8 *) link - offsetof(JSContext, link)); |
1531 |
} |
1532 |
|
1533 |
/* |
1534 |
* If unlocked, acquire and release rt->gcLock around *iterp update; otherwise |
1535 |
* the caller must be holding rt->gcLock. |
1536 |
*/ |
1537 |
extern JSContext * |
1538 |
js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp); |
1539 |
|
1540 |
/* |
1541 |
* Iterate through contexts with active requests. The caller must be holding |
1542 |
* rt->gcLock in case of a thread-safe build, or otherwise guarantee that the |
1543 |
* context list is not alternated asynchroniously. |
1544 |
*/ |
1545 |
extern JS_FRIEND_API(JSContext *) |
1546 |
js_NextActiveContext(JSRuntime *, JSContext *); |
1547 |
|
1548 |
#ifdef JS_THREADSAFE |
1549 |
|
1550 |
/* |
1551 |
* Count the number of contexts entered requests on the current thread. |
1552 |
*/ |
1553 |
uint32 |
1554 |
js_CountThreadRequests(JSContext *cx); |
1555 |
|
1556 |
/* |
1557 |
* This is a helper for code at can potentially run outside JS request to |
1558 |
* ensure that the GC is not running when the function returns. |
1559 |
* |
1560 |
* This function must be called with the GC lock held. |
1561 |
*/ |
1562 |
extern void |
1563 |
js_WaitForGC(JSRuntime *rt); |
1564 |
|
1565 |
/* |
1566 |
* If we're in one or more requests (possibly on more than one context) |
1567 |
* running on the current thread, indicate, temporarily, that all these |
1568 |
* requests are inactive so a possible GC can proceed on another thread. |
1569 |
* This function returns the number of discounted requests. The number must |
1570 |
* be passed later to js_ActivateRequestAfterGC to reactivate the requests. |
1571 |
* |
1572 |
* This function must be called with the GC lock held. |
1573 |
*/ |
1574 |
uint32 |
1575 |
js_DiscountRequestsForGC(JSContext *cx); |
1576 |
|
1577 |
/* |
1578 |
* This function must be called with the GC lock held. |
1579 |
*/ |
1580 |
void |
1581 |
js_RecountRequestsAfterGC(JSRuntime *rt, uint32 requestDebit); |
1582 |
|
1583 |
#else /* !JS_THREADSAFE */ |
1584 |
|
1585 |
# define js_WaitForGC(rt) ((void) 0) |
1586 |
|
1587 |
#endif |
1588 |
|
1589 |
/* |
1590 |
* JSClass.resolve and watchpoint recursion damping machinery. |
1591 |
*/ |
1592 |
extern JSBool |
1593 |
js_StartResolving(JSContext *cx, JSResolvingKey *key, uint32 flag, |
1594 |
JSResolvingEntry **entryp); |
1595 |
|
1596 |
extern void |
1597 |
js_StopResolving(JSContext *cx, JSResolvingKey *key, uint32 flag, |
1598 |
JSResolvingEntry *entry, uint32 generation); |
1599 |
|
1600 |
/* |
1601 |
* Local root set management. |
1602 |
* |
1603 |
* NB: the jsval parameters below may be properly tagged jsvals, or GC-thing |
1604 |
* pointers cast to (jsval). This relies on JSObject's tag being zero, but |
1605 |
* on the up side it lets us push int-jsval-encoded scopeMark values on the |
1606 |
* local root stack. |
1607 |
*/ |
1608 |
extern JSBool |
1609 |
js_EnterLocalRootScope(JSContext *cx); |
1610 |
|
1611 |
#define js_LeaveLocalRootScope(cx) \ |
1612 |
js_LeaveLocalRootScopeWithResult(cx, JSVAL_NULL) |
1613 |
|
1614 |
extern void |
1615 |
js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval); |
1616 |
|
1617 |
extern void |
1618 |
js_ForgetLocalRoot(JSContext *cx, jsval v); |
1619 |
|
1620 |
extern int |
1621 |
js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v); |
1622 |
|
1623 |
extern void |
1624 |
js_TraceLocalRoots(JSTracer *trc, JSLocalRootStack *lrs); |
1625 |
|
1626 |
/* |
1627 |
* Report an exception, which is currently realized as a printf-style format |
1628 |
* string and its arguments. |
1629 |
*/ |
1630 |
typedef enum JSErrNum { |
1631 |
#define MSG_DEF(name, number, count, exception, format) \ |
1632 |
name = number, |
1633 |
#include "js.msg" |
1634 |
#undef MSG_DEF |
1635 |
JSErr_Limit |
1636 |
} JSErrNum; |
1637 |
|
1638 |
extern JS_FRIEND_API(const JSErrorFormatString *) |
1639 |
js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber); |
1640 |
|
1641 |
#ifdef va_start |
1642 |
extern JSBool |
1643 |
js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap); |
1644 |
|
1645 |
extern JSBool |
1646 |
js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback, |
1647 |
void *userRef, const uintN errorNumber, |
1648 |
JSBool charArgs, va_list ap); |
1649 |
|
1650 |
extern JSBool |
1651 |
js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback, |
1652 |
void *userRef, const uintN errorNumber, |
1653 |
char **message, JSErrorReport *reportp, |
1654 |
JSBool *warningp, JSBool charArgs, va_list ap); |
1655 |
#endif |
1656 |
|
1657 |
extern void |
1658 |
js_ReportOutOfMemory(JSContext *cx); |
1659 |
|
1660 |
/* |
1661 |
* Report that cx->scriptStackQuota is exhausted. |
1662 |
*/ |
1663 |
extern void |
1664 |
js_ReportOutOfScriptQuota(JSContext *cx); |
1665 |
|
1666 |
extern void |
1667 |
js_ReportOverRecursed(JSContext *cx); |
1668 |
|
1669 |
extern void |
1670 |
js_ReportAllocationOverflow(JSContext *cx); |
1671 |
|
1672 |
#define JS_CHECK_RECURSION(cx, onerror) \ |
1673 |
JS_BEGIN_MACRO \ |
1674 |
int stackDummy_; \ |
1675 |
\ |
1676 |
if (!JS_CHECK_STACK_SIZE(cx, stackDummy_)) { \ |
1677 |
js_ReportOverRecursed(cx); \ |
1678 |
onerror; \ |
1679 |
} \ |
1680 |
JS_END_MACRO |
1681 |
|
1682 |
/* |
1683 |
* Report an exception using a previously composed JSErrorReport. |
1684 |
* XXXbe remove from "friend" API |
1685 |
*/ |
1686 |
extern JS_FRIEND_API(void) |
1687 |
js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *report); |
1688 |
|
1689 |
extern void |
1690 |
js_ReportIsNotDefined(JSContext *cx, const char *name); |
1691 |
|
1692 |
/* |
1693 |
* Report an attempt to access the property of a null or undefined value (v). |
1694 |
*/ |
1695 |
extern JSBool |
1696 |
js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, jsval v, |
1697 |
JSString *fallback); |
1698 |
|
1699 |
extern void |
1700 |
js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg); |
1701 |
|
1702 |
/* |
1703 |
* Report error using js_DecompileValueGenerator(cx, spindex, v, fallback) as |
1704 |
* the first argument for the error message. If the error message has less |
1705 |
* then 3 arguments, use null for arg1 or arg2. |
1706 |
*/ |
1707 |
extern JSBool |
1708 |
js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber, |
1709 |
intN spindex, jsval v, JSString *fallback, |
1710 |
const char *arg1, const char *arg2); |
1711 |
|
1712 |
#define js_ReportValueError(cx,errorNumber,spindex,v,fallback) \ |
1713 |
((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \ |
1714 |
spindex, v, fallback, NULL, NULL)) |
1715 |
|
1716 |
#define js_ReportValueError2(cx,errorNumber,spindex,v,fallback,arg1) \ |
1717 |
((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \ |
1718 |
spindex, v, fallback, arg1, NULL)) |
1719 |
|
1720 |
#define js_ReportValueError3(cx,errorNumber,spindex,v,fallback,arg1,arg2) \ |
1721 |
((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \ |
1722 |
spindex, v, fallback, arg1, arg2)) |
1723 |
|
1724 |
extern JSErrorFormatString js_ErrorFormatString[JSErr_Limit]; |
1725 |
|
1726 |
/* |
1727 |
* See JS_SetThreadStackLimit in jsapi.c, where we check that the stack grows |
1728 |
* in the expected direction. On Unix-y systems, JS_STACK_GROWTH_DIRECTION is |
1729 |
* computed on the build host by jscpucfg.c and written into jsautocfg.h. The |
1730 |
* macro is hardcoded in jscpucfg.h on Windows and Mac systems (for historical |
1731 |
* reasons pre-dating autoconf usage). |
1732 |
*/ |
1733 |
#if JS_STACK_GROWTH_DIRECTION > 0 |
1734 |
# define JS_CHECK_STACK_SIZE(cx, lval) ((jsuword)&(lval) < (cx)->stackLimit) |
1735 |
#else |
1736 |
# define JS_CHECK_STACK_SIZE(cx, lval) ((jsuword)&(lval) > (cx)->stackLimit) |
1737 |
#endif |
1738 |
|
1739 |
/* |
1740 |
* If the operation callback flag was set, call the operation callback. |
1741 |
* This macro can run the full GC. Return true if it is OK to continue and |
1742 |
* false otherwise. |
1743 |
*/ |
1744 |
#define JS_CHECK_OPERATION_LIMIT(cx) \ |
1745 |
(!(cx)->operationCallbackFlag || js_InvokeOperationCallback(cx)) |
1746 |
|
1747 |
/* |
1748 |
* Invoke the operation callback and return false if the current execution |
1749 |
* is to be terminated. |
1750 |
*/ |
1751 |
extern JSBool |
1752 |
js_InvokeOperationCallback(JSContext *cx); |
1753 |
|
1754 |
#ifndef JS_THREADSAFE |
1755 |
# define js_TriggerAllOperationCallbacks(rt, gcLocked) \ |
1756 |
js_TriggerAllOperationCallbacks (rt) |
1757 |
#endif |
1758 |
|
1759 |
void |
1760 |
js_TriggerAllOperationCallbacks(JSRuntime *rt, JSBool gcLocked); |
1761 |
|
1762 |
extern JSStackFrame * |
1763 |
js_GetScriptedCaller(JSContext *cx, JSStackFrame *fp); |
1764 |
|
1765 |
extern jsbytecode* |
1766 |
js_GetCurrentBytecodePC(JSContext* cx); |
1767 |
|
1768 |
#ifdef __cplusplus /* Allow inclusion from LiveConnect C files. */ |
1769 |
extern bool |
1770 |
#else |
1771 |
extern JSBool |
1772 |
#endif |
1773 |
js_CurrentPCIsInImacro(JSContext *cx); |
1774 |
|
1775 |
#ifdef JS_TRACER |
1776 |
/* |
1777 |
* Reconstruct the JS stack and clear cx->tracecx. We must be currently in a |
1778 |
* _FAIL builtin from trace on cx or another context on the same thread. The |
1779 |
* machine code for the trace remains on the C stack when js_DeepBail returns. |
1780 |
* |
1781 |
* Implemented in jstracer.cpp. |
1782 |
*/ |
1783 |
JS_FORCES_STACK JS_FRIEND_API(void) |
1784 |
js_DeepBail(JSContext *cx); |
1785 |
#endif |
1786 |
|
1787 |
static JS_FORCES_STACK JS_INLINE void |
1788 |
js_LeaveTrace(JSContext *cx) |
1789 |
{ |
1790 |
#ifdef JS_TRACER |
1791 |
if (JS_ON_TRACE(cx)) |
1792 |
js_DeepBail(cx); |
1793 |
#endif |
1794 |
} |
1795 |
|
1796 |
static JS_INLINE void |
1797 |
js_LeaveTraceIfGlobalObject(JSContext *cx, JSObject *obj) |
1798 |
{ |
1799 |
if (!obj->fslots[JSSLOT_PARENT]) |
1800 |
js_LeaveTrace(cx); |
1801 |
} |
1802 |
|
1803 |
static JS_INLINE JSBool |
1804 |
js_CanLeaveTrace(JSContext *cx) |
1805 |
{ |
1806 |
JS_ASSERT(JS_ON_TRACE(cx)); |
1807 |
#ifdef JS_TRACER |
1808 |
return cx->bailExit != NULL; |
1809 |
#else |
1810 |
return JS_FALSE; |
1811 |
#endif |
1812 |
} |
1813 |
|
1814 |
/* |
1815 |
* Get the current cx->fp, first lazily instantiating stack frames if needed. |
1816 |
* (Do not access cx->fp directly except in JS_REQUIRES_STACK code.) |
1817 |
* |
1818 |
* Defined in jstracer.cpp if JS_TRACER is defined. |
1819 |
*/ |
1820 |
static JS_FORCES_STACK JS_INLINE JSStackFrame * |
1821 |
js_GetTopStackFrame(JSContext *cx) |
1822 |
{ |
1823 |
js_LeaveTrace(cx); |
1824 |
return cx->fp; |
1825 |
} |
1826 |
|
1827 |
static JS_INLINE JSBool |
1828 |
js_IsPropertyCacheDisabled(JSContext *cx) |
1829 |
{ |
1830 |
return cx->runtime->shapeGen >= SHAPE_OVERFLOW_BIT; |
1831 |
} |
1832 |
|
1833 |
static JS_INLINE uint32 |
1834 |
js_RegenerateShapeForGC(JSContext *cx) |
1835 |
{ |
1836 |
JS_ASSERT(cx->runtime->gcRunning); |
1837 |
JS_ASSERT(cx->runtime->gcRegenShapes); |
1838 |
|
1839 |
/* |
1840 |
* Under the GC, compared with js_GenerateShape, we don't need to use |
1841 |
* atomic increments but we still must make sure that after an overflow |
1842 |
* the shape stays such. |
1843 |
*/ |
1844 |
uint32 shape = cx->runtime->shapeGen; |
1845 |
shape = (shape + 1) | (shape & SHAPE_OVERFLOW_BIT); |
1846 |
cx->runtime->shapeGen = shape; |
1847 |
return shape; |
1848 |
} |
1849 |
|
1850 |
#endif /* jscntxt_h___ */ |