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

Diff of /trunk/js/jsfun.cpp

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

revision 460 by siliconforks, Sat Sep 26 23:15:22 2009 UTC revision 507 by siliconforks, Sun Jan 10 07:23:34 2010 UTC
# Line 1  Line 1 
1  /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-  /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2   * vim: set ts=8 sw=4 et tw=99:   * vim: set ts=8 sw=4 et tw=99:
3   *   *
4   * ***** BEGIN LICENSE BLOCK *****   * ***** BEGIN LICENSE BLOCK *****
# Line 41  Line 41 
41  /*  /*
42   * JS function support.   * JS function support.
43   */   */
 #include "jsstddef.h"  
44  #include <string.h>  #include <string.h>
45  #include "jstypes.h"  #include "jstypes.h"
46    #include "jsstdint.h"
47  #include "jsbit.h"  #include "jsbit.h"
48  #include "jsutil.h" /* Added by JSIFY */  #include "jsutil.h" /* Added by JSIFY */
49  #include "jsapi.h"  #include "jsapi.h"
50  #include "jsarray.h"  #include "jsarray.h"
51  #include "jsatom.h"  #include "jsatom.h"
52    #include "jsbool.h"
53  #include "jsbuiltins.h"  #include "jsbuiltins.h"
54  #include "jscntxt.h"  #include "jscntxt.h"
55  #include "jsversion.h"  #include "jsversion.h"
# Line 68  Line 69 
69  #include "jsstr.h"  #include "jsstr.h"
70  #include "jsexn.h"  #include "jsexn.h"
71  #include "jsstaticcheck.h"  #include "jsstaticcheck.h"
72    #include "jstracer.h"
73    
74  #if JS_HAS_GENERATORS  #if JS_HAS_GENERATORS
75  # include "jsiter.h"  # include "jsiter.h"
# Line 77  Line 79 
79  # include "jsxdrapi.h"  # include "jsxdrapi.h"
80  #endif  #endif
81    
82  /* Generic function/call/arguments tinyids -- also reflected bit numbers. */  #include "jsatominlines.h"
 enum {  
     CALL_ARGUMENTS  = -1,       /* predefined arguments local variable */  
     ARGS_LENGTH     = -2,       /* number of actual args, arity if inactive */  
     ARGS_CALLEE     = -3,       /* reference from arguments to active funobj */  
     FUN_ARITY       = -4,       /* number of formal parameters; desired argc */  
     FUN_NAME        = -5,       /* function name, "" if anonymous */  
     FUN_CALLER      = -6        /* Function.prototype.caller, backward compat */  
 };  
83    
84  #if JSFRAME_OVERRIDE_BITS < 8  static inline void
85  # error "not enough override bits in JSStackFrame.flags!"  SetOverriddenArgsLength(JSObject *obj)
86  #endif  {
87        JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_ArgumentsClass);
88    
89        jsval v = obj->fslots[JSSLOT_ARGS_LENGTH];
90        v = INT_TO_JSVAL(JSVAL_TO_INT(v) | 1);
91        JS_ASSERT(JSVAL_IS_INT(v));
92        obj->fslots[JSSLOT_ARGS_LENGTH] = v;
93    }
94    
95    static inline void
96    InitArgsLengthSlot(JSObject *obj, uint32 argc)
97    {
98        JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_ArgumentsClass);
99        JS_ASSERT(argc <= JS_ARGS_LENGTH_MAX);
100        JS_ASSERT(obj->fslots[JSSLOT_ARGS_LENGTH] == JSVAL_VOID);
101        obj->fslots[JSSLOT_ARGS_LENGTH] = INT_TO_JSVAL(argc << 1);
102        JS_ASSERT(!js_IsOverriddenArgsLength(obj));
103    }
104    
105    static inline uint32
106    GetArgsLength(JSObject *obj)
107    {
108        JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_ArgumentsClass);
109    
110  #define TEST_OVERRIDE_BIT(fp, tinyid) \      uint32 argc = uint32(JSVAL_TO_INT(obj->fslots[JSSLOT_ARGS_LENGTH])) >> 1;
111      ((fp)->flags & JS_BIT(JSFRAME_OVERRIDE_SHIFT - ((tinyid) + 1)))      JS_ASSERT(argc <= JS_ARGS_LENGTH_MAX);
112        return argc;
113    }
114    
115  #define SET_OVERRIDE_BIT(fp, tinyid) \  static inline void
116      ((fp)->flags |= JS_BIT(JSFRAME_OVERRIDE_SHIFT - ((tinyid) + 1)))  SetArgsPrivateNative(JSObject *argsobj, js_ArgsPrivateNative *apn)
117    {
118        JS_ASSERT(STOBJ_GET_CLASS(argsobj) == &js_ArgumentsClass);
119        uintptr_t p = (uintptr_t) apn;
120        argsobj->setPrivate((void*) (p | 2));
121    }
122    
123  JSBool  JSBool
124  js_GetArgsValue(JSContext *cx, JSStackFrame *fp, jsval *vp)  js_GetArgsValue(JSContext *cx, JSStackFrame *fp, jsval *vp)
125  {  {
126      JSObject *argsobj;      JSObject *argsobj;
127    
128      if (TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {      if (fp->flags & JSFRAME_OVERRIDE_ARGS) {
129          JS_ASSERT(fp->callobj);          JS_ASSERT(fp->callobj);
130          return OBJ_GET_PROPERTY(cx, fp->callobj,          jsid id = ATOM_TO_JSID(cx->runtime->atomState.argumentsAtom);
131                                  ATOM_TO_JSID(cx->runtime->atomState          return fp->callobj->getProperty(cx, id, vp);
                                              .argumentsAtom),  
                                 vp);  
132      }      }
133      argsobj = js_GetArgsObject(cx, fp);      argsobj = js_GetArgsObject(cx, fp);
134      if (!argsobj)      if (!argsobj)
# Line 116  Line 137 
137      return JS_TRUE;      return JS_TRUE;
138  }  }
139    
 static JSBool  
 MarkArgDeleted(JSContext *cx, JSStackFrame *fp, uintN slot)  
 {  
     JSObject *argsobj;  
     jsval bmapval, bmapint;  
     size_t nbits, nbytes;  
     jsbitmap *bitmap;  
   
     argsobj = fp->argsobj;  
     (void) JS_GetReservedSlot(cx, argsobj, 0, &bmapval);  
     nbits = fp->argc;  
     JS_ASSERT(slot < nbits);  
     if (JSVAL_IS_VOID(bmapval)) {  
         if (nbits <= JSVAL_INT_BITS) {  
             bmapint = 0;  
             bitmap = (jsbitmap *) &bmapint;  
         } else {  
             nbytes = JS_HOWMANY(nbits, JS_BITS_PER_WORD) * sizeof(jsbitmap);  
             bitmap = (jsbitmap *) JS_malloc(cx, nbytes);  
             if (!bitmap)  
                 return JS_FALSE;  
             memset(bitmap, 0, nbytes);  
             bmapval = PRIVATE_TO_JSVAL(bitmap);  
             JS_SetReservedSlot(cx, argsobj, 0, bmapval);  
         }  
     } else {  
         if (nbits <= JSVAL_INT_BITS) {  
             bmapint = JSVAL_TO_INT(bmapval);  
             bitmap = (jsbitmap *) &bmapint;  
         } else {  
             bitmap = (jsbitmap *) JSVAL_TO_PRIVATE(bmapval);  
         }  
     }  
     JS_SET_BIT(bitmap, slot);  
     if (bitmap == (jsbitmap *) &bmapint) {  
         bmapval = INT_TO_JSVAL(bmapint);  
         JS_SetReservedSlot(cx, argsobj, 0, bmapval);  
     }  
     return JS_TRUE;  
 }  
   
 /* NB: Infallible predicate, false does not mean error/exception. */  
 static JSBool  
 ArgWasDeleted(JSContext *cx, JSStackFrame *fp, uintN slot)  
 {  
     JSObject *argsobj;  
     jsval bmapval, bmapint;  
     jsbitmap *bitmap;  
   
     argsobj = fp->argsobj;  
     (void) JS_GetReservedSlot(cx, argsobj, 0, &bmapval);  
     if (JSVAL_IS_VOID(bmapval))  
         return JS_FALSE;  
     if (fp->argc <= JSVAL_INT_BITS) {  
         bmapint = JSVAL_TO_INT(bmapval);  
         bitmap = (jsbitmap *) &bmapint;  
     } else {  
         bitmap = (jsbitmap *) JSVAL_TO_PRIVATE(bmapval);  
     }  
     return JS_TEST_BIT(bitmap, slot) != 0;  
 }  
   
140  JSBool  JSBool
141  js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, jsval *vp)  js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, jsval *vp)
142  {  {
143      jsval val;      if (fp->flags & JSFRAME_OVERRIDE_ARGS) {
     JSObject *obj;  
     uintN slot;  
   
     if (TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {  
144          JS_ASSERT(fp->callobj);          JS_ASSERT(fp->callobj);
145          if (!OBJ_GET_PROPERTY(cx, fp->callobj,  
146                                ATOM_TO_JSID(cx->runtime->atomState          jsid argumentsid = ATOM_TO_JSID(cx->runtime->atomState.argumentsAtom);
147                                             .argumentsAtom),          jsval v;
148                                &val)) {          if (!fp->callobj->getProperty(cx, argumentsid, &v))
149              return JS_FALSE;              return false;
150          }  
151          if (JSVAL_IS_PRIMITIVE(val)) {          JSObject *obj;
152              obj = js_ValueToNonNullObject(cx, val);          if (JSVAL_IS_PRIMITIVE(v)) {
153                obj = js_ValueToNonNullObject(cx, v);
154              if (!obj)              if (!obj)
155                  return JS_FALSE;                  return false;
156          } else {          } else {
157              obj = JSVAL_TO_OBJECT(val);              obj = JSVAL_TO_OBJECT(v);
158          }          }
159          return OBJ_GET_PROPERTY(cx, obj, id, vp);          return obj->getProperty(cx, id, vp);
160      }      }
161    
162      *vp = JSVAL_VOID;      *vp = JSVAL_VOID;
163      if (JSID_IS_INT(id)) {      if (JSID_IS_INT(id)) {
164          slot = (uintN) JSID_TO_INT(id);          uint32 arg = uint32(JSID_TO_INT(id));
165          if (slot < fp->argc) {          JSObject *argsobj = JSVAL_TO_OBJECT(fp->argsobj);
166              if (fp->argsobj && ArgWasDeleted(cx, fp, slot))          if (arg < fp->argc) {
167                  return OBJ_GET_PROPERTY(cx, fp->argsobj, id, vp);              if (argsobj) {
168              *vp = fp->argv[slot];                  jsval v = OBJ_GET_SLOT(cx, argsobj, JSSLOT_ARGS_COPY_START+arg);
169                    if (v == JSVAL_HOLE)
170                        return argsobj->getProperty(cx, id, vp);
171                }
172                *vp = fp->argv[arg];
173          } else {          } else {
174              /*              /*
175               * Per ECMA-262 Ed. 3, 10.1.8, last bulleted item, do not share               * Per ECMA-262 Ed. 3, 10.1.8, last bulleted item, do not share
# Line 223  Line 183 
183               * is null at this point, as it would be in the example, return               * is null at this point, as it would be in the example, return
184               * undefined in *vp.               * undefined in *vp.
185               */               */
186              if (fp->argsobj)              if (argsobj)
187                  return OBJ_GET_PROPERTY(cx, fp->argsobj, id, vp);                  return argsobj->getProperty(cx, id, vp);
         }  
     } else {  
         if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) {  
             if (fp->argsobj && TEST_OVERRIDE_BIT(fp, ARGS_LENGTH))  
                 return OBJ_GET_PROPERTY(cx, fp->argsobj, id, vp);  
             *vp = INT_TO_JSVAL((jsint) fp->argc);  
188          }          }
189        } else if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) {
190            JSObject *argsobj = JSVAL_TO_OBJECT(fp->argsobj);
191            if (argsobj && js_IsOverriddenArgsLength(argsobj))
192                return argsobj->getProperty(cx, id, vp);
193            *vp = INT_TO_JSVAL(jsint(fp->argc));
194      }      }
195      return JS_TRUE;      return true;
196    }
197    
198    static JSObject *
199    NewArguments(JSContext *cx, JSObject *parent, uint32 argc, JSObject *callee)
200    {
201        JSObject *argsobj = js_NewObject(cx, &js_ArgumentsClass, NULL, parent, 0);
202        if (!argsobj || !js_EnsureReservedSlots(cx, argsobj, argc))
203            return NULL;
204    
205        argsobj->fslots[JSSLOT_ARGS_CALLEE] = OBJECT_TO_JSVAL(callee);
206        InitArgsLengthSlot(argsobj, argc);
207        return argsobj;
208  }  }
209    
210    static void
211    PutArguments(JSContext *cx, JSObject *argsobj, jsval *args)
212    {
213        uint32 argc = GetArgsLength(argsobj);
214        JS_LOCK_OBJ(cx, argsobj);
215        for (uint32 i = 0; i != argc; ++i) {
216            jsval v = STOBJ_GET_SLOT(argsobj, JSSLOT_ARGS_COPY_START + i);
217            if (v != JSVAL_HOLE)
218                STOBJ_SET_SLOT(argsobj, JSSLOT_ARGS_COPY_START + i, args[i]);
219        }
220        JS_UNLOCK_OBJ(cx, argsobj);
221    }
222    
223    #ifdef OJI
224    JS_BEGIN_EXTERN_C
225    JS_EXPORT_API(JSObject *)
226    #else
227  JSObject *  JSObject *
228    #endif
229  js_GetArgsObject(JSContext *cx, JSStackFrame *fp)  js_GetArgsObject(JSContext *cx, JSStackFrame *fp)
230  {  {
     JSObject *argsobj, *global, *parent;  
   
231      /*      /*
232       * We must be in a function activation; the function must be lightweight       * We must be in a function activation; the function must be lightweight
233       * or else fp must have a variable object.       * or else fp must have a variable object.
# Line 252  Line 239 
239          fp = fp->down;          fp = fp->down;
240    
241      /* Create an arguments object for fp only if it lacks one. */      /* Create an arguments object for fp only if it lacks one. */
242      argsobj = fp->argsobj;      JSObject *argsobj = JSVAL_TO_OBJECT(fp->argsobj);
243      if (argsobj)      if (argsobj)
244          return argsobj;          return argsobj;
245    
     /* Link the new object to fp so it can get actual argument values. */  
     argsobj = js_NewObject(cx, &js_ArgumentsClass, NULL, NULL, 0);  
     if (!argsobj || !JS_SetPrivate(cx, argsobj, fp)) {  
         cx->weakRoots.newborn[GCX_OBJECT] = NULL;  
         return NULL;  
     }  
   
246      /*      /*
247       * Give arguments an intrinsic scope chain link to fp's global object.       * Give arguments an intrinsic scope chain link to fp's global object.
248       * Since the arguments object lacks a prototype because js_ArgumentsClass       * Since the arguments object lacks a prototype because js_ArgumentsClass
# Line 274  Line 254 
254       * js_GetClassPrototype not being able to find a global object containing       * js_GetClassPrototype not being able to find a global object containing
255       * the standard prototype by starting from arguments and following parent.       * the standard prototype by starting from arguments and following parent.
256       */       */
257      global = fp->scopeChain;      JSObject *parent, *global = fp->scopeChain;
258      while ((parent = OBJ_GET_PARENT(cx, global)) != NULL)      while ((parent = OBJ_GET_PARENT(cx, global)) != NULL)
259          global = parent;          global = parent;
260      STOBJ_SET_PARENT(argsobj, global);  
261      fp->argsobj = argsobj;      JS_ASSERT(fp->argv);
262        argsobj = NewArguments(cx, global, fp->argc, JSVAL_TO_OBJECT(fp->argv[-2]));
263        if (!argsobj)
264            return argsobj;
265    
266        /* Link the new object to fp so it can get actual argument values. */
267        argsobj->setPrivate(fp);
268        fp->argsobj = OBJECT_TO_JSVAL(argsobj);
269      return argsobj;      return argsobj;
270  }  }
271    
272  static JSBool  #ifdef OJI
273  args_enumerate(JSContext *cx, JSObject *obj);  JS_EXPORT_API(void)
274    #else
275  JS_FRIEND_API(JSBool)  void
276    #endif
277  js_PutArgsObject(JSContext *cx, JSStackFrame *fp)  js_PutArgsObject(JSContext *cx, JSStackFrame *fp)
278  {  {
279      JSObject *argsobj;      JSObject *argsobj = JSVAL_TO_OBJECT(fp->argsobj);
280      jsval bmapval, rval;      JS_ASSERT(argsobj->getPrivate() == fp);
281      JSBool ok;      PutArguments(cx, argsobj, fp->argv);
282      JSRuntime *rt;      argsobj->setPrivate(NULL);
283        fp->argsobj = JSVAL_NULL;
284    }
285    #ifdef OJI
286    JS_END_EXTERN_C
287    #endif
288    
289      /*  /*
290       * Reuse args_enumerate here to reflect fp's actual arguments as indexed   * Traced versions of js_GetArgsObject and js_PutArgsObject.
291       * elements of argsobj.  Do this first, before clearing and freeing the   */
      * deleted argument slot bitmap, because args_enumerate depends on that.  
      */  
     argsobj = fp->argsobj;  
     ok = args_enumerate(cx, argsobj);  
292    
293      /*  #ifdef JS_TRACER
294       * Now clear the deleted argument number bitmap slot and free the bitmap,  JSObject * JS_FASTCALL
295       * if one was actually created due to 'delete arguments[0]' or similar.  js_Arguments(JSContext *cx, JSObject *parent, uint32 argc, JSObject *callee,
296       */               double *argv, js_ArgsPrivateNative *apn)
297      (void) JS_GetReservedSlot(cx, argsobj, 0, &bmapval);  {
298      if (!JSVAL_IS_VOID(bmapval)) {      JSObject *argsobj = NewArguments(cx, parent, argc, callee);
299          JS_SetReservedSlot(cx, argsobj, 0, JSVAL_VOID);      if (!argsobj)
300          if (fp->argc > JSVAL_INT_BITS)          return NULL;
301              JS_free(cx, JSVAL_TO_PRIVATE(bmapval));      apn->argv = argv;
302      }      SetArgsPrivateNative(argsobj, apn);
303        return argsobj;
304    }
305    #endif
306    
307      /*  JS_DEFINE_CALLINFO_6(extern, OBJECT, js_Arguments, CONTEXT, OBJECT, UINT32, OBJECT,
308       * Now get the prototype properties so we snapshot fp->fun and fp->argc                       DOUBLEPTR, APNPTR, 0, 0)
      * before fp goes away.  
      */  
     rt = cx->runtime;  
     ok &= js_GetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.calleeAtom),  
                          &rval);  
     ok &= js_SetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.calleeAtom),  
                          &rval);  
     ok &= js_GetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.lengthAtom),  
                          &rval);  
     ok &= js_SetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.lengthAtom),  
                          &rval);  
309    
310      /*  /* FIXME change the return type to void. */
311       * Clear the private pointer to fp, which is about to go away (js_Invoke).  JSBool JS_FASTCALL
312       * Do this last because the args_enumerate and js_GetProperty calls above  js_PutArguments(JSContext *cx, JSObject *argsobj, jsval *args)
313       * need to follow the private slot to find fp.  {
314       */      JS_ASSERT(js_GetArgsPrivateNative(argsobj));
315      ok &= JS_SetPrivate(cx, argsobj, NULL);      PutArguments(cx, argsobj, args);
316      fp->argsobj = NULL;      argsobj->setPrivate(NULL);
317      return ok;      return true;
318  }  }
319    
320    JS_DEFINE_CALLINFO_3(extern, BOOL, js_PutArguments, CONTEXT, OBJECT, JSVALPTR, 0, 0)
321    
322  static JSBool  static JSBool
323  args_delProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)  args_delProperty(JSContext *cx, JSObject *obj, jsval idval, jsval *vp)
324  {  {
325      jsint slot;      JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_ArgumentsClass);
     JSStackFrame *fp;  
326    
327      if (!JSVAL_IS_INT(id))      if (JSVAL_IS_INT(idval)) {
328          return JS_TRUE;          uintN arg = uintN(JSVAL_TO_INT(idval));
329      fp = (JSStackFrame *)          if (arg < GetArgsLength(obj))
330           JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);              OBJ_SET_SLOT(cx, obj, JSSLOT_ARGS_COPY_START + arg, JSVAL_HOLE);
331      if (!fp)      } else if (idval == ATOM_KEY(cx->runtime->atomState.lengthAtom)) {
332          return JS_TRUE;          SetOverriddenArgsLength(obj);
333      JS_ASSERT(fp->argsobj);      } else if (idval == ATOM_KEY(cx->runtime->atomState.calleeAtom)) {
334            obj->fslots[JSSLOT_ARGS_CALLEE] = JSVAL_HOLE;
     slot = JSVAL_TO_INT(id);  
     switch (slot) {  
       case ARGS_CALLEE:  
       case ARGS_LENGTH:  
         SET_OVERRIDE_BIT(fp, slot);  
         break;  
   
       default:  
         if ((uintN)slot < fp->argc && !MarkArgDeleted(cx, fp, slot))  
             return JS_FALSE;  
         break;  
335      }      }
336      return JS_TRUE;      return true;
337  }  }
338    
339  static JS_REQUIRES_STACK JSObject *  static JS_REQUIRES_STACK JSObject *
# Line 384  Line 355 
355          return NULL;          return NULL;
356    
357      JSObject *wfunobj = js_NewObjectWithGivenProto(cx, &js_FunctionClass,      JSObject *wfunobj = js_NewObjectWithGivenProto(cx, &js_FunctionClass,
358                                                     funobj, scopeChain, 0);                                                     funobj, scopeChain);
359      if (!wfunobj)      if (!wfunobj)
360          return NULL;          return NULL;
361      JSAutoTempValueRooter tvr(cx, wfunobj);      JSAutoTempValueRooter tvr(cx, wfunobj);
362    
363      JSFunction *wfun = (JSFunction *) wfunobj;      JSFunction *wfun = (JSFunction *) wfunobj;
364      wfunobj->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(wfun);      wfunobj->setPrivate(wfun);
365      wfun->nargs = 0;      wfun->nargs = 0;
366      wfun->flags = fun->flags | JSFUN_HEAVYWEIGHT;      wfun->flags = fun->flags | JSFUN_HEAVYWEIGHT;
367      wfun->u.i.nvars = 0;      wfun->u.i.nvars = 0;
# Line 434  Line 405 
405      }      }
406    
407      JSScript *script = fun->u.i.script;      JSScript *script = fun->u.i.script;
408      jssrcnote *snbase = SCRIPT_NOTES(script);      jssrcnote *snbase = script->notes();
409      jssrcnote *sn = snbase;      jssrcnote *sn = snbase;
410      while (!SN_IS_TERMINATOR(sn))      while (!SN_IS_TERMINATOR(sn))
411          sn = SN_NEXT(sn);          sn = SN_NEXT(sn);
# Line 444  Line 415 
415      JSScript *wscript = js_NewScript(cx, script->length, nsrcnotes,      JSScript *wscript = js_NewScript(cx, script->length, nsrcnotes,
416                                       script->atomMap.length,                                       script->atomMap.length,
417                                       (script->objectsOffset != 0)                                       (script->objectsOffset != 0)
418                                       ? JS_SCRIPT_OBJECTS(script)->length                                       ? script->objects()->length
419                                       : 0,                                       : 0,
420                                       fun->u.i.nupvars,                                       fun->u.i.nupvars,
421                                       (script->regexpsOffset != 0)                                       (script->regexpsOffset != 0)
422                                       ? JS_SCRIPT_REGEXPS(script)->length                                       ? script->regexps()->length
423                                       : 0,                                       : 0,
424                                       (script->trynotesOffset != 0)                                       (script->trynotesOffset != 0)
425                                       ? JS_SCRIPT_TRYNOTES(script)->length                                       ? script->trynotes()->length
426                                       : 0);                                       : 0);
427      if (!wscript)      if (!wscript)
428          return NULL;          return NULL;
# Line 459  Line 430 
430      memcpy(wscript->code, script->code, script->length);      memcpy(wscript->code, script->code, script->length);
431      wscript->main = wscript->code + (script->main - script->code);      wscript->main = wscript->code + (script->main - script->code);
432    
433      memcpy(SCRIPT_NOTES(wscript), snbase, nsrcnotes);      memcpy(wscript->notes(), snbase, nsrcnotes * sizeof(jssrcnote));
434      memcpy(wscript->atomMap.vector, script->atomMap.vector,      memcpy(wscript->atomMap.vector, script->atomMap.vector,
435             wscript->atomMap.length * sizeof(JSAtom *));             wscript->atomMap.length * sizeof(JSAtom *));
436      if (script->objectsOffset != 0) {      if (script->objectsOffset != 0) {
437          memcpy(JS_SCRIPT_OBJECTS(wscript)->vector, JS_SCRIPT_OBJECTS(script)->vector,          memcpy(wscript->objects()->vector, script->objects()->vector,
438                 JS_SCRIPT_OBJECTS(wscript)->length * sizeof(JSObject *));                 wscript->objects()->length * sizeof(JSObject *));
439      }      }
440      if (script->regexpsOffset != 0) {      if (script->regexpsOffset != 0) {
441          memcpy(JS_SCRIPT_REGEXPS(wscript)->vector, JS_SCRIPT_REGEXPS(script)->vector,          memcpy(wscript->regexps()->vector, script->regexps()->vector,
442                 JS_SCRIPT_REGEXPS(wscript)->length * sizeof(JSObject *));                 wscript->regexps()->length * sizeof(JSObject *));
443      }      }
444      if (script->trynotesOffset != 0) {      if (script->trynotesOffset != 0) {
445          memcpy(JS_SCRIPT_TRYNOTES(wscript)->vector, JS_SCRIPT_TRYNOTES(script)->vector,          memcpy(wscript->trynotes()->vector, script->trynotes()->vector,
446                 JS_SCRIPT_TRYNOTES(wscript)->length * sizeof(JSTryNote));                 wscript->trynotes()->length * sizeof(JSTryNote));
447      }      }
448    
449      if (wfun->u.i.nupvars != 0) {      if (wfun->u.i.nupvars != 0) {
450          JS_ASSERT(wfun->u.i.nupvars == JS_SCRIPT_UPVARS(wscript)->length);          JS_ASSERT(wfun->u.i.nupvars == wscript->upvars()->length);
451          memcpy(JS_SCRIPT_UPVARS(wscript)->vector, JS_SCRIPT_UPVARS(script)->vector,          memcpy(wscript->upvars()->vector, script->upvars()->vector,
452                 wfun->u.i.nupvars * sizeof(uint32));                 wfun->u.i.nupvars * sizeof(uint32));
453      }      }
454    
# Line 534  Line 505 
505  }  }
506    
507  static JSBool  static JSBool
508  args_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)  ArgGetter(JSContext *cx, JSObject *obj, jsval idval, jsval *vp)
509  {  {
510      jsint slot;      if (!JS_InstanceOf(cx, obj, &js_ArgumentsClass, NULL))
511      JSStackFrame *fp;          return true;
512    
513      if (!JSVAL_IS_INT(id))      if (JSVAL_IS_INT(idval)) {
514          return JS_TRUE;          /*
515      fp = (JSStackFrame *)           * arg can exceed the number of arguments if a script changed the
516           JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);           * prototype to point to another Arguments object with a bigger argc.
517      if (!fp)           */
518          return JS_TRUE;          uintN arg = uintN(JSVAL_TO_INT(idval));
519      JS_ASSERT(fp->argsobj);          if (arg < GetArgsLength(obj)) {
520    #ifdef JS_TRACER
521                js_ArgsPrivateNative *argp = js_GetArgsPrivateNative(obj);
522                if (argp) {
523                    if (js_NativeToValue(cx, *vp, argp->typemap()[arg], &argp->argv[arg]))
524                        return true;
525                    js_LeaveTrace(cx);
526                    return false;
527                }
528    #endif
529    
530      slot = JSVAL_TO_INT(id);              JSStackFrame *fp = (JSStackFrame *) obj->getPrivate();
531      switch (slot) {              if (fp) {
532        case ARGS_CALLEE:                  *vp = fp->argv[arg];
533          if (!TEST_OVERRIDE_BIT(fp, slot)) {              } else {
534                    jsval v = OBJ_GET_SLOT(cx, obj, JSSLOT_ARGS_COPY_START + arg);
535                    if (v != JSVAL_HOLE)
536                        *vp = v;
537                }
538            }
539        } else if (idval == ATOM_KEY(cx->runtime->atomState.lengthAtom)) {
540            if (!js_IsOverriddenArgsLength(obj))
541                *vp = INT_TO_JSVAL(GetArgsLength(obj));
542        } else {
543            JS_ASSERT(idval == ATOM_KEY(cx->runtime->atomState.calleeAtom));
544            jsval v = obj->fslots[JSSLOT_ARGS_CALLEE];
545            if (v != JSVAL_HOLE) {
546              /*              /*
547               * If this function or one in it needs upvars that reach above it               * If this function or one in it needs upvars that reach above it
548               * in the scope chain, it must not be a null closure (it could be a               * in the scope chain, it must not be a null closure (it could be a
# Line 559  Line 551 
551               * to reduce code size and tell debugger users the truth instead of               * to reduce code size and tell debugger users the truth instead of
552               * passing off a fibbing wrapper.               * passing off a fibbing wrapper.
553               */               */
554              if (fp->fun->needsWrapper()) {              if (GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(v))->needsWrapper()) {
555                  JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,                  JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
556                                       JSMSG_OPTIMIZED_CLOSURE_LEAK);                                       JSMSG_OPTIMIZED_CLOSURE_LEAK);
557                  return JS_FALSE;                  return false;
558              }              }
559              *vp = OBJECT_TO_JSVAL(fp->callee);              *vp = v;
560          }          }
         break;  
   
       case ARGS_LENGTH:  
         if (!TEST_OVERRIDE_BIT(fp, slot))  
             *vp = INT_TO_JSVAL((jsint)fp->argc);  
         break;  
   
       default:  
         if ((uintN)slot < fp->argc && !ArgWasDeleted(cx, fp, slot))  
             *vp = fp->argv[slot];  
         break;  
561      }      }
562      return JS_TRUE;      return true;
563  }  }
564    
565  static JSBool  static JSBool
566  args_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)  ArgSetter(JSContext *cx, JSObject *obj, jsval idval, jsval *vp)
567  {  {
568      JSStackFrame *fp;  #ifdef JS_TRACER
569      jsint slot;      // To be able to set a property here on trace, we would have to make
570        // sure any updates also get written back to the trace native stack.
571      if (!JSVAL_IS_INT(id))      // For simplicity, we just leave trace, since this is presumably not
572          return JS_TRUE;      // a common operation.
573      fp = (JSStackFrame *)      if (JS_ON_TRACE(cx)) {
574           JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);          js_DeepBail(cx);
575      if (!fp)          return false;
576          return JS_TRUE;      }
577      JS_ASSERT(fp->argsobj);  #endif
   
     slot = JSVAL_TO_INT(id);  
     switch (slot) {  
       case ARGS_CALLEE:  
       case ARGS_LENGTH:  
         SET_OVERRIDE_BIT(fp, slot);  
         break;  
578    
579        default:      if (!JS_InstanceOf(cx, obj, &js_ArgumentsClass, NULL))
580          if (FUN_INTERPRETED(fp->fun) &&          return true;
581              (uintN)slot < fp->argc &&  
582              !ArgWasDeleted(cx, fp, slot)) {      if (JSVAL_IS_INT(idval)) {
583              fp->argv[slot] = *vp;          uintN arg = uintN(JSVAL_TO_INT(idval));
584            if (arg < GetArgsLength(obj)) {
585                JSStackFrame *fp = (JSStackFrame *) obj->getPrivate();
586                if (fp) {
587                    fp->argv[arg] = *vp;
588                    return true;
589                }
590          }          }
591          break;      } else {
592            JS_ASSERT(idval == ATOM_KEY(cx->runtime->atomState.lengthAtom) ||
593                      idval == ATOM_KEY(cx->runtime->atomState.calleeAtom));
594      }      }
595      return JS_TRUE;  
596        /*
597         * For simplicity we use delete/set to replace the property with one
598         * backed by the default Object getter and setter. Note the we rely on
599         * args_delete to clear the corresponding reserved slot so the GC can
600         * collect its value.
601         */
602        jsid id;
603        if (!JS_ValueToId(cx, idval, &id))
604            return false;
605    
606        JSAutoTempValueRooter tvr(cx);
607        return js_DeleteProperty(cx, obj, id, tvr.addr()) &&
608               js_SetProperty(cx, obj, id, vp);
609  }  }
610    
611  static JSBool  static JSBool
612  args_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,  args_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
613               JSObject **objp)               JSObject **objp)
614  {  {
615      JSStackFrame *fp;      JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_ArgumentsClass);
     uintN slot;  
     JSString *str;  
     JSAtom *atom;  
     intN tinyid;  
     jsval value;  
616    
617      *objp = NULL;      *objp = NULL;
618      fp = (JSStackFrame *)      jsid id = 0;
619           JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);      if (JSVAL_IS_INT(idval)) {
620      if (!fp)          uint32 arg = uint32(JSVAL_TO_INT(idval));
621          return JS_TRUE;          if (arg < GetArgsLength(obj) &&
622      JS_ASSERT(fp->argsobj);              OBJ_GET_SLOT(cx, obj, JSSLOT_ARGS_COPY_START + arg) != JSVAL_HOLE) {
623                id = INT_JSVAL_TO_JSID(idval);
624      if (JSVAL_IS_INT(id)) {          }
625          slot = JSVAL_TO_INT(id);      } else if (idval == ATOM_KEY(cx->runtime->atomState.lengthAtom)) {
626          if (slot < fp->argc && !ArgWasDeleted(cx, fp, slot)) {          if (!js_IsOverriddenArgsLength(obj))
627              /* XXX ECMA specs DontEnum, contrary to other array-like objects */              id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
628              if (!js_DefineProperty(cx, obj, INT_JSVAL_TO_JSID(id),  
629                                     fp->argv[slot],      } else if (idval == ATOM_KEY(cx->runtime->atomState.calleeAtom)) {
630                                     args_getProperty, args_setProperty,          if (obj->fslots[JSSLOT_ARGS_CALLEE] != JSVAL_HOLE)
631                                     0, NULL)) {              id = ATOM_TO_JSID(cx->runtime->atomState.calleeAtom);
                 return JS_FALSE;  
             }  
             *objp = obj;  
         }  
     } else if (JSVAL_IS_STRING(id)) {  
         str = JSVAL_TO_STRING(id);  
         atom = cx->runtime->atomState.lengthAtom;  
         if (str == ATOM_TO_STRING(atom)) {  
             tinyid = ARGS_LENGTH;  
             value = INT_TO_JSVAL(fp->argc);  
         } else {  
             atom = cx->runtime->atomState.calleeAtom;  
             if (str == ATOM_TO_STRING(atom)) {  
                 tinyid = ARGS_CALLEE;  
                 value = OBJECT_TO_JSVAL(fp->callee);  
             } else {  
                 atom = NULL;  
   
                 /* Quell GCC overwarnings. */  
                 tinyid = 0;  
                 value = JSVAL_NULL;  
             }  
         }  
   
         if (atom && !TEST_OVERRIDE_BIT(fp, tinyid)) {  
             if (!js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), value,  
                                          args_getProperty, args_setProperty, 0,  
                                          SPROP_HAS_SHORTID, tinyid, NULL)) {  
                 return JS_FALSE;  
             }  
             *objp = obj;  
         }  
632      }      }
633    
634      return JS_TRUE;      if (id != 0) {
635            /*
636             * XXX ECMA specs DontEnum even for indexed properties, contrary to
637             * other array-like objects.
638             */
639            if (!js_DefineProperty(cx, obj, id, JSVAL_VOID, ArgGetter, ArgSetter, JSPROP_SHARED))
640                return JS_FALSE;
641            *objp = obj;
642        }
643        return true;
644  }  }
645    
646  static JSBool  static JSBool
647  args_enumerate(JSContext *cx, JSObject *obj)  args_enumerate(JSContext *cx, JSObject *obj)
648  {  {
649      JSStackFrame *fp;      JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_ArgumentsClass);
     JSObject *pobj;  
     JSProperty *prop;  
     uintN slot, argc;  
   
     fp = (JSStackFrame *)  
          JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);  
     if (!fp)  
         return JS_TRUE;  
     JS_ASSERT(fp->argsobj);  
650    
651      /*      /*
652       * Trigger reflection with value snapshot in args_resolve using a series       * Trigger reflection in args_resolve using a series of js_LookupProperty
653       * of js_LookupProperty calls.  We handle length, callee, and the indexed       * calls.
      * argument properties.  We know that args_resolve covers all these cases  
      * and creates direct properties of obj, but that it may fail to resolve  
      * length or callee if overridden.  
654       */       */
655      if (!js_LookupProperty(cx, obj,      int argc = int(GetArgsLength(obj));
656                             ATOM_TO_JSID(cx->runtime->atomState.lengthAtom),      for (int i = -2; i != argc; i++) {
657                             &pobj, &prop)) {          jsid id = (i == -2)
658          return JS_FALSE;                    ? ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)
659      }                    : (i == -1)
660      if (prop)                    ? ATOM_TO_JSID(cx->runtime->atomState.calleeAtom)
661          OBJ_DROP_PROPERTY(cx, pobj, prop);                    : INT_JSVAL_TO_JSID(INT_TO_JSVAL(i));
662    
663      if (!js_LookupProperty(cx, obj,          JSObject *pobj;
664                             ATOM_TO_JSID(cx->runtime->atomState.calleeAtom),          JSProperty *prop;
665                             &pobj, &prop)) {          if (!js_LookupProperty(cx, obj, id, &pobj, &prop))
666          return JS_FALSE;              return false;
     }  
     if (prop)  
         OBJ_DROP_PROPERTY(cx, pobj, prop);  
667    
668      argc = fp->argc;          /* prop is null when the property was deleted. */
     for (slot = 0; slot < argc; slot++) {  
         if (!js_LookupProperty(cx, obj, INT_TO_JSID((jsint)slot), &pobj, &prop))  
             return JS_FALSE;  
669          if (prop)          if (prop)
670              OBJ_DROP_PROPERTY(cx, pobj, prop);              pobj->dropProperty(cx, prop);
671      }      }
672      return JS_TRUE;      return true;
673  }  }
674    
675  #if JS_HAS_GENERATORS  #if JS_HAS_GENERATORS
# Line 731  Line 680 
680  static void  static void
681  args_or_call_trace(JSTracer *trc, JSObject *obj)  args_or_call_trace(JSTracer *trc, JSObject *obj)
682  {  {
683      JSStackFrame *fp;      JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_ArgumentsClass ||
684                  STOBJ_GET_CLASS(obj) == &js_CallClass);
685        if (STOBJ_GET_CLASS(obj) == &js_ArgumentsClass && js_GetArgsPrivateNative(obj))
686            return;
687    
688      fp = (JSStackFrame *) JS_GetPrivate(trc->context, obj);      JSStackFrame *fp = (JSStackFrame *) obj->getPrivate();
689      if (fp && (fp->flags & JSFRAME_GENERATOR)) {      if (fp && (fp->flags & JSFRAME_GENERATOR)) {
690          JS_CALL_OBJECT_TRACER(trc, FRAME_TO_GENERATOR(fp)->obj,          JS_CALL_OBJECT_TRACER(trc, FRAME_TO_GENERATOR(fp)->obj,
691                                "FRAME_TO_GENERATOR(fp)->obj");                                "FRAME_TO_GENERATOR(fp)->obj");
# Line 743  Line 695 
695  # define args_or_call_trace NULL  # define args_or_call_trace NULL
696  #endif  #endif
697    
698    static uint32
699    args_reserveSlots(JSContext *cx, JSObject *obj)
700    {
701        JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_ArgumentsClass);
702        return GetArgsLength(obj);
703    }
704    
705  /*  /*
706   * The Arguments class is not initialized via JS_InitClass, and must not be,   * The Arguments class is not initialized via JS_InitClass, and must not be,
707   * because its name is "Object".  Per ECMA, that causes instances of it to   * because its name is "Object".  Per ECMA, that causes instances of it to
# Line 756  Line 715 
715   */   */
716  JSClass js_ArgumentsClass = {  JSClass js_ArgumentsClass = {
717      js_Object_str,      js_Object_str,
718      JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(1) |      JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE |
719        JSCLASS_HAS_RESERVED_SLOTS(ARGS_CLASS_FIXED_RESERVED_SLOTS) |
720      JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object),      JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
721      JS_PropertyStub,    args_delProperty,      JS_PropertyStub,    args_delProperty,
722      args_getProperty,   args_setProperty,      JS_PropertyStub,    JS_PropertyStub,
723      args_enumerate,     (JSResolveOp) args_resolve,      args_enumerate,     (JSResolveOp) args_resolve,
724      JS_ConvertStub,     JS_FinalizeStub,      JS_ConvertStub,     NULL,
725      NULL,               NULL,      NULL,               NULL,
726      NULL,               NULL,      NULL,               NULL,
727      NULL,               NULL,      NULL,               NULL,
728      JS_CLASS_TRACE(args_or_call_trace), NULL      JS_CLASS_TRACE(args_or_call_trace), args_reserveSlots
729  };  };
730    
731  #define JSSLOT_CALLEE                    (JSSLOT_PRIVATE + 1)  const uint32 JSSLOT_CALLEE =                    JSSLOT_PRIVATE + 1;
732  #define JSSLOT_CALL_ARGUMENTS            (JSSLOT_PRIVATE + 2)  const uint32 JSSLOT_CALL_ARGUMENTS =            JSSLOT_PRIVATE + 2;
733  #define CALL_CLASS_FIXED_RESERVED_SLOTS  2  const uint32 CALL_CLASS_FIXED_RESERVED_SLOTS =  2;
734    
735  /*  /*
736   * A Declarative Environment object stores its active JSStackFrame pointer in   * A Declarative Environment object stores its active JSStackFrame pointer in
# Line 780  Line 740 
740      js_Object_str,      js_Object_str,
741      JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object),      JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
742      JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,      JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
743      JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   JS_FinalizeStub,      JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   NULL,
744      JSCLASS_NO_OPTIONAL_MEMBERS      JSCLASS_NO_OPTIONAL_MEMBERS
745  };  };
746    
747  static JS_REQUIRES_STACK JSBool  static JSBool
748  CheckForEscapingClosure(JSContext *cx, JSObject *obj, jsval *vp)  CheckForEscapingClosure(JSContext *cx, JSObject *obj, jsval *vp)
749  {  {
750      JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_CallClass ||      JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_CallClass ||
# Line 803  Line 763 
763           * still has an active stack frame associated with it.           * still has an active stack frame associated with it.
764           */           */
765          if (fun->needsWrapper()) {          if (fun->needsWrapper()) {
766              JSStackFrame *fp = (JSStackFrame *) JS_GetPrivate(cx, obj);              js_LeaveTrace(cx);
767    
768                JSStackFrame *fp = (JSStackFrame *) obj->getPrivate();
769              if (fp) {              if (fp) {
770                  JSObject *wrapper = WrapEscapingClosure(cx, fp, funobj, fun);                  JSObject *wrapper = WrapEscapingClosure(cx, fp, funobj, fun);
771                  if (!wrapper)                  if (!wrapper)
# Line 820  Line 782 
782      return true;      return true;
783  }  }
784    
785  static JS_REQUIRES_STACK JSBool  static JSBool
786  CalleeGetter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)  CalleeGetter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
787  {  {
788      return CheckForEscapingClosure(cx, obj, vp);      return CheckForEscapingClosure(cx, obj, vp);
# Line 841  Line 803 
803      /* A call object should be a frame's outermost scope chain element.  */      /* A call object should be a frame's outermost scope chain element.  */
804      JSClass *classp = OBJ_GET_CLASS(cx, fp->scopeChain);      JSClass *classp = OBJ_GET_CLASS(cx, fp->scopeChain);
805      if (classp == &js_WithClass || classp == &js_BlockClass || classp == &js_CallClass)      if (classp == &js_WithClass || classp == &js_BlockClass || classp == &js_CallClass)
806          JS_ASSERT(OBJ_GET_PRIVATE(cx, fp->scopeChain) != fp);          JS_ASSERT(fp->scopeChain->getPrivate() != fp);
807  #endif  #endif
808    
809      /*      /*
# Line 853  Line 815 
815      JSAtom *lambdaName = (fp->fun->flags & JSFUN_LAMBDA) ? fp->fun->atom : NULL;      JSAtom *lambdaName = (fp->fun->flags & JSFUN_LAMBDA) ? fp->fun->atom : NULL;
816      if (lambdaName) {      if (lambdaName) {
817          JSObject *env = js_NewObjectWithGivenProto(cx, &js_DeclEnvClass, NULL,          JSObject *env = js_NewObjectWithGivenProto(cx, &js_DeclEnvClass, NULL,
818                                                     fp->scopeChain, 0);                                                     fp->scopeChain);
819          if (!env)          if (!env)
820              return NULL;              return NULL;
821          env->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fp);          env->setPrivate(fp);
822    
823          /* Root env before js_DefineNativeProperty (-> JSClass.addProperty). */          /* Root env before js_DefineNativeProperty (-> JSClass.addProperty). */
824          fp->scopeChain = env;          fp->scopeChain = env;
825            JS_ASSERT(fp->argv);
826          if (!js_DefineNativeProperty(cx, fp->scopeChain, ATOM_TO_JSID(lambdaName),          if (!js_DefineNativeProperty(cx, fp->scopeChain, ATOM_TO_JSID(lambdaName),
827                                       OBJECT_TO_JSVAL(fp->callee),                                       fp->argv[-2],
828                                       CalleeGetter, NULL,                                       CalleeGetter, NULL,
829                                       JSPROP_PERMANENT | JSPROP_READONLY,                                       JSPROP_PERMANENT | JSPROP_READONLY,
830                                       0, 0, NULL)) {                                       0, 0, NULL)) {
# Line 869  Line 832 
832          }          }
833      }      }
834    
835      callobj = js_NewObjectWithGivenProto(cx, &js_CallClass, NULL,      callobj = js_NewObjectWithGivenProto(cx, &js_CallClass, NULL, fp->scopeChain);
836                                           fp->scopeChain, 0);      if (!callobj ||
837      if (!callobj)          !js_EnsureReservedSlots(cx, callobj, fp->fun->countArgsAndVars())) {
838          return NULL;          return NULL;
839        }
840    
841      JS_SetPrivate(cx, callobj, fp);      callobj->setPrivate(fp);
842      JS_ASSERT(fp->fun == GET_FUNCTION_PRIVATE(cx, fp->callee));      JS_ASSERT(fp->argv);
843      STOBJ_SET_SLOT(callobj, JSSLOT_CALLEE, OBJECT_TO_JSVAL(fp->callee));      JS_ASSERT(fp->fun == GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(fp->argv[-2])));
844        STOBJ_SET_SLOT(callobj, JSSLOT_CALLEE, fp->argv[-2]);
845      fp->callobj = callobj;      fp->callobj = callobj;
846    
847      /*      /*
# Line 888  Line 853 
853      return callobj;      return callobj;
854  }  }
855    
856  static JSFunction *  JSFunction *
857  GetCallObjectFunction(JSObject *obj)  js_GetCallObjectFunction(JSObject *obj)
858  {  {
859      jsval v;      jsval v;
860    
# Line 903  Line 868 
868      return GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(v));      return GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(v));
869  }  }
870    
871  JS_FRIEND_API(JSBool)  #ifdef OJI
872    JS_BEGIN_EXTERN_C
873    JS_EXPORT_API(void)
874    #else
875    void
876    #endif
877  js_PutCallObject(JSContext *cx, JSStackFrame *fp)  js_PutCallObject(JSContext *cx, JSStackFrame *fp)
878  {  {
879      JSObject *callobj;      JSObject *callobj = fp->callobj;
880      JSBool ok;      JS_ASSERT(callobj);
881      JSFunction *fun;  
882      uintN n;      /* Get the arguments object to snapshot fp's actual argument values. */
883      JSScope *scope;      if (fp->argsobj) {
884            if (!(fp->flags & JSFRAME_OVERRIDE_ARGS))
885                STOBJ_SET_SLOT(callobj, JSSLOT_CALL_ARGUMENTS, fp->argsobj);
886            js_PutArgsObject(cx, fp);
887        }
888    
889        JSFunction *fun = fp->fun;
890        JS_ASSERT(fun == js_GetCallObjectFunction(callobj));
891        uintN n = fun->countArgsAndVars();
892    
893      /*      /*
894       * Since for a call object all fixed slots happen to be taken, we can copy       * Since for a call object all fixed slots happen to be taken, we can copy
# Line 918  Line 896 
896       */       */
897      JS_STATIC_ASSERT(JS_INITIAL_NSLOTS - JSSLOT_PRIVATE ==      JS_STATIC_ASSERT(JS_INITIAL_NSLOTS - JSSLOT_PRIVATE ==
898                       1 + CALL_CLASS_FIXED_RESERVED_SLOTS);                       1 + CALL_CLASS_FIXED_RESERVED_SLOTS);
   
     callobj = fp->callobj;  
     if (!callobj)  
         return JS_TRUE;  
   
     /*  
      * Get the arguments object to snapshot fp's actual argument values.  
      */  
     ok = JS_TRUE;  
     if (fp->argsobj) {  
         if (!TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {  
             STOBJ_SET_SLOT(callobj, JSSLOT_CALL_ARGUMENTS,  
                            OBJECT_TO_JSVAL(fp->argsobj));  
         }  
         ok &= js_PutArgsObject(cx, fp);  
     }  
   
     fun = fp->fun;  
     JS_ASSERT(fun == GetCallObjectFunction(callobj));  
     n = fun->countArgsAndVars();  
899      if (n != 0) {      if (n != 0) {
900          JS_LOCK_OBJ(cx, callobj);          JS_ASSERT(STOBJ_NSLOTS(callobj) >= JS_INITIAL_NSLOTS + n);
901          n += JS_INITIAL_NSLOTS;          n += JS_INITIAL_NSLOTS;
902          if (n > STOBJ_NSLOTS(callobj))          JS_LOCK_OBJ(cx, callobj);
903              ok &= js_ReallocSlots(cx, callobj, n, JS_TRUE);          memcpy(callobj->dslots, fp->argv, fun->nargs * sizeof(jsval));
904          scope = OBJ_SCOPE(callobj);          memcpy(callobj->dslots + fun->nargs, fp->slots,
905          if (ok) {                 fun->u.i.nvars * sizeof(jsval));
906              memcpy(callobj->dslots, fp->argv, fun->nargs * sizeof(jsval));          JS_UNLOCK_OBJ(cx, callobj);
             memcpy(callobj->dslots + fun->nargs, fp->slots,  
                    fun->u.i.nvars * sizeof(jsval));  
             if (scope->object == callobj && n > scope->freeslot)  
                 scope->freeslot = n;  
         }  
         JS_UNLOCK_SCOPE(cx, scope);  
907      }      }
908    
909      /*      /* Clear private pointers to fp, which is about to go away (js_Invoke). */
      * Clear private pointers to fp, which is about to go away (js_Invoke).  
      * Do this last because js_GetProperty calls above need to follow the  
      * call object's private slot to find fp.  
      */  
910      if ((fun->flags & JSFUN_LAMBDA) && fun->atom) {      if ((fun->flags & JSFUN_LAMBDA) && fun->atom) {
911          JSObject *env = STOBJ_GET_PARENT(callobj);          JSObject *env = STOBJ_GET_PARENT(callobj);
912    
913          JS_ASSERT(STOBJ_GET_CLASS(env) == &js_DeclEnvClass);          JS_ASSERT(STOBJ_GET_CLASS(env) == &js_DeclEnvClass);
914          JS_ASSERT(STOBJ_GET_PRIVATE(env) == fp);          JS_ASSERT(env->getPrivate() == fp);
915          JS_SetPrivate(cx, env, NULL);          env->setPrivate(NULL);
916      }      }
917    
918      JS_SetPrivate(cx, callobj, NULL);      callobj->setPrivate(NULL);
919      fp->callobj = NULL;      fp->callobj = NULL;
     return ok;  
920  }  }
921    #ifdef OJI
922    JS_END_EXTERN_C
923    #endif
924    
925  static JSBool  static JSBool
926  call_enumerate(JSContext *cx, JSObject *obj)  call_enumerate(JSContext *cx, JSObject *obj)
# Line 984  Line 934 
934      JSObject *pobj;      JSObject *pobj;
935      JSProperty *prop;      JSProperty *prop;
936    
937      fun = GetCallObjectFunction(obj);      fun = js_GetCallObjectFunction(obj);
938      n = fun ? fun->countArgsAndVars() : 0;      n = fun ? fun->countArgsAndVars() : 0;
939      if (n == 0)      if (n == 0)
940          return JS_TRUE;          return JS_TRUE;
# Line 1018  Line 968 
968           */           */
969          JS_ASSERT(prop);          JS_ASSERT(prop);
970          JS_ASSERT(pobj == obj);          JS_ASSERT(pobj == obj);
971          OBJ_DROP_PROPERTY(cx, pobj, prop);          pobj->dropProperty(cx, prop);
972      }      }
973      ok = JS_TRUE;      ok = JS_TRUE;
974    
# Line 1045  Line 995 
995      if (STOBJ_GET_CLASS(obj) != &js_CallClass)      if (STOBJ_GET_CLASS(obj) != &js_CallClass)
996          return JS_TRUE;          return JS_TRUE;
997    
998      fun = GetCallObjectFunction(obj);      fun = js_GetCallObjectFunction(obj);
999      fp = (JSStackFrame *) JS_GetPrivate(cx, obj);      fp = (JSStackFrame *) obj->getPrivate();
1000    
1001      if (kind == JSCPK_ARGUMENTS) {      if (kind == JSCPK_ARGUMENTS) {
1002          if (setter) {          if (setter) {
1003              if (fp)              if (fp)
1004                  SET_OVERRIDE_BIT(fp, CALL_ARGUMENTS);                  fp->flags |= JSFRAME_OVERRIDE_ARGS;
1005              STOBJ_SET_SLOT(obj, JSSLOT_CALL_ARGUMENTS, *vp);              STOBJ_SET_SLOT(obj, JSSLOT_CALL_ARGUMENTS, *vp);
1006          } else {          } else {
1007              if (fp && !TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {              if (fp && !(fp->flags & JSFRAME_OVERRIDE_ARGS)) {
1008                  JSObject *argsobj;                  JSObject *argsobj;
1009    
1010                  argsobj = js_GetArgsObject(cx, fp);                  argsobj = js_GetArgsObject(cx, fp);
# Line 1117  Line 1067 
1067      return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_FALSE);      return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_FALSE);
1068  }  }
1069    
1070  static JSBool  JSBool
1071  SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp)  SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
1072  {  {
1073      return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_TRUE);      return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_TRUE);
# Line 1138  Line 1088 
1088      return CheckForEscapingClosure(cx, obj, vp);      return CheckForEscapingClosure(cx, obj, vp);
1089  }  }
1090    
1091  static JSBool  JSBool
1092  SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp)  SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
1093  {  {
1094      return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_TRUE);      return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_TRUE);
1095  }  }
1096    
1097    JSBool JS_FASTCALL
1098    js_SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval v)
1099    {
1100        return CallPropertyOp(cx, obj, id, &v, JSCPK_ARG, JS_TRUE);
1101    }
1102    
1103    JSBool JS_FASTCALL
1104    js_SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval v)
1105    {
1106        return CallPropertyOp(cx, obj, id, &v, JSCPK_VAR, JS_TRUE);
1107    }
1108    
1109    JS_DEFINE_CALLINFO_4(extern, BOOL, js_SetCallArg, CONTEXT, OBJECT, JSID, JSVAL, 0, 0)
1110    JS_DEFINE_CALLINFO_4(extern, BOOL, js_SetCallVar, CONTEXT, OBJECT, JSID, JSVAL, 0, 0)
1111    
1112  static JSBool  static JSBool
1113  call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,  call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
1114               JSObject **objp)               JSObject **objp)
# Line 1245  Line 1210 
1210  static JSBool  static JSBool
1211  call_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)  call_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
1212  {  {
     JSStackFrame *fp;  
   
1213      if (type == JSTYPE_FUNCTION) {      if (type == JSTYPE_FUNCTION) {
1214          fp = (JSStackFrame *) JS_GetPrivate(cx, obj);          JSStackFrame *fp = (JSStackFrame *) obj->getPrivate();
1215          if (fp) {          if (fp) {
1216              JS_ASSERT(fp->fun);              JS_ASSERT(fp->fun);
1217              *vp = OBJECT_TO_JSVAL(fp->callee);              JS_ASSERT(fp->argv);
1218                *vp = fp->argv[-2];
1219          }          }
1220      }      }
1221      return JS_TRUE;      return JS_TRUE;
# Line 1262  Line 1226 
1226  {  {
1227      JSFunction *fun;      JSFunction *fun;
1228    
1229      fun = GetCallObjectFunction(obj);      fun = js_GetCallObjectFunction(obj);
1230      return fun->countArgsAndVars();      return fun->countArgsAndVars();
1231  }  }
1232    
# Line 1274  Line 1238 
1238      JS_PropertyStub,    JS_PropertyStub,      JS_PropertyStub,    JS_PropertyStub,
1239      JS_PropertyStub,    JS_PropertyStub,      JS_PropertyStub,    JS_PropertyStub,
1240      call_enumerate,     (JSResolveOp)call_resolve,      call_enumerate,     (JSResolveOp)call_resolve,
1241      call_convert,       JS_FinalizeStub,      call_convert,       NULL,
1242      NULL,               NULL,      NULL,               NULL,
1243      NULL,               NULL,      NULL,               NULL,
1244      NULL,               NULL,      NULL,               NULL,
1245      JS_CLASS_TRACE(args_or_call_trace), call_reserveSlots      JS_CLASS_TRACE(args_or_call_trace), call_reserveSlots
1246  };  };
1247    
1248    /* Generic function tinyids. */
1249    enum {
1250        FUN_ARGUMENTS   = -1,       /* predefined arguments local variable */
1251        FUN_LENGTH      = -2,       /* number of actual args, arity if inactive */
1252        FUN_ARITY       = -3,       /* number of formal parameters; desired argc */
1253        FUN_NAME        = -4,       /* function name, "" if anonymous */
1254        FUN_CALLER      = -5        /* Function.prototype.caller, backward compat */
1255    };
1256    
1257  static JSBool  static JSBool
1258  fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)  fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
1259  {  {
# Line 1295  Line 1268 
1268    
1269      /*      /*
1270       * Loop because getter and setter can be delegated from another class,       * Loop because getter and setter can be delegated from another class,
1271       * but loop only for ARGS_LENGTH because we must pretend that f.length       * but loop only for FUN_LENGTH because we must pretend that f.length
1272       * is in each function instance f, per ECMA-262, instead of only in the       * is in each function instance f, per ECMA-262, instead of only in the
1273       * Function.prototype object (we use JSPROP_PERMANENT with JSPROP_SHARED       * Function.prototype object (we use JSPROP_PERMANENT with JSPROP_SHARED
1274       * to make it appear so).       * to make it appear so).
# Line 1305  Line 1278 
1278       *       *
1279       * It's important to allow delegating objects, even though they inherit       * It's important to allow delegating objects, even though they inherit
1280       * this getter (fun_getProperty), to override arguments, arity, caller,       * this getter (fun_getProperty), to override arguments, arity, caller,
1281       * and name.  If we didn't return early for slot != ARGS_LENGTH, we would       * and name.  If we didn't return early for slot != FUN_LENGTH, we would
1282       * clobber *vp with the native property value, instead of letting script       * clobber *vp with the native property value, instead of letting script
1283       * override that value in delegating objects.       * override that value in delegating objects.
1284       *       *
# Line 1315  Line 1288 
1288       */       */
1289      while (!(fun = (JSFunction *)      while (!(fun = (JSFunction *)
1290                     JS_GetInstancePrivate(cx, obj, &js_FunctionClass, NULL))) {                     JS_GetInstancePrivate(cx, obj, &js_FunctionClass, NULL))) {
1291          if (slot != ARGS_LENGTH)          if (slot != FUN_LENGTH)
1292              return JS_TRUE;              return JS_TRUE;
1293          obj = OBJ_GET_PROTO(cx, obj);          obj = OBJ_GET_PROTO(cx, obj);
1294          if (!obj)          if (!obj)
# Line 1330  Line 1303 
1303      }      }
1304    
1305      switch (slot) {      switch (slot) {
1306        case CALL_ARGUMENTS:        case FUN_ARGUMENTS:
1307          /* Warn if strict about f.arguments or equivalent unqualified uses. */          /* Warn if strict about f.arguments or equivalent unqualified uses. */
1308          if (!JS_ReportErrorFlagsAndNumber(cx,          if (!JS_ReportErrorFlagsAndNumber(cx,
1309                                            JSREPORT_WARNING | JSREPORT_STRICT,                                            JSREPORT_WARNING | JSREPORT_STRICT,
# Line 1347  Line 1320 
1320          }          }
1321          break;          break;
1322    
1323        case ARGS_LENGTH:        case FUN_LENGTH:
1324        case FUN_ARITY:        case FUN_ARITY:
1325              *vp = INT_TO_JSVAL((jsint)fun->nargs);              *vp = INT_TO_JSVAL((jsint)fun->nargs);
1326          break;          break;
# Line 1375  Line 1348 
1348                  return JS_TRUE;                  return JS_TRUE;
1349              }              }
1350    
1351              *vp = OBJECT_TO_JSVAL(fp->down->callee);              JS_ASSERT(fp->down->argv);
1352                *vp = fp->down->argv[-2];
1353          } else {          } else {
1354              *vp = JSVAL_NULL;              *vp = JSVAL_NULL;
1355          }          }
# Line 1416  Line 1390 
1390  #define LENGTH_PROP_ATTRS (JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED)  #define LENGTH_PROP_ATTRS (JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED)
1391    
1392  static JSPropertySpec function_props[] = {  static JSPropertySpec function_props[] = {
1393      {js_length_str,    ARGS_LENGTH,    LENGTH_PROP_ATTRS, fun_getProperty, JS_PropertyStub},      {js_length_str,    FUN_LENGTH,    LENGTH_PROP_ATTRS, fun_getProperty, JS_PropertyStub},
1394      {0,0,0,0,0}      {0,0,0,0,0}
1395  };  };
1396    
# Line 1428  Line 1402 
1402    
1403  /* NB: no sentinel at the end -- use JS_ARRAY_LENGTH to bound loops. */  /* NB: no sentinel at the end -- use JS_ARRAY_LENGTH to bound loops. */
1404  static LazyFunctionProp lazy_function_props[] = {  static LazyFunctionProp lazy_function_props[] = {
1405      {ATOM_OFFSET(arguments), CALL_ARGUMENTS, JSPROP_PERMANENT},      {ATOM_OFFSET(arguments), FUN_ARGUMENTS, JSPROP_PERMANENT},
1406      {ATOM_OFFSET(arity),     FUN_ARITY,      JSPROP_PERMANENT},      {ATOM_OFFSET(arity),     FUN_ARITY,      JSPROP_PERMANENT},
1407      {ATOM_OFFSET(caller),    FUN_CALLER,     JSPROP_PERMANENT},      {ATOM_OFFSET(caller),    FUN_CALLER,     JSPROP_PERMANENT},
1408      {ATOM_OFFSET(name),      FUN_NAME,       JSPROP_PERMANENT},      {ATOM_OFFSET(name),      FUN_NAME,       JSPROP_PERMANENT},
# Line 1442  Line 1416 
1416      JSProperty *prop;      JSProperty *prop;
1417    
1418      prototypeId = ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom);      prototypeId = ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom);
1419      if (!OBJ_LOOKUP_PROPERTY(cx, obj, prototypeId, &pobj, &prop))      if (!obj->lookupProperty(cx, prototypeId, &pobj, &prop))
1420          return JS_FALSE;          return JS_FALSE;
1421      if (prop)      if (prop)
1422          OBJ_DROP_PROPERTY(cx, pobj, prop);          pobj->dropProperty(cx, prop);
1423      return JS_TRUE;      return JS_TRUE;
1424  }  }
1425    
# Line 1487  Line 1461 
1461           * Make the prototype object to have the same parent as the function           * Make the prototype object to have the same parent as the function
1462           * object itself.           * object itself.
1463           */           */
1464          proto = js_NewObject(cx, &js_ObjectClass, NULL, OBJ_GET_PARENT(cx, obj),          proto = js_NewObject(cx, &js_ObjectClass, NULL, OBJ_GET_PARENT(cx, obj));
                              0);  
1465          if (!proto)          if (!proto)
1466              return JS_FALSE;              return JS_FALSE;
1467    
# Line 1499  Line 1472 
1472           * set the former here in fun_resolve, but eagerly define the latter           * set the former here in fun_resolve, but eagerly define the latter
1473           * in JS_InitClass, with the right attributes.           * in JS_InitClass, with the right attributes.
1474           */           */
1475          if (!js_SetClassPrototype(cx, obj, proto,          if (!js_SetClassPrototype(cx, obj, proto, JSPROP_PERMANENT))
                                   JSPROP_ENUMERATE | JSPROP_PERMANENT)) {  
             cx->weakRoots.newborn[GCX_OBJECT] = NULL;  
1476              return JS_FALSE;              return JS_FALSE;
1477          }  
1478          *objp = obj;          *objp = obj;
1479          return JS_TRUE;          return JS_TRUE;
1480      }      }
# Line 1750  Line 1721 
1721  fun_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)  fun_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
1722  {  {
1723      jsval pval;      jsval pval;
1724        jsid id = ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom);
1725      if (!OBJ_GET_PROPERTY(cx, obj,      if (!obj->getProperty(cx, id, &pval))
                           ATOM_TO_JSID(cx->runtime->atomState  
                                        .classPrototypeAtom),  
                           &pval)) {  
1726          return JS_FALSE;          return JS_FALSE;
     }  
1727    
1728      if (JSVAL_IS_PRIMITIVE(pval)) {      if (JSVAL_IS_PRIMITIVE(pval)) {
1729          /*          /*
# Line 1780  Line 1747 
1747  static void  static void
1748  fun_trace(JSTracer *trc, JSObject *obj)  fun_trace(JSTracer *trc, JSObject *obj)
1749  {  {
     JSFunction *fun;  
   
1750      /* A newborn function object may have a not yet initialized private slot. */      /* A newborn function object may have a not yet initialized private slot. */
1751      fun = (JSFunction *) JS_GetPrivate(trc->context, obj);      JSFunction *fun = (JSFunction *) obj->getPrivate();
1752      if (!fun)      if (!fun)
1753          return;          return;
1754    
# Line 1804  Line 1769 
1769  static void  static void
1770  fun_finalize(JSContext *cx, JSObject *obj)  fun_finalize(JSContext *cx, JSObject *obj)
1771  {  {
     JSFunction *fun;  
   
1772      /* Ignore newborn and cloned function objects. */      /* Ignore newborn and cloned function objects. */
1773      fun = (JSFunction *) JS_GetPrivate(cx, obj);      JSFunction *fun = (JSFunction *) obj->getPrivate();
1774      if (!fun || FUN_OBJECT(fun) != obj)      if (!fun || FUN_OBJECT(fun) != obj)
1775          return;          return;
1776    
# Line 1822  Line 1785 
1785      }      }
1786  }  }
1787    
1788    uint32
1789    JSFunction::countInterpretedReservedSlots() const
1790    {
1791        JS_ASSERT(FUN_INTERPRETED(this));
1792    
1793        uint32 nslots = (u.i.nupvars == 0)
1794                        ? 0
1795                        : u.i.script->upvars()->length;
1796        if (u.i.script->regexpsOffset != 0)
1797            nslots += u.i.script->regexps()->length;
1798        return nslots;
1799    }
1800    
1801  static uint32  static uint32
1802  fun_reserveSlots(JSContext *cx, JSObject *obj)  fun_reserveSlots(JSContext *cx, JSObject *obj)
1803  {  {
     JSFunction *fun;  
     uint32 nslots;  
   
1804      /*      /*
1805       * We use JS_GetPrivate and not GET_FUNCTION_PRIVATE because during       * We use getPrivate and not GET_FUNCTION_PRIVATE because during
1806       * js_InitFunctionClass invocation the function is called before the       * js_InitFunctionClass invocation the function is called before the
1807       * private slot of the function object is set.       * private slot of the function object is set.
1808       */       */
1809      fun = (JSFunction *) JS_GetPrivate(cx, obj);      JSFunction *fun = (JSFunction *) obj->getPrivate();
1810      nslots = 0;      return (fun && FUN_INTERPRETED(fun))
1811      if (fun && FUN_INTERPRETED(fun) && fun->u.i.script) {             ? fun->countInterpretedReservedSlots()
1812          if (fun->u.i.nupvars != 0)             : 0;
             nslots = JS_SCRIPT_UPVARS(fun->u.i.script)->length;  
         if (fun->u.i.script->regexpsOffset != 0)  
             nslots += JS_SCRIPT_REGEXPS(fun->u.i.script)->length;  
     }  
     return nslots;  
1813  }  }
1814    
1815  /*  /*
# Line 1929  Line 1897 
1897  }  }
1898  #endif  #endif
1899    
1900  JS_REQUIRES_STACK JSBool  JSBool
1901  js_fun_call(JSContext *cx, uintN argc, jsval *vp)  js_fun_call(JSContext *cx, uintN argc, jsval *vp)
1902  {  {
1903      JSObject *obj;      JSObject *obj;
# Line 1938  Line 1906 
1906      void *mark;      void *mark;
1907      JSBool ok;      JSBool ok;
1908    
1909        js_LeaveTrace(cx);
1910    
1911      obj = JS_THIS_OBJECT(cx, vp);      obj = JS_THIS_OBJECT(cx, vp);
1912      if (!obj || !OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &vp[1]))      if (!obj || !obj->defaultValue(cx, JSTYPE_FUNCTION, &vp[1]))
1913          return JS_FALSE;          return JS_FALSE;
1914      fval = vp[1];      fval = vp[1];
1915    
# Line 1988  Line 1958 
1958      return ok;      return ok;
1959  }  }
1960    
1961  JS_REQUIRES_STACK JSBool  JSBool
1962  js_fun_apply(JSContext *cx, uintN argc, jsval *vp)  js_fun_apply(JSContext *cx, uintN argc, jsval *vp)
1963  {  {
1964      JSObject *obj, *aobj;      JSObject *obj, *aobj;
# Line 2004  Line 1974 
1974          return js_fun_call(cx, argc, vp);          return js_fun_call(cx, argc, vp);
1975      }      }
1976    
1977        js_LeaveTrace(cx);
1978    
1979      obj = JS_THIS_OBJECT(cx, vp);      obj = JS_THIS_OBJECT(cx, vp);
1980      if (!obj || !OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &vp[1]))      if (!obj || !obj->defaultValue(cx, JSTYPE_FUNCTION, &vp[1]))
1981          return JS_FALSE;          return JS_FALSE;
1982      fval = vp[1];      fval = vp[1];
1983    
# Line 2055  Line 2027 
2027          return JS_FALSE;          return JS_FALSE;
2028    
2029      /* Allocate stack space for fval, obj, and the args. */      /* Allocate stack space for fval, obj, and the args. */
2030      argc = (uintN)JS_MIN(length, ARRAY_INIT_LIMIT - 1);      argc = (uintN)JS_MIN(length, JS_ARGS_LENGTH_MAX);
2031      invokevp = js_AllocStack(cx, 2 + argc, &mark);      invokevp = js_AllocStack(cx, 2 + argc, &mark);
2032      if (!invokevp)      if (!invokevp)
2033          return JS_FALSE;          return JS_FALSE;
# Line 2100  Line 2072 
2072      if (!js_GetLengthProperty(cx, aobj, &length))      if (!js_GetLengthProperty(cx, aobj, &length))
2073          return JS_FALSE;          return JS_FALSE;
2074    
2075      if (length >= ARRAY_INIT_LIMIT)      if (length > JS_ARGS_LENGTH_MAX)
2076          length = ARRAY_INIT_LIMIT - 1;          length = JS_ARGS_LENGTH_MAX;
2077      invokevp = js_AllocStack(cx, 2 + length, &mark);      invokevp = js_AllocStack(cx, 2 + length, &mark);
2078      if (!invokevp)      if (!invokevp)
2079          return JS_FALSE;          return JS_FALSE;
# Line 2148  Line 2120 
2120      const char *filename;      const char *filename;
2121      JSBool ok;      JSBool ok;
2122      JSString *str, *arg;      JSString *str, *arg;
2123      JSTokenStream ts;      JSTokenStream ts(cx);
2124      JSPrincipals *principals;      JSPrincipals *principals;
2125      jschar *collected_args, *cp;      jschar *collected_args, *cp;
2126      void *mark;      void *mark;
# Line 2156  Line 2128 
2128      JSTokenType tt;      JSTokenType tt;
2129    
2130      if (!JS_IsConstructing(cx)) {      if (!JS_IsConstructing(cx)) {
2131          obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL, 0);          obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL);
2132          if (!obj)          if (!obj)
2133              return JS_FALSE;              return JS_FALSE;
2134          *rval = OBJECT_TO_JSVAL(obj);          *rval = OBJECT_TO_JSVAL(obj);
2135      } else {      } else {
2136          /*          /*
2137           * The constructor is called before the private slot is initialized so           * The constructor is called before the private slot is initialized so
2138           * we must use JS_GetPrivate, not GET_FUNCTION_PRIVATE here.           * we must use getPrivate, not GET_FUNCTION_PRIVATE here.
2139           */           */
2140          if (JS_GetPrivate(cx, obj))          if (obj->getPrivate())
2141              return JS_TRUE;              return JS_TRUE;
2142      }      }
2143    
# Line 2240  Line 2212 
2212               * JSString length fits in 2 fewer bits than size_t has.               * JSString length fits in 2 fewer bits than size_t has.
2213               */               */
2214              old_args_length = args_length;              old_args_length = args_length;
2215              args_length = old_args_length + JSSTRING_LENGTH(arg);              args_length = old_args_length + arg->length();
2216              if (args_length < old_args_length) {              if (args_length < old_args_length) {
2217                  js_ReportAllocationOverflow(cx);                  js_ReportAllocationOverflow(cx);
2218                  return JS_FALSE;                  return JS_FALSE;
# Line 2275  Line 2247 
2247           */           */
2248          for (i = 0; i < n; i++) {          for (i = 0; i < n; i++) {
2249              arg = JSVAL_TO_STRING(argv[i]);              arg = JSVAL_TO_STRING(argv[i]);
2250              arg_length = JSSTRING_LENGTH(arg);              arg_length = arg->length();
2251              (void) js_strncpy(cp, JSSTRING_CHARS(arg), arg_length);              (void) js_strncpy(cp, arg->chars(), arg_length);
2252              cp += arg_length;              cp += arg_length;
2253    
2254              /* Add separating comma or terminating 0. */              /* Add separating comma or terminating 0. */
# Line 2284  Line 2256 
2256          }          }
2257    
2258          /* Initialize a tokenstream that reads from the given string. */          /* Initialize a tokenstream that reads from the given string. */
2259          if (!js_InitTokenStream(cx, &ts, collected_args, args_length,          if (!ts.init(cx, collected_args, args_length, NULL, filename, lineno)) {
                                 NULL, filename, lineno)) {  
2260              JS_ARENA_RELEASE(&cx->tempPool, mark);              JS_ARENA_RELEASE(&cx->tempPool, mark);
2261              return JS_FALSE;              return JS_FALSE;
2262          }          }
# Line 2348  Line 2319 
2319              JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,              JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
2320                                   JSMSG_BAD_FORMAL);                                   JSMSG_BAD_FORMAL);
2321          }          }
2322          js_CloseTokenStream(cx, &ts);          ts.close(cx);
2323          JS_ARENA_RELEASE(&cx->tempPool, mark);          JS_ARENA_RELEASE(&cx->tempPool, mark);
2324          if (state != OK)          if (state != OK)
2325              return JS_FALSE;              return JS_FALSE;
# Line 2364  Line 2335 
2335      }      }
2336    
2337      return JSCompiler::compileFunctionBody(cx, fun, principals,      return JSCompiler::compileFunctionBody(cx, fun, principals,
2338                                             JSSTRING_CHARS(str), JSSTRING_LENGTH(str),                                             str->chars(), str->length(),
2339                                             filename, lineno);                                             filename, lineno);
2340  }  }
2341    
# Line 2380  Line 2351 
2351          return NULL;          return NULL;
2352      fun = js_NewFunction(cx, proto, NULL, 0, JSFUN_INTERPRETED, obj, NULL);      fun = js_NewFunction(cx, proto, NULL, 0, JSFUN_INTERPRETED, obj, NULL);
2353      if (!fun)      if (!fun)
2354          goto bad;          return NULL;
2355      fun->u.i.script = js_NewScript(cx, 1, 1, 0, 0, 0, 0, 0);      fun->u.i.script = js_NewScript(cx, 1, 1, 0, 0, 0, 0, 0);
2356      if (!fun->u.i.script)      if (!fun->u.i.script)
2357          goto bad;          return NULL;
2358      fun->u.i.script->code[0] = JSOP_STOP;      fun->u.i.script->code[0] = JSOP_STOP;
2359      *SCRIPT_NOTES(fun->u.i.script) = SRC_NULL;      *fun->u.i.script->notes() = SRC_NULL;
2360  #ifdef CHECK_SCRIPT_OWNER  #ifdef CHECK_SCRIPT_OWNER
2361      fun->u.i.script->owner = NULL;      fun->u.i.script->owner = NULL;
2362  #endif  #endif
2363      return proto;      return proto;
   
 bad:  
     cx->weakRoots.newborn[GCX_OBJECT] = NULL;  
     return NULL;  
2364  }  }
2365    
2366  JSFunction *  JSFunction *
# Line 2406  Line 2373 
2373          JS_ASSERT(HAS_FUNCTION_CLASS(funobj));          JS_ASSERT(HAS_FUNCTION_CLASS(funobj));
2374          OBJ_SET_PARENT(cx, funobj, parent);          OBJ_SET_PARENT(cx, funobj, parent);
2375      } else {      } else {
2376          funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent, 0);          funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent);
2377          if (!funobj)          if (!funobj)
2378              return NULL;              return NULL;
2379      }      }
2380      JS_ASSERT(JSVAL_IS_VOID(funobj->fslots[JSSLOT_PRIVATE]));      JS_ASSERT(!funobj->getPrivate());
2381      fun = (JSFunction *) funobj;      fun = (JSFunction *) funobj;
2382    
2383      /* Initialize all function members. */      /* Initialize all function members. */
2384      fun->nargs = nargs;      fun->nargs = nargs;
2385      fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_KINDMASK | JSFUN_TRACEABLE);      fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_KINDMASK | JSFUN_TRCINFO);
2386      if ((flags & JSFUN_KINDMASK) >= JSFUN_INTERPRETED) {      if ((flags & JSFUN_KINDMASK) >= JSFUN_INTERPRETED) {
2387          JS_ASSERT(!native);          JS_ASSERT(!native);
2388          JS_ASSERT(nargs == 0);          JS_ASSERT(nargs == 0);
# Line 2431  Line 2398 
2398          fun->u.n.extra = 0;          fun->u.n.extra = 0;
2399          fun->u.n.spare = 0;          fun->u.n.spare = 0;
2400          fun->u.n.clasp = NULL;          fun->u.n.clasp = NULL;
2401          if (flags & JSFUN_TRACEABLE) {          if (flags & JSFUN_TRCINFO) {
2402  #ifdef JS_TRACER  #ifdef JS_TRACER
2403              JSTraceableNative *trcinfo =              JSNativeTraceInfo *trcinfo =
2404                  JS_FUNC_TO_DATA_PTR(JSTraceableNative *, native);                  JS_FUNC_TO_DATA_PTR(JSNativeTraceInfo *, native);
2405              fun->u.n.native = (JSNative) trcinfo->native;              fun->u.n.native = (JSNative) trcinfo->native;
2406              fun->u.n.trcinfo = trcinfo;              fun->u.n.trcinfo = trcinfo;
2407  #else  #else
# Line 2449  Line 2416 
2416      fun->atom = atom;      fun->atom = atom;
2417    
2418      /* Set private to self to indicate non-cloned fully initialized function. */      /* Set private to self to indicate non-cloned fully initialized function. */
2419      FUN_OBJECT(fun)->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fun);      FUN_OBJECT(fun)->setPrivate(fun);
2420      return fun;      return fun;
2421  }  }
2422    
# Line 2460  Line 2427 
2427       * The cloned function object does not need the extra JSFunction members       * The cloned function object does not need the extra JSFunction members
2428       * beyond JSObject as it points to fun via the private slot.       * beyond JSObject as it points to fun via the private slot.
2429       */       */
2430      JSObject *clone = js_NewObject(cx, &js_FunctionClass, NULL, parent,      JSObject *clone = js_NewObject(cx, &js_FunctionClass, NULL, parent, sizeof(JSObject));
                                    sizeof(JSObject));  
2431      if (!clone)      if (!clone)
2432          return NULL;          return NULL;
2433      clone->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fun);      clone->setPrivate(fun);
2434      return clone;      return clone;
2435  }  }
2436    
2437  JSObject *  /*
2438  js_NewFlatClosure(JSContext *cx, JSFunction *fun)   * Create a new flat closure, but don't initialize the imported upvar
2439     * values. The tracer calls this function and then initializes the upvar
2440     * slots on trace.
2441     */
2442    JSObject * JS_FASTCALL
2443    js_AllocFlatClosure(JSContext *cx, JSFunction *fun, JSObject *scopeChain)
2444  {  {
2445      JS_ASSERT(FUN_FLAT_CLOSURE(fun));      JS_ASSERT(FUN_FLAT_CLOSURE(fun));
2446        JS_ASSERT((fun->u.i.script->upvarsOffset
2447                   ? fun->u.i.script->upvars()->length
2448                   : 0) == fun->u.i.nupvars);
2449    
2450      JSObject *closure = js_CloneFunctionObject(cx, fun, cx->fp->scopeChain);      JSObject *closure = js_CloneFunctionObject(cx, fun, scopeChain);
2451      if (!closure || fun->u.i.script->upvarsOffset == 0)      if (!closure)
2452          return closure;          return closure;
2453    
2454      uint32 nslots = JSSLOT_FREE(&js_FunctionClass);      uint32 nslots = fun->countInterpretedReservedSlots();
2455      JS_ASSERT(nslots == JS_INITIAL_NSLOTS);      if (!nslots)
2456      nslots += fun_reserveSlots(cx, closure);          return closure;
2457      if (!js_ReallocSlots(cx, closure, nslots, JS_TRUE))      if (!js_EnsureReservedSlots(cx, closure, nslots))
2458          return NULL;          return NULL;
2459    
2460      JSUpvarArray *uva = JS_SCRIPT_UPVARS(fun->u.i.script);      return closure;
2461    }
2462    
2463    JS_DEFINE_CALLINFO_3(extern, OBJECT, js_AllocFlatClosure,
2464                         CONTEXT, FUNCTION, OBJECT, 0, 0)
2465    
2466    JSObject *
2467    js_NewFlatClosure(JSContext *cx, JSFunction *fun)
2468    {
2469        JSObject *closure = js_AllocFlatClosure(cx, fun, cx->fp->scopeChain);
2470        if (!closure || fun->u.i.nupvars == 0)
2471            return closure;
2472    
2473        JSUpvarArray *uva = fun->u.i.script->upvars();
2474      JS_ASSERT(uva->length <= size_t(closure->dslots[-1]));      JS_ASSERT(uva->length <= size_t(closure->dslots[-1]));
2475    
2476      uintN level = fun->u.i.script->staticLevel;      uintN level = fun->u.i.script->staticLevel;
# Line 2524  Line 2511 
2511      fun = js_NewFunction(cx, NULL, native, nargs, attrs, obj, atom);      fun = js_NewFunction(cx, NULL, native, nargs, attrs, obj, atom);
2512      if (!fun)      if (!fun)
2513          return NULL;          return NULL;
2514      if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom),      if (!obj->defineProperty(cx, ATOM_TO_JSID(atom), OBJECT_TO_JSVAL(FUN_OBJECT(fun)),
2515                               OBJECT_TO_JSVAL(FUN_OBJECT(fun)),                               gsop, gsop, attrs & ~JSFUN_FLAGS_MASK)) {
                              gsop, gsop,  
                              attrs & ~JSFUN_FLAGS_MASK, NULL)) {  
2516          return NULL;          return NULL;
2517      }      }
2518      return fun;      return fun;
# Line 2548  Line 2533 
2533      if (JSVAL_IS_OBJECT(v)) {      if (JSVAL_IS_OBJECT(v)) {
2534          obj = JSVAL_TO_OBJECT(v);          obj = JSVAL_TO_OBJECT(v);
2535          if (obj && OBJ_GET_CLASS(cx, obj) != &js_FunctionClass) {          if (obj && OBJ_GET_CLASS(cx, obj) != &js_FunctionClass) {
2536              if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &v))              if (!obj->defaultValue(cx, JSTYPE_FUNCTION, &v))
2537                  return NULL;                  return NULL;
2538              obj = VALUE_IS_FUNCTION(cx, v) ? JSVAL_TO_OBJECT(v) : NULL;              obj = VALUE_IS_FUNCTION(cx, v) ? JSVAL_TO_OBJECT(v) : NULL;
2539          }          }
# Line 2619  Line 2604 
2604      if (flags & JSV2F_ITERATOR) {      if (flags & JSV2F_ITERATOR) {
2605          error = JSMSG_BAD_ITERATOR;          error = JSMSG_BAD_ITERATOR;
2606          name = js_iterator_str;          name = js_iterator_str;
2607          tvr.u.string = js_ValueToSource(cx, *vp);          JSString *src = js_ValueToSource(cx, *vp);
2608          if (!tvr.u.string)          if (!src)
2609              goto out;              goto out;
2610          tvr.u.string = js_QuoteString(cx, tvr.u.string, 0);          tvr.u.value = STRING_TO_JSVAL(src);
2611          if (!tvr.u.string)          JSString *qsrc = js_QuoteString(cx, src, 0);
2612            if (!qsrc)
2613              goto out;              goto out;
2614          source = js_GetStringBytes(cx, tvr.u.string);          tvr.u.value = STRING_TO_JSVAL(qsrc);
2615            source = js_GetStringBytes(cx, qsrc);
2616          if (!source)          if (!source)
2617              goto out;              goto out;
2618      } else if (flags & JSV2F_CONSTRUCT) {      } else if (flags & JSV2F_CONSTRUCT) {
# Line 2695  Line 2682 
2682    
2683      for (dup = map->lastdup; dup; dup = next) {      for (dup = map->lastdup; dup; dup = next) {
2684          next = dup->link;          next = dup->link;
2685          JS_free(cx, dup);          cx->free(dup);
2686      }      }
2687      JS_DHashTableFinish(&map->names);      JS_DHashTableFinish(&map->names);
2688      JS_free(cx, map);      cx->free(map);
2689  }  }
2690    
2691  static JSBool  static JSBool
# Line 2725  Line 2712 
2712      }      }
2713      if (entry->name) {      if (entry->name) {
2714          JS_ASSERT(entry->name == name);          JS_ASSERT(entry->name == name);
2715          JS_ASSERT(entry->localKind == JSLOCAL_ARG);          JS_ASSERT(entry->localKind == JSLOCAL_ARG && localKind == JSLOCAL_ARG);
2716          dup = (JSNameIndexPair *) JS_malloc(cx, sizeof *dup);          dup = (JSNameIndexPair *) cx->malloc(sizeof *dup);
2717          if (!dup)          if (!dup)
2718              return JS_FALSE;              return JS_FALSE;
2719          dup->name = entry->name;          dup->name = entry->name;
# Line 2772  Line 2759 
2759          if (n > 1) {          if (n > 1) {
2760              array = fun->u.i.names.array;              array = fun->u.i.names.array;
2761          } else {          } else {
2762              array = (jsuword *) JS_malloc(cx, MAX_ARRAY_LOCALS * sizeof *array);              array = (jsuword *) cx->malloc(MAX_ARRAY_LOCALS * sizeof *array);
2763              if (!array)              if (!array)
2764                  return JS_FALSE;                  return JS_FALSE;
2765              array[0] = fun->u.i.names.taggedAtom;              array[0] = fun->u.i.names.taggedAtom;
# Line 2797  Line 2784 
2784          }          }
2785      } else if (n == MAX_ARRAY_LOCALS) {      } else if (n == MAX_ARRAY_LOCALS) {
2786          array = fun->u.i.names.array;          array = fun->u.i.names.array;
2787          map = (JSLocalNameMap *) JS_malloc(cx, sizeof *map);          map = (JSLocalNameMap *) cx->malloc(sizeof *map);
2788          if (!map)          if (!map)
2789              return JS_FALSE;              return JS_FALSE;
2790          if (!JS_DHashTableInit(&map->names, JS_DHashGetStubOps(),          if (!JS_DHashTableInit(&map->names, JS_DHashGetStubOps(),
# Line 2805  Line 2792 
2792                                 JS_DHASH_DEFAULT_CAPACITY(MAX_ARRAY_LOCALS                                 JS_DHASH_DEFAULT_CAPACITY(MAX_ARRAY_LOCALS
2793                                                           * 2))) {                                                           * 2))) {
2794              JS_ReportOutOfMemory(cx);              JS_ReportOutOfMemory(cx);
2795              JS_free(cx, map);              cx->free(map);
2796              return JS_FALSE;              return JS_FALSE;
2797          }          }
2798    
# Line 2838  Line 2825 
2825           * to replace fun->u.i.names with the built map.           * to replace fun->u.i.names with the built map.
2826           */           */
2827          fun->u.i.names.map = map;          fun->u.i.names.map = map;
2828          JS_free(cx, array);          cx->free(array);
2829      } else {      } else {
2830          if (*indexp == JS_BITMASK(16)) {          if (*indexp == JS_BITMASK(16)) {
2831              JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,              JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
# Line 2949  Line 2936 
2936      return JS_DHASH_NEXT;      return JS_DHASH_NEXT;
2937  }  }
2938    
2939  jsuword *  JS_FRIEND_API(jsuword *)
2940  js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool)  js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool)
2941  {  {
2942      uintN n;      uintN n;
# Line 3060  Line 3047 
3047      if (n <= 1)      if (n <= 1)
3048          return;          return;
3049      if (n <= MAX_ARRAY_LOCALS)      if (n <= MAX_ARRAY_LOCALS)
3050          JS_free(cx, fun->u.i.names.array);          cx->free(fun->u.i.names.array);
3051      else      else
3052          FreeLocalNameHash(cx, fun->u.i.names.map);          FreeLocalNameHash(cx, fun->u.i.names.map);
3053  }  }
# Line 3076  Line 3063 
3063      n = fun->nargs + fun->u.i.nvars + fun->u.i.nupvars;      n = fun->nargs + fun->u.i.nvars + fun->u.i.nupvars;
3064      if (2 <= n && n < MAX_ARRAY_LOCALS) {      if (2 <= n && n < MAX_ARRAY_LOCALS) {
3065          /* Shrink over-allocated array ignoring realloc failures. */          /* Shrink over-allocated array ignoring realloc failures. */
3066          array = (jsuword *) JS_realloc(cx, fun->u.i.names.array,          array = (jsuword *) cx->realloc(fun->u.i.names.array,
3067                                         n * sizeof *array);                                          n * sizeof *array);
3068          if (array)          if (array)
3069              fun->u.i.names.array = array;              fun->u.i.names.array = array;
3070      }      }
3071  #ifdef DEBUG  #ifdef DEBUG
3072  // XXX no JS_DHashMarkTableImmutable on 1.9.1      if (n > MAX_ARRAY_LOCALS)
3073  //    if (n > MAX_ARRAY_LOCALS)          JS_DHashMarkTableImmutable(&fun->u.i.names.map->names);
 //        JS_DHashMarkTableImmutable(&fun->u.i.names.map->names);  
3074  #endif  #endif
3075  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.24