LCOV - code coverage report
Current view: directory - js/src - jscntxt.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 503 408 81.1 %
Date: 2012-06-02 Functions: 47 43 91.5 %

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

Generated by: LCOV version 1.7