/[jscoverage]/trunk/js/jsapi.cpp
ViewVC logotype

Diff of /trunk/js/jsapi.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 459 by siliconforks, Tue Dec 9 03:37:47 2008 UTC revision 460 by siliconforks, Sat Sep 26 23:15:22 2009 UTC
# Line 79  Line 79 
79  #include "jsscope.h"  #include "jsscope.h"
80  #include "jsscript.h"  #include "jsscript.h"
81  #include "jsstr.h"  #include "jsstr.h"
82    #include "jstracer.h"
83    #include "jsdbgapi.h"
84  #include "prmjtime.h"  #include "prmjtime.h"
85  #include "jsstaticcheck.h"  #include "jsstaticcheck.h"
86    
 #if !defined JS_THREADSAFE && defined JS_TRACER  
 #include "jstracer.h"  
 #endif  
   
87  #if JS_HAS_FILE_OBJECT  #if JS_HAS_FILE_OBJECT
88  #include "jsfile.h"  #include "jsfile.h"
89  #endif  #endif
# Line 107  Line 105 
105  #define CHECK_REQUEST(cx)       ((void)0)  #define CHECK_REQUEST(cx)       ((void)0)
106  #endif  #endif
107    
108    /* Check that we can cast JSObject* as jsval without tag bit manipulations. */
109    JS_STATIC_ASSERT(JSVAL_OBJECT == 0);
110    
111    /* Check that JSVAL_TRACE_KIND works. */
112    JS_STATIC_ASSERT(JSVAL_TRACE_KIND(JSVAL_OBJECT) == JSTRACE_OBJECT);
113    JS_STATIC_ASSERT(JSVAL_TRACE_KIND(JSVAL_DOUBLE) == JSTRACE_DOUBLE);
114    JS_STATIC_ASSERT(JSVAL_TRACE_KIND(JSVAL_STRING) == JSTRACE_STRING);
115    
116  JS_PUBLIC_API(int64)  JS_PUBLIC_API(int64)
117  JS_Now()  JS_Now()
118  {  {
# Line 322  Line 328 
328              continue;              continue;
329          argc++;          argc++;
330      }      }
331        js_LeaveTrace(cx);
332      sp = js_AllocStack(cx, argc, markp);      sp = js_AllocStack(cx, argc, markp);
333      if (!sp)      if (!sp)
334          return NULL;          return NULL;
# Line 418  Line 425 
425  JS_PopArguments(JSContext *cx, void *mark)  JS_PopArguments(JSContext *cx, void *mark)
426  {  {
427      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
428        JS_ASSERT_NOT_ON_TRACE(cx);
429      js_FreeStack(cx, mark);      js_FreeStack(cx, mark);
430  }  }
431    
# Line 638  Line 646 
646          type = JSTYPE_OBJECT;           /* XXXbe JSTYPE_NULL for JS2 */          type = JSTYPE_OBJECT;           /* XXXbe JSTYPE_NULL for JS2 */
647          obj = JSVAL_TO_OBJECT(v);          obj = JSVAL_TO_OBJECT(v);
648          if (obj) {          if (obj) {
649              JSObject *wrapped;              obj = js_GetWrappedObject(cx, obj);
   
             wrapped = js_GetWrappedObject(cx, obj);  
             if (wrapped)  
                 obj = wrapped;  
650    
651              ops = obj->map->ops;              ops = obj->map->ops;
652  #if JS_HAS_XML_SUPPORT  #if JS_HAS_XML_SUPPORT
653              if (ops == &js_XMLObjectOps.base) {              if (ops == &js_XMLObjectOps) {
654                  type = JSTYPE_XML;                  type = JSTYPE_XML;
655              } else              } else
656  #endif  #endif
657              {              {
658                  /*                  /*
659                   * ECMA 262, 11.4.3 says that any native object that implements                   * ECMA 262, 11.4.3 says that any native object that implements
660                   * [[Call]] should be of type "function". Note that RegExp and                   * [[Call]] should be of type "function". However, RegExp is of
661                   * Script are both of type "function" for compatibility with                   * type "object", not "function", for Web compatibility.
                  * older SpiderMonkeys.  
662                   */                   */
663                  clasp = OBJ_GET_CLASS(cx, obj);                  clasp = OBJ_GET_CLASS(cx, obj);
664                  if ((ops == &js_ObjectOps)                  if ((ops == &js_ObjectOps)
# Line 743  Line 746 
746  #include "js.msg"  #include "js.msg"
747  #undef MSG_DEF  #undef MSG_DEF
748    
749            /*
750             * If it were possible for pure inline function calls with constant
751             * arguments to be computed at compile time, these would be static
752             * assertions, but since it isn't, this is the best we can do.
753             */
754            JS_ASSERT(JSVAL_NULL == OBJECT_TO_JSVAL(NULL));
755            JS_ASSERT(JSVAL_ZERO == INT_TO_JSVAL(0));
756            JS_ASSERT(JSVAL_ONE == INT_TO_JSVAL(1));
757            JS_ASSERT(JSVAL_FALSE == BOOLEAN_TO_JSVAL(JS_FALSE));
758            JS_ASSERT(JSVAL_TRUE == BOOLEAN_TO_JSVAL(JS_TRUE));
759    
760            JS_ASSERT(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID) == 2);
761            JS_ASSERT(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_HOLE) == (2 | (JSVAL_HOLE_FLAG >> JSVAL_TAGBITS)));
762            JS_ASSERT(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_ARETURN) == 8);
763    
764          js_NewRuntimeWasCalled = JS_TRUE;          js_NewRuntimeWasCalled = JS_TRUE;
765      }      }
766  #endif /* DEBUG */  #endif /* DEBUG */
# Line 766  Line 784 
784      if (!js_InitDeflatedStringCache(rt))      if (!js_InitDeflatedStringCache(rt))
785          goto bad;          goto bad;
786  #ifdef JS_THREADSAFE  #ifdef JS_THREADSAFE
     if (!js_InitThreadPrivateIndex(js_ThreadDestructorCB))  
         goto bad;  
787      rt->gcLock = JS_NEW_LOCK();      rt->gcLock = JS_NEW_LOCK();
788      if (!rt->gcLock)      if (!rt->gcLock)
789          goto bad;          goto bad;
# Line 796  Line 812 
812  #endif  #endif
813      if (!js_InitPropertyTree(rt))      if (!js_InitPropertyTree(rt))
814          goto bad;          goto bad;
815        if (!js_InitThreads(rt))
816  #if !defined JS_THREADSAFE && defined JS_TRACER          goto bad;
     js_InitJIT(&rt->traceMonitor);  
 #endif  
817    
818      return rt;      return rt;
819    
# Line 819  Line 833 
833          while ((cx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL) {          while ((cx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL) {
834              fprintf(stderr,              fprintf(stderr,
835  "JS API usage error: found live context at %p\n",  "JS API usage error: found live context at %p\n",
836                      cx);                      (void *) cx);
837              cxcount++;              cxcount++;
838          }          }
839          fprintf(stderr,          fprintf(stderr,
# Line 828  Line 842 
842      }      }
843  #endif  #endif
844    
845  #if !defined JS_THREADSAFE && defined JS_TRACER      js_FinishThreads(rt);
     js_FinishJIT(&rt->traceMonitor);  
 #endif  
   
846      js_FreeRuntimeScriptState(rt);      js_FreeRuntimeScriptState(rt);
847      js_FinishAtomState(rt);      js_FinishAtomState(rt);
848    
# Line 863  Line 874 
874          JS_DESTROY_CONDVAR(rt->titleSharingDone);          JS_DESTROY_CONDVAR(rt->titleSharingDone);
875      if (rt->debuggerLock)      if (rt->debuggerLock)
876          JS_DESTROY_LOCK(rt->debuggerLock);          JS_DESTROY_LOCK(rt->debuggerLock);
 #else  
     GSN_CACHE_CLEAR(&rt->gsnCache);  
877  #endif  #endif
878      js_FinishPropertyTree(rt);      js_FinishPropertyTree(rt);
879      free(rt);      free(rt);
# Line 904  Line 913 
913  #ifdef JS_THREADSAFE  #ifdef JS_THREADSAFE
914      JSRuntime *rt;      JSRuntime *rt;
915    
916      JS_ASSERT(cx->thread->id == js_CurrentThreadId());      JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread));
917      if (!cx->requestDepth) {      if (!cx->requestDepth) {
918          JS_ASSERT(cx->gcLocalFreeLists == &js_GCEmptyFreeListSet);          JS_ASSERT(cx->gcLocalFreeLists == &js_GCEmptyFreeListSet);
919    
# Line 912  Line 921 
921          rt = cx->runtime;          rt = cx->runtime;
922          JS_LOCK_GC(rt);          JS_LOCK_GC(rt);
923    
         /* NB: we use cx->thread here, not js_GetCurrentThread(). */  
924          if (rt->gcThread != cx->thread) {          if (rt->gcThread != cx->thread) {
925              while (rt->gcLevel > 0)              while (rt->gcLevel > 0)
926                  JS_AWAIT_GC_DONE(rt);                  JS_AWAIT_GC_DONE(rt);
# Line 935  Line 943 
943  {  {
944  #ifdef JS_THREADSAFE  #ifdef JS_THREADSAFE
945      JSRuntime *rt;      JSRuntime *rt;
     JSTitle *title, **todop;  
     JSBool shared;  
946    
947      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
948        JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread));
949      JS_ASSERT(cx->requestDepth > 0);      JS_ASSERT(cx->requestDepth > 0);
950      JS_ASSERT(cx->outstandingRequests > 0);      JS_ASSERT(cx->outstandingRequests > 0);
951      if (cx->requestDepth == 1) {      if (cx->requestDepth == 1) {
952            js_LeaveTrace(cx);  /* for GC safety */
953    
954          /* Lock before clearing to interlock with ClaimScope, in jslock.c. */          /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
955          rt = cx->runtime;          rt = cx->runtime;
956          JS_LOCK_GC(rt);          JS_LOCK_GC(rt);
957          cx->requestDepth = 0;          cx->requestDepth = 0;
958          cx->outstandingRequests--;          cx->outstandingRequests--;
959    
960          /* See whether cx has any single-threaded titles to start sharing. */          js_ShareWaitingTitles(cx);
         todop = &rt->titleSharingTodo;  
         shared = JS_FALSE;  
         while ((title = *todop) != NO_TITLE_SHARING_TODO) {  
             if (title->ownercx != cx) {  
                 todop = &title->u.link;  
                 continue;  
             }  
             *todop = title->u.link;  
             title->u.link = NULL;       /* null u.link for sanity ASAP */  
   
             /*  
              * If js_DropObjectMap returns null, we held the last ref to scope.  
              * The waiting thread(s) must have been killed, after which the GC  
              * collected the object that held this scope.  Unlikely, because it  
              * requires that the GC ran (e.g., from an operation callback)  
              * during this request, but possible.  
              */  
             if (js_DropObjectMap(cx, TITLE_TO_MAP(title), NULL)) {  
                 js_InitLock(&title->lock);  
                 title->u.count = 0;   /* NULL may not pun as 0 */  
                 js_FinishSharingTitle(cx, title); /* set ownercx = NULL */  
                 shared = JS_TRUE;  
             }  
         }  
         if (shared)  
             JS_NOTIFY_ALL_CONDVAR(rt->titleSharingDone);  
   
961          js_RevokeGCLocalFreeLists(cx);          js_RevokeGCLocalFreeLists(cx);
962    
963          /* Give the GC a chance to run if this was the last request running. */          /* Give the GC a chance to run if this was the last request running. */
# Line 1175  Line 1157 
1157      return cx->options;      return cx->options;
1158  }  }
1159    
 #define SYNC_OPTIONS_TO_VERSION(cx)                                           \  
     JS_BEGIN_MACRO                                                            \  
         if ((cx)->options & JSOPTION_XML)                                     \  
             (cx)->version |= JSVERSION_HAS_XML;                               \  
         else                                                                  \  
             (cx)->version &= ~JSVERSION_HAS_XML;                              \  
     JS_END_MACRO  
   
1160  JS_PUBLIC_API(uint32)  JS_PUBLIC_API(uint32)
1161  JS_SetOptions(JSContext *cx, uint32 options)  JS_SetOptions(JSContext *cx, uint32 options)
1162  {  {
1163      uint32 oldopts = cx->options;      uint32 oldopts = cx->options;
1164      cx->options = options;      cx->options = options;
1165      SYNC_OPTIONS_TO_VERSION(cx);      js_SyncOptionsToVersion(cx);
1166      return oldopts;      return oldopts;
1167  }  }
1168    
# Line 1197  Line 1171 
1171  {  {
1172      uint32 oldopts = cx->options;      uint32 oldopts = cx->options;
1173      cx->options ^= options;      cx->options ^= options;
1174      SYNC_OPTIONS_TO_VERSION(cx);      js_SyncOptionsToVersion(cx);
1175      return oldopts;      return oldopts;
1176  }  }
1177    
# Line 1343  Line 1317 
1317      /* Define a top-level property 'undefined' with the undefined value. */      /* Define a top-level property 'undefined' with the undefined value. */
1318      atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];      atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
1319      if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,      if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
1320                               NULL, NULL, JSPROP_PERMANENT, NULL)) {                               JS_PropertyStub, JS_PropertyStub, JSPROP_PERMANENT,
1321                                 NULL)) {
1322          return JS_FALSE;          return JS_FALSE;
1323      }      }
1324    
# Line 1353  Line 1328 
1328    
1329      /* Initialize the rest of the standard objects and functions. */      /* Initialize the rest of the standard objects and functions. */
1330      return js_InitArrayClass(cx, obj) &&      return js_InitArrayClass(cx, obj) &&
            js_InitBlockClass(cx, obj) &&  
1331             js_InitBooleanClass(cx, obj) &&             js_InitBooleanClass(cx, obj) &&
            js_InitCallClass(cx, obj) &&  
1332             js_InitExceptionClasses(cx, obj) &&             js_InitExceptionClasses(cx, obj) &&
1333             js_InitMathClass(cx, obj) &&             js_InitMathClass(cx, obj) &&
1334             js_InitNumberClass(cx, obj) &&             js_InitNumberClass(cx, obj) &&
# Line 1379  Line 1352 
1352  }  }
1353    
1354  #define CLASP(name)                 (&js_##name##Class)  #define CLASP(name)                 (&js_##name##Class)
1355  #define EXT_CLASP(name)             (&js_##name##Class.base)  #define XCLASP(name)                (&js_##name##Class.base)
1356  #define EAGER_ATOM(name)            ATOM_OFFSET(name), NULL  #define EAGER_ATOM(name)            ATOM_OFFSET(name), NULL
1357  #define EAGER_CLASS_ATOM(name)      CLASS_ATOM_OFFSET(name), NULL  #define EAGER_CLASS_ATOM(name)      CLASS_ATOM_OFFSET(name), NULL
1358  #define EAGER_ATOM_AND_CLASP(name)  EAGER_CLASS_ATOM(name), CLASP(name)  #define EAGER_ATOM_AND_CLASP(name)  EAGER_CLASS_ATOM(name), CLASP(name)
1359  #define EAGER_ATOM_AND_EXT_CLASP(name) EAGER_CLASS_ATOM(name), EXT_CLASP(name)  #define EAGER_ATOM_AND_XCLASP(name) EAGER_CLASS_ATOM(name), XCLASP(name)
1360  #define LAZY_ATOM(name)             ATOM_OFFSET(lazy.name), js_##name##_str  #define LAZY_ATOM(name)             ATOM_OFFSET(lazy.name), js_##name##_str
1361    
1362  typedef struct JSStdName {  typedef struct JSStdName {
# Line 1420  Line 1393 
1393      {js_InitFunctionAndObjectClasses,   EAGER_ATOM_AND_CLASP(Function)},      {js_InitFunctionAndObjectClasses,   EAGER_ATOM_AND_CLASP(Function)},
1394      {js_InitFunctionAndObjectClasses,   EAGER_ATOM_AND_CLASP(Object)},      {js_InitFunctionAndObjectClasses,   EAGER_ATOM_AND_CLASP(Object)},
1395      {js_InitArrayClass,                 EAGER_ATOM_AND_CLASP(Array)},      {js_InitArrayClass,                 EAGER_ATOM_AND_CLASP(Array)},
     {js_InitBlockClass,                 EAGER_ATOM_AND_CLASP(Block)},  
1396      {js_InitBooleanClass,               EAGER_ATOM_AND_CLASP(Boolean)},      {js_InitBooleanClass,               EAGER_ATOM_AND_CLASP(Boolean)},
1397      {js_InitDateClass,                  EAGER_ATOM_AND_CLASP(Date)},      {js_InitDateClass,                  EAGER_ATOM_AND_CLASP(Date)},
1398      {js_InitMathClass,                  EAGER_ATOM_AND_CLASP(Math)},      {js_InitMathClass,                  EAGER_ATOM_AND_CLASP(Math)},
1399      {js_InitNumberClass,                EAGER_ATOM_AND_CLASP(Number)},      {js_InitNumberClass,                EAGER_ATOM_AND_CLASP(Number)},
1400      {js_InitStringClass,                EAGER_ATOM_AND_CLASP(String)},      {js_InitStringClass,                EAGER_ATOM_AND_CLASP(String)},
     {js_InitCallClass,                  EAGER_ATOM_AND_CLASP(Call)},  
1401      {js_InitExceptionClasses,           EAGER_ATOM_AND_CLASP(Error)},      {js_InitExceptionClasses,           EAGER_ATOM_AND_CLASP(Error)},
1402      {js_InitRegExpClass,                EAGER_ATOM_AND_CLASP(RegExp)},      {js_InitRegExpClass,                EAGER_ATOM_AND_CLASP(RegExp)},
1403  #if JS_HAS_SCRIPT_OBJECT  #if JS_HAS_SCRIPT_OBJECT
# Line 1434  Line 1405 
1405  #endif  #endif
1406  #if JS_HAS_XML_SUPPORT  #if JS_HAS_XML_SUPPORT
1407      {js_InitXMLClass,                   EAGER_ATOM_AND_CLASP(XML)},      {js_InitXMLClass,                   EAGER_ATOM_AND_CLASP(XML)},
1408      {js_InitNamespaceClass,             EAGER_ATOM_AND_EXT_CLASP(Namespace)},      {js_InitNamespaceClass,             EAGER_ATOM_AND_XCLASP(Namespace)},
1409      {js_InitQNameClass,                 EAGER_ATOM_AND_EXT_CLASP(QName)},      {js_InitQNameClass,                 EAGER_ATOM_AND_XCLASP(QName)},
1410  #endif  #endif
1411  #if JS_HAS_FILE_OBJECT  #if JS_HAS_FILE_OBJECT
1412      {js_InitFileClass,                  EAGER_ATOM_AND_CLASP(File)},      {js_InitFileClass,                  EAGER_ATOM_AND_CLASP(File)},
# Line 1553  Line 1524 
1524      if (idstr == ATOM_TO_STRING(atom)) {      if (idstr == ATOM_TO_STRING(atom)) {
1525          *resolved = JS_TRUE;          *resolved = JS_TRUE;
1526          return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,          return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
1527                                     NULL, NULL, JSPROP_PERMANENT, NULL);                                     JS_PropertyStub, JS_PropertyStub,
1528                                       JSPROP_PERMANENT, NULL);
1529      }      }
1530    
1531      /* Try for class constructors/prototypes named by well-known atoms. */      /* Try for class constructors/prototypes named by well-known atoms. */
# Line 1647  Line 1619 
1619      atom = rt->atomState.typeAtoms[JSTYPE_VOID];      atom = rt->atomState.typeAtoms[JSTYPE_VOID];
1620      if (!AlreadyHasOwnProperty(cx, obj, atom) &&      if (!AlreadyHasOwnProperty(cx, obj, atom) &&
1621          !OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,          !OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
1622                               NULL, NULL, JSPROP_PERMANENT, NULL)) {                               JS_PropertyStub, JS_PropertyStub, JSPROP_PERMANENT,
1623                                 NULL)) {
1624          return JS_FALSE;          return JS_FALSE;
1625      }      }
1626    
# Line 1802  Line 1775 
1775      JSStackFrame *fp;      JSStackFrame *fp;
1776    
1777      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
1778      fp = cx->fp;      fp = js_GetTopStackFrame(cx);
1779      if (!fp) {      if (!fp) {
1780          /*          /*
1781           * There is no code active on this context. In place of an actual           * There is no code active on this context. In place of an actual
# Line 1850  Line 1823 
1823      void *p;      void *p;
1824    
1825      JS_ASSERT(nbytes != 0);      JS_ASSERT(nbytes != 0);
     JS_COUNT_OPERATION(cx, JSOW_ALLOCATION);  
1826      if (nbytes == 0)      if (nbytes == 0)
1827          nbytes = 1;          nbytes = 1;
1828    
# Line 1867  Line 1839 
1839  JS_PUBLIC_API(void *)  JS_PUBLIC_API(void *)
1840  JS_realloc(JSContext *cx, void *p, size_t nbytes)  JS_realloc(JSContext *cx, void *p, size_t nbytes)
1841  {  {
1842      JS_COUNT_OPERATION(cx, JSOW_ALLOCATION);      void *orig = p;
1843      p = realloc(p, nbytes);      p = realloc(p, nbytes);
1844      if (!p)      if (!p) {
1845          JS_ReportOutOfMemory(cx);          JS_ReportOutOfMemory(cx);
1846            return NULL;
1847        }
1848        if (!orig)
1849            js_UpdateMallocCounter(cx, nbytes);
1850      return p;      return p;
1851  }  }
1852    
# Line 1917  Line 1893 
1893  JS_PUBLIC_API(JSBool)  JS_PUBLIC_API(JSBool)
1894  JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval)  JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval)
1895  {  {
     jsint i;  
   
1896      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
1897      if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {      return js_NewWeaklyRootedNumber(cx, d, rval);
         *rval = INT_TO_JSVAL(i);  
         return JS_TRUE;  
     }  
     return JS_NewDoubleValue(cx, d, rval);  
1898  }  }
1899    
1900  #undef JS_AddRoot  #undef JS_AddRoot
# Line 2061  Line 2031 
2031  {  {
2032      JSBool allAtoms = trc->context->runtime->gcKeepAtoms != 0;      JSBool allAtoms = trc->context->runtime->gcKeepAtoms != 0;
2033    
2034        js_LeaveTrace(trc->context);
2035      js_TraceRuntime(trc, allAtoms);      js_TraceRuntime(trc, allAtoms);
2036  }  }
2037    
# Line 2477  Line 2448 
2448  JS_PUBLIC_API(void)  JS_PUBLIC_API(void)
2449  JS_GC(JSContext *cx)  JS_GC(JSContext *cx)
2450  {  {
2451        js_LeaveTrace(cx);
2452    
2453      /* Don't nuke active arenas if executing or compiling. */      /* Don't nuke active arenas if executing or compiling. */
2454      if (cx->stackPool.current == &cx->stackPool.first)      if (cx->stackPool.current == &cx->stackPool.first)
2455          JS_FinishArenaPool(&cx->stackPool);          JS_FinishArenaPool(&cx->stackPool);
# Line 2540  Line 2513 
2513       * free cells. Indeed if we still have free cells, then B == Bl since       * free cells. Indeed if we still have free cells, then B == Bl since
2514       * we did not yet allocated any new arenas and the condition means       * we did not yet allocated any new arenas and the condition means
2515       *   1 - F > 3/2 (1-Fl) or 3/2Fl > 1/2 + F       *   1 - F > 3/2 (1-Fl) or 3/2Fl > 1/2 + F
2516       * That implies 3/2 Fl > 1/2 or Fl > 1/3. That can not be fulfilled       * That implies 3/2 Fl > 1/2 or Fl > 1/3. That cannot be fulfilled
2517       * for the state described by the stats. So we can write the original       * for the state described by the stats. So we can write the original
2518       * condition as:       * condition as:
2519       *   F == 0 && B > 3/2 Bl(1-Fl)       *   F == 0 && B > 3/2 Bl(1-Fl)
# Line 2593  Line 2566 
2566        case JSGC_STACKPOOL_LIFESPAN:        case JSGC_STACKPOOL_LIFESPAN:
2567          rt->gcEmptyArenaPoolLifespan = value;          rt->gcEmptyArenaPoolLifespan = value;
2568          break;          break;
2569          default:
2570            JS_ASSERT(key == JSGC_TRIGGER_FACTOR);
2571            JS_ASSERT(value >= 100);
2572            rt->gcTriggerFactor = value;
2573            return;
2574      }      }
2575  }  }
2576    
2577    JS_PUBLIC_API(uint32)
2578    JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key)
2579    {
2580        switch (key) {
2581          case JSGC_MAX_BYTES:
2582            return rt->gcMaxBytes;
2583          case JSGC_MAX_MALLOC_BYTES:
2584            return rt->gcMaxMallocBytes;
2585          case JSGC_STACKPOOL_LIFESPAN:
2586            return rt->gcEmptyArenaPoolLifespan;
2587          case JSGC_TRIGGER_FACTOR:
2588            return rt->gcTriggerFactor;
2589          case JSGC_BYTES:
2590            return rt->gcBytes;
2591          default:
2592            JS_ASSERT(key == JSGC_NUMBER);
2593            return rt->gcNumber;
2594        }
2595    }
2596    
2597    JS_PUBLIC_API(void)
2598    JS_SetGCParameterForThread(JSContext *cx, JSGCParamKey key, uint32 value)
2599    {
2600        JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES);
2601    #ifdef JS_TRACER
2602        js_SetMaxCodeCacheBytes(cx, value);
2603    #endif
2604    }
2605    
2606    JS_PUBLIC_API(uint32)
2607    JS_GetGCParameterForThread(JSContext *cx, JSGCParamKey key)
2608    {
2609        JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES);
2610    #ifdef JS_TRACER
2611        return JS_THREAD_DATA(cx)->traceMonitor.maxCodeCacheBytes;
2612    #else
2613        return 0;
2614    #endif
2615    }
2616    
2617  JS_PUBLIC_API(intN)  JS_PUBLIC_API(intN)
2618  JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer)  JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer)
2619  {  {
# Line 2712  Line 2730 
2730               JSPropertySpec *ps, JSFunctionSpec *fs,               JSPropertySpec *ps, JSFunctionSpec *fs,
2731               JSPropertySpec *static_ps, JSFunctionSpec *static_fs)               JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
2732  {  {
     JSAtom *atom;  
     JSProtoKey key;  
     JSObject *proto, *ctor;  
     JSTempValueRooter tvr;  
     jsval cval, rval;  
     JSBool named;  
     JSFunction *fun;  
   
2733      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
2734      atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);      return js_InitClass(cx, obj, parent_proto, clasp, constructor, nargs,
2735      if (!atom)                          ps, fs, static_ps, static_fs);
         return NULL;  
   
     /*  
      * When initializing a standard class, if no parent_proto (grand-proto of  
      * instances of the class, parent-proto of the class's prototype object)  
      * is given, we must use Object.prototype if it is available.  Otherwise,  
      * we could look up the wrong binding for a class name in obj.  Example:  
      *  
      *   String = Array;  
      *   print("hi there".join);  
      *  
      * should print undefined, not Array.prototype.join.  This is required by  
      * ECMA-262, alas.  It might have been better to make String readonly and  
      * permanent in the global object, instead -- but that's too big a change  
      * to swallow at this point.  
      */  
     key = JSCLASS_CACHED_PROTO_KEY(clasp);  
     if (key != JSProto_Null &&  
         !parent_proto &&  
         !js_GetClassPrototype(cx, obj, INT_TO_JSID(JSProto_Object),  
                               &parent_proto)) {  
         return NULL;  
     }  
   
     /* Create a prototype object for this class. */  
     proto = js_NewObject(cx, clasp, parent_proto, obj, 0);  
     if (!proto)  
         return NULL;  
   
     /* After this point, control must exit via label bad or out. */  
     JS_PUSH_TEMP_ROOT_OBJECT(cx, proto, &tvr);  
   
     if (!constructor) {  
         /*  
          * Lacking a constructor, name the prototype (e.g., Math) unless this  
          * class (a) is anonymous, i.e. for internal use only; (b) the class  
          * of obj (the global object) is has a reserved slot indexed by key;  
          * and (c) key is not the null key.  
          */  
         if ((clasp->flags & JSCLASS_IS_ANONYMOUS) &&  
             (OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL) &&  
             key != JSProto_Null) {  
             named = JS_FALSE;  
         } else {  
             named = OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom),  
                                         OBJECT_TO_JSVAL(proto),  
                                         JS_PropertyStub, JS_PropertyStub,  
                                         (clasp->flags & JSCLASS_IS_ANONYMOUS)  
                                         ? JSPROP_READONLY | JSPROP_PERMANENT  
                                         : 0,  
                                         NULL);  
             if (!named)  
                 goto bad;  
         }  
   
         ctor = proto;  
     } else {  
         /* Define the constructor function in obj's scope. */  
         fun = js_DefineFunction(cx, obj, atom, constructor, nargs,  
                                 JSFUN_STUB_GSOPS);  
         named = (fun != NULL);  
         if (!fun)  
             goto bad;  
   
         /*  
          * Remember the class this function is a constructor for so that  
          * we know to create an object of this class when we call the  
          * constructor.  
          */  
         FUN_CLASP(fun) = clasp;  
   
         /*  
          * Optionally construct the prototype object, before the class has  
          * been fully initialized.  Allow the ctor to replace proto with a  
          * different object, as is done for operator new -- and as at least  
          * XML support requires.  
          */  
         ctor = FUN_OBJECT(fun);  
         if (clasp->flags & JSCLASS_CONSTRUCT_PROTOTYPE) {  
             cval = OBJECT_TO_JSVAL(ctor);  
             if (!js_InternalConstruct(cx, proto, cval, 0, NULL, &rval))  
                 goto bad;  
             if (!JSVAL_IS_PRIMITIVE(rval) && JSVAL_TO_OBJECT(rval) != proto)  
                 proto = JSVAL_TO_OBJECT(rval);  
         }  
   
         /* Connect constructor and prototype by named properties. */  
         if (!js_SetClassPrototype(cx, ctor, proto,  
                                   JSPROP_READONLY | JSPROP_PERMANENT)) {  
             goto bad;  
         }  
   
         /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */  
         if (OBJ_GET_CLASS(cx, ctor) == clasp) {  
             OBJ_SET_PROTO(cx, ctor, proto);  
         }  
     }  
   
     /* Add properties and methods to the prototype and the constructor. */  
     if ((ps && !JS_DefineProperties(cx, proto, ps)) ||  
         (fs && !JS_DefineFunctions(cx, proto, fs)) ||  
         (static_ps && !JS_DefineProperties(cx, ctor, static_ps)) ||  
         (static_fs && !JS_DefineFunctions(cx, ctor, static_fs))) {  
         goto bad;  
     }  
   
     /* If this is a standard class, cache its prototype. */  
     if (key != JSProto_Null && !js_SetClassObject(cx, obj, key, ctor))  
         goto bad;  
   
 out:  
     JS_POP_TEMP_ROOT(cx, &tvr);  
     return proto;  
   
 bad:  
     if (named)  
         (void) OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &rval);  
     proto = NULL;  
     goto out;  
2736  }  }
2737    
2738  #ifdef JS_THREADSAFE  #ifdef JS_THREADSAFE
# Line 2931  Line 2822 
2822  JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)  JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
2823  {  {
2824      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
2825      JS_ASSERT(obj != proto);      return js_SetProtoOrParent(cx, obj, JSSLOT_PROTO, proto, JS_FALSE);
 #ifdef DEBUG  
     /*  
      * FIXME: bug 408416. The cycle-detection required for script-writeable  
      * __proto__ lives in js_SetProtoOrParent over in jsobj.c, also known as  
      * js_ObjectOps.setProto. This hook must detect cycles, to prevent scripts  
      * from ilooping SpiderMonkey trivially. But the overhead of detecting  
      * cycles is high enough, and the threat from JS-API-calling C++ code is  
      * low enough, that it's not worth burdening the non-DEBUG callers. Same  
      * goes for JS_SetParent, below.  
      */  
     if (obj->map->ops->setProto)  
         return obj->map->ops->setProto(cx, obj, JSSLOT_PROTO, proto);  
 #else  
     if (OBJ_IS_NATIVE(obj)) {  
         JS_LOCK_OBJ(cx, obj);  
         if (!js_GetMutableScope(cx, obj)) {  
             JS_UNLOCK_OBJ(cx, obj);  
             return JS_FALSE;  
         }  
         LOCKED_OBJ_SET_PROTO(obj, proto);  
         JS_UNLOCK_OBJ(cx, obj);  
         return JS_TRUE;  
     }  
 #endif  
     OBJ_SET_PROTO(cx, obj, proto);  
     return JS_TRUE;  
2826  }  }
2827    
2828  JS_PUBLIC_API(JSObject *)  JS_PUBLIC_API(JSObject *)
# Line 2975  Line 2840 
2840  JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)  JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
2841  {  {
2842      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
2843      JS_ASSERT(obj != parent);      return js_SetProtoOrParent(cx, obj, JSSLOT_PARENT, parent, JS_FALSE);
 #ifdef DEBUG  
     /* FIXME: bug 408416, see JS_SetPrototype just above. */  
     if (obj->map->ops->setParent)  
         return obj->map->ops->setParent(cx, obj, JSSLOT_PARENT, parent);  
 #endif  
     OBJ_SET_PARENT(cx, obj, parent);  
     return JS_TRUE;  
2844  }  }
2845    
2846  JS_PUBLIC_API(JSObject *)  JS_PUBLIC_API(JSObject *)
# Line 3043  Line 2901 
2901      uint32 nslots, i;      uint32 nslots, i;
2902      jsval v;      jsval v;
2903    
2904        if (OBJ_IS_DENSE_ARRAY(cx, obj) && !js_MakeArraySlow(cx, obj))
2905            return JS_FALSE;
2906    
2907      if (!OBJ_IS_NATIVE(obj)) {      if (!OBJ_IS_NATIVE(obj)) {
2908          JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,          JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
2909                               JSMSG_CANT_SEAL_OBJECT,                               JSMSG_CANT_SEAL_OBJECT,
# Line 3077  Line 2938 
2938      scope = js_GetMutableScope(cx, obj);      scope = js_GetMutableScope(cx, obj);
2939      if (scope) {      if (scope) {
2940          SCOPE_SET_SEALED(scope);          SCOPE_SET_SEALED(scope);
2941          SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);          js_MakeScopeShapeUnique(cx, scope);
2942      }      }
2943      JS_UNLOCK_OBJ(cx, obj);      JS_UNLOCK_OBJ(cx, obj);
2944      if (!scope)      if (!scope)
# Line 3088  Line 2949 
2949          return JS_TRUE;          return JS_TRUE;
2950    
2951      /* Walk slots in obj and if any value is a non-null object, seal it. */      /* Walk slots in obj and if any value is a non-null object, seal it. */
2952      nslots = scope->map.freeslot;      nslots = scope->freeslot;
2953      for (i = 0; i != nslots; ++i) {      for (i = 0; i != nslots; ++i) {
2954          v = STOBJ_GET_SLOT(obj, i);          v = STOBJ_GET_SLOT(obj, i);
2955          if (JSVAL_IS_PRIMITIVE(v))          if (JSVAL_IS_PRIMITIVE(v))
# Line 3126  Line 2987 
2987  {  {
2988      if (flags != 0 && OBJ_IS_NATIVE(obj)) {      if (flags != 0 && OBJ_IS_NATIVE(obj)) {
2989          JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING);          JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING);
2990          return js_DefineNativeProperty(cx, obj, id, value, getter, setter,          return !!js_DefineNativeProperty(cx, obj, id, value, getter, setter,
2991                                         attrs, flags, tinyid, NULL);                                           attrs, flags, tinyid, NULL);
2992      }      }
2993      return OBJ_DEFINE_PROPERTY(cx, obj, id, value, getter, setter, attrs,      return OBJ_DEFINE_PROPERTY(cx, obj, id, value, getter, setter, attrs,
2994                                 NULL);                                   NULL);  
# Line 3170  Line 3031 
3031          return JS_FALSE;          return JS_FALSE;
3032      if (flags != 0 && OBJ_IS_NATIVE(obj)) {      if (flags != 0 && OBJ_IS_NATIVE(obj)) {
3033          JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING);          JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING);
3034          return js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), value,          return !!js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), value,
3035                                         getter, setter, attrs, flags, tinyid,                                           getter, setter, attrs, flags, tinyid,
3036                                         NULL);                                           NULL);
3037      }      }
3038      return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), value,      return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), value,
3039                                 getter, setter, attrs, NULL);                                 getter, setter, attrs, NULL);
# Line 3268  Line 3129 
3129                     JSObject **objp, JSProperty **propp)                     JSObject **objp, JSProperty **propp)
3130  {  {
3131      JSAutoResolveFlags rf(cx, flags);      JSAutoResolveFlags rf(cx, flags);
3132        CHECK_FOR_STRING_INDEX(id);
3133      return OBJ_LOOKUP_PROPERTY(cx, obj, id, objp, propp);      return OBJ_LOOKUP_PROPERTY(cx, obj, id, objp, propp);
3134  }  }
3135    
# Line 3334  Line 3196 
3196      return ok;      return ok;
3197  }  }
3198    
3199  static jsval  static JSBool
3200  LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop)  LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop,
3201                 jsval *vp)
3202  {  {
     JSScopeProperty *sprop;  
     jsval rval;  
   
3203      if (!prop) {      if (!prop) {
3204          /* XXX bad API: no way to tell "not defined" from "void value" */          /* XXX bad API: no way to tell "not defined" from "void value" */
3205          return JSVAL_VOID;          *vp = JSVAL_VOID;
3206            return JS_TRUE;
3207      }      }
3208    
3209        JSBool ok = JS_TRUE;
3210      if (OBJ_IS_NATIVE(obj2)) {      if (OBJ_IS_NATIVE(obj2)) {
3211            JSScopeProperty *sprop = (JSScopeProperty *) prop;
3212    
3213          /* Peek at the native property's slot value, without doing a Get. */          /* Peek at the native property's slot value, without doing a Get. */
3214          sprop = (JSScopeProperty *)prop;          *vp = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2))
         rval = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2))  
3215                 ? LOCKED_OBJ_GET_SLOT(obj2, sprop->slot)                 ? LOCKED_OBJ_GET_SLOT(obj2, sprop->slot)
3216                 : JSVAL_TRUE;                 : JSVAL_TRUE;
3217        } else if (OBJ_IS_DENSE_ARRAY(cx, obj2)) {
3218            ok = js_GetDenseArrayElementValue(cx, obj2, prop, vp);
3219      } else {      } else {
3220          /* XXX bad API: no way to return "defined but value unknown" */          /* XXX bad API: no way to return "defined but value unknown" */
3221          rval = JSVAL_TRUE;          *vp = JSVAL_TRUE;
3222      }      }
3223      OBJ_DROP_PROPERTY(cx, obj2, prop);      OBJ_DROP_PROPERTY(cx, obj2, prop);
3224      return rval;      return ok;
3225  }  }
3226    
3227  static JSBool  static JSBool
3228  GetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,  GetPropertyAttributesById(JSContext *cx, JSObject *obj, jsid id, uintN flags,
3229                        uintN *attrsp, JSBool *foundp,                            JSBool own, JSPropertyDescriptor *desc)
                       JSPropertyOp *getterp, JSPropertyOp *setterp)  
3230  {  {
3231      JSObject *obj2;      JSObject *obj2;
3232      JSProperty *prop;      JSProperty *prop;
3233      JSBool ok;      JSBool ok;
3234    
3235      if (!atom)      if (!LookupPropertyById(cx, obj, id, flags, &obj2, &prop))
         return JS_FALSE;  
     if (!LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), JSRESOLVE_QUALIFIED,  
                             &obj2, &prop)) {  
3236          return JS_FALSE;          return JS_FALSE;
     }  
3237    
3238      if (!prop || obj != obj2) {      if (!prop || (own && obj != obj2)) {
3239          *attrsp = 0;          desc->obj = NULL;
3240          *foundp = JS_FALSE;          desc->attrs = 0;
3241          if (getterp)          desc->getter = NULL;
3242              *getterp = NULL;          desc->setter = NULL;
3243          if (setterp)          desc->value = JSVAL_VOID;
             *setterp = NULL;  
3244          if (prop)          if (prop)
3245              OBJ_DROP_PROPERTY(cx, obj2, prop);              OBJ_DROP_PROPERTY(cx, obj2, prop);
3246          return JS_TRUE;          return JS_TRUE;
3247      }      }
3248    
3249      *foundp = JS_TRUE;      desc->obj = obj2;
3250      ok = OBJ_GET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, attrsp);  
3251      if (ok && OBJ_IS_NATIVE(obj)) {      ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &desc->attrs);
3252          JSScopeProperty *sprop = (JSScopeProperty *) prop;      if (ok) {
3253            if (OBJ_IS_NATIVE(obj2)) {
3254                JSScopeProperty *sprop = (JSScopeProperty *) prop;
3255    
3256          if (getterp)              desc->getter = sprop->getter;
3257              *getterp = sprop->getter;              desc->setter = sprop->setter;
3258          if (setterp)              desc->value = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2))
3259              *setterp = sprop->setter;                            ? LOCKED_OBJ_GET_SLOT(obj2, sprop->slot)
3260                              : JSVAL_VOID;
3261            } else {
3262                desc->getter = NULL;
3263                desc->setter = NULL;
3264                desc->value = JSVAL_VOID;
3265            }
3266      }      }
3267      OBJ_DROP_PROPERTY(cx, obj, prop);      OBJ_DROP_PROPERTY(cx, obj2, prop);
3268      return ok;      return ok;
3269  }  }
3270    
3271  static JSBool  static JSBool
3272    GetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
3273                          uintN *attrsp, JSBool *foundp,
3274                          JSPropertyOp *getterp, JSPropertyOp *setterp)
3275    
3276    {
3277        if (!atom)
3278            return JS_FALSE;
3279    
3280        JSPropertyDescriptor desc;
3281        if (!GetPropertyAttributesById(cx, obj, ATOM_TO_JSID(atom),
3282                                       JSRESOLVE_QUALIFIED, JS_FALSE, &desc)) {
3283            return JS_FALSE;
3284        }
3285    
3286        *attrsp = desc.attrs;
3287        *foundp = (desc.obj != NULL);
3288        if (getterp)
3289            *getterp = desc.getter;
3290        if (setterp)
3291            *setterp = desc.setter;
3292        return JS_TRUE;
3293    }
3294    
3295    static JSBool
3296  SetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,  SetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
3297                        uintN attrs, JSBool *foundp)                        uintN attrs, JSBool *foundp)
3298  {  {
# Line 3451  Line 3343 
3343  }  }
3344    
3345  JS_PUBLIC_API(JSBool)  JS_PUBLIC_API(JSBool)
3346    JS_GetPropertyAttrsGetterAndSetterById(JSContext *cx, JSObject *obj,
3347                                           jsid id,
3348                                           uintN *attrsp, JSBool *foundp,
3349                                           JSPropertyOp *getterp,
3350                                           JSPropertyOp *setterp)
3351    {
3352        CHECK_REQUEST(cx);
3353    
3354        JSPropertyDescriptor desc;
3355        if (!GetPropertyAttributesById(cx, obj, id, JSRESOLVE_QUALIFIED, JS_FALSE, &desc))
3356            return JS_FALSE;
3357    
3358        *attrsp = desc.attrs;
3359        *foundp = (desc.obj != NULL);
3360        if (getterp)
3361            *getterp = desc.getter;
3362        if (setterp)
3363            *setterp = desc.setter;
3364        return JS_TRUE;
3365    }
3366    
3367    JS_PUBLIC_API(JSBool)
3368  JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,  JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
3369                           uintN attrs, JSBool *foundp)                           uintN attrs, JSBool *foundp)
3370  {  {
# Line 3550  Line 3464 
3464  JS_PUBLIC_API(JSBool)  JS_PUBLIC_API(JSBool)
3465  JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)  JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
3466  {  {
     JSBool ok;  
3467      JSObject *obj2;      JSObject *obj2;
3468      JSProperty *prop;      JSProperty *prop;
3469    
3470      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
3471      ok = LookupProperty(cx, obj, name, JSRESOLVE_QUALIFIED, &obj2, &prop);      return LookupProperty(cx, obj, name, JSRESOLVE_QUALIFIED, &obj2, &prop) &&
3472      if (ok)             LookupResult(cx, obj, obj2, prop, vp);
         *vp = LookupResult(cx, obj, obj2, prop);  
     return ok;  
3473  }  }
3474    
3475  JS_PUBLIC_API(JSBool)  JS_PUBLIC_API(JSBool)
3476  JS_LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)  JS_LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
3477  {  {
     JSBool ok;  
3478      JSObject *obj2;      JSObject *obj2;
3479      JSProperty *prop;      JSProperty *prop;
3480    
3481      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
3482      ok = LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop);      return LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop) &&
3483      if (ok)             LookupResult(cx, obj, obj2, prop, vp);
         *vp = LookupResult(cx, obj, obj2, prop);  
     return ok;  
3484  }  }
3485    
3486  JS_PUBLIC_API(JSBool)  JS_PUBLIC_API(JSBool)
# Line 3600  Line 3508 
3508           ? js_LookupPropertyWithFlags(cx, obj, id, flags, objp, &prop) >= 0           ? js_LookupPropertyWithFlags(cx, obj, id, flags, objp, &prop) >= 0
3509           : OBJ_LOOKUP_PROPERTY(cx, obj, id, objp, &prop);           : OBJ_LOOKUP_PROPERTY(cx, obj, id, objp, &prop);
3510      if (ok)      if (ok)
3511          *vp = LookupResult(cx, obj, *objp, prop);          ok = LookupResult(cx, obj, *objp, prop, vp);
3512      return ok;      return ok;
3513  }  }
3514    
3515  JS_PUBLIC_API(JSBool)  JS_PUBLIC_API(JSBool)
3516    JS_GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, uintN flags,
3517                                 JSPropertyDescriptor *desc)
3518    {
3519        CHECK_REQUEST(cx);
3520    
3521        return GetPropertyAttributesById(cx, obj, id, flags, JS_FALSE, desc);
3522    }
3523    
3524    JS_PUBLIC_API(JSBool)
3525  JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)  JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
3526  {  {
3527      JSAtom *atom;      JSAtom *atom;
# Line 3633  Line 3550 
3550      JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);      JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
3551    
3552      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
3553  #if JS_HAS_XML_SUPPORT      if (!js_GetMethod(cx, obj, id, false, vp))
3554      if (OBJECT_IS_XML(cx, obj)) {          return JS_FALSE;
3555          JSXMLObjectOps *ops;      if (objp)
3556            *objp = obj;
         ops = (JSXMLObjectOps *) obj->map->ops;  
         obj = ops->getMethod(cx, obj, id, vp);  
         if (!obj)  
             return JS_FALSE;  
     } else  
 #endif  
     {  
         if (!OBJ_GET_PROPERTY(cx, obj, id, vp))  
             return JS_FALSE;  
     }  
   
     *objp = obj;  
3557      return JS_TRUE;      return JS_TRUE;
3558  }  }
3559    
# Line 3823  Line 3728 
3728                      const jschar *name, size_t namelen,                      const jschar *name, size_t namelen,
3729                      jsval *vp)                      jsval *vp)
3730  {  {
     JSBool ok;  
3731      JSObject *obj2;      JSObject *obj2;
3732      JSProperty *prop;      JSProperty *prop;
3733    
3734      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
3735      ok = LookupUCProperty(cx, obj, name, namelen, JSRESOLVE_QUALIFIED,      return LookupUCProperty(cx, obj, name, namelen, JSRESOLVE_QUALIFIED,
3736                            &obj2, &prop);                              &obj2, &prop) &&
3737      if (ok)             LookupResult(cx, obj, obj2, prop, vp);
         *vp = LookupResult(cx, obj, obj2, prop);  
     return ok;  
3738  }  }
3739    
3740  JS_PUBLIC_API(JSBool)  JS_PUBLIC_API(JSBool)
# Line 3991  Line 3893 
3893  JS_PUBLIC_API(JSBool)  JS_PUBLIC_API(JSBool)
3894  JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)  JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
3895  {  {
     JSBool ok;  
3896      JSObject *obj2;      JSObject *obj2;
3897      JSProperty *prop;      JSProperty *prop;
3898    
3899      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
3900      ok = LookupPropertyById(cx, obj, INT_TO_JSID(index), JSRESOLVE_QUALIFIED,      return LookupPropertyById(cx, obj, INT_TO_JSID(index), JSRESOLVE_QUALIFIED,
3901                              &obj2, &prop);                                &obj2, &prop) &&
3902      if (ok)             LookupResult(cx, obj, obj2, prop, vp);
         *vp = LookupResult(cx, obj, obj2, prop);  
     return ok;  
3903  }  }
3904    
3905  JS_PUBLIC_API(JSBool)  JS_PUBLIC_API(JSBool)
# Line 4223  Line 4122 
4122          index = ida->length;          index = ida->length;
4123      }      }
4124    
4125      /* iterobj can not escape to other threads here. */      /* iterobj cannot escape to other threads here. */
4126      STOBJ_SET_SLOT(iterobj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(pdata));      STOBJ_SET_SLOT(iterobj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(pdata));
4127      STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_INDEX, INT_TO_JSVAL(index));      STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_INDEX, INT_TO_JSVAL(index));
4128      return iterobj;      return iterobj;
# Line 4416  Line 4315 
4315  {  {
4316      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
4317      if (OBJ_GET_CLASS(cx, funobj) != &js_FunctionClass) {      if (OBJ_GET_CLASS(cx, funobj) != &js_FunctionClass) {
4318          /* Indicate we cannot clone this object. */          /*
4319          return funobj;           * We cannot clone this object, so fail (we used to return funobj, bad
4320             * idea, but we changed incompatibly to teach any abusers a lesson!).
4321             */
4322            jsval v = OBJECT_TO_JSVAL(funobj);
4323            js_ReportIsNotFunction(cx, &v, 0);
4324            return NULL;
4325      }      }
4326      return js_CloneFunctionObject(cx, GET_FUNCTION_PRIVATE(cx, funobj), parent);  
4327        JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
4328        JSObject *clone = js_CloneFunctionObject(cx, fun, parent);
4329        if (!clone)
4330            return NULL;
4331    
4332        /*
4333         * A flat closure carries its own environment, so why clone it? In case
4334         * someone wants to mutate its fixed slots or add ad-hoc properties. API
4335         * compatibility suggests we not return funobj and let callers mutate the
4336         * returned object at will.
4337         *
4338         * But it's worse than that: API compatibility according to the test for
4339         * bug 300079 requires we get "upvars" from parent and its ancestors! So
4340         * we do that (grudgingly!). The scope chain ancestors are searched as if
4341         * they were activations, respecting the skip field in each upvar's cookie
4342         * but looking up the property by name instead of frame slot.
4343         */
4344        if (FUN_FLAT_CLOSURE(fun)) {
4345            JS_ASSERT(funobj->dslots);
4346            JS_ASSERT(JSSLOT_FREE(&js_FunctionClass) == JS_INITIAL_NSLOTS);
4347    
4348            uint32 nslots = JSSLOT_FREE(&js_FunctionClass);
4349            JS_ASSERT(nslots == JS_INITIAL_NSLOTS);
4350            nslots += js_FunctionClass.reserveSlots(cx, clone);
4351            if (!js_ReallocSlots(cx, clone, nslots, JS_TRUE))
4352                return NULL;
4353    
4354            JSUpvarArray *uva = JS_SCRIPT_UPVARS(fun->u.i.script);
4355            JS_ASSERT(uva->length <= size_t(clone->dslots[-1]));
4356    
4357            void *mark = JS_ARENA_MARK(&cx->tempPool);
4358            jsuword *names = js_GetLocalNameArray(cx, fun, &cx->tempPool);
4359            if (!names)
4360                return NULL;
4361    
4362            uint32 i = 0, n = uva->length;
4363            for (; i < n; i++) {
4364                JSObject *obj = parent;
4365                int skip = UPVAR_FRAME_SKIP(uva->vector[i]);
4366                while (--skip > 0) {
4367                    if (!obj) {
4368                        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
4369                                             JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
4370                        goto break2;
4371                    }
4372                    obj = OBJ_GET_PARENT(cx, obj);
4373                }
4374    
4375                JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(names[i]);
4376                if (!OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &clone->dslots[i]))
4377                    break;
4378            }
4379    
4380          break2:
4381            JS_ARENA_RELEASE(&cx->tempPool, mark);
4382            if (i < n)
4383                return NULL;
4384        }
4385    
4386        return clone;
4387  }  }
4388    
4389  JS_PUBLIC_API(JSObject *)  JS_PUBLIC_API(JSObject *)
# Line 4445  Line 4409 
4409  JS_PUBLIC_API(uintN)  JS_PUBLIC_API(uintN)
4410  JS_GetFunctionFlags(JSFunction *fun)  JS_GetFunctionFlags(JSFunction *fun)
4411  {  {
 #ifdef MOZILLA_1_8_BRANCH  
     uintN flags = fun->flags;  
   
     return JSFUN_DISJOINT_FLAGS(flags) |  
            (JSFUN_GETTER_TEST(flags) ? JSFUN_GETTER : 0) |  
            (JSFUN_SETTER_TEST(flags) ? JSFUN_SETTER : 0) |  
            (JSFUN_BOUND_METHOD_TEST(flags) ? JSFUN_BOUND_METHOD : 0) |  
            (JSFUN_HEAVYWEIGHT_TEST(flags) ? JSFUN_HEAVYWEIGHT : 0);  
 #else  
4412      return fun->flags;      return fun->flags;
 #endif  
4413  }  }
4414    
4415  JS_PUBLIC_API(uint16)  JS_PUBLIC_API(uint16)
# Line 4519  Line 4473 
4473       * it as if the static was called with one parameter, the explicit |this|       * it as if the static was called with one parameter, the explicit |this|
4474       * object.       * object.
4475       */       */
4476      if (argc != 0)      if (argc != 0) {
4477          --argc;          /* Clear the last parameter in case too few arguments were passed. */
4478            vp[2 + --argc] = JSVAL_VOID;
4479        }
4480    
4481      native =      native =
4482  #ifdef JS_TRACER  #ifdef JS_TRACER
4483               (fs->flags & JSFUN_TRACEABLE)               (fs->flags & JSFUN_TRACEABLE)
4484               ? ((JSTraceableNative *) fs->call)->native               ? JS_FUNC_TO_DATA_PTR(JSTraceableNative *, fs->call)->native
4485               :               :
4486  #endif  #endif
4487                 (JSFastNative) fs->call;                 (JSFastNative) fs->call;
# Line 4574  Line 4530 
4530       * Follow Function.prototype.apply and .call by using the global object as       * Follow Function.prototype.apply and .call by using the global object as
4531       * the 'this' param if no args.       * the 'this' param if no args.
4532       */       */
     JS_ASSERT(cx->fp->argv == argv);  
4533      if (!js_ComputeThis(cx, JS_TRUE, argv))      if (!js_ComputeThis(cx, JS_TRUE, argv))
4534          return JS_FALSE;          return JS_FALSE;
4535      cx->fp->thisp = JSVAL_TO_OBJECT(argv[-1]);      js_GetTopStackFrame(cx)->thisp = JSVAL_TO_OBJECT(argv[-1]);
4536        JS_ASSERT(cx->fp->argv == argv);
4537    
4538      /*      /*
4539       * Protect against argc underflowing. By calling js_ComputeThis, we made       * Protect against argc underflowing. By calling js_ComputeThis, we made
4540       * it as if the static was called with one parameter, the explicit |this|       * it as if the static was called with one parameter, the explicit |this|
4541       * object.       * object.
4542       */       */
4543      if (argc != 0)      if (argc != 0) {
4544          --argc;          /* Clear the last parameter in case too few arguments were passed. */
4545            argv[--argc] = JSVAL_VOID;
4546        }
4547    
4548      return fs->call(cx, JSVAL_TO_OBJECT(argv[-1]), argc, argv, rval);      return fs->call(cx, JSVAL_TO_OBJECT(argv[-1]), argc, argv, rval);
4549  }  }
# Line 4724  Line 4682 
4682    
4683  #define LAST_FRAME_CHECKS(cx,result)                                          \  #define LAST_FRAME_CHECKS(cx,result)                                          \
4684      JS_BEGIN_MACRO                                                            \      JS_BEGIN_MACRO                                                            \
4685          if (!(cx)->fp) {                                                      \          if (!JS_IsRunning(cx)) {                                              \
4686              (cx)->weakRoots.lastInternalResult = JSVAL_NULL;                  \              (cx)->weakRoots.lastInternalResult = JSVAL_NULL;                  \
4687              LAST_FRAME_EXCEPTION_CHECK(cx, result);                           \              LAST_FRAME_EXCEPTION_CHECK(cx, result);                           \
4688          }                                                                     \          }                                                                     \
# Line 4745  Line 4703 
4703    
4704      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
4705      tcflags = JS_OPTIONS_TO_TCFLAGS(cx);      tcflags = JS_OPTIONS_TO_TCFLAGS(cx);
4706      script = js_CompileScript(cx, obj, NULL, principals, tcflags,      script = JSCompiler::compileScript(cx, obj, NULL, principals, tcflags,
4707                                chars, length, NULL, filename, lineno);                                         chars, length, NULL, filename, lineno);
4708      LAST_FRAME_CHECKS(cx, script);      LAST_FRAME_CHECKS(cx, script);
4709      return script;      return script;
4710  }  }
# Line 4758  Line 4716 
4716      jschar *chars;      jschar *chars;
4717      JSBool result;      JSBool result;
4718      JSExceptionState *exnState;      JSExceptionState *exnState;
     JSParseContext pc;  
4719      JSErrorReporter older;      JSErrorReporter older;
4720    
4721      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
# Line 4772  Line 4729 
4729       */       */
4730      result = JS_TRUE;      result = JS_TRUE;
4731      exnState = JS_SaveExceptionState(cx);      exnState = JS_SaveExceptionState(cx);
4732      if (js_InitParseContext(cx, &pc, NULL, NULL, chars, length, NULL, NULL,      {
4733                              1)) {          JSCompiler jsc(cx);
4734          older = JS_SetErrorReporter(cx, NULL);          if (jsc.init(chars, length, NULL, NULL, 1)) {
4735          if (!js_ParseScript(cx, obj, &pc) &&              older = JS_SetErrorReporter(cx, NULL);
4736              (pc.tokenStream.flags & TSF_UNEXPECTED_EOF)) {              if (!jsc.parse(obj) &&
4737              /*                  (jsc.tokenStream.flags & TSF_UNEXPECTED_EOF)) {
4738               * We ran into an error.  If it was because we ran out of source,                  /*
4739               * we return false, so our caller will know to try to collect more                   * We ran into an error. If it was because we ran out of
4740               * buffered source.                   * source, we return false so our caller knows to try to
4741               */                   * collect more buffered source.
4742              result = JS_FALSE;                   */
4743                    result = JS_FALSE;
4744                }
4745                JS_SetErrorReporter(cx, older);
4746          }          }
         JS_SetErrorReporter(cx, older);  
         js_FinishParseContext(cx, &pc);  
4747      }      }
4748      JS_free(cx, chars);      JS_free(cx, chars);
4749      JS_RestoreExceptionState(cx, exnState);      JS_RestoreExceptionState(cx, exnState);
# Line 4812  Line 4770 
4770      }      }
4771    
4772      tcflags = JS_OPTIONS_TO_TCFLAGS(cx);      tcflags = JS_OPTIONS_TO_TCFLAGS(cx);
4773      script = js_CompileScript(cx, obj, NULL, NULL, tcflags,      script = JSCompiler::compileScript(cx, obj, NULL, NULL, tcflags,
4774                                NULL, 0, fp, filename, 1);                                         NULL, 0, fp, filename, 1);
4775      if (fp != stdin)      if (fp != stdin)
4776          fclose(fp);          fclose(fp);
4777      LAST_FRAME_CHECKS(cx, script);      LAST_FRAME_CHECKS(cx, script);
# Line 4837  Line 4795 
4795    
4796      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
4797      tcflags = JS_OPTIONS_TO_TCFLAGS(cx);      tcflags = JS_OPTIONS_TO_TCFLAGS(cx);
4798      script = js_CompileScript(cx, obj, NULL, principals, tcflags,      script = JSCompiler::compileScript(cx, obj, NULL, principals, tcflags,
4799                                NULL, 0, file, filename, 1);                                         NULL, 0, file, filename, 1);
4800      LAST_FRAME_CHECKS(cx, script);      LAST_FRAME_CHECKS(cx, script);
4801      return script;      return script;
4802  }  }
# Line 4974  Line 4932 
4932          }          }
4933      }      }
4934    
4935      if (!js_CompileFunctionBody(cx, fun, principals, chars, length,      if (!JSCompiler::compileFunctionBody(cx, fun, principals,
4936                                  filename, lineno)) {                                           chars, length, filename, lineno)) {
4937          fun = NULL;          fun = NULL;
4938          goto out;          goto out;
4939      }      }
# Line 5175  Line 5133 
5133      JSBool ok;      JSBool ok;
5134    
5135      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
5136      script = js_CompileScript(cx, obj, NULL, principals,      script = JSCompiler::compileScript(cx, obj, NULL, principals,
5137                                !rval                                         !rval
5138                                ? TCF_COMPILE_N_GO | TCF_NO_SCRIPT_RVAL                                         ? TCF_COMPILE_N_GO | TCF_NO_SCRIPT_RVAL
5139                                : TCF_COMPILE_N_GO,                                         : TCF_COMPILE_N_GO,
5140                                chars, length, NULL, filename, lineno);                                         chars, length, NULL, filename, lineno);
5141      if (!script) {      if (!script) {
5142          LAST_FRAME_CHECKS(cx, script);          LAST_FRAME_CHECKS(cx, script);
5143          return JS_FALSE;          return JS_FALSE;
# Line 5207  Line 5165 
5165  JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc,  JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc,
5166                      jsval *argv, jsval *rval)                      jsval *argv, jsval *rval)
5167  {  {
     JSBool ok;  
     jsval fval;  
   
5168      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
 #if JS_HAS_XML_SUPPORT  
     if (OBJECT_IS_XML(cx, obj)) {  
         JSXMLObjectOps *ops;  
         JSAtom *atom;  
5169    
5170          ops = (JSXMLObjectOps *) obj->map->ops;      JSAutoTempValueRooter tvr(cx);
5171          atom = js_Atomize(cx, name, strlen(name), 0);      JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
5172          if (!atom)      JSBool ok = atom &&
5173              return JS_FALSE;                  JS_GetMethodById(cx, obj, ATOM_TO_JSID(atom), NULL,
5174          obj = ops->getMethod(cx, obj, ATOM_TO_JSID(atom), &fval);                                   tvr.addr()) &&
5175          if (!obj)                  js_InternalCall(cx, obj, tvr.value(), argc, argv, rval);
             return JS_FALSE;  
     } else  
 #endif  
     if (!JS_GetProperty(cx, obj, name, &fval))  
         return JS_FALSE;  
     ok = js_InternalCall(cx, obj, fval, argc, argv, rval);  
5176      LAST_FRAME_CHECKS(cx, ok);      LAST_FRAME_CHECKS(cx, ok);
5177      return ok;      return ok;
5178  }  }
# Line 5244  Line 5189 
5189      return ok;      return ok;
5190  }  }
5191    
5192  JS_PUBLIC_API(void)  JS_PUBLIC_API(JSOperationCallback)
5193  JS_SetOperationCallback(JSContext *cx, JSOperationCallback callback,  JS_SetOperationCallback(JSContext *cx, JSOperationCallback callback)
                         uint32 operationLimit)  
5194  {  {
5195      JS_ASSERT(callback);  #ifdef JS_THREADSAFE
5196      JS_ASSERT(operationLimit <= JS_MAX_OPERATION_LIMIT);      JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread));
5197      JS_ASSERT(operationLimit > 0);  #endif    
5198        JSOperationCallback old = cx->operationCallback;
     cx->operationCount = (int32) operationLimit;  
     cx->operationLimit = operationLimit;  
     cx->operationCallbackIsSet = 1;  
5199      cx->operationCallback = callback;      cx->operationCallback = callback;
5200  }      return old;
   
 JS_PUBLIC_API(void)  
 JS_ClearOperationCallback(JSContext *cx)  
 {  
     cx->operationCount = (int32) JS_MAX_OPERATION_LIMIT;  
     cx->operationLimit = JS_MAX_OPERATION_LIMIT;  
     cx->operationCallbackIsSet = 0;  
     cx->operationCallback = NULL;  
5201  }  }
5202    
5203  JS_PUBLIC_API(JSOperationCallback)  JS_PUBLIC_API(JSOperationCallback)
5204  JS_GetOperationCallback(JSContext *cx)  JS_GetOperationCallback(JSContext *cx)
5205  {  {
     JS_ASSERT(cx->operationCallbackIsSet || !cx->operationCallback);  
5206      return cx->operationCallback;      return cx->operationCallback;
5207  }  }
5208    
 JS_PUBLIC_API(uint32)  
 JS_GetOperationLimit(JSContext *cx)  
 {  
     JS_ASSERT(cx->operationCallbackIsSet);  
     return cx->operationLimit;  
 }  
   
5209  JS_PUBLIC_API(void)  JS_PUBLIC_API(void)
5210  JS_SetOperationLimit(JSContext *cx, uint32 operationLimit)  JS_TriggerOperationCallback(JSContext *cx)
5211  {  {
5212      JS_ASSERT(operationLimit <= JS_MAX_OPERATION_LIMIT);      /*
5213      JS_ASSERT(operationLimit > 0);       * Use JS_ATOMIC_SET in the hope that it will make sure the write
5214      JS_ASSERT(cx->operationCallbackIsSet);       * will become immediately visible to other processors polling
5215         * cx->operationCallbackFlag. Note that we only care about
5216      cx->operationLimit = operationLimit;       * visibility here, not read/write ordering.
5217      if (cx->operationCount > (int32) operationLimit)       */
5218          cx->operationCount = (int32) operationLimit;      JS_ATOMIC_SET(&cx->operationCallbackFlag, 1);
5219  }  }
5220    
5221  JS_PUBLIC_API(JSBranchCallback)  JS_PUBLIC_API(void)
5222  JS_SetBranchCallback(JSContext *cx, JSBranchCallback cb)  JS_TriggerAllOperationCallbacks(JSRuntime *rt)
5223  {  {
5224      JSBranchCallback oldcb;      js_TriggerAllOperationCallbacks(rt, JS_FALSE);
   
     if (cx->operationCallbackIsSet) {  
 #ifdef DEBUG  
         fprintf(stderr,  
 "JS API usage error: call to JS_SetOperationCallback is followed by\n"  
 "invocation of deprecated JS_SetBranchCallback\n");  
         JS_ASSERT(0);  
 #endif  
         cx->operationCallbackIsSet = 0;  
         oldcb = NULL;  
     } else {  
         oldcb = (JSBranchCallback) cx->operationCallback;  
     }  
     if (cb) {  
         cx->operationCount = JSOW_SCRIPT_JUMP;  
         cx->operationLimit = JSOW_SCRIPT_JUMP;  
         cx->operationCallback = (JSOperationCallback) cb;  
     } else {  
         JS_ClearOperationCallback(cx);  
     }  
     return oldcb;  
5225  }  }
5226    
5227  JS_PUBLIC_API(JSBool)  JS_PUBLIC_API(JSBool)
5228  JS_IsRunning(JSContext *cx)  JS_IsRunning(JSContext *cx)
5229  {  {
5230      return cx->fp != NULL;      /* The use of cx->fp below is safe: if we're on trace, it is skipped. */
5231        VOUCH_DOES_NOT_REQUIRE_STACK();
5232    
5233        return JS_ON_TRACE(cx) || cx->fp != NULL;
5234  }  }
5235    
5236  JS_PUBLIC_API(JSBool)  JS_PUBLIC_API(JSBool)
5237  JS_IsConstructing(JSContext *cx)  JS_IsConstructing(JSContext *cx)
5238  {  {
5239      return cx->fp && (cx->fp->flags & JSFRAME_CONSTRUCTING);  #ifdef JS_TRACER
5240        if (JS_ON_TRACE(cx)) {
5241            JS_ASSERT(cx->bailExit);
5242            return *cx->bailExit->pc == JSOP_NEW;
5243        }
5244    #endif
5245    
5246        JSStackFrame *fp = js_GetTopStackFrame(cx);
5247        return fp && (fp->flags & JSFRAME_CONSTRUCTING);
5248  }  }
5249    
5250  JS_FRIEND_API(JSBool)  JS_FRIEND_API(JSBool)
# Line 5337  Line 5252 
5252  {  {
5253      JSStackFrame *fp;      JSStackFrame *fp;
5254    
5255      for (fp = cx->fp; fp && !fp->script; fp = fp->down)      fp = js_GetScriptedCaller(cx, NULL);
         continue;  
5256      if (!fp || !fp->regs)      if (!fp || !fp->regs)
5257          return JS_FALSE;          return JS_FALSE;
5258      return (js_CodeSpec[*fp->regs->pc].format & JOF_ASSIGNING) != 0;      return (js_CodeSpec[*fp->regs->pc].format & JOF_ASSIGNING) != 0;
# Line 5358  Line 5272 
5272  {  {
5273      JSStackFrame *fp;      JSStackFrame *fp;
5274    
5275      fp = cx->fp;      fp = js_GetTopStackFrame(cx);
5276      if (!fp)      if (!fp)
5277          return fp;          return fp;
5278    
# Line 5372  Line 5286 
5286  JS_PUBLIC_API(void)  JS_PUBLIC_API(void)
5287  JS_RestoreFrameChain(JSContext *cx, JSStackFrame *fp)  JS_RestoreFrameChain(JSContext *cx, JSStackFrame *fp)
5288  {  {
5289        JS_ASSERT_NOT_ON_TRACE(cx);
5290      JS_ASSERT(!cx->fp);      JS_ASSERT(!cx->fp);
5291      if (!fp)      if (!fp)
5292          return;          return;
# Line 5535  Line 5450 
5450          if (s) {          if (s) {
5451              memcpy(s, JSSTRDEP_CHARS(str), n * sizeof *s);              memcpy(s, JSSTRDEP_CHARS(str), n * sizeof *s);
5452              s[n] = 0;              s[n] = 0;
5453              JSFLATSTR_INIT(str, s, n);              JSFLATSTR_REINIT(str, s, n);
5454          } else {          } else {
5455              s = JSSTRDEP_CHARS(str);              s = JSSTRDEP_CHARS(str);
5456          }          }
# Line 5633  Line 5548 
5548  }  }
5549    
5550  JS_PUBLIC_API(JSBool)  JS_PUBLIC_API(JSBool)
5551  JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer,  JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer, jsval space,
5552               JSONWriteCallback callback, void *data)               JSONWriteCallback callback, void *data)
5553  {  {
5554      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
5555      return js_Stringify(cx, vp, replacer, callback, data, 0);      return js_Stringify(cx, vp, replacer, space, callback, data);
5556  }  }
5557    
5558  JS_PUBLIC_API(JSBool)  JS_PUBLIC_API(JSBool)
# Line 5662  Line 5577 
5577  }  }
5578    
5579  JS_PUBLIC_API(JSBool)  JS_PUBLIC_API(JSBool)
5580  JS_FinishJSONParse(JSContext *cx, JSONParser *jp)  JS_FinishJSONParse(JSContext *cx, JSONParser *jp, jsval reviver)
5581  {  {
5582      CHECK_REQUEST(cx);      CHECK_REQUEST(cx);
5583      return js_FinishJSONParse(cx, jp);      return js_FinishJSONParse(cx, jp, reviver);
5584  }  }
5585    
5586  /*  /*
# Line 5983  Line 5898 
5898  JS_ThrowReportedError(JSContext *cx, const char *message,  JS_ThrowReportedError(JSContext *cx, const char *message,
5899                        JSErrorReport *reportp)                        JSErrorReport *reportp)
5900  {  {
5901      return cx->fp && js_ErrorToException(cx, message, reportp);      return JS_IsRunning(cx) && js_ErrorToException(cx, message, reportp);
5902  }  }
5903    
5904  JS_PUBLIC_API(JSBool)  JS_PUBLIC_API(JSBool)
# Line 6014  Line 5929 
5929  JS_SetContextThread(JSContext *cx)  JS_SetContextThread(JSContext *cx)
5930  {  {
5931  #ifdef JS_THREADSAFE  #ifdef JS_THREADSAFE
5932      jsword old = JS_THREAD_ID(cx);      JS_ASSERT(cx->requestDepth == 0);
5933      if (!js_SetContextThread(cx))      if (cx->thread) {
5934            JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread));
5935            return cx->thread->id;
5936        }
5937    
5938        if (!js_InitContextThread(cx)) {
5939            js_ReportOutOfMemory(cx);
5940          return -1;          return -1;
5941      return old;      }
5942  #else  
5943      return 0;      /* Here the GC lock is still held after js_InitContextThread took it. */
5944        JS_UNLOCK_GC(cx->runtime);
5945  #endif  #endif
5946        return 0;
5947  }  }
5948    
5949  JS_PUBLIC_API(jsword)  JS_PUBLIC_API(jsword)
5950  JS_ClearContextThread(JSContext *cx)  JS_ClearContextThread(JSContext *cx)
5951  {  {
5952  #ifdef JS_THREADSAFE  #ifdef JS_THREADSAFE
5953      jsword old = JS_THREAD_ID(cx);      /*
5954         * This must be called outside a request and, if cx is associated with a
5955         * thread, this must be called only from that thread.  If not, this is a
5956         * harmless no-op.
5957         */
5958        JS_ASSERT(cx->requestDepth == 0);
5959        if (!cx->thread)
5960            return 0;
5961        JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread));
5962        jsword old = cx->thread->id;
5963    
5964        /*
5965         * We must not race with a GC that accesses cx->thread for all threads,
5966         * see bug 476934.
5967         */
5968        JSRuntime *rt = cx->runtime;
5969        JS_LOCK_GC(rt);
5970        js_WaitForGC(rt);
5971      js_ClearContextThread(cx);      js_ClearContextThread(cx);
5972        JS_UNLOCK_GC(rt);
5973      return old;      return old;
5974  #else  #else
5975      return 0;      return 0;

Legend:
Removed from v.459  
changed lines
  Added in v.460

  ViewVC Help
Powered by ViewVC 1.1.24