LCOV - code coverage report
Current view: directory - js/src - jscntxt.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 505 386 76.4 %
Date: 2012-04-07 Functions: 47 41 87.2 %

       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, &regexp, &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

Generated by: LCOV version 1.7