1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sw=4 et tw=80:
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 : /*
42 : * JS execution context.
43 : */
44 :
45 : #include <limits.h> /* make sure that <features.h> is included and we can use
46 : __GLIBC__ to detect glibc presence */
47 : #include <new>
48 : #include <stdarg.h>
49 : #include <stdlib.h>
50 : #include <string.h>
51 : #ifdef ANDROID
52 : # include <android/log.h>
53 : # include <fstream>
54 : # include <string>
55 : #endif // ANDROID
56 :
57 : #include "jstypes.h"
58 : #include "jsutil.h"
59 : #include "jsclist.h"
60 : #include "jsprf.h"
61 : #include "jsatom.h"
62 : #include "jscntxt.h"
63 : #include "jsversion.h"
64 : #include "jsdbgapi.h"
65 : #include "jsexn.h"
66 : #include "jsfun.h"
67 : #include "jsgc.h"
68 : #include "jsgcmark.h"
69 : #include "jsiter.h"
70 : #include "jslock.h"
71 : #include "jsmath.h"
72 : #include "jsnum.h"
73 : #include "jsobj.h"
74 : #include "jsopcode.h"
75 : #include "jspubtd.h"
76 : #include "jsscope.h"
77 : #include "jsscript.h"
78 : #include "jsstr.h"
79 :
80 : #ifdef JS_METHODJIT
81 : # include "assembler/assembler/MacroAssembler.h"
82 : # include "methodjit/MethodJIT.h"
83 : #endif
84 : #include "frontend/TokenStream.h"
85 : #include "frontend/ParseMaps.h"
86 : #include "yarr/BumpPointerAllocator.h"
87 :
88 : #include "jsatominlines.h"
89 : #include "jscntxtinlines.h"
90 : #include "jscompartment.h"
91 : #include "jsobjinlines.h"
92 :
93 : using namespace js;
94 : using namespace js::gc;
95 :
96 : void
97 0 : JSRuntime::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *normal, size_t *temporary,
98 : size_t *regexpCode, size_t *stackCommitted, size_t *gcMarkerSize)
99 : {
100 0 : if (normal)
101 0 : *normal = mallocSizeOf(dtoaState);
102 :
103 0 : if (temporary)
104 0 : *temporary = tempLifoAlloc.sizeOfExcludingThis(mallocSizeOf);
105 :
106 0 : if (regexpCode) {
107 0 : size_t method = 0, regexp = 0, unused = 0;
108 0 : if (execAlloc_)
109 0 : execAlloc_->sizeOfCode(&method, ®exp, &unused);
110 0 : JS_ASSERT(method == 0); /* this execAlloc is only used for regexp code */
111 0 : *regexpCode = regexp + unused;
112 : }
113 :
114 0 : if (stackCommitted)
115 0 : *stackCommitted = stackSpace.sizeOfCommitted();
116 :
117 0 : if (gcMarkerSize)
118 0 : *gcMarkerSize = gcMarker.sizeOfExcludingThis(mallocSizeOf);
119 0 : }
120 :
121 : void
122 172 : JSRuntime::triggerOperationCallback()
123 : {
124 : /*
125 : * Use JS_ATOMIC_SET in the hope that it ensures the write will become
126 : * immediately visible to other processors polling the flag.
127 : */
128 172 : JS_ATOMIC_SET(&interrupt, 1);
129 172 : }
130 :
131 : void
132 0 : JSRuntime::setJitHardening(bool enabled)
133 : {
134 0 : jitHardening = enabled;
135 0 : if (execAlloc_)
136 0 : execAlloc_->setRandomize(enabled);
137 0 : }
138 :
139 : JSC::ExecutableAllocator *
140 1015 : JSRuntime::createExecutableAllocator(JSContext *cx)
141 : {
142 1015 : JS_ASSERT(!execAlloc_);
143 1015 : JS_ASSERT(cx->runtime == this);
144 :
145 : JSC::AllocationBehavior randomize =
146 1015 : jitHardening ? JSC::AllocationCanRandomize : JSC::AllocationDeterministic;
147 1015 : execAlloc_ = new_<JSC::ExecutableAllocator>(randomize);
148 1015 : if (!execAlloc_)
149 0 : js_ReportOutOfMemory(cx);
150 1015 : return execAlloc_;
151 : }
152 :
153 : WTF::BumpPointerAllocator *
154 90 : JSRuntime::createBumpPointerAllocator(JSContext *cx)
155 : {
156 90 : JS_ASSERT(!bumpAlloc_);
157 90 : JS_ASSERT(cx->runtime == this);
158 :
159 90 : bumpAlloc_ = new_<WTF::BumpPointerAllocator>();
160 90 : if (!bumpAlloc_)
161 0 : js_ReportOutOfMemory(cx);
162 90 : return bumpAlloc_;
163 : }
164 :
165 : JSScript *
166 0 : js_GetCurrentScript(JSContext *cx)
167 : {
168 0 : return cx->hasfp() ? cx->fp()->maybeScript() : NULL;
169 : }
170 :
171 : JSContext *
172 18771 : js_NewContext(JSRuntime *rt, size_t stackChunkSize)
173 : {
174 18771 : JS_AbortIfWrongThread(rt);
175 :
176 18771 : JSContext *cx = OffTheBooks::new_<JSContext>(rt);
177 18771 : if (!cx)
178 0 : return NULL;
179 :
180 18771 : JS_ASSERT(cx->findVersion() == JSVERSION_DEFAULT);
181 :
182 18771 : if (!cx->busyArrays.init()) {
183 0 : Foreground::delete_(cx);
184 0 : return NULL;
185 : }
186 :
187 : /*
188 : * Here the GC lock is still held after js_InitContextThreadAndLockGC took it and
189 : * the GC is not running on another thread.
190 : */
191 18771 : bool first = JS_CLIST_IS_EMPTY(&rt->contextList);
192 18771 : JS_APPEND_LINK(&cx->link, &rt->contextList);
193 :
194 18771 : js_InitRandom(cx);
195 :
196 : /*
197 : * If cx is the first context on this runtime, initialize well-known atoms,
198 : * keywords, numbers, and strings. If one of these steps should fail, the
199 : * runtime will be left in a partially initialized state, with zeroes and
200 : * nulls stored in the default-initialized remainder of the struct. We'll
201 : * clean the runtime up under js_DestroyContext, because cx will be "last"
202 : * as well as "first".
203 : */
204 18771 : if (first) {
205 : #ifdef JS_THREADSAFE
206 18761 : JS_BeginRequest(cx);
207 : #endif
208 18761 : bool ok = rt->staticStrings.init(cx);
209 18761 : if (ok)
210 18761 : ok = InitCommonAtoms(cx);
211 :
212 : #ifdef JS_THREADSAFE
213 18761 : JS_EndRequest(cx);
214 : #endif
215 18761 : if (!ok) {
216 0 : js_DestroyContext(cx, JSDCM_NEW_FAILED);
217 0 : return NULL;
218 : }
219 : }
220 :
221 18771 : JSContextCallback cxCallback = rt->cxCallback;
222 18771 : if (cxCallback && !cxCallback(cx, JSCONTEXT_NEW)) {
223 0 : js_DestroyContext(cx, JSDCM_NEW_FAILED);
224 0 : return NULL;
225 : }
226 :
227 18771 : return cx;
228 : }
229 :
230 : void
231 18771 : js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
232 : {
233 18771 : JSRuntime *rt = cx->runtime;
234 18771 : JS_AbortIfWrongThread(rt);
235 :
236 18771 : JS_ASSERT(!cx->enumerators);
237 :
238 : #ifdef JS_THREADSAFE
239 18771 : JS_ASSERT(cx->outstandingRequests == 0);
240 : #endif
241 :
242 18771 : if (mode != JSDCM_NEW_FAILED) {
243 18771 : if (JSContextCallback cxCallback = rt->cxCallback) {
244 : /*
245 : * JSCONTEXT_DESTROY callback is not allowed to fail and must
246 : * return true.
247 : */
248 0 : DebugOnly<JSBool> callbackStatus = cxCallback(cx, JSCONTEXT_DESTROY);
249 0 : JS_ASSERT(callbackStatus);
250 : }
251 : }
252 :
253 18771 : JS_REMOVE_LINK(&cx->link);
254 18771 : bool last = !rt->hasContexts();
255 18771 : if (last) {
256 18761 : JS_ASSERT(!rt->gcRunning);
257 :
258 : #ifdef JS_THREADSAFE
259 : {
260 37522 : AutoLockGC lock(rt);
261 18761 : rt->gcHelperThread.waitBackgroundSweepEnd();
262 : }
263 : #endif
264 :
265 : /*
266 : * Dump remaining type inference results first. This printing
267 : * depends on atoms still existing.
268 : */
269 60022 : for (CompartmentsIter c(rt); !c.done(); c.next())
270 41261 : c->types.print(cx, false);
271 :
272 : /* Unpin all common atoms before final GC. */
273 18761 : FinishCommonAtoms(cx->runtime);
274 :
275 : /* Clear debugging state to remove GC roots. */
276 60022 : for (CompartmentsIter c(rt); !c.done(); c.next())
277 41261 : c->clearTraps(cx);
278 18761 : JS_ClearAllWatchPoints(cx);
279 :
280 18761 : PrepareForFullGC(rt);
281 18761 : GC(cx, GC_NORMAL, gcreason::LAST_CONTEXT);
282 10 : } else if (mode == JSDCM_FORCE_GC) {
283 10 : JS_ASSERT(!rt->gcRunning);
284 10 : PrepareForFullGC(rt);
285 10 : GC(cx, GC_NORMAL, gcreason::DESTROY_CONTEXT);
286 0 : } else if (mode == JSDCM_MAYBE_GC) {
287 0 : JS_ASSERT(!rt->gcRunning);
288 0 : JS_MaybeGC(cx);
289 : }
290 :
291 : #ifdef JS_THREADSAFE
292 : {
293 37542 : AutoLockGC lock(rt);
294 18771 : rt->gcHelperThread.waitBackgroundSweepEnd();
295 : }
296 : #endif
297 18771 : Foreground::delete_(cx);
298 18771 : }
299 :
300 : namespace js {
301 :
302 : bool
303 150616 : AutoResolving::alreadyStartedSlow() const
304 : {
305 150616 : JS_ASSERT(link);
306 150616 : AutoResolving *cursor = link;
307 619432 : do {
308 626381 : JS_ASSERT(this != cursor);
309 626381 : if (object == cursor->object && id == cursor->id && kind == cursor->kind)
310 6949 : return true;
311 : } while (!!(cursor = cursor->link));
312 143667 : return false;
313 : }
314 :
315 : } /* namespace js */
316 :
317 : static void
318 475006 : ReportError(JSContext *cx, const char *message, JSErrorReport *reportp,
319 : JSErrorCallback callback, void *userRef)
320 : {
321 : /*
322 : * Check the error report, and set a JavaScript-catchable exception
323 : * if the error is defined to have an associated exception. If an
324 : * exception is thrown, then the JSREPORT_EXCEPTION flag will be set
325 : * on the error report, and exception-aware hosts should ignore it.
326 : */
327 475006 : JS_ASSERT(reportp);
328 475006 : if ((!callback || callback == js_GetErrorMessage) &&
329 : reportp->errorNumber == JSMSG_UNCAUGHT_EXCEPTION)
330 153 : reportp->flags |= JSREPORT_EXCEPTION;
331 :
332 : /*
333 : * Call the error reporter only if an exception wasn't raised.
334 : *
335 : * If an exception was raised, then we call the debugErrorHook
336 : * (if present) to give it a chance to see the error before it
337 : * propagates out of scope. This is needed for compatibility
338 : * with the old scheme.
339 : */
340 949858 : if (!JS_IsRunning(cx) ||
341 474852 : !js_ErrorToException(cx, message, reportp, callback, userRef)) {
342 464689 : js_ReportErrorAgain(cx, message, reportp);
343 10317 : } else if (JSDebugErrorHook hook = cx->runtime->debugHooks.debugErrorHook) {
344 0 : if (cx->errorReporter)
345 0 : hook(cx, message, reportp, cx->runtime->debugHooks.debugErrorHookData);
346 : }
347 475006 : }
348 :
349 : /*
350 : * The given JSErrorReport object have been zeroed and must not outlive
351 : * cx->fp() (otherwise report->originPrincipals may become invalid).
352 : */
353 : static void
354 475025 : PopulateReportBlame(JSContext *cx, JSErrorReport *report)
355 : {
356 : /*
357 : * Walk stack until we find a frame that is associated with some script
358 : * rather than a native frame.
359 : */
360 475025 : for (FrameRegsIter iter(cx); !iter.done(); ++iter) {
361 474871 : if (iter.fp()->isScriptFrame()) {
362 474871 : report->filename = iter.fp()->script()->filename;
363 474871 : report->lineno = PCToLineNumber(iter.fp()->script(), iter.pc());
364 474871 : report->originPrincipals = iter.fp()->script()->originPrincipals;
365 474871 : break;
366 : }
367 : }
368 475025 : }
369 :
370 : /*
371 : * We don't post an exception in this case, since doing so runs into
372 : * complications of pre-allocating an exception object which required
373 : * running the Exception class initializer early etc.
374 : * Instead we just invoke the errorReporter with an "Out Of Memory"
375 : * type message, and then hope the process ends swiftly.
376 : */
377 : void
378 19 : js_ReportOutOfMemory(JSContext *cx)
379 : {
380 19 : cx->runtime->hadOutOfMemory = true;
381 :
382 : JSErrorReport report;
383 19 : JSErrorReporter onError = cx->errorReporter;
384 :
385 : /* Get the message for this error, but we won't expand any arguments. */
386 : const JSErrorFormatString *efs =
387 19 : js_GetLocalizedErrorMessage(cx, NULL, NULL, JSMSG_OUT_OF_MEMORY);
388 19 : const char *msg = efs ? efs->format : "Out of memory";
389 :
390 : /* Fill out the report, but don't do anything that requires allocation. */
391 19 : PodZero(&report);
392 19 : report.flags = JSREPORT_ERROR;
393 19 : report.errorNumber = JSMSG_OUT_OF_MEMORY;
394 19 : PopulateReportBlame(cx, &report);
395 :
396 : /*
397 : * If debugErrorHook is present then we give it a chance to veto sending
398 : * the error on to the regular ErrorReporter. We also clear a pending
399 : * exception if any now so the hooks can replace the out-of-memory error
400 : * by a script-catchable exception.
401 : */
402 19 : cx->clearPendingException();
403 19 : if (onError) {
404 19 : JSDebugErrorHook hook = cx->runtime->debugHooks.debugErrorHook;
405 19 : if (hook &&
406 0 : !hook(cx, msg, &report, cx->runtime->debugHooks.debugErrorHookData)) {
407 0 : onError = NULL;
408 : }
409 : }
410 :
411 19 : if (onError) {
412 38 : AutoAtomicIncrement incr(&cx->runtime->inOOMReport);
413 19 : onError(cx, msg, &report);
414 : }
415 19 : }
416 :
417 : JS_FRIEND_API(void)
418 464779 : js_ReportOverRecursed(JSContext *maybecx)
419 : {
420 : #ifdef JS_MORE_DETERMINISTIC
421 : /*
422 : * We cannot make stack depth deterministic across different
423 : * implementations (e.g. JIT vs. interpreter will differ in
424 : * their maximum stack depth).
425 : * However, we can detect externally when we hit the maximum
426 : * stack depth which is useful for external testing programs
427 : * like fuzzers.
428 : */
429 : fprintf(stderr, "js_ReportOverRecursed called\n");
430 : #endif
431 464779 : if (maybecx)
432 464779 : JS_ReportErrorNumber(maybecx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED);
433 464779 : }
434 :
435 : void
436 18 : js_ReportAllocationOverflow(JSContext *maybecx)
437 : {
438 18 : if (maybecx)
439 18 : JS_ReportErrorNumber(maybecx, js_GetErrorMessage, NULL, JSMSG_ALLOC_OVERFLOW);
440 18 : }
441 :
442 : /*
443 : * Given flags and the state of cx, decide whether we should report an
444 : * error, a warning, or just continue execution normally. Return
445 : * true if we should continue normally, without reporting anything;
446 : * otherwise, adjust *flags as appropriate and return false.
447 : */
448 : static bool
449 475592 : checkReportFlags(JSContext *cx, unsigned *flags)
450 : {
451 475592 : if (JSREPORT_IS_STRICT_MODE_ERROR(*flags)) {
452 : /*
453 : * Error in strict code; warning with strict option; okay otherwise.
454 : * We assume that if the top frame is a native, then it is strict if
455 : * the nearest scripted frame is strict, see bug 536306.
456 : */
457 83 : JSScript *script = cx->stack.currentScript();
458 83 : if (script && script->strictModeCode)
459 28 : *flags &= ~JSREPORT_WARNING;
460 55 : else if (cx->hasStrictOption())
461 0 : *flags |= JSREPORT_WARNING;
462 : else
463 55 : return true;
464 475509 : } else if (JSREPORT_IS_STRICT(*flags)) {
465 : /* Warning/error only when JSOPTION_STRICT is set. */
466 531 : if (!cx->hasStrictOption())
467 531 : return true;
468 : }
469 :
470 : /* Warnings become errors when JSOPTION_WERROR is set. */
471 475006 : if (JSREPORT_IS_WARNING(*flags) && cx->hasWErrorOption())
472 0 : *flags &= ~JSREPORT_WARNING;
473 :
474 475006 : return false;
475 : }
476 :
477 : JSBool
478 63 : js_ReportErrorVA(JSContext *cx, unsigned flags, const char *format, va_list ap)
479 : {
480 : char *message;
481 : jschar *ucmessage;
482 : size_t messagelen;
483 : JSErrorReport report;
484 : JSBool warning;
485 :
486 63 : if (checkReportFlags(cx, &flags))
487 0 : return JS_TRUE;
488 :
489 63 : message = JS_vsmprintf(format, ap);
490 63 : if (!message)
491 0 : return JS_FALSE;
492 63 : messagelen = strlen(message);
493 :
494 63 : PodZero(&report);
495 63 : report.flags = flags;
496 63 : report.errorNumber = JSMSG_USER_DEFINED_ERROR;
497 63 : report.ucmessage = ucmessage = InflateString(cx, message, &messagelen);
498 63 : PopulateReportBlame(cx, &report);
499 :
500 63 : warning = JSREPORT_IS_WARNING(report.flags);
501 :
502 63 : ReportError(cx, message, &report, NULL, NULL);
503 63 : Foreground::free_(message);
504 63 : Foreground::free_(ucmessage);
505 63 : return warning;
506 : }
507 :
508 : namespace js {
509 :
510 : /* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */
511 : void
512 0 : ReportUsageError(JSContext *cx, JSObject *callee, const char *msg)
513 : {
514 0 : const char *usageStr = "usage";
515 0 : JSAtom *usageAtom = js_Atomize(cx, usageStr, strlen(usageStr));
516 0 : DebugOnly<const Shape *> shape = callee->nativeLookup(cx, ATOM_TO_JSID(usageAtom));
517 0 : JS_ASSERT(!shape->configurable());
518 0 : JS_ASSERT(!shape->writable());
519 0 : JS_ASSERT(shape->hasDefaultGetter());
520 :
521 : jsval usage;
522 0 : if (!JS_LookupProperty(cx, callee, "usage", &usage))
523 : return;
524 :
525 0 : if (JSVAL_IS_VOID(usage)) {
526 0 : JS_ReportError(cx, "%s", msg);
527 : } else {
528 0 : JSString *str = JSVAL_TO_STRING(usage);
529 0 : JS::Anchor<JSString *> a_str(str);
530 0 : const jschar *chars = JS_GetStringCharsZ(cx, str);
531 0 : if (!chars)
532 : return;
533 0 : JS_ReportError(cx, "%s. Usage: %hs", msg, chars);
534 : }
535 : }
536 :
537 : } /* namespace js */
538 :
539 : /*
540 : * The arguments from ap need to be packaged up into an array and stored
541 : * into the report struct.
542 : *
543 : * The format string addressed by the error number may contain operands
544 : * identified by the format {N}, where N is a decimal digit. Each of these
545 : * is to be replaced by the Nth argument from the va_list. The complete
546 : * message is placed into reportp->ucmessage converted to a JSString.
547 : *
548 : * Returns true if the expansion succeeds (can fail if out of memory).
549 : */
550 : JSBool
551 475550 : js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
552 : void *userRef, const unsigned errorNumber,
553 : char **messagep, JSErrorReport *reportp,
554 : bool charArgs, va_list ap)
555 : {
556 : const JSErrorFormatString *efs;
557 : int i;
558 : int argCount;
559 :
560 475550 : *messagep = NULL;
561 :
562 : /* Most calls supply js_GetErrorMessage; if this is so, assume NULL. */
563 475550 : if (!callback || callback == js_GetErrorMessage)
564 475280 : efs = js_GetLocalizedErrorMessage(cx, userRef, NULL, errorNumber);
565 : else
566 270 : efs = callback(userRef, NULL, errorNumber);
567 475550 : if (efs) {
568 475550 : size_t totalArgsLength = 0;
569 : size_t argLengths[10]; /* only {0} thru {9} supported */
570 475550 : argCount = efs->argCount;
571 475550 : JS_ASSERT(argCount <= 10);
572 475550 : if (argCount > 0) {
573 : /*
574 : * Gather the arguments into an array, and accumulate
575 : * their sizes. We allocate 1 more than necessary and
576 : * null it out to act as the caboose when we free the
577 : * pointers later.
578 : */
579 : reportp->messageArgs = (const jschar **)
580 9515 : cx->malloc_(sizeof(jschar *) * (argCount + 1));
581 9515 : if (!reportp->messageArgs)
582 0 : return JS_FALSE;
583 9515 : reportp->messageArgs[argCount] = NULL;
584 25049 : for (i = 0; i < argCount; i++) {
585 15534 : if (charArgs) {
586 15534 : char *charArg = va_arg(ap, char *);
587 15534 : size_t charArgLength = strlen(charArg);
588 15534 : reportp->messageArgs[i] = InflateString(cx, charArg, &charArgLength);
589 15534 : if (!reportp->messageArgs[i])
590 0 : goto error;
591 : } else {
592 0 : reportp->messageArgs[i] = va_arg(ap, jschar *);
593 : }
594 15534 : argLengths[i] = js_strlen(reportp->messageArgs[i]);
595 15534 : totalArgsLength += argLengths[i];
596 : }
597 : /* NULL-terminate for easy copying. */
598 9515 : reportp->messageArgs[i] = NULL;
599 : }
600 : /*
601 : * Parse the error format, substituting the argument X
602 : * for {X} in the format.
603 : */
604 475550 : if (argCount > 0) {
605 9515 : if (efs->format) {
606 : jschar *buffer, *fmt, *out;
607 9515 : int expandedArgs = 0;
608 : size_t expandedLength;
609 9515 : size_t len = strlen(efs->format);
610 :
611 9515 : buffer = fmt = InflateString(cx, efs->format, &len);
612 9515 : if (!buffer)
613 0 : goto error;
614 : expandedLength = len
615 : - (3 * argCount) /* exclude the {n} */
616 9515 : + totalArgsLength;
617 :
618 : /*
619 : * Note - the above calculation assumes that each argument
620 : * is used once and only once in the expansion !!!
621 : */
622 : reportp->ucmessage = out = (jschar *)
623 9515 : cx->malloc_((expandedLength + 1) * sizeof(jschar));
624 9515 : if (!out) {
625 0 : cx->free_(buffer);
626 0 : goto error;
627 : }
628 264057 : while (*fmt) {
629 245027 : if (*fmt == '{') {
630 15534 : if (isdigit(fmt[1])) {
631 15534 : int d = JS7_UNDEC(fmt[1]);
632 15534 : JS_ASSERT(d < argCount);
633 15534 : js_strncpy(out, reportp->messageArgs[d],
634 31068 : argLengths[d]);
635 15534 : out += argLengths[d];
636 15534 : fmt += 3;
637 15534 : expandedArgs++;
638 15534 : continue;
639 : }
640 : }
641 229493 : *out++ = *fmt++;
642 : }
643 9515 : JS_ASSERT(expandedArgs == argCount);
644 9515 : *out = 0;
645 9515 : cx->free_(buffer);
646 : *messagep = DeflateString(cx, reportp->ucmessage,
647 9515 : size_t(out - reportp->ucmessage));
648 9515 : if (!*messagep)
649 0 : goto error;
650 : }
651 : } else {
652 : /*
653 : * Zero arguments: the format string (if it exists) is the
654 : * entire message.
655 : */
656 466035 : if (efs->format) {
657 : size_t len;
658 466035 : *messagep = JS_strdup(cx, efs->format);
659 466035 : if (!*messagep)
660 0 : goto error;
661 466035 : len = strlen(*messagep);
662 466035 : reportp->ucmessage = InflateString(cx, *messagep, &len);
663 466035 : if (!reportp->ucmessage)
664 0 : goto error;
665 : }
666 : }
667 : }
668 475550 : if (*messagep == NULL) {
669 : /* where's the right place for this ??? */
670 : const char *defaultErrorMessage
671 0 : = "No error message available for error number %d";
672 0 : size_t nbytes = strlen(defaultErrorMessage) + 16;
673 0 : *messagep = (char *)cx->malloc_(nbytes);
674 0 : if (!*messagep)
675 0 : goto error;
676 0 : JS_snprintf(*messagep, nbytes, defaultErrorMessage, errorNumber);
677 : }
678 475550 : return JS_TRUE;
679 :
680 : error:
681 0 : if (reportp->messageArgs) {
682 : /* free the arguments only if we allocated them */
683 0 : if (charArgs) {
684 0 : i = 0;
685 0 : while (reportp->messageArgs[i])
686 0 : cx->free_((void *)reportp->messageArgs[i++]);
687 : }
688 0 : cx->free_((void *)reportp->messageArgs);
689 0 : reportp->messageArgs = NULL;
690 : }
691 0 : if (reportp->ucmessage) {
692 0 : cx->free_((void *)reportp->ucmessage);
693 0 : reportp->ucmessage = NULL;
694 : }
695 0 : if (*messagep) {
696 0 : cx->free_((void *)*messagep);
697 0 : *messagep = NULL;
698 : }
699 0 : return JS_FALSE;
700 : }
701 :
702 : JSBool
703 475529 : js_ReportErrorNumberVA(JSContext *cx, unsigned flags, JSErrorCallback callback,
704 : void *userRef, const unsigned errorNumber,
705 : JSBool charArgs, va_list ap)
706 : {
707 : JSErrorReport report;
708 : char *message;
709 : JSBool warning;
710 :
711 475529 : if (checkReportFlags(cx, &flags))
712 586 : return JS_TRUE;
713 474943 : warning = JSREPORT_IS_WARNING(flags);
714 :
715 474943 : PodZero(&report);
716 474943 : report.flags = flags;
717 474943 : report.errorNumber = errorNumber;
718 474943 : PopulateReportBlame(cx, &report);
719 :
720 474943 : if (!js_ExpandErrorArguments(cx, callback, userRef, errorNumber,
721 474943 : &message, &report, !!charArgs, ap)) {
722 0 : return JS_FALSE;
723 : }
724 :
725 474943 : ReportError(cx, message, &report, callback, userRef);
726 :
727 474943 : if (message)
728 474943 : cx->free_(message);
729 474943 : if (report.messageArgs) {
730 : /*
731 : * js_ExpandErrorArguments owns its messageArgs only if it had to
732 : * inflate the arguments (from regular |char *|s).
733 : */
734 9308 : if (charArgs) {
735 9308 : int i = 0;
736 33754 : while (report.messageArgs[i])
737 15138 : cx->free_((void *)report.messageArgs[i++]);
738 : }
739 9308 : cx->free_((void *)report.messageArgs);
740 : }
741 474943 : if (report.ucmessage)
742 474943 : cx->free_((void *)report.ucmessage);
743 :
744 474943 : return warning;
745 : }
746 :
747 : JS_FRIEND_API(void)
748 465386 : js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp)
749 : {
750 : JSErrorReporter onError;
751 :
752 465386 : if (!message)
753 0 : return;
754 :
755 465386 : if (cx->lastMessage)
756 464439 : Foreground::free_(cx->lastMessage);
757 465386 : cx->lastMessage = JS_strdup(cx, message);
758 465386 : if (!cx->lastMessage)
759 0 : return;
760 465386 : onError = cx->errorReporter;
761 :
762 : /*
763 : * If debugErrorHook is present then we give it a chance to veto
764 : * sending the error on to the regular ErrorReporter.
765 : */
766 465386 : if (onError) {
767 914 : JSDebugErrorHook hook = cx->runtime->debugHooks.debugErrorHook;
768 914 : if (hook && !hook(cx, cx->lastMessage, reportp, cx->runtime->debugHooks.debugErrorHookData))
769 0 : onError = NULL;
770 : }
771 465386 : if (onError)
772 914 : onError(cx, cx->lastMessage, reportp);
773 : }
774 :
775 : void
776 1441 : js_ReportIsNotDefined(JSContext *cx, const char *name)
777 : {
778 1441 : JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_DEFINED, name);
779 1441 : }
780 :
781 : JSBool
782 313 : js_ReportIsNullOrUndefined(JSContext *cx, int spindex, const Value &v,
783 : JSString *fallback)
784 : {
785 : char *bytes;
786 : JSBool ok;
787 :
788 313 : bytes = DecompileValueGenerator(cx, spindex, v, fallback);
789 313 : if (!bytes)
790 0 : return JS_FALSE;
791 :
792 617 : if (strcmp(bytes, js_undefined_str) == 0 ||
793 304 : strcmp(bytes, js_null_str) == 0) {
794 : ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
795 : js_GetErrorMessage, NULL,
796 : JSMSG_NO_PROPERTIES, bytes,
797 36 : NULL, NULL);
798 277 : } else if (v.isUndefined()) {
799 : ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
800 : js_GetErrorMessage, NULL,
801 : JSMSG_UNEXPECTED_TYPE, bytes,
802 232 : js_undefined_str, NULL);
803 : } else {
804 45 : JS_ASSERT(v.isNull());
805 : ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
806 : js_GetErrorMessage, NULL,
807 : JSMSG_UNEXPECTED_TYPE, bytes,
808 45 : js_null_str, NULL);
809 : }
810 :
811 313 : cx->free_(bytes);
812 313 : return ok;
813 : }
814 :
815 : void
816 0 : js_ReportMissingArg(JSContext *cx, const Value &v, unsigned arg)
817 : {
818 : char argbuf[11];
819 : char *bytes;
820 : JSAtom *atom;
821 :
822 0 : JS_snprintf(argbuf, sizeof argbuf, "%u", arg);
823 0 : bytes = NULL;
824 0 : if (IsFunctionObject(v)) {
825 0 : atom = v.toObject().toFunction()->atom;
826 : bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK,
827 0 : v, atom);
828 0 : if (!bytes)
829 0 : return;
830 : }
831 : JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
832 : JSMSG_MISSING_FUN_ARG, argbuf,
833 0 : bytes ? bytes : "");
834 0 : cx->free_(bytes);
835 : }
836 :
837 : JSBool
838 3133 : js_ReportValueErrorFlags(JSContext *cx, unsigned flags, const unsigned errorNumber,
839 : int spindex, const Value &v, JSString *fallback,
840 : const char *arg1, const char *arg2)
841 : {
842 : char *bytes;
843 : JSBool ok;
844 :
845 3133 : JS_ASSERT(js_ErrorFormatString[errorNumber].argCount >= 1);
846 3133 : JS_ASSERT(js_ErrorFormatString[errorNumber].argCount <= 3);
847 3133 : bytes = DecompileValueGenerator(cx, spindex, v, fallback);
848 3133 : if (!bytes)
849 0 : return JS_FALSE;
850 :
851 : ok = JS_ReportErrorFlagsAndNumber(cx, flags, js_GetErrorMessage,
852 3133 : NULL, errorNumber, bytes, arg1, arg2);
853 3133 : cx->free_(bytes);
854 3133 : return ok;
855 : }
856 :
857 : JSErrorFormatString js_ErrorFormatString[JSErr_Limit] = {
858 : #define MSG_DEF(name, number, count, exception, format) \
859 : { format, count, exception } ,
860 : #include "js.msg"
861 : #undef MSG_DEF
862 : };
863 :
864 : JS_FRIEND_API(const JSErrorFormatString *)
865 950416 : js_GetErrorMessage(void *userRef, const char *locale, const unsigned errorNumber)
866 : {
867 950416 : if ((errorNumber > 0) && (errorNumber < JSErr_Limit))
868 950416 : return &js_ErrorFormatString[errorNumber];
869 0 : return NULL;
870 : }
871 :
872 : JSBool
873 160 : js_InvokeOperationCallback(JSContext *cx)
874 : {
875 160 : JS_ASSERT_REQUEST_DEPTH(cx);
876 :
877 160 : JSRuntime *rt = cx->runtime;
878 160 : JS_ASSERT(rt->interrupt != 0);
879 :
880 : /*
881 : * Reset the callback counter first, then run GC and yield. If another
882 : * thread is racing us here we will accumulate another callback request
883 : * which will be serviced at the next opportunity.
884 : */
885 160 : JS_ATOMIC_SET(&rt->interrupt, 0);
886 :
887 160 : if (rt->gcIsNeeded)
888 160 : GCSlice(cx, GC_NORMAL, rt->gcTriggerReason);
889 :
890 : #ifdef JS_THREADSAFE
891 : /*
892 : * We automatically yield the current context every time the operation
893 : * callback is hit since we might be called as a result of an impending
894 : * GC on another thread, which would deadlock if we do not yield.
895 : * Operation callbacks are supposed to happen rarely (seconds, not
896 : * milliseconds) so it is acceptable to yield at every callback.
897 : *
898 : * As the GC can be canceled before it does any request checks we yield
899 : * even if rt->gcIsNeeded was true above. See bug 590533.
900 : */
901 160 : JS_YieldRequest(cx);
902 : #endif
903 :
904 160 : JSOperationCallback cb = cx->operationCallback;
905 :
906 : /*
907 : * Important: Additional callbacks can occur inside the callback handler
908 : * if it re-enters the JS engine. The embedding must ensure that the
909 : * callback is disconnected before attempting such re-entry.
910 : */
911 :
912 160 : return !cb || cb(cx);
913 : }
914 :
915 : JSBool
916 458 : js_HandleExecutionInterrupt(JSContext *cx)
917 : {
918 458 : JSBool result = JS_TRUE;
919 458 : if (cx->runtime->interrupt)
920 160 : result = js_InvokeOperationCallback(cx) && result;
921 458 : return result;
922 : }
923 :
924 : jsbytecode*
925 919961 : js_GetCurrentBytecodePC(JSContext* cx)
926 : {
927 919961 : return cx->hasfp() ? cx->regs().pc : NULL;
928 : }
929 :
930 : void
931 18771 : DSTOffsetCache::purge()
932 : {
933 : /*
934 : * NB: The initial range values are carefully chosen to result in a cache
935 : * miss on first use given the range of possible values. Be careful
936 : * to keep these values and the caching algorithm in sync!
937 : */
938 18771 : offsetMilliseconds = 0;
939 18771 : rangeStartSeconds = rangeEndSeconds = INT64_MIN;
940 18771 : oldOffsetMilliseconds = 0;
941 18771 : oldRangeStartSeconds = oldRangeEndSeconds = INT64_MIN;
942 :
943 18771 : sanityCheck();
944 18771 : }
945 :
946 : /*
947 : * Since getDSTOffsetMilliseconds guarantees that all times seen will be
948 : * positive, we can initialize the range at construction time with large
949 : * negative numbers to ensure the first computation is always a cache miss and
950 : * doesn't return a bogus offset.
951 : */
952 18771 : DSTOffsetCache::DSTOffsetCache()
953 : {
954 18771 : purge();
955 18771 : }
956 :
957 18771 : JSContext::JSContext(JSRuntime *rt)
958 : : ContextFriendFields(rt),
959 : defaultVersion(JSVERSION_DEFAULT),
960 : hasVersionOverride(false),
961 : throwing(false),
962 : exception(UndefinedValue()),
963 : runOptions(0),
964 : reportGranularity(JS_DEFAULT_JITREPORT_GRANULARITY),
965 : localeCallbacks(NULL),
966 : resolvingList(NULL),
967 : generatingError(false),
968 : compartment(NULL),
969 : stack(thisDuringConstruction()), /* depends on cx->thread_ */
970 : parseMapPool_(NULL),
971 : globalObject(NULL),
972 : sharpObjectMap(thisDuringConstruction()),
973 : argumentFormatMap(NULL),
974 : lastMessage(NULL),
975 : errorReporter(NULL),
976 : operationCallback(NULL),
977 : data(NULL),
978 : data2(NULL),
979 : #ifdef JS_THREADSAFE
980 : outstandingRequests(0),
981 : #endif
982 : resolveFlags(0),
983 : rngSeed(0),
984 : iterValue(MagicValue(JS_NO_ITER_VALUE)),
985 : #ifdef JS_METHODJIT
986 : methodJitEnabled(false),
987 : #endif
988 : inferenceEnabled(false),
989 : #ifdef MOZ_TRACE_JSCALLS
990 : functionCallback(NULL),
991 : #endif
992 : enumerators(NULL),
993 : #ifdef JS_THREADSAFE
994 : gcBackgroundFree(NULL),
995 : #endif
996 : activeCompilations(0)
997 : #ifdef DEBUG
998 18771 : , stackIterAssertionEnabled(true)
999 : #endif
1000 : {
1001 18771 : PodZero(&link);
1002 : #ifdef JSGC_ROOT_ANALYSIS
1003 : PodArrayZero(thingGCRooters);
1004 : #ifdef DEBUG
1005 : checkGCRooters = NULL;
1006 : #endif
1007 : #endif
1008 18771 : }
1009 :
1010 37542 : JSContext::~JSContext()
1011 : {
1012 : /* Free the stuff hanging off of cx. */
1013 18771 : if (parseMapPool_)
1014 17423 : Foreground::delete_<ParseMapPool>(parseMapPool_);
1015 :
1016 18771 : if (lastMessage)
1017 947 : Foreground::free_(lastMessage);
1018 :
1019 : /* Remove any argument formatters. */
1020 18771 : JSArgumentFormatMap *map = argumentFormatMap;
1021 37542 : while (map) {
1022 0 : JSArgumentFormatMap *temp = map;
1023 0 : map = map->next;
1024 0 : Foreground::free_(temp);
1025 : }
1026 :
1027 18771 : JS_ASSERT(!resolvingList);
1028 18771 : }
1029 :
1030 : void
1031 304269 : JSContext::resetCompartment()
1032 : {
1033 : JSObject *scopeobj;
1034 304269 : if (stack.hasfp()) {
1035 191146 : scopeobj = &fp()->scopeChain();
1036 : } else {
1037 113123 : scopeobj = globalObject;
1038 113123 : if (!scopeobj)
1039 2 : goto error;
1040 :
1041 : /*
1042 : * Innerize. Assert, but check anyway, that this succeeds. (It
1043 : * can only fail due to bugs in the engine or embedding.)
1044 : */
1045 113121 : OBJ_TO_INNER_OBJECT(this, scopeobj);
1046 113121 : if (!scopeobj)
1047 0 : goto error;
1048 : }
1049 :
1050 304267 : compartment = scopeobj->compartment();
1051 304267 : inferenceEnabled = compartment->types.inferenceEnabled;
1052 :
1053 304267 : if (isExceptionPending())
1054 3055 : wrapPendingException();
1055 304267 : updateJITEnabled();
1056 304267 : return;
1057 :
1058 : error:
1059 :
1060 : /*
1061 : * If we try to use the context without a selected compartment,
1062 : * we will crash.
1063 : */
1064 2 : compartment = NULL;
1065 : }
1066 :
1067 : /*
1068 : * Since this function is only called in the context of a pending exception,
1069 : * the caller must subsequently take an error path. If wrapping fails, it will
1070 : * set a new (uncatchable) exception to be used in place of the original.
1071 : */
1072 : void
1073 3055 : JSContext::wrapPendingException()
1074 : {
1075 3055 : Value v = getPendingException();
1076 3055 : clearPendingException();
1077 3055 : if (compartment->wrap(this, &v))
1078 3045 : setPendingException(v);
1079 3055 : }
1080 :
1081 : JSGenerator *
1082 15714 : JSContext::generatorFor(StackFrame *fp) const
1083 : {
1084 15714 : JS_ASSERT(stack.containsSlow(fp));
1085 15714 : JS_ASSERT(fp->isGeneratorFrame());
1086 15714 : JS_ASSERT(!fp->isFloatingGenerator());
1087 15714 : JS_ASSERT(!genStack.empty());
1088 :
1089 15714 : if (JS_LIKELY(fp == genStack.back()->liveFrame()))
1090 15714 : return genStack.back();
1091 :
1092 : /* General case; should only be needed for debug APIs. */
1093 0 : for (size_t i = 0; i < genStack.length(); ++i) {
1094 0 : if (genStack[i]->liveFrame() == fp)
1095 0 : return genStack[i];
1096 : }
1097 0 : JS_NOT_REACHED("no matching generator");
1098 : return NULL;
1099 : }
1100 :
1101 : bool
1102 9471560 : JSContext::runningWithTrustedPrincipals() const
1103 : {
1104 9471560 : return !compartment || compartment->principals == runtime->trustedPrincipals();
1105 : }
1106 :
1107 : void
1108 16533840 : JSRuntime::updateMallocCounter(JSContext *cx, size_t nbytes)
1109 : {
1110 : /* We tolerate any thread races when updating gcMallocBytes. */
1111 16533840 : ptrdiff_t oldCount = gcMallocBytes;
1112 16533840 : ptrdiff_t newCount = oldCount - ptrdiff_t(nbytes);
1113 16533840 : gcMallocBytes = newCount;
1114 16533840 : if (JS_UNLIKELY(newCount <= 0 && oldCount > 0))
1115 144 : onTooMuchMalloc();
1116 16533696 : else if (cx && cx->compartment)
1117 16143748 : cx->compartment->updateMallocCounter(nbytes);
1118 16533840 : }
1119 :
1120 : JS_FRIEND_API(void)
1121 144 : JSRuntime::onTooMuchMalloc()
1122 : {
1123 144 : TriggerGC(this, gcreason::TOO_MUCH_MALLOC);
1124 144 : }
1125 :
1126 : JS_FRIEND_API(void *)
1127 9 : JSRuntime::onOutOfMemory(void *p, size_t nbytes, JSContext *cx)
1128 : {
1129 : /*
1130 : * Retry when we are done with the background sweeping and have stopped
1131 : * all the allocations and released the empty GC chunks.
1132 : */
1133 9 : ShrinkGCBuffers(this);
1134 : #ifdef JS_THREADSAFE
1135 : {
1136 18 : AutoLockGC lock(this);
1137 9 : gcHelperThread.waitBackgroundSweepOrAllocEnd();
1138 : }
1139 : #endif
1140 9 : if (!p)
1141 0 : p = OffTheBooks::malloc_(nbytes);
1142 9 : else if (p == reinterpret_cast<void *>(1))
1143 9 : p = OffTheBooks::calloc_(nbytes);
1144 : else
1145 0 : p = OffTheBooks::realloc_(p, nbytes);
1146 9 : if (p)
1147 0 : return p;
1148 9 : if (cx)
1149 9 : js_ReportOutOfMemory(cx);
1150 9 : return NULL;
1151 : }
1152 :
1153 : void
1154 21103 : JSContext::purge()
1155 : {
1156 21103 : if (!activeCompilations) {
1157 21091 : Foreground::delete_<ParseMapPool>(parseMapPool_);
1158 21091 : parseMapPool_ = NULL;
1159 : }
1160 21103 : }
1161 :
1162 : #if defined(JS_METHODJIT)
1163 : static bool
1164 14521 : ComputeIsJITBroken()
1165 : {
1166 : #if !defined(ANDROID) || defined(GONK)
1167 14521 : return false;
1168 : #else // ANDROID
1169 : if (getenv("JS_IGNORE_JIT_BROKENNESS")) {
1170 : return false;
1171 : }
1172 :
1173 : std::string line;
1174 :
1175 : // Check for the known-bad kernel version (2.6.29).
1176 : std::ifstream osrelease("/proc/sys/kernel/osrelease");
1177 : std::getline(osrelease, line);
1178 : __android_log_print(ANDROID_LOG_INFO, "Gecko", "Detected osrelease `%s'",
1179 : line.c_str());
1180 :
1181 : if (line.npos == line.find("2.6.29")) {
1182 : // We're using something other than 2.6.29, so the JITs should work.
1183 : __android_log_print(ANDROID_LOG_INFO, "Gecko", "JITs are not broken");
1184 : return false;
1185 : }
1186 :
1187 : // We're using 2.6.29, and this causes trouble with the JITs on i9000.
1188 : line = "";
1189 : bool broken = false;
1190 : std::ifstream cpuinfo("/proc/cpuinfo");
1191 : do {
1192 : if (0 == line.find("Hardware")) {
1193 : const char* blacklist[] = {
1194 : "SCH-I400", // Samsung Continuum
1195 : "SGH-T959", // Samsung i9000, Vibrant device
1196 : "SGH-I897", // Samsung i9000, Captivate device
1197 : "SCH-I500", // Samsung i9000, Fascinate device
1198 : "SPH-D700", // Samsung i9000, Epic device
1199 : "GT-I9000", // Samsung i9000, UK/Europe device
1200 : NULL
1201 : };
1202 : for (const char** hw = &blacklist[0]; *hw; ++hw) {
1203 : if (line.npos != line.find(*hw)) {
1204 : __android_log_print(ANDROID_LOG_INFO, "Gecko",
1205 : "Blacklisted device `%s'", *hw);
1206 : broken = true;
1207 : break;
1208 : }
1209 : }
1210 : break;
1211 : }
1212 : std::getline(cpuinfo, line);
1213 : } while(!cpuinfo.fail() && !cpuinfo.eof());
1214 :
1215 : __android_log_print(ANDROID_LOG_INFO, "Gecko", "JITs are %sbroken",
1216 : broken ? "" : "not ");
1217 :
1218 : return broken;
1219 : #endif // ifndef ANDROID
1220 : }
1221 :
1222 : static bool
1223 274650 : IsJITBrokenHere()
1224 : {
1225 : static bool computedIsBroken = false;
1226 : static bool isBroken = false;
1227 274650 : if (!computedIsBroken) {
1228 14521 : isBroken = ComputeIsJITBroken();
1229 14521 : computedIsBroken = true;
1230 : }
1231 274650 : return isBroken;
1232 : }
1233 : #endif
1234 :
1235 : void
1236 422963 : JSContext::updateJITEnabled()
1237 : {
1238 : #ifdef JS_METHODJIT
1239 : // This allocator randomization is actually a compartment-wide option.
1240 422963 : if (compartment && compartment->hasJaegerCompartment())
1241 181343 : compartment->jaegerCompartment()->execAlloc()->setRandomize(runtime->getJitHardening());
1242 422963 : methodJitEnabled = (runOptions & JSOPTION_METHODJIT) && !IsJITBrokenHere();
1243 : #endif
1244 422963 : }
1245 :
1246 : size_t
1247 0 : JSContext::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const
1248 : {
1249 : /*
1250 : * There are other JSContext members that could be measured; the following
1251 : * ones have been found by DMD to be worth measuring. More stuff may be
1252 : * added later.
1253 : */
1254 0 : return mallocSizeOf(this) + busyArrays.sizeOfExcludingThis(mallocSizeOf);
1255 : }
1256 :
1257 : void
1258 22875 : JSContext::mark(JSTracer *trc)
1259 : {
1260 : /* Stack frames and slots are traced by StackSpace::mark. */
1261 :
1262 : /* Mark other roots-by-definition in the JSContext. */
1263 22875 : if (globalObject && !hasRunOption(JSOPTION_UNROOTED_GLOBAL))
1264 22875 : MarkObjectRoot(trc, &globalObject, "global object");
1265 22875 : if (isExceptionPending())
1266 73 : MarkValueRoot(trc, &exception, "exception");
1267 :
1268 22875 : if (sharpObjectMap.depth > 0)
1269 2 : js_TraceSharpMap(trc, &sharpObjectMap);
1270 :
1271 22875 : MarkValueRoot(trc, &iterValue, "iterValue");
1272 22875 : }
1273 :
1274 : namespace JS {
1275 :
1276 : #if defined JS_THREADSAFE && defined DEBUG
1277 :
1278 1162197621 : AutoCheckRequestDepth::AutoCheckRequestDepth(JSContext *cx)
1279 1162197621 : : cx(cx)
1280 : {
1281 1162197621 : JS_ASSERT(cx->runtime->requestDepth || cx->runtime->gcRunning);
1282 1162197621 : JS_ASSERT(cx->runtime->onOwnerThread());
1283 1162197621 : cx->runtime->checkRequestDepth++;
1284 1162197621 : }
1285 :
1286 1162197621 : AutoCheckRequestDepth::~AutoCheckRequestDepth()
1287 : {
1288 1162197621 : JS_ASSERT(cx->runtime->checkRequestDepth != 0);
1289 1162197621 : cx->runtime->checkRequestDepth--;
1290 1162197621 : }
1291 :
1292 : #endif
1293 :
1294 : } // namespace JS
|