Merge tracemonkey to mozilla-central.
authorRobert Sayre <sayrer@gmail.com>
Wed, 29 Jul 2009 17:05:05 -0400
changeset 30861 970564ae5e53575e73d707049a3dc39b3c6bffbd
parent 30840 ffcc4c3efed0cf32d9ed7af837cf0bb758d99de3 (current diff)
parent 30860 12a07f9a7d4e71f054d6f0a6630ba2e007db52dc (diff)
child 30862 ab1686101bfb1dd70be717649c772ee8ecd2b912
push idunknown
push userunknown
push dateunknown
milestone1.9.2a1pre
Merge tracemonkey to mozilla-central.
configure.in
js/src/Makefile.in
js/src/configure.in
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -292,16 +292,17 @@ ACDEFINES	= @MOZ_DEFINES@
 WARNINGS_AS_ERRORS = @WARNINGS_AS_ERRORS@
 
 MOZ_OPTIMIZE	= @MOZ_OPTIMIZE@
 MOZ_OPTIMIZE_FLAGS = @MOZ_OPTIMIZE_FLAGS@
 MOZ_OPTIMIZE_LDFLAGS = @MOZ_OPTIMIZE_LDFLAGS@
 MOZ_OPTIMIZE_SIZE_TWEAK = @MOZ_OPTIMIZE_SIZE_TWEAK@
 
 MOZ_RTTI_FLAGS_ON = @_MOZ_RTTI_FLAGS_ON@
+MOZ_EXCEPTIONS_FLAGS_ON = @_MOZ_EXCEPTIONS_FLAGS_ON@
 
 MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE = @MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE@
 PROFILE_GEN_CFLAGS = @PROFILE_GEN_CFLAGS@
 PROFILE_GEN_LDFLAGS = @PROFILE_GEN_LDFLAGS@
 PROFILE_USE_CFLAGS = @PROFILE_USE_CFLAGS@
 PROFILE_USE_LDFLAGS = @PROFILE_USE_LDFLAGS@
 
 XCFLAGS		= @XCFLAGS@
--- a/configure.in
+++ b/configure.in
@@ -7325,16 +7325,18 @@ MOZ_ARG_ENABLE_BOOL(cpp-exceptions,
 [ _MOZ_CPP_EXCEPTIONS= ])
 
 if test "$_MOZ_CPP_EXCEPTIONS"; then
     _MOZ_EXCEPTIONS_FLAGS=$_MOZ_EXCEPTIONS_FLAGS_ON
 else
     _MOZ_EXCEPTIONS_FLAGS=$_MOZ_EXCEPTIONS_FLAGS_OFF
 fi
 
+AC_SUBST(_MOZ_EXCEPTIONS_FLAGS_ON)
+
 # Irix & OSF native compilers do not like exception declarations 
 # when exceptions are disabled
 if test -n "$MIPSPRO_CXX" -o -n "$COMPAQ_CXX" -o -n "$VACPP"; then
     AC_DEFINE(CPP_THROW_NEW, [])
 else
     AC_DEFINE(CPP_THROW_NEW, [throw()])
 fi
 AC_LANG_C
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -139,16 +139,17 @@ CPPSRCS		= \
 		jsopcode.cpp \
 		jsparse.cpp \
 		jsprf.cpp \
 		jsregexp.cpp \
 		jsscan.cpp \
 		jsscope.cpp \
 		jsscript.cpp \
 		jsstr.cpp \
+		jstask.cpp \
 		jsutil.cpp \
 		jsxdrapi.cpp \
 		jsxml.cpp \
 		prmjtime.cpp \
 		$(NULL)
 
 ifdef HAVE_DTRACE
 CPPSRCS 	+= \
@@ -195,16 +196,17 @@ INSTALLED_HEADERS = \
 		jsprvtd.h \
 		jspubtd.h \
 		jsregexp.h \
 		jsscan.h \
 		jsscope.h \
 		jsscript.h \
 		jsstaticcheck.h \
 		jsstr.h \
+		jstask.h \
 		jstracer.h \
 		jstypes.h \
 		jsutil.h \
 		jsversion.h \
 		jsxdrapi.h \
 		jsxml.h \
 		$(NULL)
 
--- a/js/src/config/autoconf.mk.in
+++ b/js/src/config/autoconf.mk.in
@@ -157,16 +157,17 @@ ACDEFINES	= @MOZ_DEFINES@
 WARNINGS_AS_ERRORS = @WARNINGS_AS_ERRORS@
 
 MOZ_OPTIMIZE	= @MOZ_OPTIMIZE@
 MOZ_OPTIMIZE_FLAGS = @MOZ_OPTIMIZE_FLAGS@
 MOZ_OPTIMIZE_LDFLAGS = @MOZ_OPTIMIZE_LDFLAGS@
 MOZ_OPTIMIZE_SIZE_TWEAK = @MOZ_OPTIMIZE_SIZE_TWEAK@
 
 MOZ_RTTI_FLAGS_ON = @_MOZ_RTTI_FLAGS_ON@
+MOZ_EXCEPTIONS_FLAGS_ON = @_MOZ_EXCEPTIONS_FLAGS_ON@
 
 MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE = @MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE@
 PROFILE_GEN_CFLAGS = @PROFILE_GEN_CFLAGS@
 PROFILE_GEN_LDFLAGS = @PROFILE_GEN_LDFLAGS@
 PROFILE_USE_CFLAGS = @PROFILE_USE_CFLAGS@
 PROFILE_USE_LDFLAGS = @PROFILE_USE_LDFLAGS@
 
 WIN_TOP_SRC	= @WIN_TOP_SRC@
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -4737,16 +4737,18 @@ MOZ_ARG_ENABLE_BOOL(cpp-exceptions,
 [ _MOZ_CPP_EXCEPTIONS= ])
 
 if test "$_MOZ_CPP_EXCEPTIONS"; then
     _MOZ_EXCEPTIONS_FLAGS=$_MOZ_EXCEPTIONS_FLAGS_ON
 else
     _MOZ_EXCEPTIONS_FLAGS=$_MOZ_EXCEPTIONS_FLAGS_OFF
 fi
 
+AC_SUBST(_MOZ_EXCEPTIONS_FLAGS_ON)
+
 # Irix & OSF native compilers do not like exception declarations 
 # when exceptions are disabled
 if test -n "$MIPSPRO_CXX" -o -n "$COMPAQ_CXX" -o -n "$VACPP"; then
     AC_DEFINE(CPP_THROW_NEW, [])
 else
     AC_DEFINE(CPP_THROW_NEW, [throw()])
 fi
 AC_LANG_C
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -74,16 +74,17 @@
 #include "jsobj.h"
 #include "jsopcode.h"
 #include "jsparse.h"
 #include "jsregexp.h"
 #include "jsscan.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jsstr.h"
+#include "jstask.h"
 #include "jstracer.h"
 #include "jsdbgapi.h"
 #include "prmjtime.h"
 #include "jsstaticcheck.h"
 
 #if JS_HAS_FILE_OBJECT
 #include "jsfile.h"
 #endif
@@ -443,17 +444,17 @@ JS_AddArgumentFormatter(JSContext *cx, c
     while ((map = *mpp) != NULL) {
         /* Insert before any shorter string to match before prefixes. */
         if (map->length < length)
             break;
         if (map->length == length && !strcmp(map->format, format))
             goto out;
         mpp = &map->next;
     }
-    map = (JSArgumentFormatMap *) JS_malloc(cx, sizeof *map);
+    map = (JSArgumentFormatMap *) cx->malloc(sizeof *map);
     if (!map)
         return JS_FALSE;
     map->format = format;
     map->length = length;
     map->next = *mpp;
     *mpp = map;
 out:
     map->formatter = formatter;
@@ -466,17 +467,17 @@ JS_RemoveArgumentFormatter(JSContext *cx
     size_t length;
     JSArgumentFormatMap **mpp, *map;
 
     length = strlen(format);
     mpp = &cx->argumentFormatMap;
     while ((map = *mpp) != NULL) {
         if (map->length == length && !strcmp(map->format, format)) {
             *mpp = map->next;
-            JS_free(cx, map);
+            cx->free(map);
             return;
         }
         mpp = &map->next;
     }
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
@@ -768,17 +769,17 @@ JS_NewRuntime(uint32 maxbytes)
         JS_ASSERT(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID) == 2);
         JS_ASSERT(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_HOLE) == (2 | (JSVAL_HOLE_FLAG >> JSVAL_TAGBITS)));
         JS_ASSERT(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_ARETURN) == 8);
 
         js_NewRuntimeWasCalled = JS_TRUE;
     }
 #endif /* DEBUG */
 
-    rt = (JSRuntime *) malloc(sizeof(JSRuntime));
+    rt = (JSRuntime *) js_malloc(sizeof(JSRuntime));
     if (!rt)
         return NULL;
 
     /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
     memset(rt, 0, sizeof(JSRuntime));
     JS_INIT_CLIST(&rt->contextList);
     JS_INIT_CLIST(&rt->trapList);
     JS_INIT_CLIST(&rt->watchPointList);
@@ -812,16 +813,19 @@ JS_NewRuntime(uint32 maxbytes)
         goto bad;
     rt->titleSharingDone = JS_NEW_CONDVAR(rt->gcLock);
     if (!rt->titleSharingDone)
         goto bad;
     rt->titleSharingTodo = NO_TITLE_SHARING_TODO;
     rt->debuggerLock = JS_NEW_LOCK();
     if (!rt->debuggerLock)
         goto bad;
+    rt->deallocatorThread = new JSBackgroundThread();
+    if (!rt->deallocatorThread || !rt->deallocatorThread->init())
+        goto bad;
 #endif
     if (!js_InitPropertyTree(rt))
         goto bad;
     if (!js_InitThreads(rt))
         goto bad;
 
     return rt;
 
@@ -881,19 +885,23 @@ JS_DestroyRuntime(JSRuntime *rt)
     if (rt->rtLock)
         JS_DESTROY_LOCK(rt->rtLock);
     if (rt->stateChange)
         JS_DESTROY_CONDVAR(rt->stateChange);
     if (rt->titleSharingDone)
         JS_DESTROY_CONDVAR(rt->titleSharingDone);
     if (rt->debuggerLock)
         JS_DESTROY_LOCK(rt->debuggerLock);
+    if (rt->deallocatorThread) {
+        rt->deallocatorThread->cancel();
+        delete rt->deallocatorThread;
+    }
 #endif
     js_FinishPropertyTree(rt);
-    free(rt);
+    js_free(rt);
 }
 
 JS_PUBLIC_API(void)
 JS_ShutDown(void)
 {
 #ifdef MOZ_TRACEVIS
     JS_StopTraceVis();
 #endif
@@ -1323,17 +1331,17 @@ JS_InitStandardClasses(JSContext *cx, JS
 {
     JSAtom *atom;
 
     CHECK_REQUEST(cx);
 
     /* Define a top-level property 'undefined' with the undefined value. */
     atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
     if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
-                             JS_PropertyStub, JS_PropertyStub, JSPROP_PERMANENT, 
+                             JS_PropertyStub, JS_PropertyStub, JSPROP_PERMANENT,
                              NULL)) {
         return JS_FALSE;
     }
 
     /* Function and Object require cooperative bootstrapping magic. */
     if (!js_InitFunctionAndObjectClasses(cx, obj))
         return JS_FALSE;
 
@@ -1530,17 +1538,17 @@ JS_ResolveStandardClass(JSContext *cx, J
 
     idstr = JSVAL_TO_STRING(id);
 
     /* Check whether we're resolving 'undefined', and define it if so. */
     atom = rt->atomState.typeAtoms[JSTYPE_VOID];
     if (idstr == ATOM_TO_STRING(atom)) {
         *resolved = JS_TRUE;
         return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
-                                   JS_PropertyStub, JS_PropertyStub, 
+                                   JS_PropertyStub, JS_PropertyStub,
                                    JSPROP_PERMANENT, NULL);
     }
 
     /* Try for class constructors/prototypes named by well-known atoms. */
     stdnm = NULL;
     for (i = 0; standard_class_atoms[i].init; i++) {
         atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
         if (idstr == ATOM_TO_STRING(atom)) {
@@ -1625,17 +1633,17 @@ JS_EnumerateStandardClasses(JSContext *c
 
     CHECK_REQUEST(cx);
     rt = cx->runtime;
 
     /* Check whether we need to bind 'undefined' and define it if so. */
     atom = rt->atomState.typeAtoms[JSTYPE_VOID];
     if (!AlreadyHasOwnProperty(cx, obj, atom) &&
         !OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
-                             JS_PropertyStub, JS_PropertyStub, JSPROP_PERMANENT, 
+                             JS_PropertyStub, JS_PropertyStub, JSPROP_PERMANENT,
                              NULL)) {
         return JS_FALSE;
     }
 
     /* Initialize any classes that have not been resolved yet. */
     for (i = 0; standard_class_atoms[i].init; i++) {
         atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
         if (!AlreadyHasOwnProperty(cx, obj, atom) &&
@@ -1648,17 +1656,17 @@ JS_EnumerateStandardClasses(JSContext *c
 }
 
 static JSIdArray *
 NewIdArray(JSContext *cx, jsint length)
 {
     JSIdArray *ida;
 
     ida = (JSIdArray *)
-          JS_malloc(cx, offsetof(JSIdArray, vector) + length * sizeof(jsval));
+        cx->malloc(offsetof(JSIdArray, vector) + length * sizeof(jsval));
     if (ida)
         ida->length = length;
     return ida;
 }
 
 /*
  * Unlike realloc(3), this function frees ida on failure.
  */
@@ -1826,61 +1834,39 @@ JS_ComputeThis(JSContext *cx, jsval *vp)
     if (!js_ComputeThis(cx, JS_FALSE, vp + 2))
         return JSVAL_NULL;
     return vp[1];
 }
 
 JS_PUBLIC_API(void *)
 JS_malloc(JSContext *cx, size_t nbytes)
 {
-    void *p;
-
-    JS_ASSERT(nbytes != 0);
-    if (nbytes == 0)
-        nbytes = 1;
-
-    p = malloc(nbytes);
-    if (!p) {
-        JS_ReportOutOfMemory(cx);
-        return NULL;
-    }
-    cx->updateMallocCounter(nbytes);
-
-    return p;
+    return cx->malloc(nbytes);
 }
 
 JS_PUBLIC_API(void *)
 JS_realloc(JSContext *cx, void *p, size_t nbytes)
 {
-    void *orig = p;
-    p = realloc(p, nbytes);
-    if (!p) {
-        JS_ReportOutOfMemory(cx);
-        return NULL;
-    }
-    if (!orig)
-        cx->updateMallocCounter(nbytes);
-    return p;
+    return cx->realloc(p, nbytes);
 }
 
 JS_PUBLIC_API(void)
 JS_free(JSContext *cx, void *p)
 {
-    if (p)
-        free(p);
+    return cx->free(p);
 }
 
 JS_PUBLIC_API(char *)
 JS_strdup(JSContext *cx, const char *s)
 {
     size_t n;
     void *p;
 
     n = strlen(s) + 1;
-    p = JS_malloc(cx, n);
+    p = cx->malloc(n);
     if (!p)
         return NULL;
     return (char *)memcpy(p, s, n);
 }
 
 JS_PUBLIC_API(jsdouble *)
 JS_NewDouble(JSContext *cx, jsdouble d)
 {
@@ -2255,17 +2241,17 @@ DumpNotify(JSTracer *trc, void *thing, u
                     dtrc->base.debugPrintIndex);
         edgeName = dtrc->buffer;
     } else {
         edgeName = (const char*)dtrc->base.debugPrintArg;
     }
 
     edgeNameSize = strlen(edgeName) + 1;
     node = (JSHeapDumpNode *)
-        JS_malloc(cx, offsetof(JSHeapDumpNode, edgeName) + edgeNameSize);
+        cx->malloc(offsetof(JSHeapDumpNode, edgeName) + edgeNameSize);
     if (!node) {
         dtrc->ok = JS_FALSE;
         return;
     }
 
     node->thing = thing;
     node->kind = kind;
     node->next = NULL;
@@ -2407,17 +2393,17 @@ JS_DumpHeap(JSContext *cx, FILE *fp, voi
                 }
             }
         }
 
         /* Move to next or parents next and free the node. */
         for (;;) {
             next = node->next;
             parent = node->parent;
-            JS_free(cx, node);
+            cx->free(node);
             node = next;
             if (node)
                 break;
             if (!parent)
                 goto dump_out;
             JS_ASSERT(depth > 1);
             --depth;
             node = parent;
@@ -2674,17 +2660,17 @@ JS_SetScriptStackQuota(JSContext *cx, si
     cx->scriptStackQuota = quota;
 }
 
 /************************************************************************/
 
 JS_PUBLIC_API(void)
 JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
 {
-    JS_free(cx, ida);
+    cx->free(ida);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ValueToId(JSContext *cx, jsval v, jsid *idp)
 {
     CHECK_REQUEST(cx);
     if (JSVAL_IS_INT(v))
         *idp = INT_JSVAL_TO_JSID(v);
@@ -2996,17 +2982,17 @@ DefinePropertyById(JSContext *cx, JSObje
                    uintN flags, intN tinyid)
 {
     if (flags != 0 && OBJ_IS_NATIVE(obj)) {
         JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING);
         return !!js_DefineNativeProperty(cx, obj, id, value, getter, setter,
                                          attrs, flags, tinyid, NULL);
     }
     return OBJ_DEFINE_PROPERTY(cx, obj, id, value, getter, setter, attrs,
-                               NULL);   
+                               NULL);
 }
 
 static JSBool
 DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
                JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
                uintN flags, intN tinyid)
 {
     jsid id;
@@ -3715,17 +3701,17 @@ JS_HasUCProperty(JSContext *cx, JSObject
                  const jschar *name, size_t namelen,
                  JSBool *vp)
 {
     JSBool ok;
     JSObject *obj2;
     JSProperty *prop;
 
     CHECK_REQUEST(cx);
-    ok = LookupUCProperty(cx, obj, name, namelen, 
+    ok = LookupUCProperty(cx, obj, name, namelen,
                           JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
                           &obj2, &prop);
     if (ok) {
         *vp = (prop != NULL);
         if (prop)
             OBJ_DROP_PROPERTY(cx, obj2, prop);
     }
     return ok;
@@ -4067,23 +4053,23 @@ prop_iter_trace(JSTracer *trc, JSObject 
     v = obj->fslots[JSSLOT_PRIVATE];
     JS_ASSERT(!JSVAL_IS_VOID(v));
 
     i = JSVAL_TO_INT(obj->fslots[JSSLOT_ITER_INDEX]);
     if (i < 0) {
         /* Native case: just mark the next property to visit. */
         sprop = (JSScopeProperty *) JSVAL_TO_PRIVATE(v);
         if (sprop)
-            TRACE_SCOPE_PROPERTY(trc, sprop);
+            sprop->trace(trc);
     } else {
         /* Non-native case: mark each id in the JSIdArray private. */
         ida = (JSIdArray *) JSVAL_TO_PRIVATE(v);
         for (i = 0, n = ida->length; i < n; i++) {
             id = ida->vector[i];
-            TRACE_ID(trc, id);
+            js_TraceId(trc, id);
         }
     }
 }
 
 static JSClass prop_iter_class = {
     "PropertyIterator",
     JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
     JSCLASS_MARK_IS_TRACE,
@@ -4639,17 +4625,17 @@ JS_CompileScript(JSContext *cx, JSObject
     jschar *chars;
     JSScript *script;
 
     CHECK_REQUEST(cx);
     chars = js_InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
     script = JS_CompileUCScript(cx, obj, chars, length, filename, lineno);
-    JS_free(cx, chars);
+    cx->free(chars);
     return script;
 }
 
 JS_PUBLIC_API(JSScript *)
 JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
                               JSPrincipals *principals,
                               const char *bytes, size_t length,
                               const char *filename, uintN lineno)
@@ -4658,17 +4644,17 @@ JS_CompileScriptForPrincipals(JSContext 
     JSScript *script;
 
     CHECK_REQUEST(cx);
     chars = js_InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
     script = JS_CompileUCScriptForPrincipals(cx, obj, principals,
                                              chars, length, filename, lineno);
-    JS_free(cx, chars);
+    cx->free(chars);
     return script;
 }
 
 JS_PUBLIC_API(JSScript *)
 JS_CompileUCScript(JSContext *cx, JSObject *obj,
                    const jschar *chars, size_t length,
                    const char *filename, uintN lineno)
 {
@@ -4743,17 +4729,17 @@ JS_BufferIsCompilableUnit(JSContext *cx,
                  * source, we return false so our caller knows to try to
                  * collect more buffered source.
                  */
                 result = JS_FALSE;
             }
             JS_SetErrorReporter(cx, older);
         }
     }
-    JS_free(cx, chars);
+    cx->free(chars);
     JS_RestoreExceptionState(cx, exnState);
     return result;
 }
 
 JS_PUBLIC_API(JSScript *)
 JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename)
 {
     FILE *fp;
@@ -4852,17 +4838,17 @@ JS_CompileFunction(JSContext *cx, JSObje
     JSFunction *fun;
 
     CHECK_REQUEST(cx);
     chars = js_InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
     fun = JS_CompileUCFunction(cx, obj, name, nargs, argnames, chars, length,
                                filename, lineno);
-    JS_free(cx, chars);
+    cx->free(chars);
     return fun;
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
                                 JSPrincipals *principals, const char *name,
                                 uintN nargs, const char **argnames,
                                 const char *bytes, size_t length,
@@ -4873,17 +4859,17 @@ JS_CompileFunctionForPrincipals(JSContex
 
     CHECK_REQUEST(cx);
     chars = js_InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
     fun = JS_CompileUCFunctionForPrincipals(cx, obj, principals, name,
                                             nargs, argnames, chars, length,
                                             filename, lineno);
-    JS_free(cx, chars);
+    cx->free(chars);
     return fun;
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
                      uintN nargs, const char **argnames,
                      const jschar *chars, size_t length,
                      const char *filename, uintN lineno)
@@ -5083,17 +5069,17 @@ JS_EvaluateScript(JSContext *cx, JSObjec
     jschar *chars;
     JSBool ok;
 
     CHECK_REQUEST(cx);
     chars = js_InflateString(cx, bytes, &length);
     if (!chars)
         return JS_FALSE;
     ok = JS_EvaluateUCScript(cx, obj, chars, length, filename, lineno, rval);
-    JS_free(cx, chars);
+    cx->free(chars);
     return ok;
 }
 
 /* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
 JS_PUBLIC_API(JSBool)
 JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj,
                                JSPrincipals *principals,
                                const char *bytes, uintN nbytes,
@@ -5105,17 +5091,17 @@ JS_EvaluateScriptForPrincipals(JSContext
     JSBool ok;
 
     CHECK_REQUEST(cx);
     chars = js_InflateString(cx, bytes, &length);
     if (!chars)
         return JS_FALSE;
     ok = JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length,
                                           filename, lineno, rval);
-    JS_free(cx, chars);
+    cx->free(chars);
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_EvaluateUCScript(JSContext *cx, JSObject *obj,
                     const jschar *chars, uintN length,
                     const char *filename, uintN lineno,
                     jsval *rval)
@@ -5192,17 +5178,17 @@ JS_CallFunctionValue(JSContext *cx, JSOb
     return ok;
 }
 
 JS_PUBLIC_API(JSOperationCallback)
 JS_SetOperationCallback(JSContext *cx, JSOperationCallback callback)
 {
 #ifdef JS_THREADSAFE
     JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread));
-#endif    
+#endif
     JSOperationCallback old = cx->operationCallback;
     cx->operationCallback = callback;
     return old;
 }
 
 JS_PUBLIC_API(JSOperationCallback)
 JS_GetOperationCallback(JSContext *cx)
 {
@@ -5314,39 +5300,39 @@ JS_NewString(JSContext *cx, char *bytes,
     /* Make a UTF-16 vector from the 8-bit char codes in bytes. */
     chars = js_InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
 
     /* Free chars (but not bytes, which caller frees on error) if we fail. */
     str = js_NewString(cx, chars, length);
     if (!str) {
-        JS_free(cx, chars);
+        cx->free(chars);
         return NULL;
     }
 
     /* Hand off bytes to the deflated string cache, if possible. */
     if (!js_SetStringBytes(cx, str, bytes, nbytes))
-        JS_free(cx, bytes);
+        cx->free(bytes);
     return str;
 }
 
 JS_PUBLIC_API(JSString *)
 JS_NewStringCopyN(JSContext *cx, const char *s, size_t n)
 {
     jschar *js;
     JSString *str;
 
     CHECK_REQUEST(cx);
     js = js_InflateString(cx, s, &n);
     if (!js)
         return NULL;
     str = js_NewString(cx, js, n);
     if (!str)
-        JS_free(cx, js);
+        cx->free(js);
     return str;
 }
 
 JS_PUBLIC_API(JSString *)
 JS_NewStringCopyZ(JSContext *cx, const char *s)
 {
     size_t n;
     jschar *js;
@@ -5356,17 +5342,17 @@ JS_NewStringCopyZ(JSContext *cx, const c
     if (!s)
         return cx->runtime->emptyString;
     n = strlen(s);
     js = js_InflateString(cx, s, &n);
     if (!js)
         return NULL;
     str = js_NewString(cx, js, n);
     if (!str)
-        JS_free(cx, js);
+        cx->free(js);
     return str;
 }
 
 JS_PUBLIC_API(JSString *)
 JS_InternString(JSContext *cx, const char *s)
 {
     JSAtom *atom;
 
@@ -5444,17 +5430,17 @@ JS_GetStringChars(JSString *str)
      *
      * The gain of dependent strings, which cure quadratic and cubic growth
      * rate bugs in string concatenation, is worth this slight loss in API
      * compatibility.
      */
     if (str->isDependent()) {
         n = str->dependentLength();
         size = (n + 1) * sizeof(jschar);
-        s = (jschar *) malloc(size);
+        s = (jschar *) js_malloc(size);
         if (s) {
             memcpy(s, str->dependentChars(), n * sizeof *s);
             s[n] = 0;
             str->reinitFlat(s, n);
         } else {
             s = str->dependentChars();
         }
     } else {
@@ -5722,17 +5708,17 @@ JS_NewRegExpObject(JSContext *cx, char *
     jschar *chars;
     JSObject *obj;
 
     CHECK_REQUEST(cx);
     chars = js_InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
     obj = js_NewRegExpObject(cx, NULL, chars, length, flags);
-    JS_free(cx, chars);
+    cx->free(chars);
     return obj;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags)
 {
     CHECK_REQUEST(cx);
     return js_NewRegExpObject(cx, NULL, chars, length, flags);
@@ -5852,17 +5838,17 @@ struct JSExceptionState {
 };
 
 JS_PUBLIC_API(JSExceptionState *)
 JS_SaveExceptionState(JSContext *cx)
 {
     JSExceptionState *state;
 
     CHECK_REQUEST(cx);
-    state = (JSExceptionState *) JS_malloc(cx, sizeof(JSExceptionState));
+    state = (JSExceptionState *) cx->malloc(sizeof(JSExceptionState));
     if (state) {
         state->throwing = JS_GetPendingException(cx, &state->exception);
         if (state->throwing && JSVAL_IS_GCTHING(state->exception))
             js_AddRoot(cx, &state->exception, "JSExceptionState.exception");
     }
     return state;
 }
 
@@ -5881,17 +5867,17 @@ JS_RestoreExceptionState(JSContext *cx, 
 
 JS_PUBLIC_API(void)
 JS_DropExceptionState(JSContext *cx, JSExceptionState *state)
 {
     CHECK_REQUEST(cx);
     if (state) {
         if (state->throwing && JSVAL_IS_GCTHING(state->exception))
             JS_RemoveRoot(cx, &state->exception);
-        JS_free(cx, state);
+        cx->free(state);
     }
 }
 
 JS_PUBLIC_API(JSErrorReport *)
 JS_ErrorFromException(JSContext *cx, jsval v)
 {
     CHECK_REQUEST(cx);
     return js_ErrorFromException(cx, v);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -49,45 +49,132 @@
 #include "jspubtd.h"
 #include "jsutil.h"
 
 JS_BEGIN_EXTERN_C
 
 /*
  * Type tags stored in the low bits of a jsval.
  */
-#define JSVAL_OBJECT            0x0     /* untagged reference to object */
-#define JSVAL_INT               0x1     /* tagged 31-bit integer value */
-#define JSVAL_DOUBLE            0x2     /* tagged reference to double */
-#define JSVAL_STRING            0x4     /* tagged reference to string */
-#define JSVAL_BOOLEAN           0x6     /* tagged boolean value */
+typedef enum jsvaltag {
+    JSVAL_OBJECT  =         0x0,     /* untagged reference to object */
+    JSVAL_INT     =         0x1,     /* tagged 31-bit integer value */
+    JSVAL_DOUBLE  =         0x2,     /* tagged reference to double */
+    JSVAL_STRING  =         0x4,     /* tagged reference to string */
+    JSVAL_BOOLEAN =         0x6      /* tagged boolean value */
+} jsvaltag;
+
+#define JSVAL_OBJECT ((jsvaltag)0x0)
+#define JSVAL_INT ((jsvaltag)0x1)
+#define JSVAL_DOUBLE ((jsvaltag)0x2)
+#define JSVAL_STRING ((jsvaltag)0x4)
+#define JSVAL_BOOLEAN ((jsvaltag)0x6)
 
 /* Type tag bitfield length and derived macros. */
 #define JSVAL_TAGBITS           3
 #define JSVAL_TAGMASK           JS_BITMASK(JSVAL_TAGBITS)
-#define JSVAL_TAG(v)            ((v) & JSVAL_TAGMASK)
-#define JSVAL_SETTAG(v,t)       ((v) | (t))
-#define JSVAL_CLRTAG(v)         ((v) & ~(jsval)JSVAL_TAGMASK)
 #define JSVAL_ALIGN             JS_BIT(JSVAL_TAGBITS)
 
+/* Not a function, because we have static asserts that use it */
+#define JSVAL_TAG(v)            ((jsvaltag)((v) & JSVAL_TAGMASK))
+
+/* Not a function, because we have static asserts that use it */
+#define JSVAL_SETTAG(v, t) ((v) | (t))
+
+static JS_ALWAYS_INLINE jsval
+JSVAL_CLRTAG(jsval v)
+{
+    return v & ~(jsval)JSVAL_TAGMASK;
+}
+
+/*
+ * Well-known JS values.  The extern'd variables are initialized when the
+ * first JSContext is created by JS_NewContext (see below).
+ */
+#define JSVAL_NULL              ((jsval) 0)
+#define JSVAL_ZERO              INT_TO_JSVAL(0)
+#define JSVAL_ONE               INT_TO_JSVAL(1)
+#define JSVAL_FALSE             PSEUDO_BOOLEAN_TO_JSVAL(JS_FALSE)
+#define JSVAL_TRUE              PSEUDO_BOOLEAN_TO_JSVAL(JS_TRUE)
+#define JSVAL_VOID              PSEUDO_BOOLEAN_TO_JSVAL(2)
+
+/*
+ * A pseudo-boolean is a 29-bit (for 32-bit jsval) or 61-bit (for 64-bit jsval)
+ * value other than 0 or 1 encoded as a jsval whose tag is JSVAL_BOOLEAN.
+ *
+ * JSVAL_VOID happens to be defined as a jsval encoding a pseudo-boolean, but
+ * embedders MUST NOT rely on this. All other possible pseudo-boolean values
+ * are implementation-reserved and MUST NOT be constructed by any embedding of
+ * SpiderMonkey.
+ */
+#define JSVAL_TO_PSEUDO_BOOLEAN(v) ((JSBool) ((v) >> JSVAL_TAGBITS))
+#define PSEUDO_BOOLEAN_TO_JSVAL(b)                                            \
+    JSVAL_SETTAG((jsval) (b) << JSVAL_TAGBITS, JSVAL_BOOLEAN)
+
 /* Predicates for type testing. */
-#define JSVAL_IS_OBJECT(v)      (JSVAL_TAG(v) == JSVAL_OBJECT)
-#define JSVAL_IS_NUMBER(v)      (JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v))
-#define JSVAL_IS_INT(v)         ((v) & JSVAL_INT)
-#define JSVAL_IS_DOUBLE(v)      (JSVAL_TAG(v) == JSVAL_DOUBLE)
-#define JSVAL_IS_STRING(v)      (JSVAL_TAG(v) == JSVAL_STRING)
-#define JSVAL_IS_BOOLEAN(v)     (((v) & ~((jsval)1 << JSVAL_TAGBITS)) ==      \
-                                 JSVAL_BOOLEAN)
-#define JSVAL_IS_NULL(v)        ((v) == JSVAL_NULL)
-#define JSVAL_IS_VOID(v)        ((v) == JSVAL_VOID)
-#define JSVAL_IS_PRIMITIVE(v)   (!JSVAL_IS_OBJECT(v) || JSVAL_IS_NULL(v))
+static JS_ALWAYS_INLINE JSBool
+JSVAL_IS_OBJECT(jsval v)
+{
+    return JSVAL_TAG(v) == JSVAL_OBJECT;
+}
+
+static JS_ALWAYS_INLINE JSBool
+JSVAL_IS_INT(jsval v)
+{
+    return v & JSVAL_INT;
+}
+
+static JS_ALWAYS_INLINE JSBool
+JSVAL_IS_DOUBLE(jsval v)
+{
+    return JSVAL_TAG(v) == JSVAL_DOUBLE;
+}
+
+static JS_ALWAYS_INLINE JSBool
+JSVAL_IS_NUMBER(jsval v)
+{
+    return JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v);
+}
+
+static JS_ALWAYS_INLINE JSBool
+JSVAL_IS_STRING(jsval v)
+{
+    return JSVAL_TAG(v) == JSVAL_STRING;
+}
+
+static JS_ALWAYS_INLINE JSBool
+JSVAL_IS_BOOLEAN(jsval v)
+{
+    return (v & ~((jsval)1 << JSVAL_TAGBITS)) == JSVAL_BOOLEAN;
+}
+
+static JS_ALWAYS_INLINE JSBool
+JSVAL_IS_NULL(jsval v)
+{
+    return v == JSVAL_NULL;
+}
+
+static JS_ALWAYS_INLINE JSBool
+JSVAL_IS_VOID(jsval v)
+{
+    return v == JSVAL_VOID;
+}
+
+static JS_ALWAYS_INLINE JSBool
+JSVAL_IS_PRIMITIVE(jsval v)
+{
+    return !JSVAL_IS_OBJECT(v) || JSVAL_IS_NULL(v);
+}
 
 /* Objects, strings, and doubles are GC'ed. */
-#define JSVAL_IS_GCTHING(v)     (!((v) & JSVAL_INT) &&                        \
-                                 JSVAL_TAG(v) != JSVAL_BOOLEAN)
+static JS_ALWAYS_INLINE JSBool
+JSVAL_IS_GCTHING(jsval v)
+{
+    return !(v & JSVAL_INT) && JSVAL_TAG(v) != JSVAL_BOOLEAN;
+}
 
 static JS_ALWAYS_INLINE void *
 JSVAL_TO_GCTHING(jsval v)
 {
     JS_ASSERT(JSVAL_IS_GCTHING(v));
     return (void *) JSVAL_CLRTAG(v);
 }
 
@@ -140,46 +227,28 @@ STRING_TO_JSVAL(JSString *str)
                                  ? JS_UnlockGCThing(cx, JSVAL_TO_GCTHING(v))  \
                                  : JS_TRUE)
 
 /* Domain limits for the jsval int type. */
 #define JSVAL_INT_BITS          31
 #define JSVAL_INT_POW2(n)       ((jsval)1 << (n))
 #define JSVAL_INT_MIN           (-JSVAL_INT_POW2(30))
 #define JSVAL_INT_MAX           (JSVAL_INT_POW2(30) - 1)
+
+/* Not a function, because we have static asserts that use it */
 #define INT_FITS_IN_JSVAL(i)    ((jsuint)(i) - (jsuint)JSVAL_INT_MIN <=      \
                                  (jsuint)(JSVAL_INT_MAX - JSVAL_INT_MIN))
+/* Not a function, because we have static asserts that use it */
+/* FIXME:  Bug 506721, since that means we can't assert JSVAL_IS_INT(v) */
 #define JSVAL_TO_INT(v)         ((jsint)(v) >> 1)
+
+/* Not a function, because we have static asserts that use it */
+/* FIXME:  Bug 506721, since that means we can't assert INT_FITS_IN_JSVAL(i) */
 #define INT_TO_JSVAL(i)         (((jsval)(i) << 1) | JSVAL_INT)
 
-/*
- * A pseudo-boolean is a 29-bit (for 32-bit jsval) or 61-bit (for 64-bit jsval)
- * value other than 0 or 1 encoded as a jsval whose tag is JSVAL_BOOLEAN.
- *
- * JSVAL_VOID happens to be defined as a jsval encoding a pseudo-boolean, but
- * embedders MUST NOT rely on this. All other possible pseudo-boolean values
- * are implementation-reserved and MUST NOT be constructed by any embedding of
- * SpiderMonkey.
- */
-#define JSVAL_TO_PSEUDO_BOOLEAN(v) ((JSBool) ((v) >> JSVAL_TAGBITS))
-#define PSEUDO_BOOLEAN_TO_JSVAL(b)                                            \
-    JSVAL_SETTAG((jsval) (b) << JSVAL_TAGBITS, JSVAL_BOOLEAN)
-
-/*
- * Well-known JS values.  The extern'd variables are initialized when the
- * first JSContext is created by JS_NewContext (see below).
- */
-#define JSVAL_NULL              ((jsval) 0)
-#define JSVAL_ZERO              INT_TO_JSVAL(0)
-#define JSVAL_ONE               INT_TO_JSVAL(1)
-#define JSVAL_FALSE             PSEUDO_BOOLEAN_TO_JSVAL(JS_FALSE)
-#define JSVAL_TRUE              PSEUDO_BOOLEAN_TO_JSVAL(JS_TRUE)
-#define JSVAL_VOID              PSEUDO_BOOLEAN_TO_JSVAL(2)
-
-
 /* Convert between boolean and jsval, asserting that inputs are valid. */
 static JS_ALWAYS_INLINE JSBool
 JSVAL_TO_BOOLEAN(jsval v)
 {
     JS_ASSERT(v == JSVAL_TRUE || v == JSVAL_FALSE);
     return JSVAL_TO_PSEUDO_BOOLEAN(v);
 }
 
@@ -2224,24 +2293,24 @@ JS_CallFunctionName(JSContext *cx, JSObj
 extern JS_PUBLIC_API(JSBool)
 JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc,
                      jsval *argv, jsval *rval);
 
 /*
  * These functions allow setting an operation callback that will be called
  * from the thread the context is associated with some time after any thread
  * triggered the callback using JS_TriggerOperationCallback(cx).
- * 
+ *
  * In a threadsafe build the engine internally triggers operation callbacks
  * under certain circumstances (i.e. GC and title transfer) to force the
- * context to yield its current request, which the engine always 
+ * context to yield its current request, which the engine always
  * automatically does immediately prior to calling the callback function.
  * The embedding should thus not rely on callbacks being triggered through
  * the external API only.
- * 
+ *
  * Important note: Additional callbacks can occur inside the callback handler
  * if it re-enters the JS engine. The embedding must ensure that the callback
  * is disconnected before attempting such re-entry.
  */
 
 extern JS_PUBLIC_API(JSOperationCallback)
 JS_SetOperationCallback(JSContext *cx, JSOperationCallback callback);
 
--- a/js/src/jsarena.cpp
+++ b/js/src/jsarena.cpp
@@ -155,22 +155,22 @@ JS_ArenaAllocate(JSArenaPool *pool, size
             extra = (nb > pool->arenasize) ? HEADER_SIZE(pool) : 0;
             hdrsz = sizeof *a + extra + pool->mask;
             gross = hdrsz + JS_MAX(nb, pool->arenasize);
             if (gross < nb)
                 return NULL;
             if (pool->quotap) {
                 if (gross > *pool->quotap)
                     return NULL;
-                b = (JSArena *) malloc(gross);
+                b = (JSArena *) js_malloc(gross);
                 if (!b)
                     return NULL;
                 *pool->quotap -= gross;
             } else {
-                b = (JSArena *) malloc(gross);
+                b = (JSArena *) js_malloc(gross);
                 if (!b)
                     return NULL;
             }
 
             b->next = NULL;
             b->limit = (jsuword)b + gross;
             JS_COUNT_ARENA(pool,++);
             COUNT(pool, nmallocs);
@@ -222,22 +222,22 @@ JS_ArenaRealloc(JSArenaPool *pool, void 
     extra = HEADER_SIZE(pool);                  /* oversized header holds ap */
     hdrsz = sizeof *a + extra + pool->mask;     /* header and alignment slop */
     gross = hdrsz + aoff;
     JS_ASSERT(gross > aoff);
     if (pool->quotap) {
         growth = gross - (a->limit - (jsuword) a);
         if (growth > *pool->quotap)
             return NULL;
-        a = (JSArena *) realloc(a, gross);
+        a = (JSArena *) js_realloc(a, gross);
         if (!a)
             return NULL;
         *pool->quotap -= growth;
     } else {
-        a = (JSArena *) realloc(a, gross);
+        a = (JSArena *) js_realloc(a, gross);
         if (!a)
             return NULL;
     }
 #ifdef JS_ARENAMETER
     pool->stats.nreallocs++;
 #endif
 
     if (a != *ap) {
@@ -310,17 +310,17 @@ FreeArenaList(JSArenaPool *pool, JSArena
 #endif
 
     do {
         *ap = a->next;
         if (pool->quotap)
             *pool->quotap += a->limit - (jsuword) a;
         JS_CLEAR_ARENA(a);
         JS_COUNT_ARENA(pool,--);
-        free(a);
+        js_free(a);
     } while ((a = *ap) != NULL);
 
     pool->current = head;
 }
 
 JS_PUBLIC_API(void)
 JS_ArenaRelease(JSArenaPool *pool, char *mark)
 {
@@ -349,17 +349,17 @@ JS_PUBLIC_API(void)
 JS_FinishArenaPool(JSArenaPool *pool)
 {
     FreeArenaList(pool, &pool->first);
 #ifdef JS_ARENAMETER
     {
         JSArenaStats *stats, **statsp;
 
         if (pool->stats.name) {
-            free(pool->stats.name);
+            js_free(pool->stats.name);
             pool->stats.name = NULL;
         }
         for (statsp = &arena_stats_list; (stats = *statsp) != 0;
              statsp = &stats->next) {
             if (stats == &pool->stats) {
                 *statsp = stats->next;
                 return;
             }
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -309,33 +309,33 @@ BigIndexToId(JSContext *cx, JSObject *ob
 
 static JSBool
 ResizeSlots(JSContext *cx, JSObject *obj, uint32 oldsize, uint32 size)
 {
     jsval *slots, *newslots;
 
     if (size == 0) {
         if (obj->dslots) {
-            JS_free(cx, obj->dslots - 1);
+            cx->free(obj->dslots - 1);
             obj->dslots = NULL;
         }
         return JS_TRUE;
     }
 
     /*
      * MAX_DSLOTS_LENGTH is the maximum net capacity supported. Since we allocate
      * one additional slot to hold the array length, we have to use >= here.
      */
     if (size >= MAX_DSLOTS_LENGTH) {
         js_ReportAllocationOverflow(cx);
         return JS_FALSE;
     }
 
     slots = obj->dslots ? obj->dslots - 1 : NULL;
-    newslots = (jsval *) JS_realloc(cx, slots, (size + 1) * sizeof(jsval));
+    newslots = (jsval *) cx->realloc(slots, (size + 1) * sizeof(jsval));
     if (!newslots)
         return JS_FALSE;
 
     obj->dslots = newslots + 1;
     js_SetDenseArrayCapacity(obj, size);
 
     for (slots = obj->dslots + oldsize; slots < obj->dslots + size; slots++)
         *slots = JSVAL_HOLE;
@@ -1094,34 +1094,34 @@ array_enumerate(JSContext *cx, JSObject 
         capacity = js_DenseArrayCapacity(obj);
         if (idp)
             *idp = INT_TO_JSVAL(obj->fslots[JSSLOT_ARRAY_COUNT]);
         ii = NULL;
         for (i = 0; i != capacity; ++i) {
             if (obj->dslots[i] == JSVAL_HOLE) {
                 if (!ii) {
                     ii = (JSIndexIterState *)
-                         JS_malloc(cx, offsetof(JSIndexIterState, holes) +
+                         cx->malloc(offsetof(JSIndexIterState, holes) +
                                    JS_BITMAP_SIZE(capacity));
                     if (!ii)
                         return JS_FALSE;
                     ii->hasHoles = JS_TRUE;
                     memset(ii->holes, 0, JS_BITMAP_SIZE(capacity));
                 }
                 JS_SET_BIT(ii->holes, i);
             }
         }
         if (!ii) {
             /* Array has no holes. */
             if (capacity <= PACKED_UINT_PAIR_MASK) {
                 *statep = UINT_PAIR_TO_BOOLEAN_JSVAL(0, capacity);
                 break;
             }
             ii = (JSIndexIterState *)
-                 JS_malloc(cx, offsetof(JSIndexIterState, holes));
+                 cx->malloc(offsetof(JSIndexIterState, holes));
             if (!ii)
                 return JS_FALSE;
             ii->hasHoles = JS_FALSE;
         }
         ii->index = 0;
         ii->length = capacity;
         *statep = (jsval) ii | INDEX_ITER_TAG;
         JS_ASSERT(*statep & JSVAL_INT);
@@ -1152,17 +1152,17 @@ array_enumerate(JSContext *cx, JSObject 
             }
         }
         /* FALL THROUGH */
 
       case JSENUMERATE_DESTROY:
         if (JSVAL_TAG(*statep) != JSVAL_BOOLEAN) {
             JS_ASSERT((*statep & INDEX_ITER_TAG) == INDEX_ITER_TAG);
             ii = (JSIndexIterState *) (*statep & ~INDEX_ITER_TAG);
-            JS_free(cx, ii);
+            cx->free(ii);
         }
         *statep = JSVAL_NULL;
         break;
     }
     return JS_TRUE;
 }
 
 static JSBool
@@ -1183,17 +1183,17 @@ slowarray_enumerate(JSContext *cx, JSObj
     JS_ASSERT(*statep == JSVAL_NULL || (*statep & INDEX_ITER_TAG) == JSVAL_INT);
     return ok;
 }
 
 static void
 array_finalize(JSContext *cx, JSObject *obj)
 {
     if (obj->dslots)
-        JS_free(cx, obj->dslots - 1);
+        cx->free(obj->dslots - 1);
     obj->dslots = NULL;
 }
 
 static void
 array_trace(JSTracer *trc, JSObject *obj)
 {
     uint32 capacity;
     size_t i;
@@ -1331,17 +1331,17 @@ js_MakeArraySlow(JSContext *cx, JSObject
 /* Transfer ownership of buffer to returned string. */
 static JSBool
 BufferToString(JSContext *cx, JSTempVector<jschar> &buf, jsval *rval)
 {
     size_t length = buf.size() - 1;
     jschar *chars = buf.extractRawBuffer();
     JSString *str = js_NewString(cx, chars, length);
     if (!str) {
-        JS_free(cx, chars);
+        cx->free(chars);
         return JS_FALSE;
     }
     *rval = STRING_TO_JSVAL(str);
     return JS_TRUE;
 }
 
 #if JS_HAS_TOSOURCE
 static JSBool
@@ -1363,17 +1363,17 @@ array_toSource(JSContext *cx, uintN argc
         return JS_FALSE;
     JSBool initiallySharp = IS_SHARP(he) ? JS_TRUE : JS_FALSE;
 
     /* After this point, all paths exit through the 'done' label. */
     MUST_FLOW_THROUGH("done");
     JSBool ok = JS_TRUE;
 
     /*
-     * This object will take responsibility for the jschar buffer until the 
+     * This object will take responsibility for the jschar buffer until the
      * buffer is transferred to the returned JSString.
      */
     JSTempVector<jschar> buf(cx);
     if (!(ok = buf.reserve(3)))
         goto done;
 
     /* Cycles/joins are indicated by sharp objects. */
 #if JS_HAS_SHARP_VARS
@@ -1387,17 +1387,17 @@ array_toSource(JSContext *cx, uintN argc
         buf.replaceRawBuffer(sharpchars, js_strlen(sharpchars));
     }
 #else
     if (IS_SHARP(he)) {
         static const jschar arr[] = { '[', ']', 0 };
         if (!(ok = buf.pushBack(arr, arr + 3)))
             goto done;
         if (sharpchars)
-            JS_free(cx, sharpchars);
+            cx->free(sharpchars);
         goto make_string;
     }
 #endif
 
     if (!(ok = buf.pushBack('[')))
         goto done;
 
     jsuint length;
@@ -1515,17 +1515,17 @@ array_toString_sub(JSContext *cx, JSObje
     if (sepstr) {
         sepstr->getCharsAndLength(sep, seplen);
     } else {
         sep = &comma;
         seplen = 1;
     }
 
     /*
-     * This object will take responsibility for the jschar buffer until the 
+     * This object will take responsibility for the jschar buffer until the
      * buffer is transferred to the returned JSString.
      */
     JSTempVector<jschar> buf(cx);
 
     jsuint length;
     ok = js_GetLengthProperty(cx, obj, &length);
     if (!ok)
         goto done;
@@ -2146,17 +2146,17 @@ array_sort(JSContext *cx, uintN argc, js
      * malloc'd vector.
      */
 #if JS_BITS_PER_WORD == 32
     if ((size_t)len > ~(size_t)0 / (2 * sizeof(jsval))) {
         js_ReportAllocationOverflow(cx);
         return JS_FALSE;
     }
 #endif
-    vec = (jsval *) JS_malloc(cx, 2 * (size_t) len * sizeof(jsval));
+    vec = (jsval *) cx->malloc(2 * (size_t) len * sizeof(jsval));
     if (!vec)
         return JS_FALSE;
 
     /*
      * Initialize vec as a root. We will clear elements of vec one by
      * one while increasing tvr.count when we know that the property at
      * the corresponding index exists and its value must be rooted.
      *
@@ -2275,18 +2275,18 @@ array_sort(JSContext *cx, uintN argc, js
                     ok = JS_FALSE;
                     goto out;
                 }
                 vec[2 * i] = STRING_TO_JSVAL(str);
                 vec[2 * i + 1] = v;
             } while (i != 0);
 
             JS_ASSERT(tvr.u.array == vec);
-            vec = (jsval *) JS_realloc(cx, vec,
-                                       4 * (size_t) newlen * sizeof(jsval));
+            vec = (jsval *) cx->realloc(vec,
+                                        4 * (size_t) newlen * sizeof(jsval));
             if (!vec) {
                 vec = tvr.u.array;
                 ok = JS_FALSE;
                 goto out;
             }
             tvr.u.array = vec;
             mergesort_tmp = vec + 2 * newlen;
             memset(mergesort_tmp, 0, newlen * 2 * sizeof(jsval));
@@ -2337,17 +2337,17 @@ array_sort(JSContext *cx, uintN argc, js
     tvr.count = newlen;
     ok = InitArrayElements(cx, obj, 0, newlen, vec, TargetElementsMayContainValues,
                            SourceVectorAllValues);
     if (!ok)
         goto out;
 
   out:
     JS_POP_TEMP_ROOT(cx, &tvr);
-    JS_free(cx, vec);
+    cx->free(vec);
     if (!ok)
         return JS_FALSE;
 
     /* Set undefs that sorted after the rest of elements. */
     while (undefs != 0) {
         --undefs;
         if (!JS_CHECK_OPERATION_LIMIT(cx) ||
             !SetArrayElement(cx, obj, newlen++, JSVAL_VOID)) {
@@ -3502,29 +3502,29 @@ js_ArrayInfo(JSContext *cx, JSObject *ob
 
         bytes = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, argv[i],
                                            NULL);
         if (!bytes)
             return JS_FALSE;
         if (JSVAL_IS_PRIMITIVE(argv[i]) ||
             !OBJ_IS_ARRAY(cx, (array = JSVAL_TO_OBJECT(argv[i])))) {
             fprintf(stderr, "%s: not array\n", bytes);
-            JS_free(cx, bytes);
+            cx->free(bytes);
             continue;
         }
         fprintf(stderr, "%s: %s (len %lu", bytes,
                 OBJ_IS_DENSE_ARRAY(cx, array) ? "dense" : "sparse",
                 array->fslots[JSSLOT_ARRAY_LENGTH]);
         if (OBJ_IS_DENSE_ARRAY(cx, array)) {
             fprintf(stderr, ", count %lu, capacity %lu",
                     array->fslots[JSSLOT_ARRAY_COUNT],
                     js_DenseArrayCapacity(array));
         }
         fputs(")\n", stderr);
-        JS_free(cx, bytes);
+        cx->free(bytes);
     }
     return JS_TRUE;
 }
 #endif
 
 JS_FRIEND_API(JSBool)
 js_CoerceArrayToCanvasImageData(JSObject *obj, jsuint offset, jsuint count,
                                 JSUint8 *dest)
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -202,11 +202,15 @@ js_PrototypeHasIndexedProperties(JSConte
 
 /*
  * Utility to access the value from the id returned by array_lookupProperty.
  */
 JSBool
 js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, JSProperty *prop,
                              jsval *vp);
 
+/* Array constructor native. Exposed only so the JIT can know its address. */
+JSBool
+js_Array(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
+
 JS_END_EXTERN_C
 
 #endif /* jsarray_h___ */
--- a/js/src/jsatom.cpp
+++ b/js/src/jsatom.cpp
@@ -778,17 +778,17 @@ js_Atomize(JSContext *cx, const char *by
         if (!chars)
             return NULL;
         flags |= ATOM_NOCOPY;
     }
 
     str.initFlat(chars, inflatedLength);
     atom = js_AtomizeString(cx, &str, ATOM_TMPSTR | flags);
     if (chars != inflated && str.flatChars())
-        JS_free(cx, chars);
+        cx->free(chars);
     return atom;
 }
 
 JSAtom *
 js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags)
 {
     JSString str;
 
--- a/js/src/jsbuiltins.cpp
+++ b/js/src/jsbuiltins.cpp
@@ -124,17 +124,17 @@ js_BoxInt32(JSContext* cx, int32 i)
     if (JS_LIKELY(INT_FITS_IN_JSVAL(i)))
         return INT_TO_JSVAL(i);
     JS_ASSERT(JS_ON_TRACE(cx));
     jsval v; /* not rooted but ok here because we know GC won't run */
     jsdouble d = (jsdouble)i;
     if (!js_NewDoubleInRootedValue(cx, d, &v))
         return JSVAL_ERROR_COOKIE;
     return v;
-} 
+}
 JS_DEFINE_CALLINFO_2(extern, JSVAL, js_BoxInt32, CONTEXT, INT32, 1, 1)
 
 jsdouble FASTCALL
 js_UnboxDouble(jsval v)
 {
     if (JS_LIKELY(JSVAL_IS_INT(v)))
         return (jsdouble)JSVAL_TO_INT(v);
     return *JSVAL_TO_DOUBLE(v);
@@ -237,18 +237,16 @@ js_CallTree(InterpState* state, Fragment
     return lr;
 }
 JS_DEFINE_CALLINFO_2(extern, SIDEEXIT, js_CallTree, INTERPSTATE, FRAGMENT, 0, 0)
 
 JSBool FASTCALL
 js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
 {
     JS_ASSERT(OBJ_IS_NATIVE(obj));
-    JS_ASSERT(SPROP_HAS_STUB_SETTER(sprop));
-
     JS_LOCK_OBJ(cx, obj);
 
     JSScope* scope = OBJ_SCOPE(obj);
     uint32 slot;
     if (scope->owned()) {
         JS_ASSERT(!scope->has(sprop));
     } else {
         scope = js_GetMutableScope(cx, obj);
--- a/js/src/jsbuiltins.h
+++ b/js/src/jsbuiltins.h
@@ -81,17 +81,17 @@ enum { JSTN_ERRTYPE_MASK = 0x07, JSTN_UN
  * 'f': a JSObject* argument that is of class js_FunctionClass
  * 'v': a jsval argument (boxing whatever value is actually being passed in)
  */
 struct JSTraceableNative {
     JSFastNative            native;
     const nanojit::CallInfo *builtin;
     const char              *prefix;
     const char              *argtypes;
-    uintN                   flags;  /* JSTNErrType | JSTN_UNBOX_AFTER | JSTN_MORE | 
+    uintN                   flags;  /* JSTNErrType | JSTN_UNBOX_AFTER | JSTN_MORE |
                                        JSTN_CONSTRUCTOR */
 };
 
 /*
  * We use a magic boxed pointer value to represent error conditions that
  * trigger a side exit. The address is so low that it should never be actually
  * in use. If it is, a performance regression occurs, not an actual runtime
  * error.
@@ -112,17 +112,17 @@ struct JSTraceableNative {
 #define  _JS_PTR_ARGSIZE    nanojit::ARGSIZE_LO
 #if defined AVMPLUS_64BIT
 # define _JS_PTR_RETSIZE    nanojit::ARGSIZE_Q
 #else
 # define _JS_PTR_RETSIZE    nanojit::ARGSIZE_LO
 #endif
 
 /*
- * Supported types for builtin functions. 
+ * Supported types for builtin functions.
  *
  * Types with -- for the two string fields are not permitted as argument types
  * in JS_DEFINE_TRCINFO.
  *
  * There are three kinds of traceable-native error handling.
  *
  *   - If a traceable native's return type ends with _FAIL, it always runs to
  *     completion.  It can either succeed or fail with an error or exception;
@@ -160,17 +160,17 @@ struct JSTraceableNative {
  *
  * Special builtins known to the tracer can have their own idiosyncratic
  * error codes.
  *
  * When a traceable native returns a value indicating failure, we fall off
  * trace.  If an exception is pending, it is thrown; otherwise, we assume the
  * builtin had no side effects and retry the current bytecode in the
  * interpreter.
- * 
+ *
  * So a builtin must not return a value indicating failure after causing side
  * effects (such as reporting an error), without setting an exception pending.
  * The operation would be retried, despite the first attempt's observable
  * effects.
  */
 #define _JS_CTYPE(ctype, size, pch, ach, flags)     (ctype, size, pch, ach, flags)
 #define _JS_JSVAL_CTYPE(size, pch, ach, flags)  (jsval, size, pch, ach, (flags | JSTN_UNBOX_AFTER))
 
@@ -182,16 +182,17 @@ struct JSTraceableNative {
 #define _JS_CTYPE_CALLEE            _JS_CTYPE(JSObject *,             _JS_PTR,"f","",  INFALLIBLE)
 #define _JS_CTYPE_CALLEE_PROTOTYPE  _JS_CTYPE(JSObject *,             _JS_PTR,"p","",  INFALLIBLE)
 #define _JS_CTYPE_FUNCTION          _JS_CTYPE(JSFunction *,           _JS_PTR, --, --, INFALLIBLE)
 #define _JS_CTYPE_PC                _JS_CTYPE(jsbytecode *,           _JS_PTR,"P", "", INFALLIBLE)
 #define _JS_CTYPE_JSVALPTR          _JS_CTYPE(jsval *,                _JS_PTR,"P", "", INFALLIBLE)
 #define _JS_CTYPE_JSVAL             _JS_JSVAL_CTYPE(                  _JS_PTR, "","v", INFALLIBLE)
 #define _JS_CTYPE_JSVAL_RETRY       _JS_JSVAL_CTYPE(                  _JS_PTR, --, --, FAIL_COOKIE)
 #define _JS_CTYPE_JSVAL_FAIL        _JS_JSVAL_CTYPE(                  _JS_PTR, --, --, FAIL_STATUS)
+#define _JS_CTYPE_JSID              _JS_CTYPE(jsid,                   _JS_PTR, --, --, INFALLIBLE)
 #define _JS_CTYPE_BOOL              _JS_CTYPE(JSBool,                 _JS_I32, "","i", INFALLIBLE)
 #define _JS_CTYPE_BOOL_RETRY        _JS_CTYPE(JSBool,                 _JS_I32, --, --, FAIL_VOID)
 #define _JS_CTYPE_BOOL_FAIL         _JS_CTYPE(JSBool,                 _JS_I32, --, --, FAIL_STATUS)
 #define _JS_CTYPE_INT32             _JS_CTYPE(int32,                  _JS_I32, "","i", INFALLIBLE)
 #define _JS_CTYPE_INT32_RETRY       _JS_CTYPE(int32,                  _JS_I32, --, --, FAIL_NEG)
 #define _JS_CTYPE_INT32_FAIL        _JS_CTYPE(int32,                  _JS_I32, --, --, FAIL_STATUS)
 #define _JS_CTYPE_UINT32            _JS_CTYPE(uint32,                 _JS_I32, "","i", INFALLIBLE)
 #define _JS_CTYPE_UINT32_RETRY      _JS_CTYPE(uint32,                 _JS_I32, --, --, FAIL_NEG)
@@ -409,16 +410,19 @@ js_StringToNumber(JSContext* cx, JSStrin
 
 jsdouble FASTCALL
 js_BooleanOrUndefinedToNumber(JSContext* cx, int32 unboxed);
 
 /* Extern version of js_SetBuiltinError. */
 extern JS_FRIEND_API(void)
 js_SetTraceableNativeFailed(JSContext *cx);
 
+extern jsdouble FASTCALL
+js_dmod(jsdouble a, jsdouble b);
+
 #else
 
 #define JS_DEFINE_CALLINFO_1(linkage, rt, op, at0, cse, fold)
 #define JS_DEFINE_CALLINFO_2(linkage, rt, op, at0, at1, cse, fold)
 #define JS_DEFINE_CALLINFO_3(linkage, rt, op, at0, at1, at2, cse, fold)
 #define JS_DEFINE_CALLINFO_4(linkage, rt, op, at0, at1, at2, at3, cse, fold)
 #define JS_DEFINE_CALLINFO_5(linkage, rt, op, at0, at1, at2, at3, at4, cse, fold)
 #define JS_DECLARE_CALLINFO(name)
@@ -439,16 +443,20 @@ JS_DECLARE_CALLINFO(js_Array_dense_setel
 JS_DECLARE_CALLINFO(js_NewEmptyArray)
 JS_DECLARE_CALLINFO(js_NewUninitializedArray)
 JS_DECLARE_CALLINFO(js_ArrayCompPush)
 
 /* Defined in jsfun.cpp. */
 JS_DECLARE_CALLINFO(js_AllocFlatClosure)
 JS_DECLARE_CALLINFO(js_PutArguments)
 
+/* Defined in jsfun.cpp. */
+JS_DECLARE_CALLINFO(js_SetCallVar)
+JS_DECLARE_CALLINFO(js_SetCallArg)
+
 /* Defined in jsnum.cpp. */
 JS_DECLARE_CALLINFO(js_NumberToString)
 
 /* Defined in jsstr.cpp. */
 JS_DECLARE_CALLINFO(js_String_tn)
 JS_DECLARE_CALLINFO(js_CompareStrings)
 JS_DECLARE_CALLINFO(js_ConcatStrings)
 JS_DECLARE_CALLINFO(js_EqualStrings)
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -137,33 +137,33 @@ PurgeThreadData(JSContext *cx, JSThreadD
 }
 
 #ifdef JS_THREADSAFE
 
 static JSThread *
 NewThread(jsword id)
 {
     JS_ASSERT(js_CurrentThreadId() == id);
-    JSThread *thread = (JSThread *) calloc(1, sizeof(JSThread));
+    JSThread *thread = (JSThread *) js_calloc(sizeof(JSThread));
     if (!thread)
         return NULL;
     JS_INIT_CLIST(&thread->contextList);
     thread->id = id;
     InitThreadData(&thread->data);
     return thread;
 }
 
 static void
 DestroyThread(JSThread *thread)
 {
     /* The thread must have zero contexts. */
     JS_ASSERT(JS_CLIST_IS_EMPTY(&thread->contextList));
     JS_ASSERT(!thread->titleToShare);
     FinishThreadData(&thread->data);
-    free(thread);
+    js_free(thread);
 }
 
 JSBool
 js_InitContextThread(JSContext *cx)
 {
     JS_ASSERT(!cx->thread);
     jsword id = js_CurrentThreadId();
     JSRuntime *rt = cx->runtime;
@@ -365,17 +365,17 @@ js_NewContext(JSRuntime *rt, size_t stac
     JSBool ok, first;
     JSContextCallback cxCallback;
 
     /*
      * We need to initialize the new context fully before adding it to the
      * runtime list. After that it can be accessed from another thread via
      * js_ContextIterator.
      */
-    cx = (JSContext *) calloc(1, sizeof *cx);
+    cx = (JSContext *) js_calloc(sizeof *cx);
     if (!cx)
         return NULL;
 
     cx->runtime = rt;
     cx->debugHooks = &rt->globalDebugHooks;
 #if JS_STACK_GROWTH_DIRECTION > 0
     cx->stackLimit = (jsuword) -1;
 #endif
@@ -738,24 +738,24 @@ FreeContext(JSContext *cx)
 
     /* Free the stuff hanging off of cx. */
     js_FreeRegExpStatics(cx);
     VOUCH_DOES_NOT_REQUIRE_STACK();
     JS_FinishArenaPool(&cx->stackPool);
     JS_FinishArenaPool(&cx->tempPool);
 
     if (cx->lastMessage)
-        free(cx->lastMessage);
+        js_free(cx->lastMessage);
 
     /* Remove any argument formatters. */
     map = cx->argumentFormatMap;
     while (map) {
         JSArgumentFormatMap *temp = map;
         map = map->next;
-        JS_free(cx, temp);
+        cx->free(temp);
     }
 
     /* Destroy the busy array table. */
     if (cx->busyArrayTable) {
         JS_HashTableDestroy(cx->busyArrayTable);
         cx->busyArrayTable = NULL;
     }
 
@@ -764,23 +764,23 @@ FreeContext(JSContext *cx)
         JS_DHashTableDestroy(cx->resolvingTable);
         cx->resolvingTable = NULL;
     }
 
     lrs = cx->localRootStack;
     if (lrs) {
         while ((lrc = lrs->topChunk) != &lrs->firstChunk) {
             lrs->topChunk = lrc->down;
-            JS_free(cx, lrc);
+            cx->free(lrc);
         }
-        JS_free(cx, lrs);
+        cx->free(lrs);
     }
 
     /* Finally, free cx itself. */
-    free(cx);
+    js_free(cx);
 }
 
 JSBool
 js_ValidContextPointer(JSRuntime *rt, JSContext *cx)
 {
     JSCList *cl;
 
     for (cl = rt->contextList.next; cl != &rt->contextList; cl = cl->next) {
@@ -814,17 +814,17 @@ js_NextActiveContext(JSRuntime *rt, JSCo
 #ifdef JS_THREADSAFE
     while ((cx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) {
         if (cx->requestDepth)
             break;
     }
     return cx;
 #else
     return js_ContextIterator(rt, JS_FALSE, &iter);
-#endif           
+#endif
 }
 
 #ifdef JS_THREADSAFE
 
 uint32
 js_CountThreadRequests(JSContext *cx)
 {
     JSCList *head, *link;
@@ -1008,17 +1008,17 @@ js_StopResolving(JSContext *cx, JSResolv
 JSBool
 js_EnterLocalRootScope(JSContext *cx)
 {
     JSLocalRootStack *lrs;
     int mark;
 
     lrs = cx->localRootStack;
     if (!lrs) {
-        lrs = (JSLocalRootStack *) JS_malloc(cx, sizeof *lrs);
+        lrs = (JSLocalRootStack *) cx->malloc(sizeof *lrs);
         if (!lrs)
             return JS_FALSE;
         lrs->scopeMark = JSLRS_NULL_MARK;
         lrs->rootCount = 0;
         lrs->topChunk = &lrs->firstChunk;
         lrs->firstChunk.down = NULL;
         cx->localRootStack = lrs;
     }
@@ -1051,17 +1051,17 @@ js_LeaveLocalRootScopeWithResult(JSConte
 
     /* Free any chunks being popped by this leave operation. */
     m = mark >> JSLRS_CHUNK_SHIFT;
     n = (lrs->rootCount - 1) >> JSLRS_CHUNK_SHIFT;
     while (n > m) {
         lrc = lrs->topChunk;
         JS_ASSERT(lrc != &lrs->firstChunk);
         lrs->topChunk = lrc->down;
-        JS_free(cx, lrc);
+        cx->free(lrc);
         --n;
     }
 
     /*
      * Pop the scope, restoring lrs->scopeMark.  If rval is a GC-thing, push
      * it on the caller's scope, or store it in lastInternalResult if we are
      * leaving the outermost scope.  We don't need to allocate a new lrc
      * because we can overwrite the old mark's slot with rval.
@@ -1091,20 +1091,20 @@ js_LeaveLocalRootScopeWithResult(JSConte
      * tested by the GC in addition to the cx->localRootStack non-null test.
      *
      * That approach would risk hoarding 264 bytes (net) per context.  Right
      * now it seems better to give fresh (dirty in CPU write-back cache, and
      * the data is no longer needed) memory back to the malloc heap.
      */
     if (mark == 0) {
         cx->localRootStack = NULL;
-        JS_free(cx, lrs);
+        cx->free(lrs);
     } else if (m == 0) {
         lrs->topChunk = lrc->down;
-        JS_free(cx, lrc);
+        cx->free(lrc);
     }
 }
 
 void
 js_ForgetLocalRoot(JSContext *cx, jsval v)
 {
     JSLocalRootStack *lrs;
     uint32 i, j, m, n, mark;
@@ -1153,17 +1153,17 @@ js_ForgetLocalRoot(JSContext *cx, jsval 
 
     /* Pop the last value from the stack. */
     lrc->roots[m] = JSVAL_NULL;
     lrs->rootCount = n;
     if (m == 0) {
         JS_ASSERT(n != 0);
         JS_ASSERT(lrc != &lrs->firstChunk);
         lrs->topChunk = lrc->down;
-        JS_free(cx, lrc);
+        cx->free(lrc);
     }
 }
 
 int
 js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v)
 {
     uint32 n, m;
     JSLocalRootChunk *lrc;
@@ -1182,17 +1182,17 @@ js_PushLocalRoot(JSContext *cx, JSLocalR
         }
         lrc = lrs->topChunk;
         JS_ASSERT(n != 0 || lrc == &lrs->firstChunk);
     } else {
         /*
          * After lrs->firstChunk, trying to index at a power-of-two chunk
          * boundary: need a new chunk.
          */
-        lrc = (JSLocalRootChunk *) JS_malloc(cx, sizeof *lrc);
+        lrc = (JSLocalRootChunk *) cx->malloc(sizeof *lrc);
         if (!lrc)
             return -1;
         lrc->down = lrs->topChunk;
         lrs->topChunk = lrc;
     }
     lrs->rootCount = n + 1;
     lrc->roots[m] = v;
     return (int) n;
@@ -1375,18 +1375,18 @@ js_ReportErrorVA(JSContext *cx, uintN fl
 
     warning = JSREPORT_IS_WARNING(report.flags);
     if (warning && JS_HAS_WERROR_OPTION(cx)) {
         report.flags &= ~JSREPORT_WARNING;
         warning = JS_FALSE;
     }
 
     ReportError(cx, message, &report);
-    free(message);
-    JS_free(cx, ucmessage);
+    js_free(message);
+    cx->free(ucmessage);
     return warning;
 }
 
 /*
  * The arguments from ap need to be packaged up into an array and stored
  * into the report struct.
  *
  * The format string addressed by the error number may contain operands
@@ -1427,17 +1427,17 @@ js_ExpandErrorArguments(JSContext *cx, J
         if (argCount > 0) {
             /*
              * Gather the arguments into an array, and accumulate
              * their sizes. We allocate 1 more than necessary and
              * null it out to act as the caboose when we free the
              * pointers later.
              */
             reportp->messageArgs = (const jschar **)
-                JS_malloc(cx, sizeof(jschar *) * (argCount + 1));
+                cx->malloc(sizeof(jschar *) * (argCount + 1));
             if (!reportp->messageArgs)
                 return JS_FALSE;
             reportp->messageArgs[argCount] = NULL;
             for (i = 0; i < argCount; i++) {
                 if (charArgs) {
                     char *charArg = va_arg(ap, char *);
                     size_t charArgLength = strlen(charArg);
                     reportp->messageArgs[i]
@@ -1471,19 +1471,19 @@ js_ExpandErrorArguments(JSContext *cx, J
                                  - (3 * argCount)       /* exclude the {n} */
                                  + totalArgsLength;
 
                 /*
                 * Note - the above calculation assumes that each argument
                 * is used once and only once in the expansion !!!
                 */
                 reportp->ucmessage = out = (jschar *)
-                    JS_malloc(cx, (expandedLength + 1) * sizeof(jschar));
+                    cx->malloc((expandedLength + 1) * sizeof(jschar));
                 if (!out) {
-                    JS_free (cx, buffer);
+                    cx->free(buffer);
                     goto error;
                 }
                 while (*fmt) {
                     if (*fmt == '{') {
                         if (isdigit(fmt[1])) {
                             int d = JS7_UNDEC(fmt[1]);
                             JS_ASSERT(d < argCount);
                             js_strncpy(out, reportp->messageArgs[d],
@@ -1493,17 +1493,17 @@ js_ExpandErrorArguments(JSContext *cx, J
                             expandedArgs++;
                             continue;
                         }
                     }
                     *out++ = *fmt++;
                 }
                 JS_ASSERT(expandedArgs == argCount);
                 *out = 0;
-                JS_free (cx, buffer);
+                cx->free(buffer);
                 *messagep =
                     js_DeflateString(cx, reportp->ucmessage,
                                      (size_t)(out - reportp->ucmessage));
                 if (!*messagep)
                     goto error;
             }
         } else {
             /*
@@ -1522,40 +1522,40 @@ js_ExpandErrorArguments(JSContext *cx, J
             }
         }
     }
     if (*messagep == NULL) {
         /* where's the right place for this ??? */
         const char *defaultErrorMessage
             = "No error message available for error number %d";
         size_t nbytes = strlen(defaultErrorMessage) + 16;
-        *messagep = (char *)JS_malloc(cx, nbytes);
+        *messagep = (char *)cx->malloc(nbytes);
         if (!*messagep)
             goto error;
         JS_snprintf(*messagep, nbytes, defaultErrorMessage, errorNumber);
     }
     return JS_TRUE;
 
 error:
     if (reportp->messageArgs) {
         /* free the arguments only if we allocated them */
         if (charArgs) {
             i = 0;
             while (reportp->messageArgs[i])
-                JS_free(cx, (void *)reportp->messageArgs[i++]);
+                cx->free((void *)reportp->messageArgs[i++]);
         }
-        JS_free(cx, (void *)reportp->messageArgs);
+        cx->free((void *)reportp->messageArgs);
         reportp->messageArgs = NULL;
     }
     if (reportp->ucmessage) {
-        JS_free(cx, (void *)reportp->ucmessage);
+        cx->free((void *)reportp->ucmessage);
         reportp->ucmessage = NULL;
     }
     if (*messagep) {
-        JS_free(cx, (void *)*messagep);
+        cx->free((void *)*messagep);
         *messagep = NULL;
     }
     return JS_FALSE;
 }
 
 JSBool
 js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
                        void *userRef, const uintN errorNumber,
@@ -1576,45 +1576,45 @@ js_ReportErrorNumberVA(JSContext *cx, ui
     if (!js_ExpandErrorArguments(cx, callback, userRef, errorNumber,
                                  &message, &report, &warning, charArgs, ap)) {
         return JS_FALSE;
     }
 
     ReportError(cx, message, &report);
 
     if (message)
-        JS_free(cx, message);
+        cx->free(message);
     if (report.messageArgs) {
         /*
          * js_ExpandErrorArguments owns its messageArgs only if it had to
          * inflate the arguments (from regular |char *|s).
          */
         if (charArgs) {
             int i = 0;
             while (report.messageArgs[i])
-                JS_free(cx, (void *)report.messageArgs[i++]);
+                cx->free((void *)report.messageArgs[i++]);
         }
-        JS_free(cx, (void *)report.messageArgs);
+        cx->free((void *)report.messageArgs);
     }
     if (report.ucmessage)
-        JS_free(cx, (void *)report.ucmessage);
+        cx->free((void *)report.ucmessage);
 
     return warning;
 }
 
 JS_FRIEND_API(void)
 js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp)
 {
     JSErrorReporter onError;
 
     if (!message)
         return;
 
     if (cx->lastMessage)
-        free(cx->lastMessage);
+        js_free(cx->lastMessage);
     cx->lastMessage = JS_strdup(cx, message);
     if (!cx->lastMessage)
         return;
     onError = cx->errorReporter;
 
     /*
      * If debugErrorHook is present then we give it a chance to veto
      * sending the error on to the regular ErrorReporter.
@@ -1662,17 +1662,17 @@ js_ReportIsNullOrUndefined(JSContext *cx
     } else {
         JS_ASSERT(JSVAL_IS_NULL(v));
         ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
                                           js_GetErrorMessage, NULL,
                                           JSMSG_NULL_OR_UNDEFINED, bytes,
                                           js_null_str, NULL);
     }
 
-    JS_free(cx, bytes);
+    cx->free(bytes);
     return ok;
 }
 
 void
 js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg)
 {
     char argbuf[11];
     char *bytes;
@@ -1685,17 +1685,17 @@ js_ReportMissingArg(JSContext *cx, jsval
         bytes = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, *vp,
                                            ATOM_TO_STRING(atom));
         if (!bytes)
             return;
     }
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                          JSMSG_MISSING_FUN_ARG, argbuf,
                          bytes ? bytes : "");
-    JS_free(cx, bytes);
+    cx->free(bytes);
 }
 
 JSBool
 js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber,
                          intN spindex, jsval v, JSString *fallback,
                          const char *arg1, const char *arg2)
 {
     char *bytes;
@@ -1704,17 +1704,17 @@ js_ReportValueErrorFlags(JSContext *cx, 
     JS_ASSERT(js_ErrorFormatString[errorNumber].argCount >= 1);
     JS_ASSERT(js_ErrorFormatString[errorNumber].argCount <= 3);
     bytes = js_DecompileValueGenerator(cx, spindex, v, fallback);
     if (!bytes)
         return JS_FALSE;
 
     ok = JS_ReportErrorFlagsAndNumber(cx, flags, js_GetErrorMessage,
                                       NULL, errorNumber, bytes, arg1, arg2);
-    JS_free(cx, bytes);
+    cx->free(bytes);
     return ok;
 }
 
 #if defined DEBUG && defined XP_UNIX
 /* For gdb usage. */
 void js_traceon(JSContext *cx)  { cx->tracefp = stderr; cx->tracePrevPc = NULL; }
 void js_traceoff(JSContext *cx) { cx->tracefp = NULL; }
 #endif
@@ -1733,34 +1733,34 @@ js_GetErrorMessage(void *userRef, const 
         return &js_ErrorFormatString[errorNumber];
     return NULL;
 }
 
 JSBool
 js_InvokeOperationCallback(JSContext *cx)
 {
     JS_ASSERT(cx->operationCallbackFlag);
-    
+
     /*
      * Reset the callback flag first, then yield. If another thread is racing
-     * us here we will accumulate another callback request which will be 
+     * us here we will accumulate another callback request which will be
      * serviced at the next opportunity.
      */
     cx->operationCallbackFlag = 0;
 
     /*
      * Unless we are going to run the GC, we automatically yield the current
      * context every time the operation callback is hit since we might be
      * called as a result of an impending GC, which would deadlock if we do
      * not yield. Operation callbacks are supposed to happen rarely (seconds,
      * not milliseconds) so it is acceptable to yield at every callback.
      */
     if (cx->runtime->gcIsNeeded)
         js_GC(cx, GC_NORMAL);
-#ifdef JS_THREADSAFE    
+#ifdef JS_THREADSAFE
     else
         JS_YieldRequest(cx);
 #endif
 
     JSOperationCallback cb = cx->operationCallback;
 
     /*
      * Important: Additional callbacks can occur inside the callback handler
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -52,16 +52,17 @@
 #include "jsgc.h"
 #include "jsinterp.h"
 #include "jsobj.h"
 #include "jsprvtd.h"
 #include "jspubtd.h"
 #include "jsregexp.h"
 #include "jsutil.h"
 #include "jsarray.h"
+#include "jstask.h"
 
 JS_BEGIN_EXTERN_C
 
 /*
  * js_GetSrcNote cache to avoid O(n^2) growth in finding a source note for a
  * given pc in a script. We use the script->code pointer to tag the cache,
  * instead of the script address itself, so that source notes are always found
  * by offset from the bytecode with which they were generated.
@@ -250,16 +251,23 @@ struct JSThreadData {
     JSEvalCacheMeter    evalCacheMeter;
 #endif
 
     /*
      * Thread-local version of JSRuntime.gcMallocBytes to avoid taking
      * locks on each JS_malloc.
      */
     size_t              gcMallocBytes;
+
+#ifdef JS_THREADSAFE
+    /*
+     * Deallocator task for this thread.
+     */
+    JSFreePointerListTask *deallocatorTask;
+#endif
 };
 
 #ifdef JS_THREADSAFE
 
 /*
  * Structure uniquely representing a thread.  It holds thread-private data
  * that can be accessed without a global lock.
  */
@@ -386,17 +394,28 @@ struct JSRuntime {
      * NB: do not pack another flag here by claiming gcPadding unless the new
      * flag is written only by the GC thread.  Atomic updates to packed bytes
      * are not guaranteed, so stores issued by one thread may be lost due to
      * unsynchronized read-modify-write cycles on other threads.
      */
     JSPackedBool        gcPoke;
     JSPackedBool        gcRunning;
     JSPackedBool        gcRegenShapes;
-    uint8               gcPadding;
+
+    /*
+     * During gc, if rt->gcRegenShapes &&
+     *   (scope->flags & JSScope::SHAPE_REGEN) == rt->gcRegenShapesScopeFlag,
+     * then the scope's shape has already been regenerated during this GC.
+     * To avoid having to sweep JSScopes, the bit's meaning toggles with each
+     * shape-regenerating GC.
+     *
+     * FIXME Once scopes are GC'd (bug 505004), this will be obsolete.
+     */
+    uint8              gcRegenShapesScopeFlag;
+
 #ifdef JS_GC_ZEAL
     jsrefcount          gcZeal;
 #endif
 
     JSGCCallback        gcCallback;
     size_t              gcMallocBytes;
     JSGCArenaInfo       *gcUntracedArenaStackTop;
 #ifdef DEBUG
@@ -683,16 +702,36 @@ struct JSRuntime {
 
 #ifdef JS_FUNCTION_METERING
     JSFunctionMeter     functionMeter;
     char                lastScriptFilename[1024];
 #endif
 
     void setGCTriggerFactor(uint32 factor);
     void setGCLastBytes(size_t lastBytes);
+
+    inline void* malloc(size_t bytes) {
+        return ::js_malloc(bytes);
+    }
+
+    inline void* calloc(size_t bytes) {
+        return ::js_calloc(bytes);
+    }
+
+    inline void* realloc(void* p, size_t bytes) {
+        return ::js_realloc(p, bytes);
+    }
+
+    inline void free(void* p) {
+        ::js_free(p);
+    }
+
+#ifdef JS_THREADSAFE
+    JSBackgroundThread    *deallocatorThread;
+#endif
 };
 
 /* Common macros to access thread-local caches in JSThread or JSRuntime. */
 #define JS_GSN_CACHE(cx)        (JS_THREAD_DATA(cx)->gsnCache)
 #define JS_PROPERTY_CACHE(cx)   (JS_THREAD_DATA(cx)->propertyCache)
 #define JS_TRACE_MONITOR(cx)    (JS_THREAD_DATA(cx)->traceMonitor)
 #define JS_SCRIPTS_TO_GC(cx)    (JS_THREAD_DATA(cx)->scriptsToGC)
 
@@ -1034,26 +1073,96 @@ struct JSContext {
     InterpState         *interpState;
     VMSideExit          *bailExit;
 
     /* Used when calling natives from trace to root the vp vector. */
     uintN               nativeVpLen;
     jsval               *nativeVp;
 #endif
 
+#ifdef JS_THREADSAFE
+    inline void createDeallocatorTask() {
+        JSThreadData* tls = JS_THREAD_DATA(this);
+        JS_ASSERT(!tls->deallocatorTask);
+        if (runtime->deallocatorThread && !runtime->deallocatorThread->busy())
+            tls->deallocatorTask = new JSFreePointerListTask();
+    }
+
+    inline void submitDeallocatorTask() {
+        JSThreadData* tls = JS_THREAD_DATA(this);
+        if (tls->deallocatorTask) {
+            runtime->deallocatorThread->schedule(tls->deallocatorTask);
+            tls->deallocatorTask = NULL;
+        }
+    }
+#endif
+
     /* Call this after succesful malloc of memory for GC-related things. */
-    inline void
-    updateMallocCounter(size_t nbytes)
-    {
+    inline void updateMallocCounter(size_t nbytes) {
         size_t *pbytes, bytes;
 
         pbytes = &JS_THREAD_DATA(this)->gcMallocBytes;
         bytes = *pbytes;
         *pbytes = (size_t(-1) - bytes <= nbytes) ? size_t(-1) : bytes + nbytes;
     }
+
+    inline void* malloc(size_t bytes) {
+        JS_ASSERT(bytes != 0);
+        void *p = runtime->malloc(bytes);
+        if (!p) {
+            JS_ReportOutOfMemory(this);
+            return NULL;
+        }
+        updateMallocCounter(bytes);
+        return p;
+    }
+
+    inline void* calloc(size_t bytes) {
+        JS_ASSERT(bytes != 0);
+        void *p = runtime->calloc(bytes);
+        if (!p) {
+            JS_ReportOutOfMemory(this);
+            return NULL;
+        }
+        updateMallocCounter(bytes);
+        return p;
+    }
+
+    inline void* realloc(void* p, size_t bytes) {
+        void *orig = p;
+        p = runtime->realloc(p, bytes);
+        if (!p) {
+            JS_ReportOutOfMemory(this);
+            return NULL;
+        }
+        if (!orig)
+            updateMallocCounter(bytes);
+        return p;
+    }
+
+#ifdef JS_THREADSAFE
+    inline void free(void* p) {
+        if (!p)
+            return;
+        if (thread) {
+            JSFreePointerListTask* task = JS_THREAD_DATA(this)->deallocatorTask;
+            if (task) {
+                task->add(p);
+                return;
+            }
+        }
+        runtime->free(p);
+    }
+#else
+    inline void free(void* p) {
+        if (!p)
+            return;
+        runtime->free(p);
+    }
+#endif
 };
 
 #ifdef JS_THREADSAFE
 # define JS_THREAD_ID(cx)       ((cx)->thread ? (cx)->thread->id : 0)
 #endif
 
 #ifdef __cplusplus
 
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -1956,17 +1956,17 @@ date_toSource(JSContext *cx, uintN argc,
     bytes = JS_smprintf("(new %s(%s))", js_Date_str, numStr);
     if (!bytes) {
         JS_ReportOutOfMemory(cx);
         return JS_FALSE;
     }
 
     str = JS_NewString(cx, bytes, strlen(bytes));
     if (!str) {
-        free(bytes);
+        js_free(bytes);
         return JS_FALSE;
     }
     *vp = STRING_TO_JSVAL(str);
     return JS_TRUE;
 }
 #endif
 
 static JSBool
--- a/js/src/jsdate.h
+++ b/js/src/jsdate.h
@@ -119,11 +119,15 @@ js_DateSetSeconds(JSContext *cx, JSObjec
 extern JS_FRIEND_API(jsdouble)
 js_DateGetMsecSinceEpoch(JSContext *cx, JSObject *obj);
 
 typedef uint32 JSIntervalTime;
 
 extern JS_FRIEND_API(JSIntervalTime)
 js_IntervalNow();
 
+/* Date constructor native. Exposed only so the JIT can know its address. */
+JSBool
+js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
 JS_END_EXTERN_C
 
 #endif /* jsdate_h___ */
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -118,17 +118,17 @@ js_UntrapScriptCode(JSContext *cx, JSScr
                 size_t nbytes;
 
                 nbytes = script->length * sizeof(jsbytecode);
                 notes = SCRIPT_NOTES(script);
                 for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn))
                     continue;
                 nbytes += (sn - notes + 1) * sizeof *sn;
 
-                code = (jsbytecode *) JS_malloc(cx, nbytes);
+                code = (jsbytecode *) cx->malloc(nbytes);
                 if (!code)
                     break;
                 memcpy(code, script->code, nbytes);
                 JS_PURGE_GSN_CACHE(cx);
             }
             code[trap->pc - script->code] = trap->op;
         }
     }
@@ -150,22 +150,22 @@ JS_SetTrap(JSContext *cx, JSScript *scri
     DBG_LOCK(rt);
     trap = FindTrap(rt, script, pc);
     if (trap) {
         JS_ASSERT(trap->script == script && trap->pc == pc);
         JS_ASSERT(*pc == JSOP_TRAP);
     } else {
         sample = rt->debuggerMutations;
         DBG_UNLOCK(rt);
-        trap = (JSTrap *) JS_malloc(cx, sizeof *trap);
+        trap = (JSTrap *) cx->malloc(sizeof *trap);
         if (!trap)
             return JS_FALSE;
         trap->closure = NULL;
         if(!js_AddRoot(cx, &trap->closure, "trap->closure")) {
-            JS_free(cx, trap);
+            cx->free(trap);
             return JS_FALSE;
         }
         DBG_LOCK(rt);
         twin = (rt->debuggerMutations != sample)
                ? FindTrap(rt, script, pc)
                : NULL;
         if (twin) {
             junk = trap;
@@ -179,17 +179,17 @@ JS_SetTrap(JSContext *cx, JSScript *scri
             *pc = JSOP_TRAP;
         }
     }
     trap->handler = handler;
     trap->closure = closure;
     DBG_UNLOCK(rt);
     if (junk) {
         js_RemoveRoot(rt, &junk->closure);
-        JS_free(cx, junk);
+        cx->free(junk);
     }
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSOp)
 JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc)
 {
     JSRuntime *rt;
@@ -208,17 +208,17 @@ static void
 DestroyTrapAndUnlock(JSContext *cx, JSTrap *trap)
 {
     ++cx->runtime->debuggerMutations;
     JS_REMOVE_LINK(&trap->links);
     *trap->pc = (jsbytecode)trap->op;
     DBG_UNLOCK(cx->runtime);
 
     js_RemoveRoot(cx->runtime, &trap->closure);
-    JS_free(cx, trap);
+    cx->free(trap);
 }
 
 JS_PUBLIC_API(void)
 JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
              JSTrapHandler *handlerp, void **closurep)
 {
     JSTrap *trap;
 
@@ -408,17 +408,17 @@ DropWatchPointAndUnlock(JSContext *cx, J
         if (found) {
             sprop = scope->change(cx, sprop, 0, sprop->attrs,
                                   sprop->getter, wp->setter);
             if (!sprop)
                 ok = JS_FALSE;
         }
     }
 
-    JS_free(cx, wp);
+    cx->free(wp);
     return ok;
 }
 
 /*
  * NB: js_TraceWatchPoints does not acquire cx->runtime->debuggerLock, since
  * the debugger should never be racing with the GC (i.e., the debugger must
  * respect the request model).
  */
@@ -429,17 +429,17 @@ js_TraceWatchPoints(JSTracer *trc, JSObj
     JSWatchPoint *wp;
 
     rt = trc->context->runtime;
 
     for (wp = (JSWatchPoint *)rt->watchPointList.next;
          &wp->links != &rt->watchPointList;
          wp = (JSWatchPoint *)wp->links.next) {
         if (wp->object == obj) {
-            TRACE_SCOPE_PROPERTY(trc, wp->sprop);
+            wp->sprop->trace(trc);
             if ((wp->sprop->attrs & JSPROP_SETTER) && wp->setter) {
                 JS_CALL_OBJECT_TRACER(trc, js_CastAsObject(wp->setter),
                                       "wp->setter");
             }
             JS_SET_TRACING_NAME(trc, "wp->closure");
             js_CallValueTracerIfGCThing(trc, (jsval) wp->closure);
         }
     }
@@ -614,17 +614,17 @@ js_watch_set(JSContext *cx, JSObject *ob
                 }
                 if (script)
                     nslots += script->nslots;
 
                 if (injectFrame) {
                     if (nslots <= JS_ARRAY_LENGTH(smallv)) {
                         argv = smallv;
                     } else {
-                        argv = (jsval *) JS_malloc(cx, nslots * sizeof(jsval));
+                        argv = (jsval *) cx->malloc(nslots * sizeof(jsval));
                         if (!argv) {
                             DBG_LOCK(rt);
                             DropWatchPointAndUnlock(cx, wp, JSWP_HELD);
                             return JS_FALSE;
                         }
                     }
 
                     argv[0] = OBJECT_TO_JSVAL(closure);
@@ -646,17 +646,17 @@ js_watch_set(JSContext *cx, JSObject *ob
                         regs.pc = script->code + script->length
                                   - JSOP_STOP_LENGTH;
                         regs.sp = NULL;
                         frame.regs = &regs;
                         if (fun &&
                             JSFUN_HEAVYWEIGHT_TEST(fun->flags) &&
                             !js_GetCallObject(cx, &frame)) {
                             if (argv != smallv)
-                                JS_free(cx, argv);
+                                cx->free(argv);
                             DBG_LOCK(rt);
                             DropWatchPointAndUnlock(cx, wp, JSWP_HELD);
                             return JS_FALSE;
                         }
                     }
 
                     cx->fp = &frame;
                 }
@@ -674,17 +674,17 @@ js_watch_set(JSContext *cx, JSObject *ob
                     /* Evil code can cause us to have an arguments object. */
                     if (frame.callobj)
                         ok &= js_PutCallObject(cx, &frame);
                     if (frame.argsobj)
                         ok &= js_PutArgsObject(cx, &frame);
 
                     cx->fp = frame.down;
                     if (argv != smallv)
-                        JS_free(cx, argv);
+                        cx->free(argv);
                 }
             }
             DBG_LOCK(rt);
             return DropWatchPointAndUnlock(cx, wp, JSWP_HELD) && ok;
         }
     }
     DBG_UNLOCK(rt);
     return JS_TRUE;
@@ -820,17 +820,17 @@ JS_SetWatchPoint(JSContext *cx, JSObject
     if (!wp) {
         DBG_UNLOCK(rt);
         watcher = js_WrapWatchedSetter(cx, propid, sprop->attrs, sprop->setter);
         if (!watcher) {
             ok = JS_FALSE;
             goto out;
         }
 
-        wp = (JSWatchPoint *) JS_malloc(cx, sizeof *wp);
+        wp = (JSWatchPoint *) cx->malloc(sizeof *wp);
         if (!wp) {
             ok = JS_FALSE;
             goto out;
         }
         wp->handler = NULL;
         wp->closure = NULL;
         wp->object = obj;
         JS_ASSERT(sprop->setter != js_watch_set || pobj != obj);
@@ -1338,17 +1338,17 @@ JS_EvaluateInStackFrame(JSContext *cx, J
     size_t len = length;
 
     chars = js_InflateString(cx, bytes, &len);
     if (!chars)
         return JS_FALSE;
     length = (uintN) len;
     ok = JS_EvaluateUCInStackFrame(cx, fp, chars, length, filename, lineno,
                                    rval);
-    JS_free(cx, chars);
+    cx->free(chars);
 
     return ok;
 }
 
 /************************************************************************/
 
 /* XXXbe this all needs to be reworked to avoid requiring JSScope types. */
 
@@ -1464,17 +1464,17 @@ JS_GetPropertyDescArray(JSContext *cx, J
     scope = OBJ_SCOPE(obj);
     if (scope->entryCount == 0) {
         pda->length = 0;
         pda->array = NULL;
         return JS_TRUE;
     }
 
     n = scope->entryCount;
-    pd = (JSPropertyDesc *) JS_malloc(cx, (size_t)n * sizeof(JSPropertyDesc));
+    pd = (JSPropertyDesc *) cx->malloc((size_t)n * sizeof(JSPropertyDesc));
     if (!pd)
         return JS_FALSE;
     i = 0;
     for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
         if (scope->hadMiddleDelete() && !scope->has(sprop))
             continue;
         if (!js_AddRoot(cx, &pd[i].id, NULL))
             goto bad;
@@ -1506,17 +1506,17 @@ JS_PutPropertyDescArray(JSContext *cx, J
 
     pd = pda->array;
     for (i = 0; i < pda->length; i++) {
         js_RemoveRoot(cx->runtime, &pd[i].id);
         js_RemoveRoot(cx->runtime, &pd[i].value);
         if (pd[i].flags & JSPD_ALIAS)
             js_RemoveRoot(cx->runtime, &pd[i].alias);
     }
-    JS_free(cx, pd);
+    cx->free(pd);
 }
 
 /************************************************************************/
 
 JS_PUBLIC_API(JSBool)
 JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure)
 {
     rt->globalDebugHooks.debuggerHandler = handler;
@@ -1879,17 +1879,17 @@ js_DumpCallgrind(JSContext *cx, JSObject
     JSString *str;
     char *cstr;
 
     if (argc > 0 && JSVAL_IS_STRING(argv[0])) {
         str = JSVAL_TO_STRING(argv[0]);
         cstr = js_DeflateString(cx, str->chars(), str->length());
         if (cstr) {
             CALLGRIND_DUMP_STATS_AT(cstr);
-            JS_free(cx, cstr);
+            cx->free(cstr);
             return JS_TRUE;
         }
     }
     CALLGRIND_DUMP_STATS;
 
     return JS_TRUE;
 }
 
@@ -1957,17 +1957,17 @@ js_StartVtune(JSContext *cx, JSObject *o
     if (argc > 0 && JSVAL_IS_STRING(argv[0])) {
         str = JSVAL_TO_STRING(argv[0]);
         params.tb5Filename = js_DeflateString(cx, str->chars(), str->length());
     }
 
     status = VTStartSampling(&params);
 
     if (params.tb5Filename != default_filename)
-        JS_free(cx, params.tb5Filename);
+        cx->free(params.tb5Filename);
 
     if (status != 0) {
         if (status == VTAPI_MULTIPLE_RUNS)
             VTStopSampling(0);
         if (status < sizeof(vtuneErrorMessages))
             JS_ReportError(cx, "Vtune setup error: %s",
                            vtuneErrorMessages[status]);
         else
--- a/js/src/jsdhash.cpp
+++ b/js/src/jsdhash.cpp
@@ -106,23 +106,23 @@
 #define INCREMENT_RECURSION_LEVEL(table_)   JS_BEGIN_MACRO JS_END_MACRO
 #define DECREMENT_RECURSION_LEVEL(table_)   JS_BEGIN_MACRO JS_END_MACRO
 
 #endif /* defined(DEBUG) */
 
 JS_PUBLIC_API(void *)
 JS_DHashAllocTable(JSDHashTable *table, uint32 nbytes)
 {
-    return malloc(nbytes);
+    return js_malloc(nbytes);
 }
 
 JS_PUBLIC_API(void)
 JS_DHashFreeTable(JSDHashTable *table, void *ptr)
 {
-    free(ptr);
+    js_free(ptr);
 }
 
 JS_PUBLIC_API(JSDHashNumber)
 JS_DHashStringKey(JSDHashTable *table, const void *key)
 {
     JSDHashNumber h;
     const unsigned char *s;
 
@@ -175,17 +175,17 @@ JS_DHashClearEntryStub(JSDHashTable *tab
     memset(entry, 0, table->entrySize);
 }
 
 JS_PUBLIC_API(void)
 JS_DHashFreeStringKey(JSDHashTable *table, JSDHashEntryHdr *entry)
 {
     const JSDHashEntryStub *stub = (const JSDHashEntryStub *)entry;
 
-    free((void *) stub->key);
+    js_free((void *) stub->key);
     memset(entry, 0, table->entrySize);
 }
 
 JS_PUBLIC_API(void)
 JS_DHashFinalizeStub(JSDHashTable *table)
 {
 }
 
@@ -207,31 +207,31 @@ JS_DHashGetStubOps(void)
 }
 
 JS_PUBLIC_API(JSDHashTable *)
 JS_NewDHashTable(const JSDHashTableOps *ops, void *data, uint32 entrySize,
                  uint32 capacity)
 {
     JSDHashTable *table;
 
-    table = (JSDHashTable *) malloc(sizeof *table);
+    table = (JSDHashTable *) js_malloc(sizeof *table);
     if (!table)
         return NULL;
     if (!JS_DHashTableInit(table, ops, data, entrySize, capacity)) {
-        free(table);
+        js_free(table);
         return NULL;
     }
     return table;
 }
 
 JS_PUBLIC_API(void)
 JS_DHashTableDestroy(JSDHashTable *table)
 {
     JS_DHashTableFinish(table);
-    free(table);
+    js_free(table);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DHashTableInit(JSDHashTable *table, const JSDHashTableOps *ops, void *data,
                   uint32 entrySize, uint32 capacity)
 {
     int log2;
     uint32 nbytes;
--- a/js/src/jsdtoa.cpp
+++ b/js/src/jsdtoa.cpp
@@ -363,17 +363,17 @@ JS_dtobasestr(int base, double dinput)
     char *q;
     uint32 digit;
     U di;                /* d truncated to an integer */
     U df;                /* The fractional part of d */
 
     JS_ASSERT(base >= 2 && base <= 36);
 
     dval(d) = dinput;
-    buffer = (char*) malloc(DTOBASESTR_BUFFER_SIZE);
+    buffer = (char*) js_malloc(DTOBASESTR_BUFFER_SIZE);
     if (buffer) {
         p = buffer;
         if (dval(d) < 0.0
 #if defined(XP_WIN) || defined(XP_OS2)
             && !((word0(d) & Exp_mask) == Exp_mask && ((word0(d) & Frac_mask) || word1(d))) /* Visual C++ doesn't know how to compare against NaN */
 #endif
            ) {
             *p++ = '-';
@@ -407,17 +407,17 @@ JS_dtobasestr(int base, double dinput)
             Bigint *b = d2b(di, &e, &bits);
             if (!b)
                 goto nomem1;
             b = lshift(b, e);
             if (!b) {
               nomem1:
                 Bfree(b);
                 UNLOCK_DTOA();
-                free(buffer);
+                js_free(buffer);
                 return NULL;
             }
             do {
                 digit = divrem(b, base);
                 JS_ASSERT(digit < (uint32)base);
                 *p++ = BASEDIGIT(digit);
             } while (b->wds);
             Bfree(b);
@@ -444,17 +444,17 @@ JS_dtobasestr(int base, double dinput)
             if (!b) {
               nomem2:
                 Bfree(b);
                 Bfree(s);
                 if (mlo != mhi)
                     Bfree(mlo);
                 Bfree(mhi);
                 UNLOCK_DTOA();
-                free(buffer);
+                js_free(buffer);
                 return NULL;
             }
             JS_ASSERT(e < 0);
             /* At this point df = b * 2^e.  e must be less than zero because 0 < df < 1. */
 
             s2 = -(int32)(word0(d) >> Exp_shift1 & Exp_mask>>Exp_shift1);
 #ifndef Sudden_Underflow
             if (!s2)
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -107,20 +107,20 @@ JSCodeGenerator::JSCodeGenerator(JSCompi
 
 JSCodeGenerator::~JSCodeGenerator()
 {
     JS_ARENA_RELEASE(codePool, codeMark);
     JS_ARENA_RELEASE(notePool, noteMark);
 
     /* NB: non-null only after OOM. */
     if (spanDeps)
-        JS_free(compiler->context, spanDeps);
+        compiler->context->free(spanDeps);
 
     if (upvarMap.vector)
-        JS_free(compiler->context, upvarMap.vector);
+        compiler->context->free(upvarMap.vector);
 }
 
 static ptrdiff_t
 EmitCheck(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t delta)
 {
     jsbytecode *base, *limit, *next;
     ptrdiff_t offset, length;
     size_t incr, size;
@@ -544,17 +544,17 @@ AddSpanDep(JSContext *cx, JSCodeGenerato
     if (index + 1 == 0) {
         ReportStatementTooLarge(cx, cg);
         return JS_FALSE;
     }
 
     if ((index & (index - 1)) == 0 &&
         (!(sdbase = cg->spanDeps) || index >= SPANDEPS_MIN)) {
         size = sdbase ? SPANDEPS_SIZE(index) : SPANDEPS_SIZE_MIN / 2;
-        sdbase = (JSSpanDep *) JS_realloc(cx, sdbase, size + size);
+        sdbase = (JSSpanDep *) cx->realloc(sdbase, size + size);
         if (!sdbase)
             return JS_FALSE;
         cg->spanDeps = sdbase;
     }
 
     cg->numSpanDeps = index + 1;
     sd = cg->spanDeps + index;
     sd->top = pc - CG_BASE(cg);
@@ -1160,17 +1160,17 @@ OptimizeSpanDeps(JSContext *cx, JSCodeGe
 #endif
 
     /*
      * Reset so we optimize at most once -- cg may be used for further code
      * generation of successive, independent, top-level statements.  No jump
      * can span top-level statements, because JS lacks goto.
      */
     size = SPANDEPS_SIZE(JS_BIT(JS_CeilingLog2(cg->numSpanDeps)));
-    JS_free(cx, cg->spanDeps);
+    cx->free(cg->spanDeps);
     cg->spanDeps = NULL;
     FreeJumpTargets(cg, cg->jumpTargets);
     cg->jumpTargets = NULL;
     cg->numSpanDeps = cg->numJumpTargets = 0;
     cg->spanDepTodo = CG_OFFSET(cg);
     return JS_TRUE;
 }
 
@@ -1894,17 +1894,17 @@ MakeUpvarForEval(JSParseNode *pn, JSCode
         JS_ASSERT(ALE_INDEX(ale) == cg->upvarList.count - 1);
 
         uint32 *vector = cg->upvarMap.vector;
         uint32 length = cg->upvarMap.length;
 
         JS_ASSERT(ALE_INDEX(ale) <= length);
         if (ALE_INDEX(ale) == length) {
             length = 2 * JS_MAX(2, length);
-            vector = (uint32 *) JS_realloc(cx, vector, length * sizeof *vector);
+            vector = (uint32 *) cx->realloc(vector, length * sizeof *vector);
             if (!vector)
                 return false;
             cg->upvarMap.vector = vector;
             cg->upvarMap.length = length;
         }
 
         if (localKind != JSLOCAL_ARG)
             index += fun->nargs;
@@ -2192,17 +2192,17 @@ BindNameToSlot(JSContext *cx, JSCodeGene
                 return JS_FALSE;
             index = ALE_INDEX(ale);
             JS_ASSERT(index == cg->upvarList.count - 1);
 
             uint32 *vector = cg->upvarMap.vector;
             if (!vector) {
                 uint32 length = cg->lexdeps.count;
 
-                vector = (uint32 *) calloc(length, sizeof *vector);
+                vector = (uint32 *) js_calloc(length * sizeof *vector);
                 if (!vector) {
                     JS_ReportOutOfMemory(cx);
                     return JS_FALSE;
                 }
                 cg->upvarMap.vector = vector;
                 cg->upvarMap.length = length;
             }
 
@@ -3139,36 +3139,35 @@ EmitSwitch(JSContext *cx, JSCodeGenerato
                 if (!intmap &&
                     i < (INTMAP_LENGTH << JS_BITS_PER_WORD_LOG2)) {
                     intmap = intmap_space;
                     intmap_bitlen = INTMAP_LENGTH << JS_BITS_PER_WORD_LOG2;
                 } else {
                     /* Just grab 8K for the worst-case bitmap. */
                     intmap_bitlen = JS_BIT(16);
                     intmap = (jsbitmap *)
-                        JS_malloc(cx,
-                                  (JS_BIT(16) >> JS_BITS_PER_WORD_LOG2)
-                                  * sizeof(jsbitmap));
+                        cx->malloc((JS_BIT(16) >> JS_BITS_PER_WORD_LOG2)
+                                   * sizeof(jsbitmap));
                     if (!intmap) {
                         JS_ReportOutOfMemory(cx);
                         return JS_FALSE;
                     }
                 }
                 memset(intmap, 0, intmap_bitlen >> JS_BITS_PER_BYTE_LOG2);
             }
             if (JS_TEST_BIT(intmap, i)) {
                 switchOp = JSOP_LOOKUPSWITCH;
                 continue;
             }
             JS_SET_BIT(intmap, i);
         }
 
       release:
         if (intmap && intmap != intmap_space)
-            JS_free(cx, intmap);
+            cx->free(intmap);
         if (!ok)
             return JS_FALSE;
 
         /*
          * Compute table length and select lookup instead if overlarge or
          * more than half-sparse.
          */
         if (switchOp == JSOP_TABLESWITCH) {
@@ -3302,17 +3301,17 @@ EmitSwitch(JSContext *cx, JSCodeGenerato
 
             /*
              * Use malloc to avoid arena bloat for programs with many switches.
              * We free table if non-null at label out, so all control flow must
              * exit this function through goto out or goto bad.
              */
             if (tableLength != 0) {
                 tableSize = (size_t)tableLength * sizeof *table;
-                table = (JSParseNode **) JS_malloc(cx, tableSize);
+                table = (JSParseNode **) cx->malloc(tableSize);
                 if (!table)
                     return JS_FALSE;
                 memset(table, 0, tableSize);
                 for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
                     if (pn3->pn_type == TOK_DEFAULT)
                         continue;
                     i = JSVAL_TO_INT(pn3->pn_val);
                     i -= low;
@@ -3470,17 +3469,17 @@ EmitSwitch(JSContext *cx, JSCodeGenerato
             if (!ok)
                 goto out;
             pc += JUMP_OFFSET_LEN;
         }
     }
 
 out:
     if (table)
-        JS_free(cx, table);
+        cx->free(table);
     if (ok) {
         ok = js_PopStatementCG(cx, cg);
 
 #if JS_HAS_BLOCK_SCOPE
         if (ok && pn->pn_right->pn_type == TOK_LEXICALSCOPE)
             EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, count);
 #endif
     }
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -159,17 +159,17 @@ CopyErrorReport(JSContext *cx, JSErrorRe
     }
 
     /*
      * The mallocSize can not overflow since it represents the sum of the
      * sizes of already allocated objects.
      */
     mallocSize = sizeof(JSErrorReport) + argsArraySize + argsCopySize +
                  ucmessageSize + uclinebufSize + linebufSize + filenameSize;
-    cursor = (uint8 *)JS_malloc(cx, mallocSize);
+    cursor = (uint8 *)cx->malloc(mallocSize);
     if (!cursor)
         return NULL;
 
     copy = (JSErrorReport *)cursor;
     memset(cursor, 0, sizeof(JSErrorReport));
     cursor += sizeof(JSErrorReport);
 
     if (argsArraySize != 0) {
@@ -296,17 +296,17 @@ InitExnPrivate(JSContext *cx, JSObject *
     overflow = (stackDepth > ((size_t)-1 - size) / sizeof(JSStackTraceElem));
     size += stackDepth * sizeof(JSStackTraceElem);
     overflow |= (valueCount > ((size_t)-1 - size) / sizeof(jsval));
     size += valueCount * sizeof(jsval);
     if (overflow) {
         js_ReportAllocationOverflow(cx);
         return JS_FALSE;
     }
-    priv = (JSExnPrivate *)JS_malloc(cx, size);
+    priv = (JSExnPrivate *)cx->malloc(size);
     if (!priv)
         return JS_FALSE;
 
     /*
      * We initialize errorReport with a copy of report after setting the
      * private slot, to prevent GC accessing a junk value we clear the field
      * here.
      */
@@ -412,18 +412,18 @@ exn_trace(JSTracer *trc, JSObject *obj)
 static void
 exn_finalize(JSContext *cx, JSObject *obj)
 {
     JSExnPrivate *priv;
 
     priv = GetExnPrivate(cx, obj);
     if (priv) {
         if (priv->errorReport)
-            JS_free(cx, priv->errorReport);
-        JS_free(cx, priv);
+            cx->free(priv->errorReport);
+        cx->free(priv);
     }
 }
 
 static JSBool
 exn_enumerate(JSContext *cx, JSObject *obj)
 {
     JSAtomState *atomState;
     uintN i;
@@ -581,17 +581,17 @@ StackTraceToString(JSContext *cx, JSExnP
 
 #define APPEND_CHAR_TO_STACK(c)                                               \
     JS_BEGIN_MACRO                                                            \
         if (stacklen == stackmax) {                                           \
             void *ptr_;                                                       \
             if (stackmax >= STACK_LENGTH_LIMIT)                               \
                 goto done;                                                    \
             stackmax = stackmax ? 2 * stackmax : 64;                          \
-            ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar));   \
+            ptr_ = cx->realloc(stackbuf, (stackmax+1) * sizeof(jschar));      \
             if (!ptr_)                                                        \
                 goto bad;                                                     \
             stackbuf = (jschar *) ptr_;                                       \
         }                                                                     \
         stackbuf[stacklen++] = (c);                                           \
     JS_END_MACRO
 
 #define APPEND_STRING_TO_STACK(str)                                           \
@@ -603,17 +603,17 @@ StackTraceToString(JSContext *cx, JSExnP
         str_->getCharsAndLength(chars_, length_);                             \
         if (length_ > stackmax - stacklen) {                                  \
             void *ptr_;                                                       \
             if (stackmax >= STACK_LENGTH_LIMIT ||                             \
                 length_ >= STACK_LENGTH_LIMIT - stacklen) {                   \
                 goto done;                                                    \
             }                                                                 \
             stackmax = JS_BIT(JS_CeilingLog2(stacklen + length_));            \
-            ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar));   \
+            ptr_ = cx->realloc(stackbuf, (stackmax+1) * sizeof(jschar));      \
             if (!ptr_)                                                        \
                 goto bad;                                                     \
             stackbuf = (jschar *) ptr_;                                       \
         }                                                                     \
         js_strncpy(stackbuf + stacklen, chars_, length_);                     \
         stacklen += length_;                                                  \
     JS_END_MACRO
 
@@ -654,29 +654,29 @@ StackTraceToString(JSContext *cx, JSExnP
         return cx->runtime->emptyString;
     }
     if (stacklen < stackmax) {
         /*
          * Realloc can fail when shrinking on some FreeBSD versions, so
          * don't use JS_realloc here; simply let the oversized allocation
          * be owned by the string in that rare case.
          */
-        void *shrunk = JS_realloc(cx, stackbuf, (stacklen+1) * sizeof(jschar));
+        void *shrunk = cx->realloc(stackbuf, (stacklen+1) * sizeof(jschar));
         if (shrunk)
             stackbuf = (jschar *) shrunk;
     }
 
     stackbuf[stacklen] = 0;
     str = js_NewString(cx, stackbuf, stacklen);
     if (str)
         return str;
 
   bad:
     if (stackbuf)
-        JS_free(cx, stackbuf);
+        cx->free(stackbuf);
     return NULL;
 }
 
 /* XXXbe Consolidate the ugly truth that we don't treat filename as UTF-8
          with these two functions. */
 static JSString *
 FilenameToString(JSContext *cx, const char *filename)
 {
@@ -795,32 +795,32 @@ exn_toString(JSContext *cx, uintN argc, 
         return JS_FALSE;
     message = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v)
                                  : cx->runtime->emptyString;
 
     if (message->length() != 0) {
         name_length = name->length();
         message_length = message->length();
         length = (name_length ? name_length + 2 : 0) + message_length;
-        cp = chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+        cp = chars = (jschar *) cx->malloc((length + 1) * sizeof(jschar));
         if (!chars)
             return JS_FALSE;
 
         if (name_length) {
             js_strncpy(cp, name->chars(), name_length);
             cp += name_length;
             *cp++ = ':'; *cp++ = ' ';
         }
         js_strncpy(cp, message->chars(), message_length);
         cp += message_length;
         *cp = 0;
 
         result = js_NewString(cx, chars, length);
         if (!result) {
-            JS_free(cx, chars);
+            cx->free(chars);
             return JS_FALSE;
         }
     } else {
         result = name;
     }
 
     *vp = STRING_TO_JSVAL(result);
     return JS_TRUE;
@@ -910,17 +910,17 @@ exn_toSource(JSContext *cx, uintN argc, 
             /*
              * no filename, but have line number,
              * need to append ``, "", {lineno_as_str}''
              */
             length += 6 + lineno_length;
         }
     }
 
-    cp = chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+    cp = chars = (jschar *) cx->malloc((length + 1) * sizeof(jschar));
     if (!chars) {
         ok = JS_FALSE;
         goto out;
     }
 
     *cp++ = '('; *cp++ = 'n'; *cp++ = 'e'; *cp++ = 'w'; *cp++ = ' ';
     js_strncpy(cp, name->chars(), name_length);
     cp += name_length;
@@ -950,17 +950,17 @@ exn_toSource(JSContext *cx, uintN argc, 
         js_strncpy(cp, lineno_as_str->chars(), lineno_length);
         cp += lineno_length;
     }
 
     *cp++ = ')'; *cp++ = ')'; *cp = 0;
 
     result = js_NewString(cx, chars, length);
     if (!result) {
-        JS_free(cx, chars);
+        cx->free(chars);
         ok = JS_FALSE;
         goto out;
     }
     *vp = STRING_TO_JSVAL(result);
     ok = JS_TRUE;
 
 out:
     JS_POP_TEMP_ROOT(cx, &tvr);
--- a/js/src/jsfile.cpp
+++ b/js/src/jsfile.cpp
@@ -291,17 +291,17 @@ js_isAbsolute(const char *name)
 /*
  * Concatenates base and name to produce a valid filename.
  * Returned string must be freed.
 */
 static char*
 js_combinePath(JSContext *cx, const char *base, const char *name)
 {
     int len = strlen(base);
-    char* result = JS_malloc(cx, len + strlen(name) + 2);
+    char* result = cx->malloc(len + strlen(name) + 2);
 
     if (!result)
         return NULL;
 
     strcpy(result, base);
 
     if (base[len - 1] != FILESEPARATOR && base[len - 1] != FILESEPARATOR2) {
         result[len] = FILESEPARATOR;
@@ -330,17 +330,17 @@ js_fileBaseName(JSContext *cx, const cha
 
     /* Now find the next separator. */
     while (index >= 0 && pathname[index] != FILESEPARATOR &&
                          pathname[index] != FILESEPARATOR2) {
         --index;
     }
 
     /* Allocate and copy. */
-    result = JS_malloc(cx, aux - index + 1);
+    result = cx->malloc(aux - index + 1);
     if (!result)
         return NULL;
     strncpy(result, pathname + index + 1, aux - index);
     result[aux - index] = '\0';
     return result;
 }
 
 /*
@@ -361,17 +361,17 @@ js_fileDirectoryName(JSContext *cx, cons
     while (cp >= pathname) {
         if (*cp != FILESEPARATOR && *cp != FILESEPARATOR2)
             break;
         --cp;
     }
 
     if (cp < pathname && end != pathname) {
         /* There were just /s, return the root. */
-        result = JS_malloc(cx, 1 + 1); /* The separator + trailing NUL. */
+        result = cx->malloc(1 + 1); /* The separator + trailing NUL. */
         result[0] = FILESEPARATOR;
         result[1] = '\0';
         return result;
     }
 
     /* Now chop off the last portion. */
     while (cp >= pathname) {
         if (*cp == FILESEPARATOR || *cp == FILESEPARATOR2)
@@ -383,30 +383,30 @@ js_fileDirectoryName(JSContext *cx, cons
     if (cp < pathname) {
         /* It is, return "pathname/". */
         if (end[-1] == FILESEPARATOR || end[-1] == FILESEPARATOR2) {
             /* Already has its terminating /. */
             return JS_strdup(cx, pathname);
         }
 
         pathsize = end - pathname + 1;
-        result = JS_malloc(cx, pathsize + 1);
+        result = cx->malloc(pathsize + 1);
         if (!result)
             return NULL;
 
         strcpy(result, pathname);
         result[pathsize - 1] = FILESEPARATOR;
         result[pathsize] = '\0';
 
         return result;
     }
 
     /* Return everything up to and including the seperator. */
     pathsize = cp - pathname + 1;
-    result = JS_malloc(cx, pathsize + 1);
+    result = cx->malloc(pathsize + 1);
     if (!result)
         return NULL;
 
     strncpy(result, pathname, pathsize);
     result[pathsize] = '\0';
 
     return result;
 }
@@ -457,41 +457,41 @@ js_canonicalPath(JSContext *cx, char *ol
 
     /* This is probably optional */
 	/* Remove possible spaces in the beginning and end */
     while (i < j && path[i] == ' ')
         i++;
     while (j >= 0 && path[j] == ' ')
         j--;
 
-    tmp = JS_malloc(cx, j-i+2);
+    tmp = cx->malloc(j-i+2);
     if (!tmp)
         return NULL;
 
     strncpy(tmp, path + i, j - i + 1);
     tmp[j - i + 1] = '\0';
 
     path = tmp;
 
     /* Pipe support. */
     if (js_filenameHasAPipe(path))
         return path;
 
     /* file:// support. */
     if (!strncmp(path, URL_PREFIX, strlen(URL_PREFIX))) {
         tmp = js_canonicalPath(cx, path + strlen(URL_PREFIX));
-        JS_free(cx, path);
+        cx->free(path);
         return tmp;
     }
 
     if (!js_isAbsolute(path)) {
         tmp = js_absolutePath(cx, path);
         if (!tmp)
             return NULL;
-        JS_free(cx, path);
+        cx->free(path);
         path = tmp;
     }
 
     result = JS_strdup(cx, "");
 
     current = path;
 
     base = js_fileBaseName(cx, current);
@@ -500,61 +500,61 @@ js_canonicalPath(JSContext *cx, char *ol
     while (strcmp(dir, current)) {
         if (!strcmp(base, "..")) {
             back++;
         } else {
             if (back > 0) {
                 back--;
             } else {
                 tmp = result;
-                result = JS_malloc(cx, strlen(base) + 1 + strlen(tmp) + 1);
+                result = cx->malloc(strlen(base) + 1 + strlen(tmp) + 1);
                 if (!result)
                     goto out;
 
                 strcpy(result, base);
                 c = strlen(result);
                 if (*tmp) {
                     result[c] = FILESEPARATOR;
                     result[c + 1] = '\0';
                     strcat(result, tmp);
                 }
-                JS_free(cx, tmp);
+                cx->free(tmp);
             }
         }
-        JS_free(cx, current);
-        JS_free(cx, base);
+        cx->free(current);
+        cx->free(base);
         current = dir;
         base =  js_fileBaseName(cx, current);
         dir = js_fileDirectoryName(cx, current);
     }
 
     tmp = result;
-    result = JS_malloc(cx, strlen(dir)+1+strlen(tmp)+1);
+    result = cx->malloc(strlen(dir) + 1 + strlen(tmp) + 1);
     if (!result)
         goto out;
 
     strcpy(result, dir);
     c = strlen(result);
     if (tmp[0]!='\0') {
         if ((result[c-1]!=FILESEPARATOR)&&(result[c-1]!=FILESEPARATOR2)) {
             result[c] = FILESEPARATOR;
             result[c+1] = '\0';
         }
         strcat(result, tmp);
     }
 
 out:
     if (tmp)
-        JS_free(cx, tmp);
+        cx->free(tmp);
     if (dir)
-        JS_free(cx, dir);
+        cx->free(dir);
     if (base)
-        JS_free(cx, base);
+        cx->free(base);
     if (current)
-        JS_free(cx, current);
+        cx->free(current);
 
     return result;
 }
 
 /* -------------------------- Text conversion ------------------------------- */
 /* The following is ripped from libi18n/unicvt.c and include files.. */
 
 /*
@@ -748,17 +748,17 @@ js_FileHasOption(JSContext *cx, const ch
                 found = atoi(equal + 1);
         }
         if (equal) *equal = '=';
         if (comma) *comma = ',';
         if (found || !comma)
             break;
         current = comma + 1;
     }
-    JS_free(cx, options);
+    cx->free(options);
     return found;
 }
 
 /* empty the buffer */
 static void
 js_ResetBuffers(JSFile * file)
 {
     file->charBufferUsed = JS_FALSE;
@@ -833,30 +833,30 @@ js_FileRead(JSContext *cx, JSFile *file,
         buf[0] = file->charBuffer;
         buf++;
         len--;
         file->charBufferUsed = JS_FALSE;
     }
 
     switch (mode) {
       case ASCII:
-        aux = (unsigned char*)JS_malloc(cx, len);
+        aux = (unsigned char*)cx->malloc(len);
         if (!aux)
             return 0;
 
         count = js_BufferedRead(file, aux, len);
         if (count == -1) {
-            JS_free(cx, aux);
+            cx->free(aux);
             return 0;
         }
 
         for (i = 0; i < len; i++)
             buf[i] = (jschar)aux[i];
 
-        JS_free(cx, aux);
+        cx->free(aux);
         break;
 
       case UTF8:
         remainder = 0;
         for (count = 0;count<len;count++) {
             i = js_BufferedRead(file, utfbuf+remainder, 3-remainder);
             if (i<=0) {
                 return count;
@@ -972,56 +972,56 @@ static int32
 js_FileWrite(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode)
 {
     unsigned char   *aux;
     int32           count = 0, i, j;
     unsigned char   *utfbuf;
 
     switch (mode) {
       case ASCII:
-        aux = (unsigned char*)JS_malloc(cx, len);
+        aux = (unsigned char*)cx->malloc(len);
         if (!aux)
             return 0;
 
         for (i = 0; i<len; i++)
             aux[i] = buf[i] % 256;
 
         count = (!file->isNative)
                 ? PR_Write(file->handle, aux, len)
                 : fwrite(aux, 1, len, file->nativehandle);
 
         if (count==-1) {
-            JS_free(cx, aux);
+            cx->free(aux);
             return 0;
         }
 
-        JS_free(cx, aux);
+        cx->free(aux);
         break;
 
       case UTF8:
-        utfbuf = (unsigned char*)JS_malloc(cx, len*3);
+        utfbuf = (unsigned char*)cx->malloc(len*3);
         if (!utfbuf)  return 0;
         i = 0;
         for (count = 0;count<len;count++) {
             j = one_ucs2_to_utf8_char(utfbuf+i, utfbuf+len*3, buf[count]);
             if (j==-1) {
-                JS_free(cx, utfbuf);
+                cx->free(utfbuf);
                 return 0;
             }
             i+=j;
         }
         j = (!file->isNative)
             ? PR_Write(file->handle, utfbuf, i)
             : fwrite(utfbuf, 1, i, file->nativehandle);
 
         if (j<i) {
-            JS_free(cx, utfbuf);
+            cx->free(utfbuf);
             return 0;
         }
-        JS_free(cx, utfbuf);
+        cx->free(utfbuf);
         break;
 
       case UCS2:
         count = (!file->isNative)
                 ? PR_Write(file->handle, buf, len*2) >> 1
                 : fwrite(buf, 1, len*2, file->nativehandle) >> 1;
 
         if (count == -1)
@@ -1174,23 +1174,23 @@ js_parent(JSContext *cx, JSFile *file, j
         return JS_FALSE;
 
     /* If the directory is equal to the original path, we're at the root. */
     if (!strcmp(file->path, str)) {
         *resultp = JSVAL_NULL;
     } else {
         JSObject *obj = js_NewFileObject(cx, str);
         if (!obj) {
-            JS_free(cx, str);
+            cx->free(str);
             return JS_FALSE;
         }
         *resultp = OBJECT_TO_JSVAL(obj);
     }
 
-    JS_free(cx, str);
+    cx->free(str);
     return JS_TRUE;
 }
 
 static JSBool
 js_name(JSContext *cx, JSFile *file, jsval *vp)
 {
     char *name;
     JSString *str;
@@ -1201,17 +1201,17 @@ js_name(JSContext *cx, JSFile *file, jsv
     }
 
     name = js_fileBaseName(cx, file->path);
     if (!name)
         return JS_FALSE;
 
     str = JS_NewString(cx, name, strlen(name));
     if (!str) {
-        JS_free(cx, name);
+        cx->free(name);
         return JS_FALSE;
     }
 
     *vp = STRING_TO_JSVAL(str);
     return JS_TRUE;
 }
 
 /* ------------------------------ File object methods ---------------------------- */
@@ -1348,41 +1348,41 @@ file_open(JSContext *cx, JSObject *obj, 
                 /* open(SPOOLER, "| cat -v | lpr -h 2>/dev/null") -- pipe for writing */
                 pipemode[i++] = 'r';
 #ifndef XP_UNIX
                 pipemode[i++] = file->type==UTF8 ? 'b' : 't';
 #endif
                 pipemode[i++] = '\0';
                 file->nativehandle = POPEN(&file->path[1], pipemode);
             } else if(file->path[len-1] == PIPE_SYMBOL) {
-                char *command = JS_malloc(cx, len);
+                char *command = cx->malloc(len);
 
                 strncpy(command, file->path, len-1);
                 command[len-1] = '\0';
                 /* open(STATUS, "netstat -an 2>&1 |") */
                 pipemode[i++] = 'w';
 #ifndef XP_UNIX
                 pipemode[i++] = file->type==UTF8 ? 'b' : 't';
 #endif
                 pipemode[i++] = '\0';
                 file->nativehandle = POPEN(command, pipemode);
-                JS_free(cx, command);
+                cx->free(command);
             }
             /* set the flags */
             file->isNative = JS_TRUE;
             file->isPipe  = JS_TRUE;
             file->hasRandomAccess = JS_FALSE;
         }
     } else {
         /* TODO: what about the permissions?? Java ignores the problem... */
         file->handle = PR_Open(file->path, mask, 0644);
     }
 
     js_ResetBuffers(file);
-    JS_free(cx, mode);
+    cx->free(mode);
     mode = NULL;
 
     /* Set the open flag and return result */
     if (file->handle == NULL && file->nativehandle == NULL) {
         file->isOpen = JS_FALSE;
 
         JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
                              JSFILEMSG_OP_FAILED, "open", file->path);
@@ -1391,17 +1391,17 @@ file_open(JSContext *cx, JSObject *obj, 
 
 good:
     file->isOpen = JS_TRUE;
     *rval = JSVAL_TRUE;
     return JS_TRUE;
 
 out:
     if(mode)
-        JS_free(cx, mode);
+        cx->free(mode);
     return JS_FALSE;
 }
 
 static JSBool
 file_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
     JSFile  *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
 
@@ -1506,39 +1506,39 @@ file_copyTo(JSContext *cx, JSObject *obj
             JSFILEMSG_OP_FAILED, "open", dest);
         goto out;
     }
 
     if ((size=js_size(cx, file))==JSVAL_VOID) {
         goto out;
     }
 
-    buffer = JS_malloc(cx, size);
+    buffer = cx->malloc(size);
 
     count = INT_TO_JSVAL(PR_Read(file->handle, buffer, size));
 
     /* reading panic */
     if (count!=size) {
-        JS_free(cx, buffer);
+        cx->free(buffer);
         JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
               JSFILEMSG_COPY_READ_ERROR, file->path);
         goto out;
     }
 
     count = INT_TO_JSVAL(PR_Write(handle, buffer, JSVAL_TO_INT(size)));
 
     /* writing panic */
     if (count!=size) {
-        JS_free(cx, buffer);
+        cx->free(buffer);
         JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
               JSFILEMSG_COPY_WRITE_ERROR, file->path);
         goto out;
     }
 
-    JS_free(cx, buffer);
+    cx->free(buffer);
 
 	if(!fileInitiallyOpen){
 		if(!file_close(cx, obj, 0, NULL, rval)) goto out;
 	}
 
     if(PR_Close(handle)!=PR_SUCCESS){
         JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
               JSFILEMSG_OP_FAILED, "close", dest);
@@ -1572,17 +1572,17 @@ file_renameTo(JSContext *cx, JSObject *o
     JSFILE_CHECK_ONE_ARG("renameTo");
     JSFILE_CHECK_NATIVE("renameTo");
     JSFILE_CHECK_CLOSED("renameTo");
 
     dest = RESOLVE_PATH(cx, JS_GetStringBytes(JS_ValueToString(cx, argv[0])));
 
     if (PR_Rename(file->path, dest)==PR_SUCCESS){
         /* copy the new filename */
-        JS_free(cx, file->path);
+        cx->free(file->path);
         file->path = dest;
         *rval = JSVAL_TRUE;
         return JS_TRUE;
     }else{
         JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
             JSFILEMSG_RENAME_FAILED, file->path, dest);
         goto out;
     }
@@ -1724,27 +1724,27 @@ file_read(JSContext *cx, JSObject *obj, 
     if (!JS_ValueToInt32(cx, argv[0], &want)){
         JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
             JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, "read", argv[0]);
         goto out;
     }
 
     /* want = (want>262144)?262144:want; * arbitrary size limitation */
 
-    buf = JS_malloc(cx, want*sizeof buf[0]);
+    buf = cx->malloc(want*sizeof buf[0]);
     if (!buf)  goto out;
 
     count =  js_FileRead(cx, file, buf, want, file->type);
     if (count>0) {
         str = JS_NewUCStringCopyN(cx, buf, count);
         *rval = STRING_TO_JSVAL(str);
-        JS_free(cx, buf);
+        cx->free(buf);
         return JS_TRUE;
     } else {
-        JS_free(cx, buf);
+        cx->free(buf);
         goto out;
     }
 out:
     *rval = JSVAL_FALSE;
     return JS_FALSE;
 }
 
 static JSBool
@@ -1755,17 +1755,17 @@ file_readln(JSContext *cx, JSObject *obj
     jschar      *buf = NULL, *tmp;
     int32       offset, read;
     intN        room;
     jschar      data, data2;
 
     SECURITY_CHECK(cx, NULL, "readln", file);
     JSFILE_CHECK_READ;
 
-    buf = JS_malloc(cx, MAX_LINE_LENGTH * sizeof data);
+    buf = cx->malloc(MAX_LINE_LENGTH * sizeof data);
     if (!buf)
         return JS_FALSE;
 
     room = MAX_LINE_LENGTH - 1;
     offset = 0;
 
     for (;;) {
         read = js_FileRead(cx, file, &data, 1, file->type);
@@ -1787,18 +1787,17 @@ file_readln(JSContext *cx, JSObject *obj
             }
 
             /* Fall through. */
           case '\n':
             goto done;
 
           default:
             if (--room < 0) {
-                tmp = JS_realloc(cx, buf,
-                                 (offset + MAX_LINE_LENGTH) * sizeof data);
+                tmp = cx->realloc(buf, (offset + MAX_LINE_LENGTH) * sizeof data);
                 if (!tmp)
                     goto out;
 
                 room = MAX_LINE_LENGTH - 1;
                 buf = tmp;
             }
 
             buf[offset++] = data;
@@ -1809,30 +1808,30 @@ file_readln(JSContext *cx, JSObject *obj
 eof:
     if (offset == 0) {
         *rval = JSVAL_NULL;
         return JS_TRUE;
     }
 
 done:
     buf[offset] = 0;
-    tmp = JS_realloc(cx, buf, (offset + 1) * sizeof data);
+    tmp = cx->realloc(buf, (offset + 1) * sizeof data);
     if (!tmp)
         goto out;
 
     str = JS_NewUCString(cx, tmp, offset);
     if (!str)
         goto out;
 
     *rval = STRING_TO_JSVAL(str);
     return JS_TRUE;
 
 out:
     if (buf)
-        JS_free(cx, buf);
+        cx->free(buf);
 
     return JS_FALSE;
 }
 
 static JSBool
 file_readAll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
     JSFile      *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
@@ -1975,17 +1974,17 @@ file_list(JSContext *cx, JSObject *obj, 
             if (v==JSVAL_FALSE) {
                 continue;
             }
         }
 
         filePath = js_combinePath(cx, file->path, (char*)entry->name);
 
         eachFile = js_NewFileObject(cx, filePath);
-        JS_free(cx, filePath);
+        cx->free(filePath);
         if (!eachFile){
             JS_ReportWarning(cx, "File %s cannot be retrieved", filePath);
             continue;
         }
         v = OBJECT_TO_JSVAL(eachFile);
         JS_SetElement(cx, array, len, &v);
         JS_SetProperty(cx, array, entry->name, &v);
         len++;
@@ -2012,36 +2011,36 @@ file_mkdir(JSContext *cx, JSObject *obj,
     JSFILE_CHECK_ONE_ARG("mkdir");
     JSFILE_CHECK_NATIVE("mkdir");
 
     /* if the current file is not a directory, find out the directory name */
     if (!js_isDirectory(cx, file)) {
         char        *dir = js_fileDirectoryName(cx, file->path);
         JSObject    *dirObj = js_NewFileObject(cx, dir);
 
-        JS_free(cx, dir);
+        cx->free(dir);
 
         /* call file_mkdir with the right set of parameters if needed */
         if (file_mkdir(cx, dirObj, argc, argv, rval))
 			return JS_TRUE;
 		else
             goto out;
     }else{
         char *dirName = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
         char *fullName;
 
         fullName = js_combinePath(cx, file->path, dirName);
         if (PR_MkDir(fullName, 0755)==PR_SUCCESS){
             *rval = JSVAL_TRUE;
-            JS_free(cx, fullName);
+            cx->free(fullName);
             return JS_TRUE;
         }else{
             JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
                 JSFILEMSG_OP_FAILED, "mkdir", fullName);
-            JS_free(cx, fullName);
+            cx->free(fullName);
             goto out;
         }
     }
 out:
     *rval = JSVAL_FALSE;
     return JS_FALSE;
 }
 
@@ -2072,17 +2071,17 @@ file_toURL(JSContext *cx, JSObject *obj,
     sprintf(url, "file://%s", file->path);
 
     len = strlen(url);
     urlChars = js_InflateString(cx, url, &len);
     if (!urlChars)
         return JS_FALSE;
     str = js_NewString(cx, urlChars, len);
     if (!str) {
-        JS_free(cx, urlChars);
+        cx->free(urlChars);
         return JS_FALSE;
     }
     *rval = STRING_TO_JSVAL(str);
 
     /* TODO: js_escape in jsstr.h may go away at some point */
     return js_str_escape(cx, obj, 0, rval, rval);
 
 out:
@@ -2099,43 +2098,43 @@ file_finalize(JSContext *cx, JSObject *o
     if(file) {
         /* Close the file before exiting. */
         if(file->isOpen && !file->isNative) {
             jsval vp;
             file_close(cx, obj, 0, NULL, &vp);
         }
 
         if (file->path)
-            JS_free(cx, file->path);
-
-        JS_free(cx, file);
+            cx->free(file->path);
+
+        cx->free(file);
     }
 }
 
 /*
     Allocates memory for the file object, sets fields to defaults.
 */
 static JSFile*
 file_init(JSContext *cx, JSObject *obj, char *bytes)
 {
     JSFile *file;
 
-    file = JS_malloc(cx, sizeof *file);
+    file = cx->malloc(sizeof *file);
     if (!file)
         return NULL;
     memset(file, 0 , sizeof *file);
 
     js_ResetAttributes(file);
 
     file->path = RESOLVE_PATH(cx, bytes);
 
     if (!JS_SetPrivate(cx, obj, file)) {
         JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
                              JSFILEMSG_CANNOT_SET_PRIVATE_FILE, file->path);
-        JS_free(cx, file);
+        cx->free(file);
         return NULL;
     }
 
     return file;
 }
 
 /* Returns a JSObject. This function is globally visible */
 JS_PUBLIC_API(JSObject*)
@@ -2171,17 +2170,17 @@ js_NewFileObjectFromFILE(JSContext *cx, 
     }
     file = file_init(cx, obj, filename);
     if(!file) return NULL;
 
     file->nativehandle = nativehandle;
 
     /* free result of RESOLVE_PATH from file_init. */
     JS_ASSERT(file->path != NULL);
-    JS_free(cx, file->path);
+    cx->free(file->path);
 
     file->path = strdup(filename);
     file->isOpen = open;
     file->mode = mode;
     file->hasRandomAccess = randomAccess;
     file->isNative = JS_TRUE;
     return obj;
 }
@@ -2394,17 +2393,17 @@ file_getProperty(JSContext *cx, JSObject
         default:
             JS_ReportWarning(cx, "Unsupported file type %d, proceeding",
                 file->type);
         }
         break;
     case FILE_MODE:
         SECURITY_CHECK(cx, NULL, "mode", file);
         JSFILE_CHECK_OPEN("mode");
-        bytes = JS_malloc(cx, MODE_SIZE);
+        bytes = cx->malloc(MODE_SIZE);
         bytes[0] = '\0';
         flag = JS_FALSE;
 
         if ((file->mode&PR_RDONLY)==PR_RDONLY) {
             if (flag) strcat(bytes, ",");
             strcat(bytes, "read");
             flag = JS_TRUE;
         }
@@ -2434,17 +2433,17 @@ file_getProperty(JSContext *cx, JSObject
             flag = JS_TRUE;
         }
         if (file->hasAutoflush) {
             if (flag) strcat(bytes, ",");
             strcat(bytes, "hasAutoFlush");
             flag = JS_TRUE;
         }
         *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, bytes));
-        JS_free(cx, bytes);
+        cx->free(bytes);
         break;
     case FILE_CREATED:
         SECURITY_CHECK(cx, NULL, "creationTime", file);
         JSFILE_CHECK_NATIVE("creationTime");
         if(((file->isOpen)?
                         PR_GetOpenFileInfo(file->handle, &info):
                         PR_GetFileInfo(file->path, &info))!=PR_SUCCESS){
             JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
@@ -2570,17 +2569,17 @@ file_getProperty(JSContext *cx, JSObject
                 return JS_FALSE;
             }
 
             while ((entry = PR_ReadDir(dir, PR_SKIP_NONE)) != NULL) {
                 if (!strcmp(entry->name, prop_name)){
                     bytes = js_combinePath(cx, file->path, prop_name);
                     *vp = OBJECT_TO_JSVAL(js_NewFileObject(cx, bytes));
                     PR_CloseDir(dir);
-                    JS_free(cx, bytes);
+                    cx->free(bytes);
                     return !JSVAL_IS_NULL(*vp);
                 }
             }
             PR_CloseDir(dir);
         }
     }
     return JS_TRUE;
 
@@ -2712,20 +2711,20 @@ js_InitFileClass(JSContext *cx, JSObject
     }
 
     ctor = JS_GetConstructor(cx, file);
     if (!ctor)  return NULL;
 
 	/* Define CURRENTDIR property. We are doing this to get a
 	slash at the end of the current dir */
     afile = js_NewFileObject(cx, CURRENT_DIR);
-    currentdir =  JS_malloc(cx, MAX_PATH_LENGTH);
-    currentdir =  getcwd(currentdir, MAX_PATH_LENGTH);
+    currentdir = cx->malloc(MAX_PATH_LENGTH);
+    currentdir = getcwd(currentdir, MAX_PATH_LENGTH);
     afile = js_NewFileObject(cx, currentdir);
-    JS_free(cx, currentdir);
+    cx->free(currentdir);
     vp = OBJECT_TO_JSVAL(afile);
     JS_DefinePropertyWithTinyId(cx, ctor, CURRENTDIR_PROPERTY, 0, vp,
                 JS_PropertyStub, file_currentDirSetter,
                 JSPROP_ENUMERATE | JSPROP_READONLY );
 
     /* Define input */
     vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stdin,
             STDINPUT_NAME, PR_RDONLY, JS_TRUE, JS_FALSE));
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -131,17 +131,17 @@ MarkArgDeleted(JSContext *cx, JSStackFra
     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);
+            bitmap = (jsbitmap *) cx->malloc(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) {
@@ -306,17 +306,17 @@ js_PutArgsObject(JSContext *cx, JSStackF
     /*
      * Now clear the deleted argument number bitmap slot and free the bitmap,
      * if one was actually created due to 'delete arguments[0]' or similar.
      */
     (void) JS_GetReservedSlot(cx, argsobj, 0, &bmapval);
     if (!JSVAL_IS_VOID(bmapval)) {
         JS_SetReservedSlot(cx, argsobj, 0, JSVAL_VOID);
         if (fp->argc > JSVAL_INT_BITS)
-            JS_free(cx, JSVAL_TO_PRIVATE(bmapval));
+            cx->free(JSVAL_TO_PRIVATE(bmapval));
     }
 
     /*
      * Now get the prototype properties so we snapshot fp->fun and fp->argc
      * before fp goes away.
      */
     rt = cx->runtime;
     ok &= js_GetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.calleeAtom),
@@ -1128,17 +1128,17 @@ SetCallArguments(JSContext *cx, JSObject
 }
 
 JSBool
 js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 {
     return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_FALSE);
 }
 
-static JSBool
+JSBool
 SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 {
     return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_TRUE);
 }
 
 JSBool
 js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 {
@@ -1149,22 +1149,37 @@ JSBool
 js_GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 {
     if (!CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_FALSE))
         return JS_FALSE;
 
     return CheckForEscapingClosure(cx, obj, vp);
 }
 
-static JSBool
+JSBool
 SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 {
     return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_TRUE);
 }
 
+JSBool JS_FASTCALL
+js_SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval v)
+{
+    return CallPropertyOp(cx, obj, id, &v, JSCPK_ARG, JS_TRUE);
+}
+
+JSBool JS_FASTCALL
+js_SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval v)
+{
+    return CallPropertyOp(cx, obj, id, &v, JSCPK_VAR, JS_TRUE);
+}
+
+JS_DEFINE_CALLINFO_4(extern, BOOL, js_SetCallArg, CONTEXT, OBJECT, JSID, JSVAL, 0, 0)
+JS_DEFINE_CALLINFO_4(extern, BOOL, js_SetCallVar, CONTEXT, OBJECT, JSID, JSVAL, 0, 0)
+
 static JSBool
 call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
              JSObject **objp)
 {
     jsval callee;
     JSFunction *fun;
     jsid id;
     JSLocalKind localKind;
@@ -2738,20 +2753,20 @@ typedef struct JSLocalNameHashEntry {
 
 static void
 FreeLocalNameHash(JSContext *cx, JSLocalNameMap *map)
 {
     JSNameIndexPair *dup, *next;
 
     for (dup = map->lastdup; dup; dup = next) {
         next = dup->link;
-        JS_free(cx, dup);
+        cx->free(dup);
     }
     JS_DHashTableFinish(&map->names);
-    JS_free(cx, map);
+    cx->free(map);
 }
 
 static JSBool
 HashLocalName(JSContext *cx, JSLocalNameMap *map, JSAtom *name,
               JSLocalKind localKind, uintN index)
 {
     JSLocalNameHashEntry *entry;
     JSNameIndexPair *dup;
@@ -2769,17 +2784,17 @@ HashLocalName(JSContext *cx, JSLocalName
             JS_DHashTableOperate(&map->names, name, JS_DHASH_ADD);
     if (!entry) {
         JS_ReportOutOfMemory(cx);
         return JS_FALSE;
     }
     if (entry->name) {
         JS_ASSERT(entry->name == name);
         JS_ASSERT(entry->localKind == JSLOCAL_ARG);
-        dup = (JSNameIndexPair *) JS_malloc(cx, sizeof *dup);
+        dup = (JSNameIndexPair *) cx->malloc(sizeof *dup);
         if (!dup)
             return JS_FALSE;
         dup->name = entry->name;
         dup->index = entry->index;
         dup->link = map->lastdup;
         map->lastdup = dup;
     }
     entry->name = name;
@@ -2815,17 +2830,17 @@ js_AddLocal(JSContext *cx, JSFunction *f
     n = fun->countLocalNames();
     if (n == 0) {
         JS_ASSERT(fun->u.i.names.taggedAtom == 0);
         fun->u.i.names.taggedAtom = taggedAtom;
     } else if (n < MAX_ARRAY_LOCALS) {
         if (n > 1) {
             array = fun->u.i.names.array;
         } else {
-            array = (jsuword *) JS_malloc(cx, MAX_ARRAY_LOCALS * sizeof *array);
+            array = (jsuword *) cx->malloc(MAX_ARRAY_LOCALS * sizeof *array);
             if (!array)
                 return JS_FALSE;
             array[0] = fun->u.i.names.taggedAtom;
             fun->u.i.names.array = array;
         }
         if (kind == JSLOCAL_ARG) {
             /*
              * A destructuring argument pattern adds variables, not arguments,
@@ -2840,25 +2855,25 @@ js_AddLocal(JSContext *cx, JSFunction *f
             JS_ASSERT(fun->u.i.nvars == 0);
 #endif
             array[fun->nargs] = taggedAtom;
         } else {
             array[n] = taggedAtom;
         }
     } else if (n == MAX_ARRAY_LOCALS) {
         array = fun->u.i.names.array;
-        map = (JSLocalNameMap *) JS_malloc(cx, sizeof *map);
+        map = (JSLocalNameMap *) cx->malloc(sizeof *map);
         if (!map)
             return JS_FALSE;
         if (!JS_DHashTableInit(&map->names, JS_DHashGetStubOps(),
                                NULL, sizeof(JSLocalNameHashEntry),
                                JS_DHASH_DEFAULT_CAPACITY(MAX_ARRAY_LOCALS
                                                          * 2))) {
             JS_ReportOutOfMemory(cx);
-            JS_free(cx, map);
+            cx->free(map);
             return JS_FALSE;
         }
 
         map->lastdup = NULL;
         for (i = 0; i != MAX_ARRAY_LOCALS; ++i) {
             taggedAtom = array[i];
             uintN j = i;
             JSLocalKind k = JSLOCAL_ARG;
@@ -2881,17 +2896,17 @@ js_AddLocal(JSContext *cx, JSFunction *f
             return JS_FALSE;
         }
 
         /*
          * At this point the entry is added and we cannot fail. It is time
          * to replace fun->u.i.names with the built map.
          */
         fun->u.i.names.map = map;
-        JS_free(cx, array);
+        cx->free(array);
     } else {
         if (*indexp == JS_BITMASK(16)) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                  (kind == JSLOCAL_ARG)
                                  ? JSMSG_TOO_MANY_FUN_ARGS
                                  : JSMSG_TOO_MANY_LOCALS);
             return JS_FALSE;
         }
@@ -3103,34 +3118,34 @@ void
 DestroyLocalNames(JSContext *cx, JSFunction *fun)
 {
     uintN n;
 
     n = fun->countLocalNames();
     if (n <= 1)
         return;
     if (n <= MAX_ARRAY_LOCALS)
-        JS_free(cx, fun->u.i.names.array);
+        cx->free(fun->u.i.names.array);
     else
         FreeLocalNameHash(cx, fun->u.i.names.map);
 }
 
 void
 js_FreezeLocalNames(JSContext *cx, JSFunction *fun)
 {
     uintN n;
     jsuword *array;
 
     JS_ASSERT(FUN_INTERPRETED(fun));
     JS_ASSERT(!fun->u.i.script);
     n = fun->nargs + fun->u.i.nvars + fun->u.i.nupvars;
     if (2 <= n && n < MAX_ARRAY_LOCALS) {
         /* Shrink over-allocated array ignoring realloc failures. */
-        array = (jsuword *) JS_realloc(cx, fun->u.i.names.array,
-                                       n * sizeof *array);
+        array = (jsuword *) cx->realloc(fun->u.i.names.array,
+                                        n * sizeof *array);
         if (array)
             fun->u.i.names.array = array;
     }
 #ifdef DEBUG
     if (n > MAX_ARRAY_LOCALS)
         JS_DHashMarkTableImmutable(&fun->u.i.names.map->names);
 #endif
 }
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -275,17 +275,35 @@ js_GetCallObject(JSContext *cx, JSStackF
 
 extern JS_FRIEND_API(JSBool)
 js_PutCallObject(JSContext *cx, JSStackFrame *fp);
 
 extern JSBool
 js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
 
 extern JSBool
-js_GetCallVar(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JSBool
+SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JSBool
+SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+/*
+ * js_SetCallArg and js_SetCallVar are extern fastcall copies of the setter
+ * functions. These versions are required in order to set call vars from traces.
+ * The normal versions must not be fastcall because they are stored in the
+ * property ops map.
+ */
+extern JSBool JS_FASTCALL
+js_SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval v);
+
+extern JSBool JS_FASTCALL
+js_SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval v);
 
 /*
  * Slower version of js_GetCallVar used when call_resolve detects an attempt to
  * leak an optimized closure via indirect or debugger eval.
  */
 extern JSBool
 js_GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
 
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -71,16 +71,17 @@
 #include "jslock.h"
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsparse.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jsstaticcheck.h"
 #include "jsstr.h"
+#include "jstask.h"
 #include "jstracer.h"
 
 #if JS_HAS_XML_SUPPORT
 #include "jsxml.h"
 #endif
 
 #ifdef INCLUDE_MOZILLA_DTRACE
 #include "jsdtracef.h"
@@ -717,17 +718,17 @@ PtrTableCapacity(size_t count, const JSP
     return capacity;
 }
 
 static void
 FreePtrTable(JSPtrTable *table, const JSPtrTableInfo *info)
 {
     if (table->array) {
         JS_ASSERT(table->count > 0);
-        free(table->array);
+        js_free(table->array);
         table->array = NULL;
         table->count = 0;
     }
     JS_ASSERT(table->count == 0);
 }
 
 static JSBool
 AddToPtrTable(JSContext *cx, JSPtrTable *table, const JSPtrTableInfo *info,
@@ -751,18 +752,18 @@ AddToPtrTable(JSContext *cx, JSPtrTable 
              */
             JS_STATIC_ASSERT(2 <= sizeof table->array[0]);
             capacity = (capacity < info->linearGrowthThreshold)
                        ? 2 * capacity
                        : capacity + info->linearGrowthThreshold;
             if (capacity > (size_t)-1 / sizeof table->array[0])
                 goto bad;
         }
-        array = (void **) realloc(table->array,
-                                  capacity * sizeof table->array[0]);
+        array = (void **) js_realloc(table->array,
+                                     capacity * sizeof table->array[0]);
         if (!array)
             goto bad;
 #ifdef DEBUG
         memset(array + count, JS_FREE_PATTERN,
                (capacity - count) * sizeof table->array[0]);
 #endif
         table->array = array;
     }
@@ -791,21 +792,21 @@ ShrinkPtrTable(JSPtrTable *table, const 
     oldCapacity = PtrTableCapacity(table->count, info);
     table->count = newCount;
     capacity = PtrTableCapacity(newCount, info);
 
     if (oldCapacity != capacity) {
         array = table->array;
         JS_ASSERT(array);
         if (capacity == 0) {
-            free(array);
+            js_free(array);
             table->array = NULL;
             return;
         }
-        array = (void **) realloc(array, capacity * sizeof array[0]);
+        array = (void **) js_realloc(array, capacity * sizeof array[0]);
         if (array)
             table->array = array;
     }
 #ifdef DEBUG
     memset(table->array + newCount, JS_FREE_PATTERN,
            (capacity - newCount) * sizeof table->array[0]);
 #endif
 }
@@ -876,17 +877,17 @@ NewGCChunk(void)
      *
      * bytes. But since we stores the gap between the malloced pointer and the
      * first arena in the chunk after the chunk, we need to ask for
      *
      *   ((js_gcArenasPerChunk + 1) << GC_ARENA_SHIFT)
      *
      * bytes to ensure that we always have room to store the gap.
      */
-    p = malloc((js_gcArenasPerChunk + 1) << GC_ARENA_SHIFT);
+    p = js_malloc((js_gcArenasPerChunk + 1) << GC_ARENA_SHIFT);
     if (!p)
         return 0;
 
     {
         jsuword chunk;
 
         chunk = ((jsuword) p + GC_ARENA_MASK) & ~GC_ARENA_MASK;
         *GetMallocedChunkGapPtr(chunk) = (uint32) (chunk - (jsuword) p);
@@ -908,21 +909,21 @@ DestroyGCChunk(jsuword chunk)
 # else
         munmap((void *) chunk, js_gcArenasPerChunk << GC_ARENA_SHIFT);
 # endif
         return;
     }
 #endif
 
 #if HAS_POSIX_MEMALIGN
-    free((void *) chunk);
+    js_free((void *) chunk);
 #else
     /* See comments in NewGCChunk. */
     JS_ASSERT(*GetMallocedChunkGapPtr(chunk) < GC_ARENA_SIZE);
-    free((void *) (chunk - *GetMallocedChunkGapPtr(chunk)));
+    js_free((void *) (chunk - *GetMallocedChunkGapPtr(chunk)));
 #endif
 }
 
 #if CHUNKED_ARENA_ALLOCATION
 
 static void
 AddChunkToList(JSRuntime *rt, JSGCChunkInfo *ci)
 {
@@ -3037,17 +3038,17 @@ js_TraceContext(JSTracer *trc, JSContext
           case JSTVU_SINGLE:
             JS_SET_TRACING_NAME(trc, "tvr->u.value");
             js_CallValueTracerIfGCThing(trc, tvr->u.value);
             break;
           case JSTVU_TRACE:
             tvr->u.trace(trc, tvr);
             break;
           case JSTVU_SPROP:
-            TRACE_SCOPE_PROPERTY(trc, tvr->u.sprop);
+            tvr->u.sprop->trace(trc);
             break;
           case JSTVU_WEAK_ROOTS:
             TraceWeakRoots(trc, tvr->u.weakRoots);
             break;
           case JSTVU_COMPILER:
             tvr->u.compiler->trace(trc);
             break;
           case JSTVU_SCRIPT:
@@ -3265,17 +3266,20 @@ js_FinalizeStringRT(JSRuntime *rt, JSStr
         chars = str->flatChars();
         valid = (chars != NULL);
         if (valid) {
             if (IN_UNIT_STRING_SPACE_RT(rt, chars)) {
                 JS_ASSERT(rt->unitStrings[*chars] == str);
                 JS_ASSERT(type < 0);
                 rt->unitStrings[*chars] = NULL;
             } else if (type < 0) {
-                free(chars);
+                if (cx)
+                    cx->free(chars);
+                else
+                    rt->free(chars);
             } else {
                 JS_ASSERT((uintN) type < JS_ARRAY_LENGTH(str_finalizers));
                 finalizer = str_finalizers[type];
                 if (finalizer) {
                     /*
                      * Assume that the finalizer for the permanently interned
                      * string knows how to deal with null context.
                      */
@@ -3514,16 +3518,17 @@ js_GC(JSContext *cx, JSGCInvocationKind 
 
     /*
      * Reset the property cache's type id generator so we can compress ids.
      * Same for the protoHazardShape proxy-shape standing in for all object
      * prototypes having readonly or setter properties.
      */
     if (rt->shapeGen & SHAPE_OVERFLOW_BIT) {
         rt->gcRegenShapes = true;
+        rt->gcRegenShapesScopeFlag ^= JSScope::SHAPE_REGEN;
         rt->shapeGen = 0;
         rt->protoHazardShape = 0;
     }
 
     js_PurgeThreads(cx);
 
     /*
      * Mark phase.
@@ -3550,16 +3555,20 @@ js_GC(JSContext *cx, JSGCInvocationKind 
         (void) rt->gcCallback(cx, JSGC_MARK_END);
         JS_ASSERT(cx->insideGCMarkCallback);
         cx->insideGCMarkCallback = JS_FALSE;
     }
     JS_ASSERT(rt->gcTraceLaterCount == 0);
 
     rt->gcMarkingTracer = NULL;
 
+#ifdef JS_THREADSAFE
+    cx->createDeallocatorTask();
+#endif
+
     /*
      * Sweep phase.
      *
      * Finalize as we sweep, outside of rt->gcLock but with rt->gcRunning set
      * so that any attempt to allocate a GC-thing from a finalizer will fail,
      * rather than nest badly and leave the unmarked newborn to be swept.
      *
      * We first sweep atom state so we can use js_IsAboutToBeFinalized on
@@ -3728,16 +3737,20 @@ js_GC(JSContext *cx, JSGCInvocationKind 
     js_SweepScriptFilenames(rt);
 
     /*
      * Destroy arenas after we finished the sweeping sofinalizers can safely
      * use js_IsAboutToBeFinalized().
      */
     DestroyGCArenas(rt, emptyArenas);
 
+#ifdef JS_THREADSAFE
+    cx->submitDeallocatorTask();
+#endif
+
     if (rt->gcCallback)
         (void) rt->gcCallback(cx, JSGC_FINALIZE_END);
 #ifdef DEBUG_srcnotesize
   { extern void DumpSrcNoteSizeHist();
     DumpSrcNoteSizeHist();
     printf("GC HEAP SIZE %lu\n", (unsigned long)rt->gcBytes);
   }
 #endif
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -42,16 +42,17 @@
 /*
  * JS Garbage Collector.
  */
 #include "jsprvtd.h"
 #include "jspubtd.h"
 #include "jsdhash.h"
 #include "jsbit.h"
 #include "jsutil.h"
+#include "jstask.h"
 
 JS_BEGIN_EXTERN_C
 
 #define JSTRACE_XML         3
 
 /*
  * One past the maximum trace kind.
  */
@@ -336,16 +337,38 @@ struct JSWeakRoots {
  * the error reported.
  */
 extern JSBool
 js_AddAsGCBytes(JSContext *cx, size_t sz);
 
 extern void
 js_RemoveAsGCBytes(JSRuntime* rt, size_t sz);
 
+#ifdef JS_THREADSAFE
+class JSFreePointerListTask : public JSBackgroundTask {
+    void *head;
+  public:
+    JSFreePointerListTask() : head(NULL) {}
+
+    void add(void* ptr) {
+        *(void**)ptr = head;
+        head = ptr;
+    }
+
+    void run() {
+        void *ptr = head;
+        while (ptr) {
+            void *next = *(void **)ptr;
+            js_free(ptr);
+            ptr = next;
+        }
+    }
+};
+#endif
+
 /*
  * Free the chars held by str when it is finalized by the GC. When type is
  * less then zero, it denotes an internal string. Otherwise it denotes the
  * type of the external string allocated with JS_NewExternalString.
  *
  * This function always needs rt but can live with null cx.
  */
 extern void
--- a/js/src/jshash.cpp
+++ b/js/src/jshash.cpp
@@ -68,30 +68,30 @@ static void *
 DefaultAllocTable(void *pool, size_t size)
 {
     return malloc(size);
 }
 
 static void
 DefaultFreeTable(void *pool, void *item, size_t size)
 {
-    free(item);
+    js_free(item);
 }
 
 static JSHashEntry *
 DefaultAllocEntry(void *pool, const void *key)
 {
     return (JSHashEntry*) malloc(sizeof(JSHashEntry));
 }
 
 static void
 DefaultFreeEntry(void *pool, JSHashEntry *he, uintN flag)
 {
     if (flag == HT_FREE_ENTRY)
-        free(he);
+        js_free(he);
 }
 
 static JSHashAllocOps defaultHashAllocOps = {
     DefaultAllocTable, DefaultFreeTable,
     DefaultAllocEntry, DefaultFreeEntry
 };
 
 JS_PUBLIC_API(JSHashTable *)
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -1529,17 +1529,17 @@ js_Execute(JSContext *cx, JSObject *chai
     void *hookData, *mark;
     JSStackFrame *oldfp, frame;
     JSObject *obj, *tmp;
     JSBool ok;
 
     js_LeaveTrace(cx);
 
 #ifdef JS_TRACER
-    /* 
+    /*
      * The JIT requires that the scope chain here is equal to its global
      * object. Disable the JIT for this call if this condition is not true.
      */
     uint32 oldOptions = cx->options;
     if ((oldOptions & JSOPTION_JIT) && chain != JS_GetGlobalForObject(cx, chain))
         cx->options &= ~JSOPTION_JIT;
 #endif
 
@@ -2090,17 +2090,17 @@ js_GetUpvar(JSContext *cx, uintN level, 
 
     if (!fp->fun) {
         vp = fp->slots + fp->script->nfixed;
     } else if (slot < fp->fun->nargs) {
         vp = fp->argv;
     } else if (slot == CALLEE_UPVAR_SLOT) {
         vp = &fp->argv[-2];
         slot = 0;
-    } else { 
+    } else {
         slot -= fp->fun->nargs;
         JS_ASSERT(slot < fp->script->nslots);
         vp = fp->slots;
     }
 
     return vp[slot];
 }
 
@@ -2127,30 +2127,30 @@ js_TraceOpcode(JSContext *cx)
      * js_DecompileValueGenerator isn't set up to handle them anyway.
      */
     if (cx->tracePrevPc && regs->pc >= fp->script->main) {
         JSOp tracePrevOp = JSOp(*cx->tracePrevPc);
         ndefs = js_GetStackDefs(cx, &js_CodeSpec[tracePrevOp], tracePrevOp,
                                 fp->script, cx->tracePrevPc);
 
         /*
-         * If there aren't that many elements on the stack, then 
+         * If there aren't that many elements on the stack, then
          * we have probably entered a new frame, and printing output
          * would just be misleading.
          */
         if (ndefs != 0 &&
             ndefs < regs->sp - fp->slots) {
             for (n = -ndefs; n < 0; n++) {
                 char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n],
                                                          NULL);
                 if (bytes) {
                     fprintf(tracefp, "%s %s",
                             (n == -ndefs) ? "  output:" : ",",
                             bytes);
-                    JS_free(cx, bytes);
+                    cx->free(bytes);
                 }
             }
             fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp)));
         }
         fprintf(tracefp, "  stack: ");
         for (siter = StackBase(fp); siter < regs->sp; siter++) {
             str = js_ValueToString(cx, *siter);
             if (!str)
@@ -2172,17 +2172,17 @@ js_TraceOpcode(JSContext *cx)
     if (nuses != 0) {
         for (n = -nuses; n < 0; n++) {
             char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n],
                                                      NULL);
             if (bytes) {
                 fprintf(tracefp, "%s %s",
                         (n == -nuses) ? "  inputs:" : ",",
                         bytes);
-                JS_free(cx, bytes);
+                cx->free(bytes);
             }
         }
         fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp)));
     }
     cx->tracePrevPc = regs->pc;
 
     /* It's nice to have complete traces when debugging a crash.  */
     fflush(tracefp);
@@ -2259,17 +2259,17 @@ js_DumpOpMeters()
                 total += count;
                 ++nedges;
             }
         }
     }
 
 # define SIGNIFICANT(count,total) (200. * (count) >= (total))
 
-    graph = (Edge *) calloc(nedges, sizeof graph[0]);
+    graph = (Edge *) js_calloc(nedges * sizeof graph[0]);
     for (i = nedges = 0; i < JSOP_LIMIT; i++) {
         from = js_CodeName[i];
         for (j = 0; j < JSOP_LIMIT; j++) {
             count = succeeds[i][j];
             if (count != 0 && SIGNIFICANT(count, total)) {
                 graph[nedges].from = from;
                 graph[nedges].to = js_CodeName[j];
                 graph[nedges].count = count;
@@ -2288,17 +2288,17 @@ js_DumpOpMeters()
             style = (i > nedges * .75) ? "dotted" :
                     (i > nedges * .50) ? "dashed" :
                     (i > nedges * .25) ? "solid" : "bold";
         }
         fprintf(fp, "  %s -> %s [label=\"%lu\" style=%s]\n",
                 graph[i].from, graph[i].to,
                 (unsigned long)graph[i].count, style);
     }
-    free(graph);
+    js_free(graph);
     fputs("}\n", fp);
     fclose(fp);
 
     name = getenv("JS_OPMETER_HIST");
     if (!name)
         name = "/tmp/ops.hist";
     fp = fopen(name, "w");
     if (!fp) {
@@ -2712,17 +2712,17 @@ js_Interpret(JSContext *cx)
     /*
      * We call this macro from BEGIN_CASE in threaded interpreters,
      * and before entering the switch in non-threaded interpreters.
      * However, reaching such points doesn't mean we've actually
      * fetched an OP from the instruction stream: some opcodes use
      * 'op=x; DO_OP()' to let another opcode's implementation finish
      * their work, and many opcodes share entry points with a run of
      * consecutive BEGIN_CASEs.
-     * 
+     *
      * Take care to trace OP only when it is the opcode fetched from
      * the instruction stream, so the trace matches what one would
      * expect from looking at the code.  (We do omit POPs after SETs;
      * unfortunate, but not worth fixing.)
      */
 #  define TRACE_OPCODE(OP)  JS_BEGIN_MACRO                                    \
                                 if (JS_UNLIKELY(cx->tracefp != NULL) &&       \
                                     (OP) == *regs.pc)                         \
@@ -4797,17 +4797,16 @@ js_Interpret(JSContext *cx)
                                  * chains. We do this after unlocking obj's
                                  * scope to avoid lock nesting.
                                  */
                                 js_PurgeScopeChain(cx, obj, sprop->id);
                                 break;
                             }
                             JS_UNLOCK_SCOPE(cx, scope);
                             PCMETER(cache->setpcmisses++);
-                            atom = NULL;
                         }
                     }
 
                     atom = js_FullTestPropertyCache(cx, regs.pc, &obj, &obj2,
                                                     &entry);
                     if (atom) {
                         PCMETER(cache->misses++);
                         PCMETER(cache->setmisses++);
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -85,29 +85,29 @@ struct JSStackFrame {
 
     /*
      * We can't determine in advance which local variables can live on
      * the stack and be freed when their dynamic scope ends, and which
      * will be closed over and need to live in the heap.  So we place
      * variables on the stack initially, note when they are closed
      * over, and copy those that are out to the heap when we leave
      * their dynamic scope.
-     * 
+     *
      * The bytecode compiler produces a tree of block objects
      * accompanying each JSScript representing those lexical blocks in
      * the script that have let-bound variables associated with them.
      * These block objects are never modified, and never become part
      * of any function's scope chain.  Their parent slots point to the
      * innermost block that encloses them, or are NULL in the
      * outermost blocks within a function or in eval or global code.
      *
      * When we are in the static scope of such a block, blockChain
      * points to its compiler-allocated block object; otherwise, it is
      * NULL.
-     * 
+     *
      * scopeChain is the current scope chain, including 'call' and
      * 'block' objects for those function calls and lexical blocks
      * whose static scope we are currently executing in, and 'with'
      * objects for with statements; the chain is typically terminated
      * by a global object.  However, as an optimization, the young end
      * of the chain omits block objects we have not yet cloned.  To
      * create a closure, we clone the missing blocks from blockChain
      * (which is always current), place them at the head of
@@ -153,17 +153,17 @@ JSStackFrame::assertValidStackDepth(uint
     JS_ASSERT(0 <= regs->sp - StackBase(this));
     JS_ASSERT(depth <= uintptr_t(regs->sp - StackBase(this)));
 }
 
 static JS_INLINE uintN
 GlobalVarCount(JSStackFrame *fp)
 {
     uintN n;
-    
+
     JS_ASSERT(!fp->fun);
     n = fp->script->nfixed;
     if (fp->script->regexpsOffset != 0)
         n -= JS_SCRIPT_REGEXPS(fp->script)->length;
     return n;
 }
 
 typedef struct JSInlineFrame {
@@ -238,16 +238,20 @@ typedef struct JSInlineFrame {
 
 #define SHAPE_OVERFLOW_BIT      JS_BIT(32 - PCVCAP_TAGBITS)
 
 struct JSPropCacheEntry {
     jsbytecode          *kpc;           /* pc if vcap tag is <= 1, else atom */
     jsuword             kshape;         /* key shape if pc, else obj for atom */
     jsuword             vcap;           /* value capability, see above */
     jsuword             vword;          /* value word, see PCVAL_* below */
+
+    bool adding() const {
+        return PCVCAP_TAG(vcap) == 0 && kshape != PCVCAP_SHAPE(vcap);
+    }
 };
 
 /*
  * Special value for functions returning JSPropCacheEntry * to distinguish
  * between failure and no no-cache-fill cases.
  */
 #define JS_NO_PROP_CACHE_FILL ((JSPropCacheEntry *) NULL + 1)
 
--- a/js/src/jsinttypes.h
+++ b/js/src/jsinttypes.h
@@ -38,17 +38,17 @@
 #define jsinttypes_h___
 
 #include "js-config.h"
 
 /*
  * Types:
  *   JSInt<N>, JSUint<N> (for <N> = 8, 16, 32, and 64)
  *   JSIntPtr, JSUIntPtr
- * 
+ *
  * JSInt<N> and JSUint<N> are signed and unsigned types known to be
  * <N> bits long.  Note that neither JSInt8 nor JSUInt8 is necessarily
  * equivalent to a plain "char".
  *
  * JSIntPtr and JSUintPtr are signed and unsigned types capable of
  * holding an object pointer.
  *
  * Use these types in public SpiderMonkey header files, not the
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -644,17 +644,17 @@ generator_finalize(JSContext *cx, JSObje
     gen = (JSGenerator *) JS_GetPrivate(cx, obj);
     if (gen) {
         /*
          * gen can be open on shutdown when close hooks are ignored or when
          * the embedding cancels scheduled close hooks.
          */
         JS_ASSERT(gen->state == JSGEN_NEWBORN || gen->state == JSGEN_CLOSED ||
                   gen->state == JSGEN_OPEN);
-        JS_free(cx, gen);
+        cx->free(gen);
     }
 }
 
 static void
 generator_trace(JSTracer *trc, JSObject *obj)
 {
     JSGenerator *gen;
 
@@ -711,17 +711,17 @@ js_NewGenerator(JSContext *cx, JSStackFr
 
     /* Load and compute stack slot counts. */
     argc = fp->argc;
     nargs = JS_MAX(argc, fp->fun->nargs);
     nslots = 2 + nargs + fp->script->nslots;
 
     /* Allocate obj's private data struct. */
     gen = (JSGenerator *)
-          JS_malloc(cx, sizeof(JSGenerator) + (nslots - 1) * sizeof(jsval));
+        cx->malloc(sizeof(JSGenerator) + (nslots - 1) * sizeof(jsval));
     if (!gen)
         goto bad;
 
     gen->obj = obj;
 
     /* Steal away objects reflecting fp and point them at gen->frame. */
     gen->frame.callobj = fp->callobj;
     if (fp->callobj) {
@@ -778,17 +778,17 @@ js_NewGenerator(JSContext *cx, JSStackFr
     /* JSOP_GENERATOR appears in the prologue, outside all blocks.  */
     JS_ASSERT(!fp->blockChain);
     gen->frame.blockChain = NULL;
 
     /* Note that gen is newborn. */
     gen->state = JSGEN_NEWBORN;
 
     if (!JS_SetPrivate(cx, obj, gen)) {
-        JS_free(cx, gen);
+        cx->free(gen);
         goto bad;
     }
     return obj;
 
   bad:
     cx->weakRoots.newborn[GCX_OBJECT] = NULL;
     return NULL;
 }
--- a/js/src/jslock.cpp
+++ b/js/src/jslock.cpp
@@ -904,17 +904,17 @@ NewFatlock()
     return fl;
 }
 
 static void
 DestroyFatlock(JSFatLock *fl)
 {
     PR_DestroyLock(fl->slock);
     PR_DestroyCondVar(fl->svar);
-    free(fl);
+    js_free(fl);
 }
 
 static JSFatLock *
 ListOfFatlocks(int listc)
 {
     JSFatLock *m;
     JSFatLock *m0;
     int i;
@@ -998,28 +998,28 @@ js_SetupLocks(int listc, int globc)
     if (listc > 10000 || listc < 0) /* listc == fat lock list chunk length */
         printf("Bad number %d in js_SetupLocks()!\n", listc);
     if (globc > 100 || globc < 0)   /* globc == number of global locks */
         printf("Bad number %d in js_SetupLocks()!\n", listc);
 #endif
     global_locks_log2 = JS_CeilingLog2(globc);
     global_locks_mask = JS_BITMASK(global_locks_log2);
     global_lock_count = JS_BIT(global_locks_log2);
-    global_locks = (PRLock **) malloc(global_lock_count * sizeof(PRLock*));
+    global_locks = (PRLock **) js_malloc(global_lock_count * sizeof(PRLock*));
     if (!global_locks)
         return JS_FALSE;
     for (i = 0; i < global_lock_count; i++) {
         global_locks[i] = PR_NewLock();
         if (!global_locks[i]) {
             global_lock_count = i;
             js_CleanupLocks();
             return JS_FALSE;
         }
     }
-    fl_list_table = (JSFatLockTable *) malloc(i * sizeof(JSFatLockTable));
+    fl_list_table = (JSFatLockTable *) js_malloc(i * sizeof(JSFatLockTable));
     if (!fl_list_table) {
         js_CleanupLocks();
         return JS_FALSE;
     }
     fl_list_table_len = global_lock_count;
     for (i = 0; i < global_lock_count; i++)
         fl_list_table[i].free = fl_list_table[i].taken = NULL;
     fl_list_chunk_len = listc;
@@ -1031,30 +1031,30 @@ void
 js_CleanupLocks()
 {
 #ifndef NSPR_LOCK
     uint32 i;
 
     if (global_locks) {
         for (i = 0; i < global_lock_count; i++)
             PR_DestroyLock(global_locks[i]);
-        free(global_locks);
+        js_free(global_locks);
         global_locks = NULL;
         global_lock_count = 1;
         global_locks_log2 = 0;
         global_locks_mask = 0;
     }
     if (fl_list_table) {
         for (i = 0; i < fl_list_table_len; i++) {
             DeleteListOfFatlocks(fl_list_table[i].free);
             fl_list_table[i].free = NULL;
             DeleteListOfFatlocks(fl_list_table[i].taken);
             fl_list_table[i].taken = NULL;
         }
-        free(fl_list_table);
+        js_free(fl_list_table);
         fl_list_table = NULL;
         fl_list_table_len = 0;
     }
 #endif /* !NSPR_LOCK */
 }
 
 #ifdef NSPR_LOCK
 
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -226,17 +226,17 @@ math_atan2(JSContext *cx, uintN argc, js
         return JS_FALSE;
     return js_NewNumberInRootedValue(cx, math_atan2_kernel (x, y), vp);
 }
 
 static inline jsdouble JS_FASTCALL
 math_ceil_kernel(jsdouble x)
 {
 #ifdef __APPLE__
-    if (x < 0 && x > -1.0) 
+    if (x < 0 && x > -1.0)
         return js_copysign(0, -1);
 #endif
     return ceil(x);
 }
 
 static JSBool
 math_ceil(JSContext *cx, uintN argc, jsval *vp)
 {
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -379,17 +379,17 @@ num_toString(JSContext *cx, uintN argc, 
         str = js_NumberToString(cx, d);
     } else {
         char *dStr = JS_dtobasestr(base, d);
         if (!dStr) {
             JS_ReportOutOfMemory(cx);
             return JS_FALSE;
         }
         str = JS_NewStringCopyZ(cx, dStr);
-        free(dStr);
+        js_free(dStr);
     }
     if (!str)
         return JS_FALSE;
     *vp = STRING_TO_JSVAL(str);
     return JS_TRUE;
 }
 
 static JSBool
@@ -455,17 +455,17 @@ num_toLocaleString(JSContext *cx, uintN 
         nrepeat = (remainder - 1) / tmpGroup[-1];
         size += thousandsLength * nrepeat;
         remainder -= nrepeat * tmpGroup[-1];
     } else {
         nrepeat = 0;
     }
     tmpGroup--;
 
-    buf = (char *)JS_malloc(cx, size + 1);
+    buf = (char *)cx->malloc(size + 1);
     if (!buf)
         return JS_FALSE;
 
     tmpDest = buf;
     tmpSrc = num;
 
     while (*tmpSrc == '-' || remainder--)
         *tmpDest++ = *tmpSrc++;
@@ -487,17 +487,17 @@ num_toLocaleString(JSContext *cx, uintN 
         strcpy(tmpDest, nint);
     }
 
     if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode)
         return cx->localeCallbacks->localeToUnicode(cx, buf, vp);
 
     str = JS_NewString(cx, buf, size);
     if (!str) {
-        JS_free(cx, buf);
+        cx->free(buf);
         return JS_FALSE;
     }
 
     *vp = STRING_TO_JSVAL(str);
     return JS_TRUE;
 }
 
 static JSBool
@@ -734,19 +734,19 @@ js_FinishRuntimeNumberState(JSContext *c
     js_UnlockGCThingRT(rt, rt->jsNaN);
     js_UnlockGCThingRT(rt, rt->jsNegativeInfinity);
     js_UnlockGCThingRT(rt, rt->jsPositiveInfinity);
 
     rt->jsNaN = NULL;
     rt->jsNegativeInfinity = NULL;
     rt->jsPositiveInfinity = NULL;
 
-    JS_free(cx, (void *)rt->thousandsSeparator);
-    JS_free(cx, (void *)rt->decimalSeparator);
-    JS_free(cx, (void *)rt->numGrouping);
+    cx->free((void *)rt->thousandsSeparator);
+    cx->free((void *)rt->decimalSeparator);
+    cx->free((void *)rt->numGrouping);
     rt->thousandsSeparator = rt->decimalSeparator = rt->numGrouping = NULL;
 }
 
 JSObject *
 js_InitNumberClass(JSContext *cx, JSObject *obj)
 {
     JSObject *proto, *ctor;
     JSRuntime *rt;
@@ -847,17 +847,17 @@ NumberToStringWithBase(JSContext *cx, js
 
     if (base < 2 || base > 36)
         return NULL;
     numStr = NumberToCString(cx, d, base, buf, sizeof buf);
     if (!numStr)
         return NULL;
     s = JS_NewStringCopyZ(cx, numStr);
     if (!(numStr >= buf && numStr < buf + sizeof buf))
-        free(numStr);
+        js_free(numStr);
     return s;
 }
 
 JSString * JS_FASTCALL
 js_NumberToString(JSContext *cx, jsdouble d)
 {
     return NumberToStringWithBase(cx, d, 10);
 }
@@ -1246,17 +1246,17 @@ js_strtod(JSContext *cx, const jschar *s
     JSBool negative;
     jsdouble d;
 
     s1 = js_SkipWhiteSpace(s, send);
     length = send - s1;
 
     /* Use cbuf to avoid malloc */
     if (length >= sizeof cbuf) {
-        cstr = (char *) JS_malloc(cx, length + 1);
+        cstr = (char *) cx->malloc(length + 1);
         if (!cstr)
            return JS_FALSE;
     } else {
         cstr = cbuf;
     }
 
     for (i = 0; i != length; i++) {
         if (s1[i] >> 8)
@@ -1287,17 +1287,17 @@ js_strtod(JSContext *cx, const jschar *s
             JSDOUBLE_HI32(d) = JSDOUBLE_HI32_SIGNBIT;
             JSDOUBLE_LO32(d) = 0;
         }
 #endif
     }
 
     i = estr - cstr;
     if (cstr != cbuf)
-        JS_free(cx, cstr);
+        cx->free(cstr);
     *ep = i ? s1 + i : s;
     *dp = d;
     return JS_TRUE;
 }
 
 struct BinaryDigitReader
 {
     uintN base;                 /* Base of number; must be a power of 2 */
@@ -1400,35 +1400,35 @@ js_strtointeger(JSContext *cx, const jsc
         if (base == 10) {
             /*
              * If we're accumulating a decimal number and the number is >=
              * 2^53, then the result from the repeated multiply-add above may
              * be inaccurate.  Call JS_strtod to get the correct answer.
              */
             size_t i;
             size_t length = s1 - start;
-            char *cstr = (char *) JS_malloc(cx, length + 1);
+            char *cstr = (char *) cx->malloc(length + 1);
             char *estr;
             int err=0;
 
             if (!cstr)
                 return JS_FALSE;
             for (i = 0; i != length; i++)
                 cstr[i] = (char)start[i];
             cstr[length] = 0;
 
             value = JS_strtod(cstr, &estr, &err);
             if (err == JS_DTOA_ENOMEM) {
                 JS_ReportOutOfMemory(cx);
-                JS_free(cx, cstr);
+                cx->free(cstr);
                 return JS_FALSE;
             }
             if (err == JS_DTOA_ERANGE && value == HUGE_VAL)
                 value = *cx->runtime->jsPositiveInfinity;
-            JS_free(cx, cstr);
+            cx->free(cstr);
         } else if ((base & (base - 1)) == 0) {
             /*
              * The number may also be inaccurate for power-of-two bases.  This
              * happens if the addition in value * base + digit causes a round-
              * down to an even least significant mantissa bit when the first
              * dropped bit is a one.  If any of the following digits in the
              * number (which haven't been added in yet) are nonzero, then the
              * correct action would have been to round up instead of down.  An
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -555,17 +555,17 @@ js_EnterSharpObject(JSContext *cx, JSObj
 
 out:
     JS_ASSERT(he);
     if ((sharpid & SHARP_BIT) == 0) {
         if (idap && !ida) {
             ida = JS_Enumerate(cx, obj);
             if (!ida) {
                 if (*sp) {
-                    JS_free(cx, *sp);
+                    cx->free(*sp);
                     *sp = NULL;
                 }
                 goto bad;
             }
         }
         map->depth++;
     }
 
@@ -699,30 +699,30 @@ obj_toSource(JSContext *cx, uintN argc, 
 #endif
         goto make_string;
     }
     JS_ASSERT(ida);
     ok = JS_TRUE;
 
     if (!chars) {
         /* If outermost, allocate 4 + 1 for "({})" and the terminator. */
-        chars = (jschar *) malloc(((outermost ? 4 : 2) + 1) * sizeof(jschar));
+        chars = (jschar *) js_malloc(((outermost ? 4 : 2) + 1) * sizeof(jschar));
         nchars = 0;
         if (!chars)
             goto error;
         if (outermost)
             chars[nchars++] = '(';
     } else {
         /* js_EnterSharpObject returned a string of the form "#n=" in chars. */
         MAKE_SHARP(he);
         nchars = js_strlen(chars);
         chars = (jschar *)
-            realloc((ochars = chars), (nchars + 2 + 1) * sizeof(jschar));
+            js_realloc((ochars = chars), (nchars + 2 + 1) * sizeof(jschar));
         if (!chars) {
-            free(ochars);
+            js_free(ochars);
             goto error;
         }
         if (outermost) {
             /*
              * No need for parentheses around the whole shebang, because #n=
              * unambiguously begins an object initializer, and never a block
              * statement.
              */
@@ -953,21 +953,21 @@ obj_toSource(JSContext *cx, uintN argc, 
             SAFE_ADD((outermost ? 2 : 1) + 1);
 #undef SAFE_ADD
 
             if (curlen > (size_t)-1 / sizeof(jschar))
                 goto overflow;
 
             /* Allocate 1 + 1 at end for closing brace and terminating 0. */
             chars = (jschar *)
-                realloc((ochars = chars), curlen * sizeof(jschar));
+                js_realloc((ochars = chars), curlen * sizeof(jschar));
             if (!chars) {
                 /* Save code space on error: let JS_free ignore null vsharp. */
-                JS_free(cx, vsharp);
-                free(ochars);
+                cx->free(vsharp);
+                js_free(ochars);
                 goto error;
             }
 
             if (comma) {
                 chars[nchars++] = comma[0];
                 chars[nchars++] = comma[1];
             }
             comma = ", ";
@@ -1000,55 +1000,55 @@ obj_toSource(JSContext *cx, uintN argc, 
             if (vsharplength) {
                 js_strncpy(&chars[nchars], vsharp, vsharplength);
                 nchars += vsharplength;
             }
             js_strncpy(&chars[nchars], vchars, vlength);
             nchars += vlength;
 
             if (vsharp)
-                JS_free(cx, vsharp);
+                cx->free(vsharp);
         }
     }
 
     chars[nchars++] = '}';
     if (outermost)
         chars[nchars++] = ')';
     chars[nchars] = 0;
 
   error:
     js_LeaveSharpObject(cx, &ida);
 
     if (!ok) {
         if (chars)
-            free(chars);
+            js_free(chars);
         goto out;
     }
 
     if (!chars) {
         JS_ReportOutOfMemory(cx);
         ok = JS_FALSE;
         goto out;
     }
   make_string:
     str = js_NewString(cx, chars, nchars);
     if (!str) {
-        free(chars);
+        js_free(chars);
         ok = JS_FALSE;
         goto out;
     }
     *vp = STRING_TO_JSVAL(str);
     ok = JS_TRUE;
   out:
     JS_POP_TEMP_ROOT(cx, &tvr);
     return ok;
 
   overflow:
-    JS_free(cx, vsharp);
-    free(chars);
+    cx->free(vsharp);
+    js_free(chars);
     chars = NULL;
     goto error;
 }
 #endif /* JS_HAS_TOSOURCE */
 
 static JSBool
 obj_toString(JSContext *cx, uintN argc, jsval *vp)
 {
@@ -1059,32 +1059,32 @@ obj_toString(JSContext *cx, uintN argc, 
     JSString *str;
 
     obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
     obj = js_GetWrappedObject(cx, obj);
     clazz = OBJ_GET_CLASS(cx, obj)->name;
     nchars = 9 + strlen(clazz);         /* 9 for "[object ]" */
-    chars = (jschar *) JS_malloc(cx, (nchars + 1) * sizeof(jschar));
+    chars = (jschar *) cx->malloc((nchars + 1) * sizeof(jschar));
     if (!chars)
         return JS_FALSE;
 
     prefix = "[object ";
     nchars = 0;
     while ((chars[nchars] = (jschar)*prefix) != 0)
         nchars++, prefix++;
     while ((chars[nchars] = (jschar)*clazz) != 0)
         nchars++, clazz++;
     chars[nchars++] = ']';
     chars[nchars] = 0;
 
     str = js_NewString(cx, chars, nchars);
     if (!str) {
-        JS_free(cx, chars);
+        cx->free(chars);
         return JS_FALSE;
     }
     *vp = STRING_TO_JSVAL(str);
     return JS_TRUE;
 }
 
 static JSBool
 obj_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
@@ -2981,17 +2981,17 @@ bad:
 
 static bool
 AllocSlots(JSContext *cx, JSObject *obj, size_t nslots)
 {
     JS_ASSERT(!obj->dslots);
     JS_ASSERT(nslots > JS_INITIAL_NSLOTS);
 
     jsval* slots;
-    slots = (jsval*) JS_malloc(cx, SLOTS_TO_DYNAMIC_WORDS(nslots) * sizeof(jsval));
+    slots = (jsval*) cx->malloc(SLOTS_TO_DYNAMIC_WORDS(nslots) * sizeof(jsval));
     if (!slots)
         return true;
 
     *slots++ = nslots;
     /* clear the newly allocated cells. */
     for (jsuint n = JS_INITIAL_NSLOTS; n < nslots; ++n)
         slots[n - JS_INITIAL_NSLOTS] = JSVAL_VOID;
     obj->dslots = slots;
@@ -3039,17 +3039,17 @@ js_GrowSlots(JSContext *cx, JSObject *ob
      * the exponential growth algorithm applied).
      */
     jsval* slots = obj->dslots;
     if (!slots)
         return AllocSlots(cx, obj, nslots);
 
     size_t oslots = size_t(slots[-1]);
 
-    slots = (jsval*) JS_realloc(cx, slots - 1, nwords * sizeof(jsval));
+    slots = (jsval*) cx->realloc(slots - 1, nwords * sizeof(jsval));
     *slots++ = nslots;
     obj->dslots = slots;
 
     /* Initialize the additional slots we added. */
     JS_ASSERT(nslots > oslots);
     for (size_t i = oslots; i < nslots; i++)
         slots[i - JS_INITIAL_NSLOTS] = JSVAL_VOID;
 
@@ -3064,21 +3064,21 @@ js_ShrinkSlots(JSContext *cx, JSObject *
     /* Nothing to shrink? */
     if (!slots)
         return;
 
     JS_ASSERT(size_t(slots[-1]) > JS_INITIAL_NSLOTS);
     JS_ASSERT(nslots <= size_t(slots[-1]));
 
     if (nslots <= JS_INITIAL_NSLOTS) {
-        JS_free(cx, slots - 1);
+        cx->free(slots - 1);
         obj->dslots = NULL;
     } else {
         size_t nwords = SLOTS_TO_DYNAMIC_WORDS(nslots);
-        slots = (jsval*) JS_realloc(cx, slots - 1, nwords * sizeof(jsval));
+        slots = (jsval*) cx->realloc(slots - 1, nwords * sizeof(jsval));
         *slots++ = nslots;
         obj->dslots = slots;
     }
 }
 
 bool
 js_EnsureReservedSlots(JSContext *cx, JSObject *obj, size_t nreserved)
 {
@@ -4960,17 +4960,17 @@ js_Enumerate(JSContext *cx, JSObject *ob
             }
             if (length == 0) {
                 /* cache the scope without enumerable properties. */
                 *cachep = ((jsuword) shape << 1) | (jsuword) 1;
                 break;
             }
 
             allocated = NativeEnumeratorSize(length);
-            ne = (JSNativeEnumerator *) JS_malloc(cx, allocated);
+            ne = (JSNativeEnumerator *) cx->malloc(allocated);
             if (!ne) {
                 JS_UNLOCK_SCOPE(cx, scope);
                 return JS_FALSE;
             }
             ne->cursor = length;
             ne->length = length;
             ne->shape = shape;
             ids = ne->ids;
@@ -4992,17 +4992,17 @@ js_Enumerate(JSContext *cx, JSObject *ob
             *statep = JSVAL_ZERO;
         } else {
             JS_ASSERT(length != 0);
             JS_ASSERT(ne->cursor == (jsword) length);
             if (allocated != 0) {
                 JS_LOCK_GC(cx->runtime);
                 if (!js_AddAsGCBytes(cx, allocated)) {
                     /* js_AddAsGCBytes releases the GC lock on failures. */
-                    JS_free(cx, ne);
+                    cx->free(ne);
                     return JS_FALSE;
                 }
                 ne->next = cx->runtime->nativeEnumerators;
                 cx->runtime->nativeEnumerators = ne;
                 JS_ASSERT(((jsuword) ne & (jsuword) 1) == (jsuword) 0);
                 *cachep = (jsuword) ne;
                 JS_UNLOCK_GC(cx->runtime);
             }
@@ -5080,22 +5080,22 @@ js_TraceNativeEnumerators(JSTracer *trc)
     nep = &rt->nativeEnumerators;
     while ((ne = *nep) != NULL) {
         JS_ASSERT(ne->length != 0);
         if (ne->cursor != 0) {
             /* Trace ids of the running enumerator. */
             cursor = ne->ids;
             end = cursor + ne->length;
             do {
-                TRACE_ID(trc, *cursor);
+                js_TraceId(trc, *cursor);
             } while (++cursor != end);
         } else if (doGC) {
             js_RemoveAsGCBytes(rt, NativeEnumeratorSize(ne->length));
             *nep = ne->next;
-            JS_free(trc->context, ne);
+            trc->context->free(ne);
             continue;
         }
         nep = &ne->next;
     }
 }
 
 JSBool
 js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
@@ -5743,17 +5743,16 @@ js_PrintObjectSlotName(JSTracer *trc, ch
 }
 #endif
 
 void
 js_TraceObject(JSTracer *trc, JSObject *obj)
 {
     JSContext *cx;
     JSScope *scope;
-    JSScopeProperty *sprop;
     JSClass *clasp;
     size_t nslots, i;
     jsval v;
 
     JS_ASSERT(OBJ_IS_NATIVE(obj));
     cx = trc->context;
     scope = OBJ_SCOPE(obj);
 
@@ -5767,42 +5766,17 @@ js_TraceObject(JSTracer *trc, JSObject *
         if (STOBJ_NSLOTS(obj) != slots)
             js_ShrinkSlots(cx, obj, slots);
     }
 
 #ifdef JS_DUMP_SCOPE_METERS
     MeterEntryCount(scope->entryCount);
 #endif
 
-    sprop = scope->lastProp;
-    if (sprop) {
-        JS_ASSERT(scope->has(sprop));
-
-        /* Regenerate property cache shape ids if GC'ing. */
-        if (IS_GC_MARKING_TRACER(trc) && cx->runtime->gcRegenShapes) {
-            if (!(sprop->flags & SPROP_FLAG_SHAPE_REGEN)) {
-                sprop->shape = js_RegenerateShapeForGC(cx);
-                sprop->flags |= SPROP_FLAG_SHAPE_REGEN;
-            }
-
-            uint32 shape = sprop->shape;
-            if (scope->hasOwnShape()) {
-                shape = js_RegenerateShapeForGC(cx);
-                JS_ASSERT(shape != sprop->shape);
-            }
-            scope->shape = shape;
-        }
-
-        /* Trace scope's property tree ancestor line. */
-        do {
-            if (scope->hadMiddleDelete() && !scope->has(sprop))
-                continue;
-            TRACE_SCOPE_PROPERTY(trc, sprop);
-        } while ((sprop = sprop->parent) != NULL);
-    }
+    scope->trace(trc);
 
     if (!JS_CLIST_IS_EMPTY(&cx->runtime->watchPointList))
         js_TraceWatchPoints(trc, obj);
 
     /* No one runs while the GC is running, so we can use LOCKED_... here. */
     clasp = LOCKED_OBJ_GET_CLASS(obj);
     if (clasp->mark) {
         if (clasp->flags & JSCLASS_MARK_IS_TRACE)
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -909,11 +909,15 @@ JS_FRIEND_API(void) js_DumpValue(jsval v
 JS_FRIEND_API(void) js_DumpId(jsid id);
 JS_FRIEND_API(void) js_DumpObject(JSObject *obj);
 JS_FRIEND_API(void) js_DumpStackFrame(JSStackFrame *fp);
 #endif
 
 extern uintN
 js_InferFlags(JSContext *cx, uintN defaultFlags);
 
+/* Object constructor native. Exposed only so the JIT can know its address. */
+JSBool
+js_Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
 JS_END_EXTERN_C
 
 #endif /* jsobj_h___ */
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -33,17 +33,17 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include <string.h>     /* memset */
+#include <string.h>
 #include "jsapi.h"
 #include "jsarena.h"
 #include "jsarray.h"
 #include "jsatom.h"
 #include "jsbool.h"
 #include "jscntxt.h"
 #include "jsdtoa.h"
 #include "jsfun.h"
@@ -73,17 +73,17 @@ JSClass js_JSONClass = {
 
 JSBool
 js_json_parse(JSContext *cx, uintN argc, jsval *vp)
 {
     JSString *s = NULL;
     jsval *argv = vp + 2;
     jsval reviver = JSVAL_NULL;
     JSAutoTempValueRooter(cx, 1, &reviver);
-    
+
     if (!JS_ConvertArguments(cx, argc, argv, "S / v", &s, &reviver))
         return JS_FALSE;
 
     JSONParser *jp = js_BeginJSONParse(cx, vp);
     JSBool ok = jp != NULL;
     if (ok) {
         ok = js_ConsumeJSONText(cx, jp, JS_GetStringChars(s), JS_GetStringLength(s));
         ok &= js_FinishJSONParse(cx, jp, reviver);
@@ -518,17 +518,17 @@ Str(JSContext *cx, jsid id, JSObject *ho
         if (JSVAL_IS_DOUBLE(*vp)) {
             jsdouble d = *JSVAL_TO_DOUBLE(*vp);
             if (!JSDOUBLE_IS_FINITE(d))
                 return  scx->callback(null_ucstr, JS_ARRAY_LENGTH(null_ucstr), scx->data);
         }
 
         char numBuf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr;
         jsdouble d = JSVAL_IS_INT(*vp) ? jsdouble(JSVAL_TO_INT(*vp)) : *JSVAL_TO_DOUBLE(*vp);
-        numStr = JS_dtostr(numBuf, sizeof numBuf, DTOSTR_STANDARD, 0, d);        
+        numStr = JS_dtostr(numBuf, sizeof numBuf, DTOSTR_STANDARD, 0, d);
         if (!numStr) {
             JS_ReportOutOfMemory(cx);
             return JS_FALSE;
         }
 
         jschar dstr[DTOSTR_STANDARD_BUFFER_SIZE];
         size_t dbufSize = DTOSTR_STANDARD_BUFFER_SIZE;
         if (!js_InflateStringToBuffer(cx, numStr, strlen(numStr), dstr, &dbufSize))
@@ -541,17 +541,17 @@ Str(JSContext *cx, jsid id, JSObject *ho
         JSBool ok;
 
         scx->depth++;
         ok = (JS_IsArrayObject(cx, JSVAL_TO_OBJECT(*vp)) ? JA : JO)(cx, vp, scx);
         scx->depth--;
 
         return ok;
     }
-    
+
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 static JSBool
 WriteStringGap(JSContext *cx, jsval space, JSStringBuffer *sb)
 {
     JSString *s = js_ValueToString(cx, space);
@@ -635,26 +635,26 @@ DestroyIdArrayOnError(JSContext *cx, JSI
     JS_DestroyIdArray(cx, ida);
     return JS_FALSE;
 }
 
 static JSBool
 Walk(JSContext *cx, jsid id, JSObject *holder, jsval reviver, jsval *vp)
 {
     JS_CHECK_RECURSION(cx, return JS_FALSE);
-    
+
     if (!OBJ_GET_PROPERTY(cx, holder, id, vp))
         return JS_FALSE;
 
     JSObject *obj;
 
     if (!JSVAL_IS_PRIMITIVE(*vp) && !js_IsCallable(obj = JSVAL_TO_OBJECT(*vp), cx)) {
         jsval propValue = JSVAL_NULL;
         JSAutoTempValueRooter tvr(cx, 1, &propValue);
-        
+
         if(OBJ_IS_ARRAY(cx, obj)) {
             jsuint length = 0;
             if (!js_GetLengthProperty(cx, obj, &length))
                 return JS_FALSE;
 
             for (jsuint i = 0; i < length; i++) {
                 jsid index;
                 if (!js_IndexToId(cx, i, &index))
@@ -708,17 +708,17 @@ Walk(JSContext *cx, jsid id, JSObject *h
     *vp = reviverResult;
 
     return JS_TRUE;
 }
 
 static JSBool
 Revive(JSContext *cx, jsval reviver, jsval *vp)
 {
-    
+
     JSObject *obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL);
     if (!obj)
         return JS_FALSE;
 
     jsval v = OBJECT_TO_JSVAL(obj);
     JSAutoTempValueRooter tvr(cx, 1, &v);
     if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(cx->runtime->atomState.emptyAtom),
                              *vp, NULL, NULL, JSPROP_ENUMERATE, NULL)) {
@@ -735,20 +735,19 @@ js_BeginJSONParse(JSContext *cx, jsval *
 {
     if (!cx)
         return NULL;
 
     JSObject *arr = js_NewArrayObject(cx, 0, NULL);
     if (!arr)
         return NULL;
 
-    JSONParser *jp = (JSONParser*) JS_malloc(cx, sizeof(JSONParser));
+    JSONParser *jp = (JSONParser*) cx->calloc(sizeof(JSONParser));
     if (!jp)
         return NULL;
-    memset(jp, 0, sizeof *jp);
 
     jp->objectStack = arr;
     if (!js_AddRoot(cx, &jp->objectStack, "JSON parse stack"))
         goto bad;
 
     jp->statep = jp->stateStack;
     *jp->statep = JSON_PARSE_STATE_INIT;
     jp->rootVal = rootVal;
@@ -793,17 +792,17 @@ js_FinishJSONParse(JSContext *cx, JSONPa
     js_FinishStringBuffer(&jp->objectKey);
     js_FinishStringBuffer(&jp->buffer);
 
     /* This internal API is infallible, in spite of its JSBool return type. */
     js_RemoveRoot(cx->runtime, &jp->objectStack);
 
     JSBool ok = *jp->statep == JSON_PARSE_STATE_FINISHED;
     jsval *vp = jp->rootVal;
-    JS_free(cx, jp);
+    cx->free(jp);
 
     if (!early_ok)
         return JS_FALSE;
 
     if (!ok) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_JSON_BAD_PARSE);
         return JS_FALSE;
     }
@@ -815,17 +814,17 @@ js_FinishJSONParse(JSContext *cx, JSONPa
 }
 
 static JSBool
 PushState(JSContext *cx, JSONParser *jp, JSONParserState state)
 {
     if (*jp->statep == JSON_PARSE_STATE_FINISHED) {
         // extra input
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_JSON_BAD_PARSE);
-        return JS_FALSE; 
+        return JS_FALSE;
     }
 
     jp->statep++;
     if ((uint32)(jp->statep - jp->stateStack) >= JS_ARRAY_LENGTH(jp->stateStack)) {
         // too deep
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_JSON_BAD_PARSE);
         return JS_FALSE;
     }
@@ -988,20 +987,20 @@ HandleNumber(JSContext *cx, JSONParser *
     if (!js_strtod(cx, buf, buf + len, &ep, &val))
         return JS_FALSE;
     if (ep != buf + len) {
         // bad number input
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_JSON_BAD_PARSE);
         return JS_FALSE;
     }
 
-    jsval numVal;        
+    jsval numVal;
     if (!JS_NewNumberValue(cx, val, &numVal))
         return JS_FALSE;
-        
+
     return PushPrimitive(cx, jp, numVal);
 }
 
 static JSBool
 HandleString(JSContext *cx, JSONParser *jp, const jschar *buf, uint32 len)
 {
     JSString *str = js_NewStringCopyN(cx, buf, len);
     if (!str)
@@ -1243,34 +1242,34 @@ js_ConsumeJSONText(JSContext *cx, JSONPa
             } else if (('a' <= c) && (c <= 'f')) {
                 jp->hexChar = (jp->hexChar << 4) | (c - 'a' + 0x0a);
             } else if (('A' <= c) && (c <= 'F')) {
                 jp->hexChar = (jp->hexChar << 4) | (c - 'A' + 0x0a);
             } else {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_JSON_BAD_PARSE);
                 return JS_FALSE;
             }
-            
+
             if (++(jp->numHex) == 4) {
                 js_FastAppendChar(&jp->buffer, jp->hexChar);
                 jp->hexChar = 0;
                 jp->numHex = 0;
                 *jp->statep = JSON_PARSE_STATE_STRING;
             }
             break;
 
           case JSON_PARSE_STATE_KEYWORD:
             if (JS7_ISLET(c)) {
                 js_FastAppendChar(&jp->buffer, c);
             } else {
                 // this character isn't part of the keyword, process it again
                 i--;
                 if (!PopState(cx, jp))
                     return JS_FALSE;
-            
+
                 if (!HandleData(cx, jp, JSON_DATA_KEYWORD))
                     return JS_FALSE;
             }
             break;
 
           case JSON_PARSE_STATE_NUMBER:
             if (IsNumChar(c)) {
                 js_FastAppendChar(&jp->buffer, c);
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -599,17 +599,17 @@ Sprint(Sprinter *sp, const char *format,
     va_start(ap, format);
     bp = JS_vsmprintf(format, ap);      /* XXX vsaprintf */
     va_end(ap);
     if (!bp) {
         JS_ReportOutOfMemory(sp->context);
         return -1;
     }
     offset = SprintCString(sp, bp);
-    free(bp);
+    js_free(bp);
     return offset;
 }
 
 const char js_EscapeMap[] = {
     '\b', 'b',
     '\f', 'f',
     '\n', 'n',
     '\r', 'r',
@@ -732,17 +732,17 @@ struct JSPrinter {
 #define JS_IN_GROUP_CONTEXT 0x10000
 
 JSPrinter *
 JS_NEW_PRINTER(JSContext *cx, const char *name, JSFunction *fun,
                uintN indent, JSBool pretty)
 {
     JSPrinter *jp;
 
-    jp = (JSPrinter *) JS_malloc(cx, sizeof(JSPrinter));
+    jp = (JSPrinter *) cx->malloc(sizeof(JSPrinter));
     if (!jp)
         return NULL;
     INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0);
     JS_INIT_ARENA_POOL(&jp->pool, name, 256, 1, &cx->scriptStackQuota);
     jp->indent = indent & ~JS_IN_GROUP_CONTEXT;
     jp->pretty = pretty;
     jp->grouped = (indent & JS_IN_GROUP_CONTEXT) != 0;
     jp->script = NULL;
@@ -759,17 +759,17 @@ JS_NEW_PRINTER(JSContext *cx, const char
     }
     return jp;
 }
 
 void
 js_DestroyPrinter(JSPrinter *jp)
 {
     JS_FinishArenaPool(&jp->pool);
-    JS_free(jp->sprinter.context, jp);
+    jp->sprinter.context->free(jp);
 }
 
 JSString *
 js_GetPrinterOutput(JSPrinter *jp)
 {
     JSContext *cx;
     JSString *str;
 
@@ -827,28 +827,28 @@ js_printf(JSPrinter *jp, const char *for
             return -1;
         fp[cc] = '\0';
         format = fp;
     }
 
     /* Allocate temp space, convert format, and put. */
     bp = JS_vsmprintf(format, ap);      /* XXX vsaprintf */
     if (fp) {
-        JS_free(jp->sprinter.context, fp);
+        jp->sprinter.context->free(fp);
         format = NULL;
     }
     if (!bp) {
         JS_ReportOutOfMemory(jp->sprinter.context);
         return -1;
     }
 
     cc = strlen(bp);
     if (SprintPut(&jp->sprinter, bp, (size_t)cc) < 0)
         cc = -1;
-    free(bp);
+    js_free(bp);
 
     va_end(ap);
     return cc;
 }
 
 JSBool
 js_puts(JSPrinter *jp, const char *s)
 {
@@ -924,17 +924,17 @@ GetOff(SprintStack *ss, uintN i)
                                     ss->printer->fun, pc);
         if (!bytes)
             return 0;
         if (bytes != FAILED_EXPRESSION_DECOMPILER) {
             off = SprintCString(&ss->sprinter, bytes);
             if (off < 0)
                 off = 0;
             ss->offsets[i] = off;
-            JS_free(ss->sprinter.context, bytes);
+            ss->sprinter.context->free(bytes);
             return off;
         }
         if (!ss->sprinter.base && SprintPut(&ss->sprinter, "", 0) >= 0) {
             memset(ss->sprinter.base, 0, ss->sprinter.offset);
             ss->offsets[i] = -1;
         }
     }
     return 0;
@@ -2503,24 +2503,24 @@ Decompile(SprintStack *ss, jsbytecode *p
                      * The offset tells distance to the end of the right-hand
                      * operand of the comma operator.
                      */
                     done = pc + len;
                     pc += js_GetSrcNoteOffset(sn, 0);
                     len = 0;
 
                     if (!Decompile(ss, done, pc - done, JSOP_POP)) {
-                        JS_free(cx, (char *)lval);
+                        cx->free((char *)lval);
                         return NULL;
                     }
 
                     /* Pop Decompile result and print comma expression. */
                     rval = POP_STR();
                     todo = Sprint(&ss->sprinter, "%s, %s", lval, rval);
-                    JS_free(cx, (char *)lval);
+                    cx->free((char *)lval);
                     break;
 
                   case SRC_HIDDEN:
                     /* Hide this pop, it's from a goto in a with or for/in. */
                     todo = -2;
                     break;
 
                   case SRC_DECL:
@@ -2542,26 +2542,26 @@ Decompile(SprintStack *ss, jsbytecode *p
 
                         lval = JS_strdup(cx, PopStr(ss, JSOP_NOP));
                         if (!lval)
                             return NULL;
 
                         /* Set saveop to reflect what we will push. */
                         saveop = JSOP_LEAVEBLOCKEXPR;
                         if (!Decompile(ss, pc, len, saveop)) {
-                            JS_free(cx, (char *)lval);
+                            cx->free((char *)lval);
                             return NULL;
                         }
                         rval = PopStr(ss, JSOP_SETNAME);
                         todo = Sprint(&ss->sprinter,
                                       (*rval == '{')
                                       ? "let (%s) (%s)"
                                       : "let (%s) %s",
                                       lval, rval);
-                        JS_free(cx, (char *)lval);
+                        cx->free((char *)lval);
                     }
                     break;
 
                   default:
                     /* Turn off parens around a yield statement. */
                     if (ss->opcodes[ss->top-1] == JSOP_YIELD)
                         op = JSOP_NOP;
 
@@ -2615,17 +2615,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                 JSAtom **atomv, *smallv[5];
                 JSScopeProperty *sprop;
 
                 LOAD_OBJECT(0);
                 argc = OBJ_BLOCK_COUNT(cx, obj);
                 if ((size_t)argc <= JS_ARRAY_LENGTH(smallv)) {
                     atomv = smallv;
                 } else {
-                    atomv = (JSAtom **) JS_malloc(cx, argc * sizeof(JSAtom *));
+                    atomv = (JSAtom **) cx->malloc(argc * sizeof(JSAtom *));
                     if (!atomv)
                         return NULL;
                 }
 
                 MUST_FLOW_THROUGH("enterblock_out");
 #define LOCAL_ASSERT_OUT(expr) LOCAL_ASSERT_CUSTOM(expr, ok = JS_FALSE; \
                                                    goto enterblock_out)
                 for (sprop = OBJ_SCOPE(obj)->lastProp; sprop;
@@ -2750,17 +2750,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                     break;
                 }
 
                 todo = -2;
 
 #undef LOCAL_ASSERT_OUT
               enterblock_out:
                 if (atomv != smallv)
-                    JS_free(cx, atomv);
+                    cx->free(atomv);
                 if (!ok)
                     return NULL;
               }
               break;
 
               case JSOP_LEAVEBLOCK:
               case JSOP_LEAVEBLOCKEXPR:
               {
@@ -3275,29 +3275,29 @@ Decompile(SprintStack *ss, jsbytecode *p
                   case SRC_COND:
                     xval = JS_strdup(cx, POP_STR());
                     if (!xval)
                         return NULL;
                     len = js_GetSrcNoteOffset(sn, 0);
                     DECOMPILE_CODE(pc + oplen, len - oplen);
                     lval = JS_strdup(cx, POP_STR());
                     if (!lval) {
-                        JS_free(cx, (void *)xval);
+                        cx->free((void *)xval);
                         return NULL;
                     }
                     pc += len;
                     LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX);
                     oplen = js_CodeSpec[*pc].length;
                     len = GetJumpOffset(pc, pc);
                     DECOMPILE_CODE(pc + oplen, len - oplen);
                     rval = POP_STR();
                     todo = Sprint(&ss->sprinter, "%s ? %s : %s",
                                   xval, lval, rval);
-                    JS_free(cx, (void *)xval);
-                    JS_free(cx, (void *)lval);
+                    cx->free((void *)xval);
+                    cx->free((void *)lval);
                     break;
 
                   default:
                     break;
                 }
                 break;
               }
 
@@ -3314,37 +3314,37 @@ Decompile(SprintStack *ss, jsbytecode *p
                 /* Top of stack is the first clause in a disjunction (||). */
                 lval = JS_strdup(cx, POP_STR());
                 if (!lval)
                     return NULL;
                 done = pc + GetJumpOffset(pc, pc);
                 pc += len;
                 len = done - pc;
                 if (!Decompile(ss, pc, len, op)) {
-                    JS_free(cx, (char *)lval);
+                    cx->free((char *)lval);
                     return NULL;
                 }
                 rval = POP_STR();
                 if (jp->pretty &&
                     jp->indent + 4 + strlen(lval) + 4 + strlen(rval) > 75) {
                     rval = JS_strdup(cx, rval);
                     if (!rval) {
                         tail = -1;
                     } else {
                         todo = Sprint(&ss->sprinter, "%s %s\n", lval, xval);
                         tail = Sprint(&ss->sprinter, "%*s%s",
                                       jp->indent + 4, "", rval);
-                        JS_free(cx, (char *)rval);
+                        cx->free((char *)rval);
                     }
                     if (tail < 0)
                         todo = -1;
                 } else {
                     todo = Sprint(&ss->sprinter, "%s %s %s", lval, xval, rval);
                 }
-                JS_free(cx, (char *)lval);
+                cx->free((char *)lval);
                 break;
 
               case JSOP_AND:
               case JSOP_ANDX:
                 xval = "&&";
                 goto do_logical_connective;
 
               case JSOP_FORARG:
@@ -3527,17 +3527,17 @@ Decompile(SprintStack *ss, jsbytecode *p
               case JSOP_CALL:
               case JSOP_EVAL:
               case JSOP_APPLY:
 #if JS_HAS_LVALUE_RETURN
               case JSOP_SETCALL:
 #endif
                 argc = GET_ARGC(pc);
                 argv = (char **)
-                    JS_malloc(cx, (size_t)(argc + 1) * sizeof *argv);
+                    cx->malloc((size_t)(argc + 1) * sizeof *argv);
                 if (!argv)
                     return NULL;
 
                 op = JSOP_SETNAME;
                 ok = JS_TRUE;
                 for (i = argc; i > 0; i--)
                     argv[i] = JS_strdup(cx, POP_STR());
 
@@ -3585,18 +3585,18 @@ Decompile(SprintStack *ss, jsbytecode *p
                         ok = JS_FALSE;
                         break;
                     }
                 }
                 if (Sprint(&ss->sprinter, rval) < 0)
                     ok = JS_FALSE;
 
                 for (i = 0; i <= argc; i++)
-                    JS_free(cx, argv[i]);
-                JS_free(cx, argv);
+                    cx->free(argv[i]);
+                cx->free(argv);
                 if (!ok)
                     return NULL;
 #if JS_HAS_LVALUE_RETURN
                 if (op == JSOP_SETCALL) {
                     if (!PushOff(ss, todo, op))
                         return NULL;
                     todo = Sprint(&ss->sprinter, "");
                 }
@@ -4090,17 +4090,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                      * the top of ss2 because both ss and ss2 arena-allocate
                      * from cx's tempPool.
                      */
                     rval = JS_strdup(cx, PopStr(&ss2, op));
                     JS_ARENA_RELEASE(&cx->tempPool, mark);
                     if (!rval)
                         return NULL;
                     todo = SprintCString(&ss->sprinter, rval);
-                    JS_free(cx, (void *)rval);
+                    cx->free((void *)rval);
                     break;
                 }
 #endif /* JS_HAS_GENERATOR_EXPRS */
                 /* FALL THROUGH */
 
                 LOAD_FUNCTION(0);
                 {
                     uintN indent = JS_DONT_PRETTY_PRINT;
@@ -4161,17 +4161,17 @@ Decompile(SprintStack *ss, jsbytecode *p
 
                 n = high - low + 1;
                 if (n == 0) {
                     table = NULL;
                     j = 0;
                     ok = JS_TRUE;
                 } else {
                     table = (TableEntry *)
-                            JS_malloc(cx, (size_t)n * sizeof *table);
+                            cx->malloc((size_t)n * sizeof *table);
                     if (!table)
                         return NULL;
                     for (i = j = 0; i < n; i++) {
                         table[j].label = NULL;
                         off2 = GetJumpOffset(pc, pc2);
                         if (off2) {
                             sn = js_GetSrcNote(jp->script, pc2);
                             if (sn) {
@@ -4181,32 +4181,32 @@ Decompile(SprintStack *ss, jsbytecode *p
                             table[j].key = INT_TO_JSVAL(low + i);
                             table[j].offset = off2;
                             table[j].order = j;
                             j++;
                         }
                         pc2 += jmplen;
                     }
                     tmp = (TableEntry *)
-                          JS_malloc(cx, (size_t)j * sizeof *table);
+                          cx->malloc((size_t)j * sizeof *table);
                     if (tmp) {
                         VOUCH_DOES_NOT_REQUIRE_STACK();
                         ok = js_MergeSort(table, (size_t)j, sizeof(TableEntry),
                                           CompareOffsets, NULL, tmp);
-                        JS_free(cx, tmp);
+                        cx->free(tmp);
                     } else {
                         ok = JS_FALSE;
                     }
                 }
 
                 if (ok) {
                     ok = DecompileSwitch(ss, table, (uintN)j, pc, len, off,
                                          JS_FALSE);
                 }
-                JS_free(cx, table);
+                cx->free(table);
                 if (!ok)
                     return NULL;
                 todo = -2;
                 break;
               }
 
               case JSOP_LOOKUPSWITCH:
               case JSOP_LOOKUPSWITCHX:
@@ -4222,17 +4222,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                                                    : JUMPX_OFFSET_LEN;
                 pc2 = pc;
                 off = GetJumpOffset(pc, pc2);
                 pc2 += jmplen;
                 npairs = GET_UINT16(pc2);
                 pc2 += UINT16_LEN;
 
                 table = (TableEntry *)
-                    JS_malloc(cx, (size_t)npairs * sizeof *table);
+                    cx->malloc((size_t)npairs * sizeof *table);
                 if (!table)
                     return NULL;
                 for (k = 0; k < npairs; k++) {
                     sn = js_GetSrcNote(jp->script, pc2);
                     if (sn) {
                         LOCAL_ASSERT(SN_TYPE(sn) == SRC_LABEL);
                         GET_SOURCE_NOTE_ATOM(sn, table[k].label);
                     } else {
@@ -4243,17 +4243,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                     off2 = GetJumpOffset(pc, pc2);
                     pc2 += jmplen;
                     table[k].key = ATOM_KEY(atom);
                     table[k].offset = off2;
                 }
 
                 ok = DecompileSwitch(ss, table, (uintN)npairs, pc, len, off,
                                      JS_FALSE);
-                JS_free(cx, table);
+                cx->free(table);
                 if (!ok)
                     return NULL;
                 todo = -2;
                 break;
               }
 
               case JSOP_CONDSWITCH:
               {
@@ -4287,17 +4287,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                 }
 
                 /*
                  * Allocate table and rescan the cases using their srcnotes,
                  * stashing each case's delta from switch top in table[i].key,
                  * and the distance to its statements in table[i].offset.
                  */
                 table = (TableEntry *)
-                    JS_malloc(cx, (size_t)ncases * sizeof *table);
+                    cx->malloc((size_t)ncases * sizeof *table);
                 if (!table)
                     return NULL;
                 pc2 = pc;
                 off2 = off;
                 for (i = 0; i < ncases; i++) {
                     pc2 += off2;
                     LOCAL_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT ||
                                  *pc2 == JSOP_CASEX || *pc2 == JSOP_DEFAULTX);
@@ -4317,17 +4317,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                  * case at the end.
                  */
                 off = JSVAL_TO_INT(table[ncases-1].key);
                 pc2 = pc + off;
                 off += GetJumpOffset(pc2, pc2);
 
                 ok = DecompileSwitch(ss, table, (uintN)ncases, pc, len, off,
                                      JS_TRUE);
-                JS_free(cx, table);
+                cx->free(table);
                 if (!ok)
                     return NULL;
                 todo = -2;
                 break;
               }
 
               case JSOP_CASE:
               case JSOP_CASEX:
@@ -4365,17 +4365,17 @@ Decompile(SprintStack *ss, jsbytecode *p
               case JSOP_NEWARRAY:
                 argc = GET_UINT16(pc);
                 LOCAL_ASSERT(ss->top >= (uintN) argc);
                 if (argc == 0) {
                     todo = SprintCString(&ss->sprinter, "[]");
                     break;
                 }
 
-                argv = (char **) JS_malloc(cx, size_t(argc) * sizeof *argv);
+                argv = (char **) cx->malloc(size_t(argc) * sizeof *argv);
                 if (!argv)
                     return NULL;
 
                 op = JSOP_SETNAME;
                 ok = JS_TRUE;
                 i = argc;
                 while (i > 0)
                     argv[--i] = JS_strdup(cx, POP_STR());
@@ -4389,18 +4389,18 @@ Decompile(SprintStack *ss, jsbytecode *p
                         Sprint(&ss->sprinter, ss_format,
                                argv[i], (i < argc - 1) ? ", " : "") < 0) {
                         ok = JS_FALSE;
                         break;
                     }
                 }
 
                 for (i = 0; i < argc; i++)
-                    JS_free(cx, argv[i]);
-                JS_free(cx, argv);
+                    cx->free(argv[i]);
+                cx->free(argv);
                 if (!ok)
                     return NULL;
 
                 sn = js_GetSrcNote(jp->script, pc);
                 if (sn && SN_TYPE(sn) == SRC_CONTINUE && SprintCString(&ss->sprinter, ", ") < 0)
                     return NULL;
                 if (SprintCString(&ss->sprinter, "]") < 0)
                     return NULL;
@@ -4723,17 +4723,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                 rval = JS_strdup(cx, POP_STR());
                 if (!rval)
                     return NULL;
                 todo = SprintPut(&ss->sprinter, "<?", 2);
                 ok = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0) &&
                      (*rval == '\0' ||
                       (SprintPut(&ss->sprinter, " ", 1) >= 0 &&
                        SprintCString(&ss->sprinter, rval)));
-                JS_free(cx, (char *)rval);
+                cx->free((char *)rval);
                 if (!ok)
                     return NULL;
                 SprintPut(&ss->sprinter, "?>", 2);
                 break;
 
               case JSOP_GETFUNNS:
                 todo = SprintPut(&ss->sprinter, js_function_str, 8);
                 break;
@@ -4831,17 +4831,17 @@ DecompileCode(JSPrinter *jp, JSScript *s
     if (code != oldcode) {
         jp->script->code = code;
         jp->script->main = code + (oldmain - oldcode);
         pc = code + (pc - oldcode);
     }
 
     ok = Decompile(&ss, pc, len, JSOP_NOP) != NULL;
     if (code != oldcode) {
-        JS_free(cx, jp->script->code);
+        cx->free(jp->script->code);
         jp->script->code = oldcode;
         jp->script->main = oldmain;
     }
     jp->script = oldscript;
 
     /* If the given code didn't empty the stack, do it now. */
     if (ok && ss.top) {
         do {
@@ -5050,17 +5050,17 @@ js_DecompileValueGenerator(JSContext *cx
     if (spindex != JSDVG_IGNORE_STACK) {
         jsbytecode **pcstack;
 
         /*
          * Prepare computing pcstack containing pointers to opcodes that
          * populated interpreter's stack with its current content.
          */
         pcstack = (jsbytecode **)
-                  JS_malloc(cx, StackDepth(script) * sizeof *pcstack);
+                  cx->malloc(StackDepth(script) * sizeof *pcstack);
         if (!pcstack)
             return NULL;
         pcdepth = ReconstructPCStack(cx, script, pc, pcstack);
         if (pcdepth < 0)
             goto release_pcstack;
 
         if (spindex != JSDVG_SEARCH_STACK) {
             JS_ASSERT(spindex < 0);
@@ -5091,17 +5091,17 @@ js_DecompileValueGenerator(JSContext *cx
              * if beneath stackBase + pcdepth; otherwise blame existing
              * (current) PC.
              */
             if (sp < stackBase + pcdepth)
                 pc = pcstack[sp - stackBase];
         }
 
       release_pcstack:
-        JS_free(cx, pcstack);
+        cx->free(pcstack);
         if (pcdepth < 0)
             goto do_fallback;
     }
 
     {
         jsbytecode* savepc = regs->pc;
         jsbytecode* imacpc = fp->imacpc;
         if (imacpc) {
@@ -5227,17 +5227,17 @@ DecompileExpression(JSContext *cx, JSScr
     }
     len = end - begin;
     if (len <= 0) {
         name = FAILED_EXPRESSION_DECOMPILER;
         goto out;
     }
 
     pcstack = (jsbytecode **)
-              JS_malloc(cx, StackDepth(script) * sizeof *pcstack);
+              cx->malloc(StackDepth(script) * sizeof *pcstack);
     if (!pcstack) {
         name = NULL;
         goto out;
     }
 
     MUST_FLOW_THROUGH("out");
     pcdepth = ReconstructPCStack(cx, script, begin, pcstack);
     if (pcdepth < 0) {
@@ -5254,22 +5254,22 @@ DecompileExpression(JSContext *cx, JSScr
             name = (jp->sprinter.base) ? jp->sprinter.base : (char *) "";
             name = JS_strdup(cx, name);
         }
         js_DestroyPrinter(jp);
     }
 
   out:
     if (code != oldcode) {
-        JS_free(cx, script->code);
+        cx->free(script->code);
         script->code = oldcode;
         script->main = oldmain;
     }
 
-    JS_free(cx, pcstack);
+    cx->free(pcstack);
     return name;
 }
 
 uintN
 js_ReconstructStackDepth(JSContext *cx, JSScript *script, jsbytecode *pc)
 {
     return ReconstructPCStack(cx, script, pc, NULL);
 }
@@ -5334,17 +5334,17 @@ SimulateOp(JSContext *cx, JSScript *scri
 
 #ifdef JS_TRACER
 static intN
 SimulateImacroCFG(JSContext *cx, JSScript *script,
                   uintN pcdepth, jsbytecode *pc, jsbytecode *target,
                   jsbytecode **pcstack)
 {
     size_t nbytes = StackDepth(script) * sizeof *pcstack;
-    jsbytecode** tmp_pcstack = (jsbytecode **) JS_malloc(cx, nbytes);
+    jsbytecode** tmp_pcstack = (jsbytecode **) cx->malloc(nbytes);
     if (!tmp_pcstack)
         return -1;
     memcpy(tmp_pcstack, pcstack, nbytes);
 
     ptrdiff_t oplen;
     for (; pc < target; pc += oplen) {
         JSOp op = js_GetOpcode(cx, script, pc);
         const JSCodeSpec *cs = &js_CodeSpec[op];
@@ -5374,21 +5374,21 @@ SimulateImacroCFG(JSContext *cx, JSScrip
 
     if (pc > target)
         goto failure;
 
     LOCAL_ASSERT(pc == target);
 
   success:
     memcpy(pcstack, tmp_pcstack, nbytes);
-    JS_free(cx, tmp_pcstack);
+    cx->free(tmp_pcstack);
     return pcdepth;
 
   failure:
-    JS_free(cx, tmp_pcstack);
+    cx->free(tmp_pcstack);
     return -1;
 }
 
 static intN
 ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
                    jsbytecode **pcstack);
 
 static intN
--- a/js/src/jsparse.cpp
+++ b/js/src/jsparse.cpp
@@ -3797,17 +3797,17 @@ CheckDestructuring(JSContext *cx, BindDa
                                 JSMSG_NO_VARIABLE_NAME);
     ok = JS_FALSE;
     goto out;
 }
 
 /*
  * This is a greatly pared down version of CheckDestructuring that extends the
  * pn_pos.end source coordinate of each name in a destructuring binding such as
- * 
+ *
  *   var [x, y] = [function () y, 42];
  *
  * to cover its corresponding initializer, so that the initialized binding does
  * not appear to dominate any closures in its initializer. See bug 496134.
  *
  * The quick-and-dirty dominance computation in JSCompiler::setFunctionKinds is
  * not very precise. With one-pass SSA construction from structured source code
  * (see "Single-Pass Generation of Static Single Assignment Form for Structured
@@ -9031,22 +9031,22 @@ js_FoldConstants(JSContext *cx, JSParseN
                     return JS_FALSE;
                 /* XXX fold only if all operands convert to string */
                 if (pn2->pn_type != TOK_STRING)
                     return JS_TRUE;
                 length += ATOM_TO_STRING(pn2->pn_atom)->flatLength();
             }
 
             /* Allocate a new buffer and string descriptor for the result. */
-            chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+            chars = (jschar *) cx->malloc((length + 1) * sizeof(jschar));
             if (!chars)
                 return JS_FALSE;
             str = js_NewString(cx, chars, length);
             if (!str) {
-                JS_free(cx, chars);
+                cx->free(chars);
                 return JS_FALSE;
             }
 
             /* Fill the buffer, advancing chars and recycling kids as we go. */
             for (pn2 = pn1; pn2; pn2 = RecycleTree(pn2, tc)) {
                 str2 = ATOM_TO_STRING(pn2->pn_atom);
                 length2 = str2->flatLength();
                 js_strncpy(chars, str2->flatChars(), length2);
--- a/js/src/jsprf.cpp
+++ b/js/src/jsprf.cpp
@@ -407,17 +407,17 @@ static int cvt_ws(SprintfState *ss, cons
      * and malloc() is used to allocate the buffer buffer.
      */
     if (ws) {
         int slen = js_strlen(ws);
         char *s = js_DeflateString(NULL, ws, slen);
         if (!s)
             return -1; /* JSStuffFunc error indicator. */
         result = cvt_s(ss, s, width, prec, flags);
-        free(s);
+        js_free(s);
     } else {
         result = cvt_s(ss, NULL, width, prec, flags);
     }
     return result;
 }
 
 /*
 ** BuildArgArray stands for Numbered Argument list Sprintf
@@ -625,17 +625,17 @@ static struct NumArgState* BuildArgArray
 
     /*
     ** third pass
     ** fill the nas[cn].ap
     */
 
     if( *rv < 0 ){
         if( nas != nasArray )
-            free( nas );
+            js_free( nas );
         return NULL;
     }
 
     cn = 0;
     while( cn < number ){
         if( nas[cn].type == TYPE_UNKNOWN ){
             cn++;
             continue;
@@ -662,17 +662,17 @@ static struct NumArgState* BuildArgArray
         case TYPE_WSTRING:      (void)va_arg( ap, jschar* );            break;
 
         case TYPE_INTSTR:       (void)va_arg( ap, JSIntn* );            break;
 
         case TYPE_DOUBLE:       (void)va_arg( ap, double );             break;
 
         default:
             if( nas != nasArray )
-                free( nas );
+                js_free( nas );
             *rv = -1;
             return NULL;
         }
 
         cn++;
     }
 
 
@@ -751,17 +751,17 @@ static int dosprintf(SprintfState *ss, c
             i = 0;
             while( c && c != '$' ){         /* should imporve error check later */
                 i = ( i * 10 ) + ( c - '0' );
                 c = *fmt++;
             }
 
             if( nas[i-1].type == TYPE_UNKNOWN ){
                 if( nas && ( nas != nasArray ) )
-                    free( nas );
+                    js_free( nas );
                 return -1;
             }
 
             ap = nas[i-1].ap;
             dolPt = fmt;
             c = *fmt++;
         }
 
@@ -1032,17 +1032,17 @@ static int dosprintf(SprintfState *ss, c
             }
         }
     }
 
     /* Stuff trailing NUL */
     rv = (*ss->stuff)(ss, "\0", 1);
 
     if( nas && ( nas != nasArray ) ){
-        free( nas );
+        js_free( nas );
     }
 
     return rv;
 }
 
 /************************************************************************/
 
 static int FuncStuff(SprintfState *ss, const char *sp, JSUint32 len)
@@ -1093,19 +1093,19 @@ static int GrowStuff(SprintfState *ss, c
     char *newbase;
     JSUint32 newlen;
 
     off = ss->cur - ss->base;
     if (off + len >= ss->maxlen) {
         /* Grow the buffer */
         newlen = ss->maxlen + ((len > 32) ? len : 32);
         if (ss->base) {
-            newbase = (char*) realloc(ss->base, newlen);
+            newbase = (char*) js_realloc(ss->base, newlen);
         } else {
-            newbase = (char*) malloc(newlen);
+            newbase = (char*) js_malloc(newlen);
         }
         if (!newbase) {
             /* Ran out of memory */
             return -1;
         }
         ss->base = newbase;
         ss->maxlen = newlen;
         ss->cur = ss->base + off;
@@ -1134,32 +1134,32 @@ JS_PUBLIC_API(char *) JS_smprintf(const 
     return rv;
 }
 
 /*
 ** Free memory allocated, for the caller, by JS_smprintf
 */
 JS_PUBLIC_API(void) JS_smprintf_free(char *mem)
 {
-        free(mem);
+        js_free(mem);
 }
 
 JS_PUBLIC_API(char *) JS_vsmprintf(const char *fmt, va_list ap)
 {
     SprintfState ss;
     int rv;
 
     ss.stuff = GrowStuff;
     ss.base = 0;
     ss.cur = 0;
     ss.maxlen = 0;
     rv = dosprintf(&ss, fmt, ap);
     if (rv < 0) {
         if (ss.base) {
-            free(ss.base);
+            js_free(ss.base);
         }
         return 0;
     }
     return ss.base;
 }
 
 /*
 ** Stuff routine that discards overflow data
@@ -1248,15 +1248,15 @@ JS_PUBLIC_API(char *) JS_vsprintf_append
     } else {
         ss.base = 0;
         ss.cur = 0;
         ss.maxlen = 0;
     }
     rv = dosprintf(&ss, fmt, ap);
     if (rv < 0) {
         if (ss.base) {
-            free(ss.base);
+            js_free(ss.base);
         }
         return 0;
     }
     return ss.base;
 }
 
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -101,18 +101,18 @@ typedef enum JSProtoKey {
     JSProto_LIMIT
 } JSProtoKey;
 
 /* JSObjectOps.checkAccess mode enumeration. */
 typedef enum JSAccessMode {
     JSACC_PROTO  = 0,           /* XXXbe redundant w.r.t. id */
     JSACC_PARENT = 1,           /* XXXbe redundant w.r.t. id */
 
-                                /* 
-                                 * enum value #2 formerly called JSACC_IMPORT, 
+                                /*
+                                 * enum value #2 formerly called JSACC_IMPORT,
                                  * gap preserved for ABI compatibility.
                                  */
 
     JSACC_WATCH  = 3,           /* a watchpoint on object foo for id 'bar' */
     JSACC_READ   = 4,           /* a "get" of foo.bar */
     JSACC_WRITE  = 8,           /* a "set" of foo.bar = baz */
     JSACC_LIMIT
 } JSAccessMode;
@@ -140,17 +140,16 @@ typedef struct JSFunctionSpec    JSFunct
 typedef struct JSTracer          JSTracer;
 typedef struct JSIdArray         JSIdArray;
 typedef struct JSPropertyDescriptor JSPropertyDescriptor;
 typedef struct JSPropertySpec    JSPropertySpec;
 typedef struct JSObject          JSObject;
 typedef struct JSObjectMap       JSObjectMap;
 typedef struct JSObjectOps       JSObjectOps;
 typedef struct JSRuntime         JSRuntime;
-typedef struct JSRuntime         JSTaskState;   /* XXX deprecated name */
 typedef struct JSScript          JSScript;
 typedef struct JSStackFrame      JSStackFrame;
 typedef struct JSString          JSString;
 typedef struct JSXDRState        JSXDRState;
 typedef struct JSExceptionState  JSExceptionState;
 typedef struct JSLocaleCallbacks JSLocaleCallbacks;
 typedef struct JSSecurityCallbacks JSSecurityCallbacks;
 typedef struct JSONParser        JSONParser;
--- a/js/src/jsregexp.cpp
+++ b/js/src/jsregexp.cpp
@@ -580,22 +580,22 @@ ParseRegExp(CompilerState *state)
 
     /* Watch out for empty regexp */
     if (state->cp == state->cpend) {
         state->result = NewRENode(state, REOP_EMPTY);
         return (state->result != NULL);
     }
 
     operatorStack = (REOpData *)
-        JS_malloc(state->context, sizeof(REOpData) * operatorStackSize);
+        state->context->malloc(sizeof(REOpData) * operatorStackSize);
     if (!operatorStack)
         return JS_FALSE;
 
     operandStack = (RENode **)
-        JS_malloc(state->context, sizeof(RENode *) * operandStackSize);
+        state->context->malloc(sizeof(RENode *) * operandStackSize);
     if (!operandStack)
         goto out;
 
     for (;;) {
         parenIndex = state->parenCount;
         if (state->cp == state->cpend) {
             /*
              * If we are at the end of the regexp and we're short one or more
@@ -677,18 +677,18 @@ ParseRegExp(CompilerState *state)
                 if (!ParseTerm(state))
                     goto out;
                 operand = state->result;
 pushOperand:
                 if (operandSP == operandStackSize) {
                     RENode **tmp;
                     operandStackSize += operandStackSize;
                     tmp = (RENode **)
-                        JS_realloc(state->context, operandStack,
-                                   sizeof(RENode *) * operandStackSize);
+                        state->context->realloc(operandStack,
+                                                sizeof(RENode *) * operandStackSize);
                     if (!tmp)
                         goto out;
                     operandStack = tmp;
                 }
                 operandStack[operandSP++] = operand;
                 break;
             }
         }
@@ -812,33 +812,33 @@ restartOperator:
           default:
             /* Anything else is the start of the next term. */
             op = REOP_CONCAT;
 pushOperator:
             if (operatorSP == operatorStackSize) {
                 REOpData *tmp;
                 operatorStackSize += operatorStackSize;
                 tmp = (REOpData *)
-                    JS_realloc(state->context, operatorStack,
-                               sizeof(REOpData) * operatorStackSize);
+                    state->context->realloc(operatorStack,
+                                            sizeof(REOpData) * operatorStackSize);
                 if (!tmp)
                     goto out;
                 operatorStack = tmp;
             }
             operatorStack[operatorSP].op = op;
             operatorStack[operatorSP].errPos = state->cp;
             operatorStack[operatorSP++].parenIndex = parenIndex;
             break;
         }
     }
 out:
     if (operatorStack)
-        JS_free(state->context, operatorStack);
+        state->context->free(operatorStack);
     if (operandStack)
-        JS_free(state->context, operandStack);
+        state->context->free(operandStack);
     return result;
 }
 
 /*
  * Hack two bits in CompilerState.flags, for use within FindParenCount to flag
  * its being on the stack, and to propagate errors to its callers.
  */
 #define JSREG_FIND_PAREN_COUNT  0x8000
@@ -1642,19 +1642,18 @@ EmitREBytecode(CompilerState *state, JSR
 {
     EmitStateStackEntry *emitStateSP, *emitStateStack;
     REOp op;
 
     if (treeDepth == 0) {
         emitStateStack = NULL;
     } else {
         emitStateStack =
-            (EmitStateStackEntry *)JS_malloc(state->context,
-                                             sizeof(EmitStateStackEntry) *
-                                             treeDepth);
+            (EmitStateStackEntry *)
+            state->context->malloc(sizeof(EmitStateStackEntry) * treeDepth);
         if (!emitStateStack)
             return NULL;
     }
     emitStateSP = emitStateStack;
     op = t->op;
     JS_ASSERT(op < REOP_LIMIT);
 
     for (;;) {
@@ -1946,17 +1945,17 @@ EmitREBytecode(CompilerState *state, JSR
             --emitStateSP;
             t = emitStateSP->continueNode;
             op = (REOp) emitStateSP->continueOp;
         }
     }
 
   cleanup:
     if (emitStateStack)
-        JS_free(state->context, emitStateStack);
+        state->context->free(emitStateStack);
     return pc;
 
   jump_too_big:
     ReportRegExpError(state, JSREPORT_ERROR, JSMSG_REGEXP_TOO_COMPLEX);
     pc = NULL;
     goto cleanup;
 }
 
@@ -1992,17 +1991,17 @@ CompileRegExpToAST(JSContext* cx, JSToke
         state.result->u.flat.chr = *state.cpbegin;
         state.result->u.flat.length = len;
         state.result->kid = (void *) state.cpbegin;
         /* Flat bytecode: REOP_FLAT compact(string_offset) compact(len). */
         state.progLength += 1 + GetCompactIndexWidth(0)
                           + GetCompactIndexWidth(len);
         return JS_TRUE;
     }
-    
+
     return ParseRegExp(&state);
 }
 
 #ifdef JS_TRACER
 typedef JSTempVector<LIns *> LInsList;
 
 /* Dummy GC for nanojit placement new. */
 static GC gc;
@@ -2405,25 +2404,25 @@ class RegExpNativeCompiler {
         }
 
     gen:
         for (int i = 0; i < nextras; ++i) {
             LIns *test = lir->ins2(LIR_eq, text_ch, lir->insImm(extras[i].ch));
             LIns *branch = lir->insBranch(LIR_jt, test, 0);
             extras[i].match = branch;
         }
-            
+
         fails.pushBack(lir->insBranch(LIR_jf, lir->ins2(LIR_eq, text_ch, lir->insImm(ch)), 0));
 
         for (int i = 0; i < nextras; ++i)
             targetCurrentPoint(extras[i].match);
         return lir->ins2(LIR_piadd, pos, lir->insImm(2));
     }
 
-    JS_INLINE bool hasCases(jschar ch) 
+    JS_INLINE bool hasCases(jschar ch)
     {
         return JS_TOLOWER(ch) != JS_TOUPPER(ch);
     }
 
     LIns* compileFlatDoubleChar(jschar ch1, jschar ch2, LIns* pos, LInsList& fails)
     {
 #ifdef IS_BIG_ENDIAN
         uint32 word = (ch1 << 16) | ch2;
@@ -3161,20 +3160,16 @@ CompileRegExpToNative(JSContext* cx, JSR
     RegExpNativeCompiler rc(re, &state, fragment);
 
     JS_ASSERT(!fragment->code());
     mark = JS_ARENA_MARK(&cx->tempPool);
     if (!CompileRegExpToAST(cx, NULL, re->source, re->flags, state)) {
         goto out;
     }
     rv = rc.compile(cx);
-    static int fail = 0;  // TODO: remove
-    if (!rv)
-        ++fail;
-    debug_only_printf(LC_TMRegexp, "## Fail? %d, Total %d\n", (int)!rv, fail);
  out:
     JS_ARENA_RELEASE(&cx->tempPool, mark);
     return rv;
 }
 
 /* Function type for a compiled native regexp. */
 typedef void *(FASTCALL *NativeRegExp)(REGlobalData*, const jschar *);
 
@@ -3227,26 +3222,26 @@ js_NewRegExp(JSContext *cx, JSTokenStrea
      * a flag, so that we keep this information in the JSRegExp, but
      * we keep the 'flat' parameter for now for compatibility.
      */
     if (flat) flags |= JSREG_FLAT;
     if (!CompileRegExpToAST(cx, ts, str, flags, state))
         goto out;
 
     resize = offsetof(JSRegExp, program) + state.progLength + 1;
-    re = (JSRegExp *) JS_malloc(cx, resize);
+    re = (JSRegExp *) cx->malloc(resize);
     if (!re)
         goto out;
 
     re->nrefs = 1;
     JS_ASSERT(state.classBitmapsMem <= CLASS_BITMAPS_MEM_LIMIT);
     re->classCount = state.classCount;
     if (re->classCount) {
         re->classList = (RECharSet *)
-            JS_malloc(cx, re->classCount * sizeof(RECharSet));
+            cx->malloc(re->classCount * sizeof(RECharSet));
         if (!re->classList) {
             js_DestroyRegExp(cx, re);
             re = NULL;
             goto out;
         }
         for (i = 0; i < re->classCount; i++)
             re->classList[i].converted = JS_FALSE;
     } else {
@@ -3265,17 +3260,17 @@ js_NewRegExp(JSContext *cx, JSTokenStrea
      * Check whether size was overestimated and shrink using realloc.
      * This is safe since no pointers to newly parsed regexp or its parts
      * besides re exist here.
      */
     if ((size_t)(endPC - re->program) != state.progLength + 1) {
         JSRegExp *tmp;
         JS_ASSERT((size_t)(endPC - re->program) < state.progLength + 1);
         resize = offsetof(JSRegExp, program) + (endPC - re->program);
-        tmp = (JSRegExp *) JS_realloc(cx, re, resize);
+        tmp = (JSRegExp *) cx->realloc(re, resize);
         if (tmp)
             re = tmp;
     }
 
     re->flags = flags;
     re->parenCount = state.parenCount;
     re->source = str;
 
@@ -3605,17 +3600,17 @@ ProcessCharSet(JSContext *cx, JSRegExp *
 
     charSet->converted = JS_TRUE;
     src = re->source->chars() + charSet->u.src.startIndex;
     end = src + charSet->u.src.length;
     JS_ASSERT(src[-1] == '[');
     JS_ASSERT(end[0] == ']');
 
     byteLength = (charSet->length >> 3) + 1;
-    charSet->u.bits = (uint8 *)JS_malloc(cx, byteLength);
+    charSet->u.bits = (uint8 *)cx->malloc(byteLength);
     if (!charSet->u.bits) {
         JS_ReportOutOfMemory(cx);
         return JS_FALSE;
     }
     memset(charSet->u.bits, 0, byteLength);
 
     if (src == end)
         return JS_TRUE;
@@ -3799,22 +3794,22 @@ MatcherProcessCharSet(REGlobalData *gDat
 void
 js_DestroyRegExp(JSContext *cx, JSRegExp *re)
 {
     if (JS_ATOMIC_DECREMENT(&re->nrefs) == 0) {
         if (re->classList) {
             uintN i;
             for (i = 0; i < re->classCount; i++) {
                 if (re->classList[i].converted)
-                    JS_free(cx, re->classList[i].u.bits);
+                    cx->free(re->classList[i].u.bits);
                 re->classList[i].u.bits = NULL;
             }
-            JS_free(cx, re->classList);
+            cx->free(re->classList);
         }
-        JS_free(cx, re);
+        cx->free(re);
     }
 }
 
 static JSBool
 ReallocStateStack(REGlobalData *gData)
 {
     size_t limit = gData->stateStackLimit;
     size_t sz = sizeof(REProgState) * limit;
@@ -4869,22 +4864,22 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp
                     res->parens[num].length = parsub->length;
                 }
             } else {
                 morenum = num - 9;
                 morepar = res->moreParens;
                 if (!morepar) {
                     res->moreLength = 10;
                     morepar = (JSSubString*)
-                        JS_malloc(cx, 10 * sizeof(JSSubString));
+                        cx->malloc(10 * sizeof(JSSubString));
                 } else if (morenum >= res->moreLength) {
                     res->moreLength += 10;
                     morepar = (JSSubString*)
-                        JS_realloc(cx, morepar,
-                                   res->moreLength * sizeof(JSSubString));
+                        cx->realloc(morepar,
+                                    res->moreLength * sizeof(JSSubString));
                 }
                 if (!morepar) {
                     cx->weakRoots.newborn[GCX_OBJECT] = NULL;
                     cx->weakRoots.newborn[GCX_STRING] = NULL;
                     ok = JS_FALSE;
                     goto out;
                 }
                 res->moreParens = morepar;
@@ -5113,17 +5108,17 @@ js_TraceRegExpStatics(JSTracer *trc, JSC
 }
 
 void
 js_FreeRegExpStatics(JSContext *cx)
 {
     JSRegExpStatics *res = &cx->regExpStatics;
 
     if (res->moreParens) {
-        JS_free(cx, res->moreParens);
+        cx->free(res->moreParens);
         res->moreParens = NULL;
     }
     JS_FinishArenaPool(&cx->regexpPool);
 }
 
 static JSBool
 regexp_static_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
 {
@@ -5364,17 +5359,17 @@ js_regexp_toString(JSContext *cx, JSObje
     if (length == 0) {
         source = empty_regexp_ucstr;
         length = JS_ARRAY_LENGTH(empty_regexp_ucstr) - 1;
     }
     length += 2;
     nflags = 0;
     for (flags = re->flags; flags != 0; flags &= flags - 1)
         nflags++;
-    chars = (jschar*) JS_malloc(cx, (length + nflags + 1) * sizeof(jschar));
+    chars = (jschar*) cx->malloc((length + nflags + 1) * sizeof(jschar));
     if (!chars) {
         JS_UNLOCK_OBJ(cx, obj);
         return JS_FALSE;
     }
 
     chars[0] = '/';
     js_strncpy(&chars[1], source, length - 2);
     chars[length-1] = '/';
@@ -5388,17 +5383,17 @@ js_regexp_toString(JSContext *cx, JSObje
         if (re->flags & JSREG_STICKY)
             chars[length++] = 'y';
     }
     JS_UNLOCK_OBJ(cx, obj);
     chars[length] = 0;
 
     str = js_NewString(cx, chars, length);
     if (!str) {
-        JS_free(cx, chars);
+        cx->free(chars);
         return JS_FALSE;
     }
     *vp = STRING_TO_JSVAL(str);
     return JS_TRUE;
 }
 
 static JSBool
 regexp_toString(JSContext *cx, uintN argc, jsval *vp)
@@ -5471,25 +5466,25 @@ regexp_compile_sub(JSContext *cx, JSObje
         /* Escape any naked slashes in the regexp source. */
         str->getCharsAndLength(start, length);
         end = start + length;
         nstart = ncp = NULL;
         for (cp = start; cp < end; cp++) {
             if (*cp == '/' && (cp == start || cp[-1] != '\\')) {
                 nbytes = (++length + 1) * sizeof(jschar);
                 if (!nstart) {
-                    nstart = (jschar *) JS_malloc(cx, nbytes);
+                    nstart = (jschar *) cx->malloc(nbytes);
                     if (!nstart)
                         return JS_FALSE;
                     ncp = nstart + (cp - start);
                     js_strncpy(nstart, start, cp - start);
                 } else {
-                    tmp = (jschar *) JS_realloc(cx, nstart, nbytes);
+                    tmp = (jschar *) cx->realloc(nstart, nbytes);
                     if (!tmp) {
-                        JS_free(cx, nstart);
+                        cx->free(nstart);
                         return JS_FALSE;
                     }
                     ncp = tmp + (ncp - nstart);
                     nstart = tmp;
                 }
                 *ncp++ = '\\';
             }
             if (nstart)
@@ -5497,17 +5492,17 @@ regexp_compile_sub(JSContext *cx, JSObje
         }
 
         if (nstart) {
             /* Don't forget to store the backstop after the new string. */
             JS_ASSERT((size_t)(ncp - nstart) == length);
             *ncp = 0;
             str = js_NewString(cx, nstart, length);
             if (!str) {
-                JS_free(cx, nstart);
+                cx->free(nstart);
                 return JS_FALSE;
             }
             argv[0] = STRING_TO_JSVAL(str);
         }
     }
 
     re = js_NewRegExpOpt(cx, str, opt, JS_FALSE);
 created:
--- a/js/src/jsscan.cpp
+++ b/js/src/jsscan.cpp
@@ -253,17 +253,17 @@ js_InitTokenStream(JSContext *cx, JSToke
     ts->listenerData = cx->debugHooks->sourceHandlerData;
     return JS_TRUE;
 }
 
 void
 js_CloseTokenStream(JSContext *cx, JSTokenStream *ts)
 {
     if (ts->flags & TSF_OWNFILENAME)
-        JS_free(cx, (void *) ts->filename);
+        cx->free((void *) ts->filename);
 }
 
 JS_FRIEND_API(int)
 js_fgets(char *buf, int size, FILE *file)
 {
     int n, i, c;
     JSBool crflag;
 
@@ -303,17 +303,17 @@ GetChar(JSTokenStream *ts)
     } else {
         if (ts->linebuf.ptr == ts->linebuf.limit) {
             len = ts->userbuf.limit - ts->userbuf.ptr;
             if (len <= 0) {
                 if (!ts->file) {
                     ts->flags |= TSF_EOF;
                     return EOF;
                 }
-        
+
                 /* Fill ts->userbuf so that \r and \r\n convert to \n. */
                 crflag = (ts->flags & TSF_CRFLAG) != 0;
                 len = js_fgets(cbuf, JS_LINE_LIMIT - crflag, ts->file);
                 if (len <= 0) {
                     ts->flags |= TSF_EOF;
                     return EOF;
                 }
                 olen = len;
@@ -331,17 +331,17 @@ GetChar(JSTokenStream *ts)
                     ubuf[i] = (jschar) (unsigned char) cbuf[j];
                 ts->userbuf.limit = ubuf + len;
                 ts->userbuf.ptr = ubuf;
             }
             if (ts->listener) {
                 ts->listener(ts->filename, ts->lineno, ts->userbuf.ptr, len,
                              &ts->listenerTSData, ts->listenerData);
             }
-        
+
             nl = ts->saveEOL;
             if (!nl) {
                 /*
                  * Any one of \n, \r, or \r\n ends a line (the longest
                  * match wins).  Also allow the Unicode line and paragraph
                  * separators.
                  */
                 for (nl = ts->userbuf.ptr; nl < ts->userbuf.limit; nl++) {
@@ -357,33 +357,33 @@ GetChar(JSTokenStream *ts)
                                 nl++;
                             break;
                         }
                         if (*nl == LINE_SEPARATOR || *nl == PARA_SEPARATOR)
                             break;
                     }
                 }
             }
-        
+
             /*
              * If there was a line terminator, copy thru it into linebuf.
              * Else copy JS_LINE_LIMIT-1 bytes into linebuf.
              */
             if (nl < ts->userbuf.limit)
                 len = (nl - ts->userbuf.ptr) + 1;
             if (len >= JS_LINE_LIMIT) {
                 len = JS_LINE_LIMIT - 1;
                 ts->saveEOL = nl;
             } else {
                 ts->saveEOL = NULL;
             }
             js_strncpy(ts->linebuf.base, ts->userbuf.ptr, len);
             ts->userbuf.ptr += len;
             olen = len;
-        
+
             /*
              * Make sure linebuf contains \n for EOL (don't do this in
              * userbuf because the user's string might be readonly).
              */
             if (nl < ts->userbuf.limit) {
                 if (*nl == '\r') {
                     if (ts->linebuf.base[len-1] == '\r') {
                         /*
@@ -415,31 +415,31 @@ GetChar(JSTokenStream *ts)
                         len--;
                         JS_ASSERT(ts->linebuf.base[len] == '\n');
                         ts->linebuf.base[len-1] = '\n';
                     }
                 } else if (*nl == LINE_SEPARATOR || *nl == PARA_SEPARATOR) {
                     ts->linebuf.base[len-1] = '\n';
                 }
             }
-        
+
             /* Reset linebuf based on adjusted segment length. */
             ts->linebuf.limit = ts->linebuf.base + len;
             ts->linebuf.ptr = ts->linebuf.base;
-        
+
             /* Update position of linebuf within physical userbuf line. */
             if (!(ts->flags & TSF_NLFLAG))
                 ts->linepos += ts->linelen;
             else
                 ts->linepos = 0;
             if (ts->linebuf.limit[-1] == '\n')
                 ts->flags |= TSF_NLFLAG;
             else
                 ts->flags &= ~TSF_NLFLAG;
-        
+
             /* Update linelen from original segment length. */
             ts->linelen = olen;
         }
         c = *ts->linebuf.ptr++;
     }
     if (c == '\n')
         ts->lineno++;
     return c;
@@ -557,17 +557,17 @@ js_ReportCompileErrorNumber(JSContext *c
             goto report;
         tp = &pn->pn_pos;
     } else {
         /* Point to the current token, not the next one to get. */
         tp = &ts->tokens[ts->cursor].pos;
     }
     report.lineno = ts->lineno;
     linelength = ts->linebuf.limit - ts->linebuf.base;
-    linechars = (jschar *)JS_malloc(cx, (linelength + 1) * sizeof(jschar));
+    linechars = (jschar *)cx->malloc((linelength + 1) * sizeof(jschar));
     if (!linechars) {
         warning = JS_FALSE;
         goto out;
     }
     memcpy(linechars, ts->linebuf.base, linelength * sizeof(jschar));
     linechars[linelength] = 0;
     linebytes = js_DeflateString(cx, linechars, linelength);
     if (!linebytes) {
@@ -646,31 +646,31 @@ js_ReportCompileErrorNumber(JSContext *c
             onError = NULL;
         }
     }
     if (onError)
         (*onError)(cx, message, &report);
 
   out:
     if (linebytes)
-        JS_free(cx, linebytes);
+        cx->free(linebytes);
     if (linechars)
-        JS_free(cx, linechars);
+        cx->free(linechars);
     if (message)
-        JS_free(cx, message);
+        cx->free(message);
     if (report.ucmessage)
-        JS_free(cx, (void *)report.ucmessage);
+        cx->free((void *)report.ucmessage);
 
     if (report.messageArgs) {
         if (!(flags & JSREPORT_UC)) {
             i = 0;
             while (report.messageArgs[i])
-                JS_free(cx, (void *)report.messageArgs[i++]);
+                cx->free((void *)report.messageArgs[i++]);
         }
-        JS_free(cx, (void *)report.messageArgs);
+        cx->free((void *)report.messageArgs);
     }
 
     if (!JSREPORT_IS_WARNING(flags)) {
         /* Set the error flag to suppress spurious reports. */
         ts->flags |= TSF_ERROR;
     }
 
     return warning;
@@ -693,38 +693,38 @@ GrowStringBuffer(JSStringBuffer *sb, siz
 
         if (newlength <= CHUNK_SIZE_MASK)
             newlength = JS_BIT(JS_CeilingLog2(newlength));
         else if (newlength & CHUNK_SIZE_MASK)
             newlength = (newlength | CHUNK_SIZE_MASK) + 1;
 
         /* Now do the full overflow check. */
         if (size_t(offset) < newlength && newlength < ~size_t(0) / sizeof(jschar)) {
-            jschar *bp = (jschar *) realloc(sb->base, newlength * sizeof(jschar));
+            jschar *bp = (jschar *) js_realloc(sb->base, newlength * sizeof(jschar));
             if (bp) {
                 sb->base = bp;
                 sb->ptr = bp + offset;
                 sb->limit = bp + newlength - 1;
                 return true;
             }
         }
     }
 
     /* Either newlength overflow or realloc failure: poison the well. */
-    free(sb->base);
+    js_free(sb->base);
     sb->base = STRING_BUFFER_ERROR_BASE;
     return false;
 }
 
 static void
 FreeStringBuffer(JSStringBuffer *sb)
 {
     JS_ASSERT(STRING_BUFFER_OK(sb));
     if (sb->base)
-        free(sb->base);
+        js_free(sb->base);
 }
 
 void
 js_InitStringBuffer(JSStringBuffer *sb)
 {
     sb->base = sb->limit = sb->ptr = NULL;
     sb->data = NULL;
     sb->grow = GrowStringBuffer;
@@ -919,17 +919,17 @@ bad:
     /* No match: throw a TypeError per ECMA-357 10.3.2.1 step 8(a). */
     JS_ASSERT(STRING_BUFFER_OK(&ts->tokenbuf));
     JS_ASSERT((ts->tokenbuf.ptr - bp) >= 1);
     bytes = js_DeflateString(cx, bp + 1,
                              (ts->tokenbuf.ptr - bp) - 1);
     if (bytes) {
         js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
                                     msg, bytes);
-        JS_free(cx, bytes);
+        cx->free(bytes);
     }
     return JS_FALSE;
 }
 
 #endif /* JS_HAS_XML_SUPPORT */
 
 JSTokenType
 js_PeekToken(JSContext *cx, JSTokenStream *ts)
@@ -1783,17 +1783,17 @@ retry:
                                     continue;
                                 }
                             }
                         }
                         filename[i] = '\0';
                         if (c == '\n') {
                             if (i > 0) {
                                 if (ts->flags & TSF_OWNFILENAME)
-                                    JS_free(cx, (void *) ts->filename);
+                                    cx->free((void *) ts->filename);
                                 ts->filename = JS_strdup(cx, filename);
                                 if (!ts->filename)
                                     goto error;
                                 ts->flags |= TSF_OWNFILENAME;
                             }
                             ts->lineno = line;
                         }
                     }
--- a/js/src/jsscope.cpp
+++ b/js/src/jsscope.cpp
@@ -161,17 +161,17 @@ JSScope::createTable(JSContext *cx, bool
          */
         sizeLog2 = JS_CeilingLog2(2 * entryCount);
         hashShift = JS_DHASH_BITS - sizeLog2;
     } else {
         JS_ASSERT(hashShift == JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2);
         sizeLog2 = MIN_SCOPE_SIZE_LOG2;
     }
 
-    table = (JSScopeProperty **) calloc(JS_BIT(sizeLog2), sizeof(JSScopeProperty *));
+    table = (JSScopeProperty **) js_calloc(JS_BIT(sizeLog2) * sizeof(JSScopeProperty *));
     if (!table) {
         if (report)
             JS_ReportOutOfMemory(cx);
         return false;
     }
     cx->updateMallocCounter(JS_BIT(sizeLog2) * sizeof(JSScopeProperty *));
 
     hashShift = JS_DHASH_BITS - sizeLog2;
@@ -183,55 +183,55 @@ JSScope::createTable(JSContext *cx, bool
 }
 
 JSScope *
 JSScope::create(JSContext *cx, JSObjectOps *ops, JSClass *clasp, JSObject *obj)
 {
     JS_ASSERT(OPS_IS_NATIVE(ops));
     JS_ASSERT(obj);
 
-    JSScope *scope = (JSScope *) JS_malloc(cx, sizeof(JSScope));
+    JSScope *scope = (JSScope *) cx->malloc(sizeof(JSScope));
     if (!scope)
         return NULL;
 
     scope->map.ops = ops;
     scope->object = obj;
     scope->nrefs = 1;
     scope->freeslot = JSSLOT_FREE(clasp);
-    scope->flags = 0;
+    scope->flags = cx->runtime->gcRegenShapesScopeFlag;
     js_LeaveTraceIfGlobalObject(cx, obj);
     scope->initMinimal(cx);
 
 #ifdef JS_THREADSAFE
     js_InitTitle(cx, &scope->title);
 #endif
     JS_RUNTIME_METER(cx->runtime, liveScopes);
     JS_RUNTIME_METER(cx->runtime, totalScopes);
     return scope;
 }
 
 JSScope *
 JSScope::createEmptyScope(JSContext *cx, JSClass *clasp)
 {
     JS_ASSERT(!emptyScope);
 
-    JSScope *scope = (JSScope *) JS_malloc(cx, sizeof(JSScope));
+    JSScope *scope = (JSScope *) cx->malloc(sizeof(JSScope));
     if (!scope)
         return NULL;
 
     scope->map.ops = map.ops;
     scope->object = NULL;
 
     /*
      * This scope holds a reference to the new empty scope. Our only caller,
      * getEmptyScope, also promises to incref on behalf of its caller.
      */
     scope->nrefs = 2;
     scope->freeslot = JSSLOT_FREE(clasp);
-    scope->flags = 0;
+    scope->flags = OWN_SHAPE | cx->runtime->gcRegenShapesScopeFlag;
     scope->initMinimal(cx);
 
 #ifdef JS_THREADSAFE
     js_InitTitle(cx, &scope->title);
 #endif
     JS_RUNTIME_METER(cx->runtime, liveScopes);
     JS_RUNTIME_METER(cx->runtime, totalScopes);
     emptyScope = scope;
@@ -247,23 +247,23 @@ JSScope::createEmptyScope(JSContext *cx,
 
 void
 JSScope::destroy(JSContext *cx, JSScope *scope)
 {
 #ifdef JS_THREADSAFE
     js_FinishTitle(cx, &scope->title);
 #endif
     if (scope->table)
-        JS_free(cx, scope->table);
+        cx->free(scope->table);
     if (scope->emptyScope)
         scope->emptyScope->drop(cx, NULL);
 
     LIVE_SCOPE_METER(cx, cx->runtime->liveScopeProps -= scope->entryCount);
     JS_RUNTIME_UNMETER(cx->runtime, liveScopes);
-    JS_free(cx, scope);
+    cx->free(scope);
 }
 
 #ifdef JS_DUMP_PROPTREE_STATS
 typedef struct JSScopeStats {
     jsrefcount          searches;
     jsrefcount          hits;
     jsrefcount          misses;
     jsrefcount          hashes;
@@ -396,21 +396,19 @@ JSScope::changeTable(JSContext *cx, int 
         return createTable(cx, true);
 
     /* Grow, shrink, or compress by changing this->table. */
     oldlog2 = JS_DHASH_BITS - hashShift;
     newlog2 = oldlog2 + change;
     oldsize = JS_BIT(oldlog2);
     newsize = JS_BIT(newlog2);
     nbytes = SCOPE_TABLE_NBYTES(newsize);
-    newtable = (JSScopeProperty **) calloc(nbytes, 1);
-    if (!newtable) {
-        JS_ReportOutOfMemory(cx);
+    newtable = (JSScopeProperty **) cx->calloc(nbytes);
+    if (!newtable)
         return false;
-    }
 
     /* Now that we have newtable allocated, update members. */
     hashShift = JS_DHASH_BITS - newlog2;
     removedCount = 0;
     oldtable = table;
     table = newtable;
 
     /* Treat the above calloc as a JS_malloc, to match CreateScopeTable. */
@@ -423,17 +421,17 @@ JSScope::changeTable(JSContext *cx, int 
             spp = search(sprop->id, true);
             JS_ASSERT(SPROP_IS_FREE(*spp));
             *spp = sprop;
         }
         oldsize--;
     }
 
     /* Finally, free the old table storage. */
-    JS_free(cx, oldtable);
+    cx->free(oldtable);
     return true;
 }
 
 /*
  * Take care to exclude the mark bits in case we're called from the GC.
  */
 #define SPROP_FLAGS_NOT_MATCHED (SPROP_MARK | SPROP_FLAG_SHAPE_REGEN)
 
@@ -573,31 +571,31 @@ struct PropTreeKidsChunk {
     PropTreeKidsChunk   *next;
 };
 
 static PropTreeKidsChunk *
 NewPropTreeKidsChunk(JSRuntime *rt)
 {
     PropTreeKidsChunk *chunk;
 
-    chunk = (PropTreeKidsChunk *) calloc(1, sizeof *chunk);
+    chunk = (PropTreeKidsChunk *) js_calloc(sizeof *chunk);
     if (!chunk)
         return NULL;
     JS_ASSERT(((jsuword)chunk & CHUNKY_KIDS_TAG) == 0);
     JS_RUNTIME_METER(rt, propTreeKidsChunks);
     return chunk;
 }
 
 static void
 DestroyPropTreeKidsChunk(JSRuntime *rt, PropTreeKidsChunk *chunk)
 {
     JS_RUNTIME_UNMETER(rt, propTreeKidsChunks);
     if (chunk->table)
         JS_DHashTableDestroy(chunk->table);
-    free(chunk);
+    js_free(chunk);
 }
 
 /* NB: Called with rt->gcLock held. */
 static bool
 InsertPropertyTreeChild(JSRuntime *rt, JSScopeProperty *parent,
                         JSScopeProperty *child, PropTreeKidsChunk *sweptChunk)
 {
     JSDHashTable *table;
@@ -1210,17 +1208,17 @@ JSScope::add(JSContext *cx, jsid id,
                 /*
                  * Enumerate live entries in this->table using a temporary
                  * vector, by walking the (possibly sparse, due to deletions)
                  * ancestor line from this->lastProp.
                  */
                 splen = entryCount;
                 JS_ASSERT(splen != 0);
                 spvec = (JSScopeProperty **)
-                        JS_malloc(cx, SCOPE_TABLE_NBYTES(splen));
+                        cx->malloc(SCOPE_TABLE_NBYTES(splen));
                 if (!spvec)
                     goto fail_overwrite;
                 i = splen;
                 sprop = SCOPE_LAST_PROP(this);
                 JS_ASSERT(sprop);
                 do {
                     /*
                      * NB: use JSScope::lookup, not JSScope::has, as the latter
@@ -1243,26 +1241,26 @@ JSScope::add(JSContext *cx, jsid id,
                  * scope. NB: sprop is null on first entry to the loop body.
                  */
                 do {
                     if (spvec[i]->parent == sprop) {
                         sprop = spvec[i];
                     } else {
                         sprop = GetPropertyTreeChild(cx, sprop, spvec[i]);
                         if (!sprop) {
-                            JS_free(cx, spvec);
+                            cx->free(spvec);
                             goto fail_overwrite;
                         }
 
                         spp2 = search(sprop->id, false);
                         JS_ASSERT(SPROP_FETCH(spp2) == spvec[i]);
                         SPROP_STORE_PRESERVING_COLLISION(spp2, sprop);
                     }
                 } while (++i < splen);
-                JS_free(cx, spvec);
+                cx->free(spvec);
 
                 /*
                  * Now sprop points to the last property in this scope, where
                  * the ancestor line from sprop to the root is dense w.r.t.
                  * this scope: it contains no nodes not mapped by this->table.
                  */
                 lastProp = sprop;
                 CHECK_ANCESTOR_LINE(this, false);
@@ -1553,17 +1551,17 @@ JSScope::remove(JSContext *cx, jsid id)
 
 void
 JSScope::clear(JSContext *cx)
 {
     CHECK_ANCESTOR_LINE(this, true);
     LIVE_SCOPE_METER(cx, cx->runtime->liveScopeProps -= entryCount);
 
     if (table)
-        free(table);
+        js_free(table);
     clearMiddleDelete();
     js_LeaveTraceIfGlobalObject(cx, object);
     initMinimal(cx);
     JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals);
 }
 
 void
 JSScope::brandingShapeChange(JSContext *cx, uint32 slot, jsval v)
@@ -1589,27 +1587,27 @@ JSScope::protoShapeChange(JSContext *cx)
     generateOwnShape(cx);
 }
 
 void
 JSScope::replacingShapeChange(JSContext *cx, JSScopeProperty *sprop, JSScopeProperty *newsprop)
 {
     if (shape == sprop->shape)
         shape = newsprop->shape;
-    else 
+    else
         generateOwnShape(cx);
 }
 
 void
 JSScope::sealingShapeChange(JSContext *cx)
 {
     generateOwnShape(cx);
 }
 
-void 
+void
 JSScope::shadowingShapeChange(JSContext *cx, JSScopeProperty *sprop)
 {
     generateOwnShape(cx);
 }
 
 void
 js_TraceId(JSTracer *trc, jsid id)
 {
@@ -1646,17 +1644,17 @@ PrintPropertyGetterOrSetter(JSTracer *tr
 }
 #endif
 
 void
 JSScopeProperty::trace(JSTracer *trc)
 {
     if (IS_GC_MARKING_TRACER(trc))
         flags |= SPROP_MARK;
-    TRACE_ID(trc, id);
+    js_TraceId(trc, id);
 
 #if JS_HAS_GETTER_SETTER
     if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
         if (attrs & JSPROP_GETTER) {
             JS_SET_TRACING_DETAILS(trc, PrintPropertyGetterOrSetter, this, 0);
             JS_CallTracer(trc, js_CastAsObject(getter), JSTRACE_OBJECT);
         }
         if (attrs & JSPROP_SETTER) {
--- a/js/src/jsscope.h
+++ b/js/src/jsscope.h
@@ -260,16 +260,18 @@ struct JSScope {
                             uintN attrs, uintN mask,
                             JSPropertyOp getter, JSPropertyOp setter);
 
     bool remove(JSContext *cx, jsid id);
     void clear(JSContext *cx);
 
     void extend(JSContext *cx, JSScopeProperty *sprop);
 
+    void trace(JSTracer *trc);
+
     void brandingShapeChange(JSContext *cx, uint32 slot, jsval v);
     void deletingShapeChange(JSContext *cx, JSScopeProperty *sprop);
     void methodShapeChange(JSContext *cx, uint32 slot, jsval toval);
     void protoShapeChange(JSContext *cx);
     void replacingShapeChange(JSContext *cx,
                               JSScopeProperty *sprop,
                               JSScopeProperty *newsprop);
     void sealingShapeChange(JSContext *cx);
@@ -278,17 +280,23 @@ struct JSScope {
 /* By definition, hashShift = JS_DHASH_BITS - log2(capacity). */
 #define SCOPE_CAPACITY(scope)           JS_BIT(JS_DHASH_BITS-(scope)->hashShift)
 
     enum {
         MIDDLE_DELETE           = 0x0001,
         SEALED                  = 0x0002,
         BRANDED                 = 0x0004,
         INDEXED_PROPERTIES      = 0x0008,
-        OWN_SHAPE               = 0x0010
+        OWN_SHAPE               = 0x0010,
+
+        /*
+         * This flag toggles with each shape-regenerating GC cycle.
+         * See JSRuntime::gcRegenShapesScopeFlag.
+         */
+        SHAPE_REGEN             = 0x0020
     };
 
     bool hadMiddleDelete()      { return flags & MIDDLE_DELETE; }
     void setMiddleDelete()      { flags |= MIDDLE_DELETE; }
     void clearMiddleDelete()    { flags &= ~MIDDLE_DELETE; }
 
     /*
      * Don't define clearSealed, as it can't be done safely because JS_LOCK_OBJ
@@ -307,16 +315,18 @@ struct JSScope {
     void setBranded()           { flags |= BRANDED; }
 
     bool hadIndexedProperties() { return flags & INDEXED_PROPERTIES; }
     void setIndexedProperties() { flags |= INDEXED_PROPERTIES; }
 
     bool hasOwnShape()          { return flags & OWN_SHAPE; }
     void setOwnShape()          { flags |= OWN_SHAPE; }
 
+    bool hasRegenFlag(uint8 regenFlag) { return (flags & SHAPE_REGEN) == regenFlag; }
+
     bool owned()                { return object != NULL; }
 };
 
 #define JS_IS_SCOPE_LOCKED(cx, scope)   JS_IS_TITLE_LOCKED(cx, &(scope)->title)
 
 #define OBJ_SCOPE(obj)                  (JS_ASSERT(OBJ_IS_NATIVE(obj)),       \
                                          (JSScope *) (obj)->map)
 #define OBJ_SHAPE(obj)                  (OBJ_SCOPE(obj)->shape)
@@ -488,16 +498,64 @@ JSScope::extend(JSContext *cx, JSScopePr
     js_LeaveTraceIfGlobalObject(cx, object);
     shape = (!lastProp || shape == lastProp->shape)
             ? sprop->shape
             : js_GenerateShape(cx, JS_FALSE);
     ++entryCount;
     lastProp = sprop;
 }
 
+inline void
+JSScope::trace(JSTracer *trc)
+{
+    JSContext *cx = trc->context;
+    JSScopeProperty *sprop = lastProp;
+    uint8 regenFlag = cx->runtime->gcRegenShapesScopeFlag;
+    if (IS_GC_MARKING_TRACER(trc) && cx->runtime->gcRegenShapes && hasRegenFlag(regenFlag)) {
+        /*
+         * Either this scope has its own shape, which must be regenerated, or
+         * it must have the same shape as lastProp.
+         */
+        uint32 newShape;
+
+        if (sprop) {
+            if (!(sprop->flags & SPROP_FLAG_SHAPE_REGEN)) {
+                sprop->shape = js_RegenerateShapeForGC(cx);
+                sprop->flags |= SPROP_FLAG_SHAPE_REGEN;
+            }
+            newShape = sprop->shape;
+        }
+        if (!sprop || hasOwnShape()) {
+            newShape = js_RegenerateShapeForGC(cx);
+            JS_ASSERT_IF(sprop, newShape != sprop->shape);
+        }
+        shape = newShape;
+        flags ^= JSScope::SHAPE_REGEN;
+
+        /* Also regenerate the shapes of empty scopes, in case they are not shared. */
+        for (JSScope *empty = emptyScope;
+             empty && empty->hasRegenFlag(regenFlag);
+             empty = empty->emptyScope) {
+            empty->shape = js_RegenerateShapeForGC(cx);
+            empty->flags ^= JSScope::SHAPE_REGEN;
+        }
+    }
+    if (sprop) {
+        JS_ASSERT(has(sprop));
+
+        /* Trace scope's property tree ancestor line. */
+        do {
+            if (hadMiddleDelete() && !has(sprop))
+                continue;
+            sprop->trace(trc);
+        } while ((sprop = sprop->parent) != NULL);
+    }
+}
+
+
 static JS_INLINE bool
 js_GetSprop(JSContext* cx, JSScopeProperty* sprop, JSObject* obj, jsval* vp)
 {
     JS_ASSERT(!SPROP_HAS_STUB_GETTER(sprop));
 
     if (sprop->attrs & JSPROP_GETTER) {
         jsval fval = js_CastAsObjectJSVal(sprop->getter);
         return js_InternalGetOrSet(cx, obj, sprop->id, fval, JSACC_READ,
@@ -540,24 +598,16 @@ js_SetSprop(JSContext* cx, JSScopeProper
 
 /* Macro for common expression to test for shared permanent attributes. */
 #define SPROP_IS_SHARED_PERMANENT(sprop)                                      \
     ((~(sprop)->attrs & (JSPROP_SHARED | JSPROP_PERMANENT)) == 0)
 
 extern JSScope *
 js_GetMutableScope(JSContext *cx, JSObject *obj);
 
-/*
- * These macros used to inline short code sequences, but they grew over time.
- * We retain them for internal backward compatibility, and in case one or both
- * ever shrink to inline-able size.
- */
-#define TRACE_ID(trc, id)                js_TraceId(trc, id)
-#define TRACE_SCOPE_PROPERTY(trc, sprop) sprop->trace(trc)
-
 extern void
 js_TraceId(JSTracer *trc, jsid id);
 
 extern void
 js_SweepScopeProperties(JSContext *cx);
 
 extern bool
 js_InitPropertyTree(JSRuntime *rt);
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -135,31 +135,31 @@ script_toSource(JSContext *cx, uintN arg
         str = js_QuoteString(cx, str, '\'');
         if (!str)
             return JS_FALSE;
         str->getCharsAndLength(s, k);
         n += k;
     }
 
     /* Allocate the source string and copy into it. */
-    t = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
+    t = (jschar *) cx->malloc((n + 1) * sizeof(jschar));
     if (!t)
         return JS_FALSE;
     for (i = 0; i < j; i++)
         t[i] = buf[i];
     for (j = 0; j < k; i++, j++)
         t[i] = s[j];
     t[i++] = ')';
     t[i++] = ')';
     t[i] = 0;
 
     /* Create and return a JS string for t. */
     str = JS_NewUCString(cx, t, n);
     if (!str) {
-        JS_free(cx, t);
+        cx->free(t);
         return JS_FALSE;
     }
     *vp = STRING_TO_JSVAL(str);
     return JS_TRUE;
 }
 #endif /* JS_HAS_TOSOURCE */
 
 static JSBool
@@ -528,17 +528,17 @@ js_XDRScript(JSXDRState *xdr, JSScript *
         if (!code)
             goto error;
     }
 
     xdr->script = script;
     ok = JS_XDRBytes(xdr, (char *) code, length * sizeof(jsbytecode));
 
     if (code != script->code)
-        JS_free(cx, code);
+        cx->free(code);
 
     if (!ok)
         goto error;
 
     if (!JS_XDRBytes(xdr, (char *)notes, nsrcnotes * sizeof(jssrcnote)) ||
         !JS_XDRCStringOrNull(xdr, (char **)&script->filename) ||
         !JS_XDRUint32(xdr, &lineno) ||
         !JS_XDRUint32(xdr, &nslots)) {
@@ -571,17 +571,17 @@ js_XDRScript(JSXDRState *xdr, JSScript *
     }
 
     if (xdr->mode == JSXDR_DECODE) {
         const char *filename = script->filename;
         if (filename) {
             filename = js_SaveScriptFilename(cx, filename);
             if (!filename)
                 goto error;
-            JS_free(cx, (void *) script->filename);
+            cx->free((void *) script->filename);
             script->filename = filename;
             filenameWasSaved = JS_TRUE;
         }
         script->lineno = (uintN)lineno;
         script->nslots = (uint16)nslots;
         script->staticLevel = (uint16)(nslots >> 16);
     }
 
@@ -660,17 +660,17 @@ js_XDRScript(JSXDRState *xdr, JSScript *
     if (xdr->mode == JSXDR_DECODE)
         JS_POP_TEMP_ROOT(cx, &tvr);
     return JS_TRUE;
 
   error:
     if (xdr->mode == JSXDR_DECODE) {
         JS_POP_TEMP_ROOT(cx, &tvr);
         if (script->filename && !filenameWasSaved) {
-            JS_free(cx, (void *) script->filename);
+            cx->free((void *) script->filename);
             script->filename = NULL;
         }
         js_DestroyScript(cx, script);
         *scriptp = NULL;
     }
     xdr->script = oldscript;
     return JS_FALSE;
 }
@@ -778,17 +778,17 @@ script_thaw(JSContext *cx, uintN argc, j
     str->getCharsAndLength(buf, len);
 #if IS_BIG_ENDIAN
   {
     jschar *from, *to;
     uint32 i;
 
     /* Swap bytes in Unichars to keep frozen strings machine-independent. */
     from = (jschar *)buf;
-    to = (jschar *) JS_malloc(cx, len * sizeof(jschar));
+    to = (jschar *) cx->malloc(len * sizeof(jschar));
     if (!to) {
         JS_XDRDestroy(xdr);
         return JS_FALSE;
     }
     for (i = 0; i < len; i++)
         to[i] = JSXDR_SWAB16(from[i]);
     buf = (char *)to;
   }
@@ -834,17 +834,17 @@ script_thaw(JSContext *cx, uintN argc, j
 out:
     /*
      * We reset the buffer to be NULL so that it doesn't free the chars
      * memory owned by str (vp[2]).
      */
     JS_XDRMemSetData(xdr, NULL, 0);
     JS_XDRDestroy(xdr);
 #if IS_BIG_ENDIAN
-    JS_free(cx, buf);
+    cx->free(buf);
 #endif
     *vp = JSVAL_TRUE;
     return ok;
 }
 
 static const char js_thaw_str[] = "thaw";
 
 #endif /* JS_HAS_SCRIPT_OBJECT && JS_HAS_XDR_FREEZE_THAW */
@@ -990,40 +990,40 @@ typedef struct ScriptFilenameEntry {
     uint32              flags;          /* user-defined filename prefix flags */
     JSPackedBool        mark;           /* GC mark flag */
     char                filename[3];    /* two or more bytes, NUL-terminated */
 } ScriptFilenameEntry;
 
 static void *
 js_alloc_table_space(void *priv, size_t size)
 {
-    return malloc(size);
+    return js_malloc(size);
 }
 
 static void
 js_free_table_space(void *priv, void *item, size_t size)
 {
-    free(item);
+    js_free(item);
 }
 
 static JSHashEntry *
 js_alloc_sftbl_entry(void *priv, const void *key)
 {
     size_t nbytes = offsetof(ScriptFilenameEntry, filename) +
                     strlen((const char *) key) + 1;
 
-    return (JSHashEntry *) malloc(JS_MAX(nbytes, sizeof(JSHashEntry)));
+    return (JSHashEntry *) js_malloc(JS_MAX(nbytes, sizeof(JSHashEntry)));
 }
 
 static void
 js_free_sftbl_entry(void *priv, JSHashEntry *he, uintN flag)
 {
     if (flag != HT_FREE_ENTRY)
         return;
-    free(he);
+    js_free(he);
 }
 
 static JSHashAllocOps sftbl_alloc_ops = {
     js_alloc_table_space,   js_free_table_space,
     js_alloc_sftbl_entry,   js_free_sftbl_entry
 };
 
 JSBool
@@ -1075,17 +1075,17 @@ js_FreeRuntimeScriptState(JSRuntime *rt)
     ScriptFilenamePrefix *sfp;
 
     if (!rt->scriptFilenameTable)
         return;
 
     while (!JS_CLIST_IS_EMPTY(&rt->scriptFilenamePrefixes)) {
         sfp = (ScriptFilenamePrefix *) rt->scriptFilenamePrefixes.next;
         JS_REMOVE_LINK(&sfp->links);
-        free(sfp);
+        js_free(sfp);
     }
     js_FinishRuntimeScriptState(rt);
 }
 
 #ifdef DEBUG_brendan
 #define DEBUG_SFTBL
 #endif
 #ifdef DEBUG_SFTBL
@@ -1138,17 +1138,17 @@ SaveScriptFilename(JSRuntime *rt, const 
                 sfp = NULL;
                 break;
             }
             sfp = NULL;
         }
 
         if (!sfp) {
             /* No such prefix: add one now. */
-            sfp = (ScriptFilenamePrefix *) malloc(sizeof(ScriptFilenamePrefix));
+            sfp = (ScriptFilenamePrefix *) js_malloc(sizeof(ScriptFilenamePrefix));
             if (!sfp)
                 return NULL;
             JS_INSERT_AFTER(&sfp->links, link);
             sfp->name = sfe->filename;
             sfp->length = length;
             sfp->flags = 0;
         }
 
@@ -1379,17 +1379,17 @@ js_NewScript(JSContext *cx, uint32 lengt
         size += sizeof(JSObjectArray) + nobjects * sizeof(JSObject *);
     if (nupvars != 0)
         size += sizeof(JSUpvarArray) + nupvars * sizeof(uint32);
     if (nregexps != 0)
         size += sizeof(JSObjectArray) + nregexps * sizeof(JSObject *);
     if (ntrynotes != 0)
         size += sizeof(JSTryNoteArray) + ntrynotes * sizeof(JSTryNote);
 
-    script = (JSScript *) JS_malloc(cx, size);
+    script = (JSScript *) cx->malloc(size);
     if (!script)
         return NULL;
     memset(script, 0, sizeof(JSScript));
     script->length = length;
     script->version = cx->version;
 
     cursor = (uint8 *)script + sizeof(JSScript);
     if (nobjects != 0) {
@@ -1531,17 +1531,17 @@ js_NewScriptFromCG(JSContext *cx, JSCode
     if (cg->flags & TCF_NO_SCRIPT_RVAL)
         script->flags |= JSSF_NO_SCRIPT_RVAL;
 
     if (cg->upvarList.count != 0) {
         JS_ASSERT(cg->upvarList.count <= cg->upvarMap.length);
         memcpy(JS_SCRIPT_UPVARS(script)->vector, cg->upvarMap.vector,
                cg->upvarList.count * sizeof(uint32));
         cg->upvarList.clear();
-        JS_free(cx, cg->upvarMap.vector);
+        cx->free(cg->upvarMap.vector);
         cg->upvarMap.vector = NULL;
     }
 
     /*
      * We initialize fun->u.script to be the script constructed above
      * so that the debugger has a valid FUN_SCRIPT(fun).
      */
     fun = NULL;
@@ -1643,17 +1643,17 @@ js_DestroyScript(JSContext *cx, JSScript
             JS_ASSERT(script->owner == cx->thread);
 #endif
 #ifdef JS_TRACER
             js_PurgeScriptFragments(cx, script);
 #endif
         }
     }
 
-    JS_free(cx, script);
+    cx->free(script);
 }
 
 void
 js_TraceScript(JSTracer *trc, JSScript *script)
 {
     JSAtomMap *map;
     uintN i, length;
     JSAtom **vector;
--- a/js/src/jsstdint.h
+++ b/js/src/jsstdint.h
@@ -35,17 +35,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /*
  * This header provides definitions for the <stdint.h> types we use,
  * even on systems that lack <stdint.h>.
- * 
+ *
  * NOTE: This header should only be included in private SpiderMonkey
  * code; public headers should use only the JS{Int,Uint}N types; see
  * the comment for them in "jsinttypes.h".
  *
  * At the moment, these types are not widely used within SpiderMonkey;
  * this file is meant to make existing uses portable, and to allow us
  * to transition portably to using them more, if desired.
  */
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -140,25 +140,25 @@ js_ConcatStrings(JSContext *cx, JSString
         return left;
 
     left->getCharsAndLength(const_cast<const jschar *&>(ls), ln);
     if (ln == 0)
         return right;
 
     if (!left->isMutable()) {
         /* We must copy if left does not own a buffer to realloc. */
-        s = (jschar *) JS_malloc(cx, (ln + rn + 1) * sizeof(jschar));
+        s = (jschar *) cx->malloc((ln + rn + 1) * sizeof(jschar));
         if (!s)
             return NULL;
         js_strncpy(s, ls, ln);
         ldep = NULL;
     } else {
         /* We can realloc left's space and make it depend on our result. */
         JS_ASSERT(left->isFlat());
-        s = (jschar *) JS_realloc(cx, ls, (ln + rn + 1) * sizeof(jschar));
+        s = (jschar *) cx->realloc(ls, (ln + rn + 1) * sizeof(jschar));
         if (!s)
             return NULL;
 
         /* Take care: right could depend on left! */
         lrdist = (size_t)(rs - ls);
         if (lrdist < ln)
             rs = s + lrdist;
         left->mChars = ls = s;
@@ -168,19 +168,19 @@ js_ConcatStrings(JSContext *cx, JSString
     js_strncpy(s + ln, rs, rn);
     n = ln + rn;
     s[n] = 0;
 
     str = js_NewString(cx, s, n);
     if (!str) {
         /* Out of memory: clean up any space we (re-)allocated. */
         if (!ldep) {
-            JS_free(cx, s);
+            cx->free(s);
         } else {
-            s = (jschar *) JS_realloc(cx, ls, (ln + 1) * sizeof(jschar));
+            s = (jschar *) cx->realloc(ls, (ln + 1) * sizeof(jschar));
             if (s)
                 left->mChars = s;
         }
     } else {
         str->flatSetMutable();
 
         /* Morph left into a dependent prefix if we realloc'd its buffer. */
         if (ldep) {
@@ -205,17 +205,17 @@ const jschar *
 js_UndependString(JSContext *cx, JSString *str)
 {
     size_t n, size;
     jschar *s;
 
     if (str->isDependent()) {
         n = str->dependentLength();
         size = (n + 1) * sizeof(jschar);
-        s = (jschar *) JS_malloc(cx, size);
+        s = (jschar *) cx->malloc(size);
         if (!s)
             return NULL;
 
         js_strncpy(s, str->dependentChars(), n);
         s[n] = 0;
         str->reinitFlat(s, n);
 
 #ifdef DEBUG
@@ -397,17 +397,17 @@ js_str_escape(JSContext *cx, JSObject *o
         }
     }
 
     if (newlength >= ~(size_t)0 / sizeof(jschar)) {
         js_ReportAllocationOverflow(cx);
         return JS_FALSE;
     }
 
-    newchars = (jschar *) JS_malloc(cx, (newlength + 1) * sizeof(jschar));
+    newchars = (jschar *) cx->malloc((newlength + 1) * sizeof(jschar));
     if (!newchars)
         return JS_FALSE;
     for (i = 0, ni = 0; i < length; i++) {
         if ((ch = chars[i]) < 128 && IS_OK(ch, mask)) {
             newchars[ni++] = ch;
         } else if (ch < 256) {
             if (mask == URL_XPALPHAS && ch == ' ') {
                 newchars[ni++] = '+'; /* convert spaces to pluses */
@@ -425,17 +425,17 @@ js_str_escape(JSContext *cx, JSObject *o
             newchars[ni++] = digits[ch & 0xF];
         }
     }
     JS_ASSERT(ni == newlength);
     newchars[newlength] = 0;
 
     str = js_NewString(cx, newchars, newlength);
     if (!str) {
-        JS_free(cx, newchars);
+        cx->free(newchars);
         return JS_FALSE;
     }
     *rval = STRING_TO_JSVAL(str);
     return JS_TRUE;
 }
 #undef IS_OK
 
 static JSBool
@@ -459,17 +459,17 @@ str_unescape(JSContext *cx, uintN argc, 
 
     str = ArgToRootedString(cx, argc, vp, 0);
     if (!str)
         return JS_FALSE;
 
     str->getCharsAndLength(chars, length);
 
     /* Don't bother allocating less space for the new string. */
-    newchars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+    newchars = (jschar *) cx->malloc((length + 1) * sizeof(jschar));
     if (!newchars)
         return JS_FALSE;
     ni = i = 0;
     while (i < length) {
         ch = chars[i++];
         if (ch == '%') {
             if (i + 1 < length &&
                 JS7_ISHEX(chars[i]) && JS7_ISHEX(chars[i + 1]))
@@ -488,17 +488,17 @@ str_unescape(JSContext *cx, uintN argc, 
             }
         }
         newchars[ni++] = ch;
     }
     newchars[ni] = 0;
 
     str = js_NewString(cx, newchars, ni);
     if (!str) {
-        JS_free(cx, newchars);
+        cx->free(newchars);
         return JS_FALSE;
     }
     *vp = STRING_TO_JSVAL(str);
     return JS_TRUE;
 }
 
 #if JS_HAS_UNEVAL
 static JSBool
@@ -690,29 +690,29 @@ str_toSource(JSContext *cx, uintN argc, 
         return JS_FALSE;
     JS_ASSERT(JSVAL_IS_STRING(v));
     str = js_QuoteString(cx, JSVAL_TO_STRING(v), '"');
     if (!str)
         return JS_FALSE;
     j = JS_snprintf(buf, sizeof buf, "(new %s(", js_StringClass.name);
     str->getCharsAndLength(s, k);
     n = j + k + 2;
-    t = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
+    t = (jschar *) cx->malloc((n + 1) * sizeof(jschar));
     if (!t)
         return JS_FALSE;
     for (i = 0; i < j; i++)
         t[i] = buf[i];
     for (j = 0; j < k; i++, j++)
         t[i] = s[j];
     t[i++] = ')';
     t[i++] = ')';
     t[i] = 0;
     str = js_NewString(cx, t, n);
     if (!str) {
-        JS_free(cx, t);
+        cx->free(t);
         return JS_FALSE;
     }
     *vp = STRING_TO_JSVAL(str);
     return JS_TRUE;
 }
 
 #endif /* JS_HAS_TOSOURCE */
 
@@ -794,25 +794,25 @@ String_p_toString(JSContext* cx, JSObjec
 JSString* JS_FASTCALL
 js_toLowerCase(JSContext *cx, JSString *str)
 {
     size_t i, n;
     const jschar *s;
     jschar *news;
 
     str->getCharsAndLength(s, n);
-    news = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
+    news = (jschar *) cx->malloc((n + 1) * sizeof(jschar));
     if (!news)
         return NULL;
     for (i = 0; i < n; i++)
         news[i] = JS_TOLOWER(s[i]);
     news[n] = 0;
     str = js_NewString(cx, news, n);
     if (!str) {
-        JS_free(cx, news);
+        cx->free(news);
         return NULL;
     }
     return str;
 }
 
 static JSBool
 str_toLowerCase(JSContext *cx, uintN argc, jsval *vp)
 {
@@ -845,25 +845,25 @@ str_toLocaleLowerCase(JSContext *cx, uin
 JSString* JS_FASTCALL
 js_toUpperCase(JSContext *cx, JSString *str)
 {
     size_t i, n;
     const jschar *s;
     jschar *news;
 
     str->getCharsAndLength(s, n);
-    news = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
+    news = (jschar *) cx->malloc((n + 1) * sizeof(jschar));
     if (!news)
         return NULL;
     for (i = 0; i < n; i++)
         news[i] = JS_TOUPPER(s[i]);
     news[n] = 0;
     str = js_NewString(cx, news, n);
     if (!str) {
-        JS_free(cx, news);
+        cx->free(news);
         return NULL;
     }
     return str;
 }
 
 static JSBool
 str_toUpperCase(JSContext *cx, uintN argc, jsval *vp)
 {
@@ -1654,17 +1654,17 @@ find_replen(JSContext *cx, ReplaceData *
                 rdata->repstr = repstr;
                 *sizep = repstr->length();
             }
         }
 
       lambda_out:
         js_FreeStack(cx, mark);
         if (freeMoreParens)
-            JS_free(cx, cx->regExpStatics.moreParens);
+            cx->free(cx->regExpStatics.moreParens);
         cx->regExpStatics = save;
         return ok;
     }
 
     repstr = rdata->repstr;
     replen = repstr->length();
     for (dp = rdata->dollar, ep = rdata->dollarEnd; dp;
          dp = js_strchr_limit(dp, '$', ep)) {
@@ -1711,17 +1711,17 @@ do_replace(JSContext *cx, ReplaceData *r
 }
 
 static void
 replace_destroy(JSContext *cx, GlobData *data)
 {
     ReplaceData *rdata;
 
     rdata = (ReplaceData *)data;
-    JS_free(cx, rdata->chars);
+    cx->free(rdata->chars);
     rdata->chars = NULL;
 }
 
 static JS_REQUIRES_STACK JSBool
 replace_glob(JSContext *cx, jsint count, GlobData *data)
 {
     ReplaceData *rdata;
     JSString *str;
@@ -1736,19 +1736,19 @@ replace_glob(JSContext *cx, jsint count,
     leftlen = cx->regExpStatics.lastMatch.chars - left;
     rdata->leftIndex = cx->regExpStatics.lastMatch.chars - str->chars();
     rdata->leftIndex += cx->regExpStatics.lastMatch.length;
     if (!find_replen(cx, rdata, &replen))
         return JS_FALSE;
     growth = leftlen + replen;
     chars = (jschar *)
         (rdata->chars
-         ? JS_realloc(cx, rdata->chars, (rdata->length + growth + 1)
+         ? cx->realloc(rdata->chars, (rdata->length + growth + 1)
                                         * sizeof(jschar))
-         : JS_malloc(cx, (growth + 1) * sizeof(jschar)));
+         : cx->malloc((growth + 1) * sizeof(jschar)));
     if (!chars)
         return JS_FALSE;
     rdata->chars = chars;
     rdata->length += growth;
     chars += rdata->index;
     rdata->index += growth;
     js_strncpy(chars, left, leftlen);
     chars += leftlen;
@@ -1821,43 +1821,43 @@ js_StringReplaceHelper(JSContext *cx, ui
             *vp = STRING_TO_JSVAL(rdata.base.str);
             goto out;
         }
         leftlen = cx->regExpStatics.leftContext.length;
         ok = find_replen(cx, &rdata, &length);
         if (!ok)
             goto out;
         length += leftlen;
-        chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+        chars = (jschar *) cx->malloc((length + 1) * sizeof(jschar));
         if (!chars) {
             ok = JS_FALSE;
             goto out;
         }
         js_strncpy(chars, cx->regExpStatics.leftContext.chars, leftlen);
         do_replace(cx, &rdata, chars + leftlen);
         rdata.chars = chars;
         rdata.length = length;
     }
 
     rightlen = cx->regExpStatics.rightContext.length;
     length = rdata.length + rightlen;
     chars = (jschar *)
-        JS_realloc(cx, rdata.chars, (length + 1) * sizeof(jschar));
+        cx->realloc(rdata.chars, (length + 1) * sizeof(jschar));
     if (!chars) {
-        JS_free(cx, rdata.chars);
+        cx->free(rdata.chars);
         ok = JS_FALSE;
         goto out;
     }
     js_strncpy(chars + rdata.length, cx->regExpStatics.rightContext.chars,
                rightlen);
     chars[length] = 0;
 
     str = js_NewString(cx, chars, length);
     if (!str) {
-        JS_free(cx, chars);
+        cx->free(chars);
         ok = JS_FALSE;
         goto out;
     }
     *vp = STRING_TO_JSVAL(str);
 
 out:
     /* If KEEP_REGEXP is still set, it's our job to destroy regexp now. */
     if (rdata.base.flags & KEEP_REGEXP)
@@ -2261,17 +2261,17 @@ tagify(JSContext *cx, const char *begin,
     endlen = strlen(end);
     taglen += str->length() + 2 + endlen + 1;    /* 'str</end>' */
 
     if (taglen >= ~(size_t)0 / sizeof(jschar)) {
         js_ReportAllocationOverflow(cx);
         return JS_FALSE;
     }
 
-    tagbuf = (jschar *) JS_malloc(cx, (taglen + 1) * sizeof(jschar));
+    tagbuf = (jschar *) cx->malloc((taglen + 1) * sizeof(jschar));
     if (!tagbuf)
         return JS_FALSE;
 
     j = 0;
     tagbuf[j++] = '<';
     for (i = 0; i < beglen; i++)
         tagbuf[j++] = (jschar)begin[i];
     if (param) {
@@ -2289,17 +2289,17 @@ tagify(JSContext *cx, const char *begin,
     for (i = 0; i < endlen; i++)
         tagbuf[j++] = (jschar)end[i];
     tagbuf[j++] = '>';
     JS_ASSERT(j == taglen);
     tagbuf[j] = 0;
 
     str = js_NewString(cx, tagbuf, taglen);
     if (!str) {
-        free((char *)tagbuf);
+        js_free((char *)tagbuf);
         return JS_FALSE;
     }
     *vp = STRING_TO_JSVAL(str);
     return JS_TRUE;
 }
 
 static JSBool
 tagify_value(JSContext *cx, uintN argc, jsval *vp,
@@ -2526,31 +2526,31 @@ str_fromCharCode(JSContext *cx, uintN ar
     if (argc == 1 &&
         (code = js_ValueToUint16(cx, &argv[0])) < UNIT_STRING_LIMIT) {
         str = js_GetUnitStringForChar(cx, code);
         if (!str)
             return JS_FALSE;
         *vp = STRING_TO_JSVAL(str);
         return JS_TRUE;
     }
-    chars = (jschar *) JS_malloc(cx, (argc + 1) * sizeof(jschar));
+    chars = (jschar *) cx->malloc((argc + 1) * sizeof(jschar));
     if (!chars)
         return JS_FALSE;
     for (i = 0; i < argc; i++) {
         code = js_ValueToUint16(cx, &argv[i]);
         if (JSVAL_IS_NULL(argv[i])) {
-            JS_free(cx, chars);
+            cx->free(chars);
             return JS_FALSE;
         }
         chars[i] = (jschar)code;
     }
     chars[i] = 0;
     str = js_NewString(cx, chars, argc);
     if (!str) {
-        JS_free(cx, chars);
+        cx->free(chars);
         return JS_FALSE;
     }
     *vp = STRING_TO_JSVAL(str);
     return JS_TRUE;
 }
 
 #ifdef JS_TRACER
 static JSString* FASTCALL
@@ -2616,35 +2616,34 @@ js_GetUnitStringForChar(JSContext *cx, j
 {
     jschar *cp, i;
     JSRuntime *rt;
     JSString **sp;
 
     JS_ASSERT(c < UNIT_STRING_LIMIT);
     rt = cx->runtime;
     if (!rt->unitStrings) {
-        sp = (JSString **) calloc(UNIT_STRING_LIMIT * sizeof(JSString *) +
-                                  UNIT_STRING_LIMIT * 2 * sizeof(jschar),
-                                  1);
+        sp = (JSString **) js_calloc(UNIT_STRING_LIMIT * sizeof(JSString *) +
+                                     UNIT_STRING_LIMIT * 2 * sizeof(jschar));
         if (!sp) {
             JS_ReportOutOfMemory(cx);
             return NULL;
         }
         cp = UNIT_STRING_SPACE(sp);
         for (i = 0; i < UNIT_STRING_LIMIT; i++) {
             *cp = i;
             cp += 2;
         }
         JS_LOCK_GC(rt);
         if (!rt->unitStrings) {
             rt->unitStrings = sp;
             JS_UNLOCK_GC(rt);
         } else {
             JS_UNLOCK_GC(rt);
-            free(sp);
+            js_free(sp);
         }
     }
     if (!rt->unitStrings[c]) {
         JSString *str;
 
         cp = UNIT_STRING_SPACE_RT(rt);
         str = js_NewString(cx, cp + 2 * c, 1);
         if (!str)
@@ -2671,17 +2670,17 @@ js_GetUnitString(JSContext *cx, JSString
     if (c >= UNIT_STRING_LIMIT)
         return js_NewDependentString(cx, str, index, 1);
     return js_GetUnitStringForChar(cx, c);
 }
 
 void
 js_FinishUnitStrings(JSRuntime *rt)
 {
-    free(rt->unitStrings);
+    js_free(rt->unitStrings);
     rt->unitStrings = NULL;
 }
 
 void
 js_FinishRuntimeStringState(JSContext *cx)
 {
     cx->runtime->emptyString = NULL;
 }
@@ -2827,43 +2826,43 @@ void printJSStringStats(JSRuntime *rt)
 #endif
 
 JSString *
 js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n)
 {
     jschar *news;
     JSString *str;
 
-    news = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
+    news = (jschar *) cx->malloc((n + 1) * sizeof(jschar));
     if (!news)
         return NULL;
     js_strncpy(news, s, n);
     news[n] = 0;
     str = js_NewString(cx, news, n);
     if (!str)
-        JS_free(cx, news);
+        cx->free(news);
     return str;
 }
 
 JSString *
 js_NewStringCopyZ(JSContext *cx, const jschar *s)
 {
     size_t n, m;
     jschar *news;
     JSString *str;
 
     n = js_strlen(s);
     m = (n + 1) * sizeof(jschar);
-    news = (jschar *) JS_malloc(cx, m);
+    news = (jschar *) cx->malloc(m);
     if (!news)
         return NULL;
     memcpy(news, s, m);
     str = js_NewString(cx, news, n);
     if (!str)
-        JS_free(cx, news);
+        cx->free(news);
     return str;
 }
 
 void
 js_PurgeDeflatedStringCache(JSRuntime *rt, JSString *str)
 {
     JSHashNumber hash;
     JSHashEntry *he, **hep;
@@ -2871,17 +2870,17 @@ js_PurgeDeflatedStringCache(JSRuntime *r
     hash = js_hash_string_pointer(str);
     JS_ACQUIRE_LOCK(rt->deflatedStringCacheLock);
     hep = JS_HashTableRawLookup(rt->deflatedStringCache, hash, str);
     he = *hep;
     if (he) {
 #ifdef DEBUG
         rt->deflatedStringCacheBytes -= str->length();
 #endif
-        free(he->value);
+        js_free(he->value);
         JS_HashTableRawRemove(rt->deflatedStringCache, hep, he);
     }
     JS_RELEASE_LOCK(rt->deflatedStringCacheLock);
 }
 
 JS_FRIEND_API(const char *)
 js_ValueToPrintable(JSContext *cx, jsval v, JSValueToStringFun v2sfun)
 {
@@ -3116,27 +3115,27 @@ js_InflateString(JSContext *cx, const ch
 #ifdef DEBUG
     JSBool ok;
 #endif
 
     nbytes = *lengthp;
     if (js_CStringsAreUTF8) {
         if (!js_InflateStringToBuffer(cx, bytes, nbytes, NULL, &nchars))
             goto bad;
-        chars = (jschar *) JS_malloc(cx, (nchars + 1) * sizeof (jschar));
+        chars = (jschar *) cx->malloc((nchars + 1) * sizeof (jschar));
         if (!chars)
             goto bad;
 #ifdef DEBUG
         ok =
 #endif
             js_InflateStringToBuffer(cx, bytes, nbytes, chars, &nchars);
         JS_ASSERT(ok);
     } else {
         nchars = nbytes;
-        chars = (jschar *) JS_malloc(cx, (nchars + 1) * sizeof(jschar));
+        chars = (jschar *) cx->malloc((nchars + 1) * sizeof(jschar));
         if (!chars)
             goto bad;
         for (i = 0; i < nchars; i++)
             chars[i] = (unsigned char) bytes[i];
     }
     *lengthp = nchars;
     chars[nchars] = 0;
     return chars;
@@ -3161,27 +3160,27 @@ js_DeflateString(JSContext *cx, const js
 #ifdef DEBUG
     JSBool ok;
 #endif
 
     if (js_CStringsAreUTF8) {
         nbytes = js_GetDeflatedStringLength(cx, chars, nchars);
         if (nbytes == (size_t) -1)
             return NULL;
-        bytes = (char *) (cx ? JS_malloc(cx, nbytes + 1) : malloc(nbytes + 1));
+        bytes = (char *) (cx ? cx->malloc(nbytes + 1) : js_malloc(nbytes + 1));
         if (!bytes)
             return NULL;
 #ifdef DEBUG
         ok =
 #endif
             js_DeflateStringToBuffer(cx, chars, nchars, bytes, &nbytes);
         JS_ASSERT(ok);
     } else {
         nbytes = nchars;
-        bytes = (char *) (cx ? JS_malloc(cx, nbytes + 1) : malloc(nbytes + 1));
+        bytes = (char *) (cx ? cx->malloc(nbytes + 1) : js_malloc(nbytes + 1));
         if (!bytes)
             return NULL;
         for (i = 0; i < nbytes; i++)
             bytes[i] = (char) chars[i];
     }
     bytes[nbytes] = 0;
     return bytes;
 }
@@ -3486,19 +3485,19 @@ js_GetStringBytes(JSContext *cx, JSStrin
         if (bytes) {
             if (JS_HashTableRawAdd(cache, hep, hash, str, bytes)) {
 #ifdef DEBUG
                 rt->deflatedStringCacheBytes += str->length();
 #endif
                 str->setDeflated();
             } else {
                 if (cx)
-                    JS_free(cx, bytes);
+                    cx->free(bytes);
                 else
-                    free(bytes);
+                    js_free(bytes);
                 bytes = NULL;
             }
         }
     }
 
     JS_RELEASE_LOCK(rt->deflatedStringCacheLock);
     return bytes;
 }
@@ -4831,18 +4830,18 @@ AddCharsToURI(JSContext *cx, JSCharBuffe
 {
     size_t total;
     jschar *newchars;
 
     total = buf->length + length + 1;
     if (!buf->chars ||
         JS_HOWMANY(total, URI_CHUNK) > JS_HOWMANY(buf->length + 1, URI_CHUNK)) {
         total = JS_ROUNDUP(total, URI_CHUNK);
-        newchars = (jschar *) JS_realloc(cx, buf->chars,
-                                         total * sizeof(jschar));
+        newchars = (jschar *) cx->realloc(buf->chars,
+                                          total * sizeof(jschar));
         if (!newchars)
             return JS_FALSE;
         buf->chars = newchars;
     }
     js_strncpy(buf->chars + buf->length, chars, length);
     buf->length += length;
     buf->chars[buf->length] = 0;
     return JS_TRUE;
@@ -4855,17 +4854,17 @@ TransferBufferToString(JSContext *cx, JS
     size_t n;
     JSString *str;
 
     /*
      * Shrinking realloc can fail (e.g., with a BSD-style allocator), but we
      * don't worry about that case here.
      */
     n = cb->length;
-    chars = (jschar *) JS_realloc(cx, cb->chars, (n + 1) * sizeof(jschar));
+    chars = (jschar *) cx->realloc(cb->chars, (n + 1) * sizeof(jschar));
     if (!chars)
         chars = cb->chars;
     str = js_NewString(cx, chars, n);
     if (!str)
         return JS_FALSE;
 
     /* Successful allocation transfer ownership of cb->chars to the string. */
 #ifdef DEBUG
@@ -4948,17 +4947,17 @@ Encode(JSContext *cx, JSString *str, con
     }
 
     if (!TransferBufferToString(cx, &cb, rval))
         goto bad;
 
     return JS_TRUE;
 
   bad:
-    JS_free(cx, cb.chars);
+    cx->free(cb.chars);
     return JS_FALSE;
 }
 
 static JSBool
 Decode(JSContext *cx, JSString *str, const jschar *reservedSet, jsval *rval)
 {
     size_t length, start, k;
     JSCharBuffer cb;
@@ -5043,17 +5042,17 @@ Decode(JSContext *cx, JSString *str, con
 
     return JS_TRUE;
 
   report_bad_uri:
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_URI);
     /* FALL THROUGH */
 
   bad:
-    JS_free(cx, cb.chars);
+    cx->free(cb.chars);
     return JS_FALSE;
 }
 
 static JSBool
 str_decodeURI(JSContext *cx, uintN argc, jsval *vp)
 {
     JSString *str;
 
new file mode 100644
--- /dev/null
+++ b/js/src/jstask.cpp
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=4 sw=4 et tw=99 ft=cpp:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9.1 code, released
+ * June 30, 2009.
+ *
+ * The Initial Developer of the Original Code is
+ *   Andreas Gal <gal@mozilla.com>
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jstask.h"
+
+#ifdef JS_THREADSAFE
+static void start(void* arg) {
+    ((JSBackgroundThread*)arg)->work();
+}
+
+JSBackgroundThread::JSBackgroundThread()
+  : thread(NULL), stack(NULL), lock(NULL), wakeup(NULL), shutdown(false)
+{
+}
+
+JSBackgroundThread::~JSBackgroundThread()
+{
+    if (wakeup)
+        PR_DestroyCondVar(wakeup);
+    if (lock)
+        PR_DestroyLock(lock);
+    /* PR_DestroyThread is not necessary. */
+}
+
+bool
+JSBackgroundThread::init()
+{
+    if (!(lock = PR_NewLock()))
+        return false;
+    if (!(wakeup = PR_NewCondVar(lock)))
+        return false;
+    thread = PR_CreateThread(PR_USER_THREAD, start, this, PR_PRIORITY_LOW,
+                             PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+    return !!thread;
+}
+
+void
+JSBackgroundThread::cancel()
+{
+    PR_Lock(lock);
+    if (shutdown) {
+        PR_Unlock(lock);
+        return;
+    }
+    shutdown = true;
+    PR_NotifyCondVar(wakeup);
+    PR_Unlock(lock);
+    PR_JoinThread(thread);
+}
+
+void
+JSBackgroundThread::work()
+{
+    PR_Lock(lock);
+    while (!shutdown) {
+        PR_WaitCondVar(wakeup, PR_INTERVAL_NO_TIMEOUT);
+        JSBackgroundTask* t;
+        while ((t = stack) != NULL) {
+            stack = t->next;
+            PR_Unlock(lock);
+            t->run();
+            delete t;
+            PR_Lock(lock);
+        }
+    }
+    PR_Unlock(lock);
+}
+
+bool
+JSBackgroundThread::busy()
+{
+    return !!stack; // we tolerate some racing here
+}
+
+void
+JSBackgroundThread::schedule(JSBackgroundTask* task)
+{
+    PR_Lock(lock);
+    if (shutdown) {
+        PR_Unlock(lock);
+        task->run();
+        delete task;
+        return;
+    }
+    task->next = stack;
+    stack = task;
+    PR_NotifyCondVar(wakeup);
+    PR_Unlock(lock);
+}
+
+#endif
new file mode 100644
--- /dev/null
+++ b/js/src/jstask.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=4 sw=4 et tw=99 ft=cpp:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
+ * June 30, 2009.
+ *
+ * The Initial Developer of the Original Code is
+ *   Andreas Gal <gal@mozilla.com>
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jstask_h___
+#define jstask_h___
+
+class JSBackgroundTask {
+    friend class JSBackgroundThread;
+    JSBackgroundTask* next;
+  public:
+    virtual void run() = 0;
+};
+
+#ifdef JS_THREADSAFE
+
+#include "prthread.h"
+#include "prlock.h"
+#include "prcvar.h"
+
+class JSBackgroundThread {
+    PRThread*         thread;
+    JSBackgroundTask* stack;
+    PRLock*           lock;
+    PRCondVar*        wakeup;
+    bool              shutdown;
+
+  public:
+    JSBackgroundThread();
+    ~JSBackgroundThread();
+
+    bool init();
+    void cancel();
+    void work();
+    bool busy();
+    void schedule(JSBackgroundTask* task);
+};
+
+#else
+
+class JSBackgroundThread {
+  public:
+    void schedule(JSBackgroundTask* task) {
+        task->run();
+    }
+};
+
+#endif
+
+#endif /* jstask_h___ */
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -75,42 +75,49 @@
 #include "jstracer.h"
 #include "jsxml.h"
 
 #include "jsatominlines.h"
 
 #include "jsautooplen.h"        // generated headers last
 #include "imacros.c.out"
 
+using namespace avmplus;
+using namespace nanojit;
+
 #if JS_HAS_XML_SUPPORT
 #define ABORT_IF_XML(v)                                                       \
     JS_BEGIN_MACRO                                                            \
     if (!JSVAL_IS_PRIMITIVE(v) && OBJECT_IS_XML(BOGUS_CX, JSVAL_TO_OBJECT(v)))\
         ABORT_TRACE("xml detected");                                          \
     JS_END_MACRO
 #else
-#define ABORT_IF_XML(cx, v) ((void) 0)
-#endif
-
-/* Never use JSVAL_IS_BOOLEAN because it restricts the value (true, false) and
-   the type. What you want to use is JSVAL_TAG(x) == JSVAL_BOOLEAN and then
-   handle the undefined case properly (bug 457363). */
+#define ABORT_IF_XML(v) ((void) 0)
+#endif
+
+/*
+ * Never use JSVAL_IS_BOOLEAN because it restricts the value (true, false) and
+ * the type. What you want to use is JSVAL_TAG(x) == JSVAL_BOOLEAN and then
+ * handle the undefined case properly (bug 457363).
+ */
 #undef JSVAL_IS_BOOLEAN
 #define JSVAL_IS_BOOLEAN(x) JS_STATIC_ASSERT(0)
 
 JS_STATIC_ASSERT(sizeof(JSTraceType) == 1);
 
 /* Map to translate a type tag into a printable representation. */
 static const char typeChar[] = "OIDXSNBF";
 static const char tagChar[]  = "OIDISIBI";
 
 /* Blacklist parameters. */
 
-/* Number of iterations of a loop where we start tracing.  That is, we don't
-   start tracing until the beginning of the HOTLOOP-th iteration. */
+/*
+ * Number of iterations of a loop where we start tracing.  That is, we don't
+ * start tracing until the beginning of the HOTLOOP-th iteration.
+ */
 #define HOTLOOP 2
 
 /* Attempt recording this many times before blacklisting permanently. */
 #define BL_ATTEMPTS 2
 
 /* Skip this many hits before attempting recording again, after an aborted attempt. */
 #define BL_BACKOFF 32
 
@@ -142,22 +149,22 @@ static const char tagChar[]  = "OIDISIBI
      sizeof(JSInlineFrame)) /* possibly slow native frame at top of stack */
 
 /* Max number of branches per tree. */
 #define MAX_BRANCHES 32
 
 #define CHECK_STATUS(expr)                                                    \
     JS_BEGIN_MACRO                                                            \
         JSRecordingStatus _status = (expr);                                   \
-        if (_status != JSRS_CONTINUE)                                        \
+        if (_status != JSRS_CONTINUE)                                         \
           return _status;                                                     \
     JS_END_MACRO
 
 #ifdef JS_JIT_SPEW
-#define ABORT_TRACE_RV(msg, value)                                    \
+#define ABORT_TRACE_RV(msg, value)                                            \
     JS_BEGIN_MACRO                                                            \
         debug_only_printf(LC_TMAbort, "abort: %d: %s\n", __LINE__, (msg));    \
         return (value);                                                       \
     JS_END_MACRO
 #else
 #define ABORT_TRACE_RV(msg, value)   return (value)
 #endif
 
@@ -245,72 +252,78 @@ js_InitJITStatsClass(JSContext *cx, JSOb
 #endif /* JS_JIT_SPEW */
 
 #define INS_CONST(c)        addName(lir->insImm(c), #c)
 #define INS_CONSTPTR(p)     addName(lir->insImmPtr(p), #p)
 #define INS_CONSTFUNPTR(p)  addName(lir->insImmPtr(JS_FUNC_TO_DATA_PTR(void*, p)), #p)
 #define INS_CONSTWORD(v)    addName(lir->insImmPtr((void *) v), #v)
 #define INS_VOID()          INS_CONST(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID))
 
-using namespace avmplus;
-using namespace nanojit;
-
 static GC gc = GC();
 static avmplus::AvmCore s_core = avmplus::AvmCore();
 static avmplus::AvmCore* core = &s_core;
 
 #ifdef JS_JIT_SPEW
-void
-js_DumpPeerStability(JSTraceMonitor* tm, const void* ip, JSObject* globalObj, uint32 globalShape, uint32 argc);
-#endif
-
-/* We really need a better way to configure the JIT. Shaver, where is
-   my fancy JIT object? */
-/* NB: this is raced on, if jstracer.cpp should ever be running MT.
-   I think it's harmless tho. */
+static void
+DumpPeerStability(JSTraceMonitor* tm, const void* ip, JSObject* globalObj, uint32 globalShape, uint32 argc);
+#endif
+
+/*
+ * We really need a better way to configure the JIT. Shaver, where is
+ * my fancy JIT object?
+ *
+ * NB: this is raced on, if jstracer.cpp should ever be running MT.
+ * I think it's harmless tho.
+ */
 static bool did_we_check_processor_features = false;
 
 /* ------ Debug logging control ------ */
 
-/* All the logging control stuff lives in here.  It is shared between
-   all threads, but I think that's OK. */
+/*
+ * All the logging control stuff lives in here.  It is shared between
+ * all threads, but I think that's OK.
+ */
 LogControl js_LogController;
 
 #ifdef JS_JIT_SPEW
 
-/* NB: this is raced on too, if jstracer.cpp should ever be running MT.
-   Also harmless. */
+/*
+ * NB: this is raced on too, if jstracer.cpp should ever be running MT.
+ * Also harmless.
+ */
 static bool did_we_set_up_debug_logging = false;
 
 static void
-js_InitJITLogController ( void )
+InitJITLogController()
 {
     char *tm, *tmf;
     uint32_t bits;
 
     js_LogController.lcbits = 0;
 
     tm = getenv("TRACEMONKEY");
     if (tm) goto help;
 
     tmf = getenv("TMFLAGS");
     if (!tmf) return;
 
     /* This is really a cheap hack as far as flag decoding goes. */
     if (strstr(tmf, "help")) goto help;
 
     bits = 0;
+
     /* flags for jstracer.cpp */
     if (strstr(tmf, "minimal"))     bits |= LC_TMMinimal;
     if (strstr(tmf, "tracer"))      bits |= LC_TMTracer;
     if (strstr(tmf, "recorder"))    bits |= LC_TMRecorder;
     if (strstr(tmf, "patcher"))     bits |= LC_TMPatcher;
     if (strstr(tmf, "abort"))       bits |= LC_TMAbort;
     if (strstr(tmf, "stats"))       bits |= LC_TMStats;
     if (strstr(tmf, "regexp"))      bits |= LC_TMRegexp;
+
     /* flags for nanojit */
     if (strstr(tmf, "liveness"))    bits |= LC_Liveness;
     if (strstr(tmf, "readlir"))     bits |= LC_ReadLIR;
     if (strstr(tmf, "aftersf_sp"))  bits |= LC_AfterSF_SP;
     if (strstr(tmf, "aftersf_rp"))  bits |= LC_AfterSF_RP;
     if (strstr(tmf, "regalloc"))    bits |= LC_RegAlloc;
     if (strstr(tmf, "assembly"))    bits |= LC_Assembly;
     if (strstr(tmf, "nocodeaddrs")) bits |= LC_NoCodeAddrs;
@@ -372,18 +385,20 @@ getExitName(ExitType type)
     };
 
     JS_ASSERT(type < TOTAL_EXIT_TYPES);
 
     return exitNames[type];
 }
 #endif
 
-/* The entire VM shares one oracle. Collisions and concurrent updates are tolerated and worst
-   case cause performance regressions. */
+/*
+ * The entire VM shares one oracle. Collisions and concurrent updates are
+ * tolerated and worst case cause performance regressions.
+ */
 static Oracle oracle;
 
 Tracker::Tracker()
 {
     pagelist = 0;
 }
 
 Tracker::~Tracker()
@@ -457,285 +472,292 @@ void
 Tracker::set(const void* v, LIns* i)
 {
     struct Tracker::Page* p = findPage(v);
     if (!p)
         p = addPage(v);
     p->map[(jsuword(v) & PAGEMASK) >> 2] = i;
 }
 
-static inline jsuint argSlots(JSStackFrame* fp)
+static inline jsuint
+argSlots(JSStackFrame* fp)
 {
     return JS_MAX(fp->argc, fp->fun->nargs);
 }
 
-static inline bool isNumber(jsval v)
+static inline bool
+isNumber(jsval v)
 {
     return JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v);
 }
 
-static inline jsdouble asNumber(jsval v)
+static inline jsdouble
+asNumber(jsval v)
 {
     JS_ASSERT(isNumber(v));
     if (JSVAL_IS_DOUBLE(v))
         return *JSVAL_TO_DOUBLE(v);
     return (jsdouble)JSVAL_TO_INT(v);
 }
 
-static inline bool isInt32(jsval v)
+static inline bool
+isInt32(jsval v)
 {
     if (!isNumber(v))
         return false;
     jsdouble d = asNumber(v);
     jsint i;
     return JSDOUBLE_IS_INT(d, i);
 }
 
-static inline jsint asInt32(jsval v)
+static inline jsint
+asInt32(jsval v)
 {
     JS_ASSERT(isNumber(v));
     if (JSVAL_IS_INT(v))
         return JSVAL_TO_INT(v);
 #ifdef DEBUG
     jsint i;
     JS_ASSERT(JSDOUBLE_IS_INT(*JSVAL_TO_DOUBLE(v), i));
 #endif
     return jsint(*JSVAL_TO_DOUBLE(v));
 }
 
 /* Return TT_DOUBLE for all numbers (int and double) and the tag otherwise. */
-static inline JSTraceType getPromotedType(jsval v)
+static inline JSTraceType
+GetPromotedType(jsval v)
 {
     if (JSVAL_IS_INT(v))
         return TT_DOUBLE;
     if (JSVAL_IS_OBJECT(v)) {
         if (JSVAL_IS_NULL(v))
             return TT_NULL;
         if (HAS_FUNCTION_CLASS(JSVAL_TO_OBJECT(v)))
             return TT_FUNCTION;
         return TT_OBJECT;
     }
     uint8_t tag = JSVAL_TAG(v);
     JS_ASSERT(tag == JSVAL_DOUBLE || tag == JSVAL_STRING || tag == JSVAL_BOOLEAN);
-    JS_STATIC_ASSERT(TT_DOUBLE == JSVAL_DOUBLE);
-    JS_STATIC_ASSERT(TT_STRING == JSVAL_STRING);
-    JS_STATIC_ASSERT(TT_PSEUDOBOOLEAN == JSVAL_BOOLEAN);
+    JS_STATIC_ASSERT(static_cast<jsvaltag>(TT_DOUBLE) == JSVAL_DOUBLE);
+    JS_STATIC_ASSERT(static_cast<jsvaltag>(TT_STRING) == JSVAL_STRING);
+    JS_STATIC_ASSERT(static_cast<jsvaltag>(TT_PSEUDOBOOLEAN) == JSVAL_BOOLEAN);
     return JSTraceType(tag);
 }
 
 /* Return TT_INT32 for all whole numbers that fit into signed 32-bit and the tag otherwise. */
-static inline JSTraceType getCoercedType(jsval v)
+static inline JSTraceType
+getCoercedType(jsval v)
 {
     if (isInt32(v))
         return TT_INT32;
     if (JSVAL_IS_OBJECT(v)) {
         if (JSVAL_IS_NULL(v))
             return TT_NULL;
         if (HAS_FUNCTION_CLASS(JSVAL_TO_OBJECT(v)))
             return TT_FUNCTION;
         return TT_OBJECT;
     }
     uint8_t tag = JSVAL_TAG(v);
     JS_ASSERT(tag == JSVAL_DOUBLE || tag == JSVAL_STRING || tag == JSVAL_BOOLEAN);
-    JS_STATIC_ASSERT(TT_DOUBLE == JSVAL_DOUBLE);
-    JS_STATIC_ASSERT(TT_STRING == JSVAL_STRING);
-    JS_STATIC_ASSERT(TT_PSEUDOBOOLEAN == JSVAL_BOOLEAN);
+    JS_STATIC_ASSERT(static_cast<jsvaltag>(TT_DOUBLE) == JSVAL_DOUBLE);
+    JS_STATIC_ASSERT(static_cast<jsvaltag>(TT_STRING) == JSVAL_STRING);
+    JS_STATIC_ASSERT(static_cast<jsvaltag>(TT_PSEUDOBOOLEAN) == JSVAL_BOOLEAN);
     return JSTraceType(tag);
 }
 
-/*
- * Constant seed and accumulate step borrowed from the DJB hash.
- */
-
-#define ORACLE_MASK (ORACLE_SIZE - 1)
-#define FRAGMENT_TABLE_MASK (FRAGMENT_TABLE_SIZE - 1)
-#define HASH_SEED 5381
+/* Constant seed and accumulate step borrowed from the DJB hash. */
+
+const uintptr_t ORACLE_MASK = ORACLE_SIZE - 1;
+JS_STATIC_ASSERT((ORACLE_MASK & ORACLE_SIZE) == 0);
+
+const uintptr_t FRAGMENT_TABLE_MASK = FRAGMENT_TABLE_SIZE - 1;
+JS_STATIC_ASSERT((FRAGMENT_TABLE_MASK & FRAGMENT_TABLE_SIZE) == 0);
+
+const uintptr_t HASH_SEED = 5381;
 
 static inline void
-hash_accum(uintptr_t& h, uintptr_t i, uintptr_t mask)
+HashAccum(uintptr_t& h, uintptr_t i, uintptr_t mask)
 {
     h = ((h << 5) + h + (mask & i)) & mask;
 }
 
-JS_REQUIRES_STACK static inline int
-stackSlotHash(JSContext* cx, unsigned slot)
+static JS_REQUIRES_STACK inline int
+StackSlotHash(JSContext* cx, unsigned slot)
 {
     uintptr_t h = HASH_SEED;
-    hash_accum(h, uintptr_t(cx->fp->script), ORACLE_MASK);
-    hash_accum(h, uintptr_t(cx->fp->regs->pc), ORACLE_MASK);
-    hash_accum(h, uintptr_t(slot), ORACLE_MASK);
+    HashAccum(h, uintptr_t(cx->fp->script), ORACLE_MASK);
+    HashAccum(h, uintptr_t(cx->fp->regs->pc), ORACLE_MASK);
+    HashAccum(h, uintptr_t(slot), ORACLE_MASK);
     return int(h);
 }
 
-JS_REQUIRES_STACK static inline int
-globalSlotHash(JSContext* cx, unsigned slot)
+static JS_REQUIRES_STACK inline int
+GlobalSlotHash(JSContext* cx, unsigned slot)
 {
     uintptr_t h = HASH_SEED;
     JSStackFrame* fp = cx->fp;
 
     while (fp->down)
         fp = fp->down;
 
-    hash_accum(h, uintptr_t(fp->script), ORACLE_MASK);
-    hash_accum(h, uintptr_t(OBJ_SHAPE(JS_GetGlobalForObject(cx, fp->scopeChain))),
-               ORACLE_MASK);
-    hash_accum(h, uintptr_t(slot), ORACLE_MASK);
+    HashAccum(h, uintptr_t(fp->script), ORACLE_MASK);
+    HashAccum(h, uintptr_t(OBJ_SHAPE(JS_GetGlobalForObject(cx, fp->scopeChain))), ORACLE_MASK);
+    HashAccum(h, uintptr_t(slot), ORACLE_MASK);
     return int(h);
 }
 
 static inline int
-pcHash(jsbytecode* pc)
+PCHash(jsbytecode* pc)
 {
     return int(uintptr_t(pc) & ORACLE_MASK);
 }
 
 Oracle::Oracle()
 {
     /* Grow the oracle bitsets to their (fixed) size here, once. */
     _stackDontDemote.set(&gc, ORACLE_SIZE-1);
     _globalDontDemote.set(&gc, ORACLE_SIZE-1);
     clear();
 }
 
 /* Tell the oracle that a certain global variable should not be demoted. */
 JS_REQUIRES_STACK void
 Oracle::markGlobalSlotUndemotable(JSContext* cx, unsigned slot)
 {
-    _globalDontDemote.set(&gc, globalSlotHash(cx, slot));
+    _globalDontDemote.set(&gc, GlobalSlotHash(cx, slot));
 }
 
 /* Consult with the oracle whether we shouldn't demote a certain global variable. */
 JS_REQUIRES_STACK bool
 Oracle::isGlobalSlotUndemotable(JSContext* cx, unsigned slot) const
 {
-    return _globalDontDemote.get(globalSlotHash(cx, slot));
+    return _globalDontDemote.get(GlobalSlotHash(cx, slot));
 }
 
 /* Tell the oracle that a certain slot at a certain stack slot should not be demoted. */
 JS_REQUIRES_STACK void
 Oracle::markStackSlotUndemotable(JSContext* cx, unsigned slot)
 {
-    _stackDontDemote.set(&gc, stackSlotHash(cx, slot));
+    _stackDontDemote.set(&gc, StackSlotHash(cx, slot));
 }
 
 /* Consult with the oracle whether we shouldn't demote a certain slot. */
 JS_REQUIRES_STACK bool
 Oracle::isStackSlotUndemotable(JSContext* cx, unsigned slot) const
 {
-    return _stackDontDemote.get(stackSlotHash(cx, slot));
+    return _stackDontDemote.get(StackSlotHash(cx, slot));
 }
 
 /* Tell the oracle that a certain slot at a certain bytecode location should not be demoted. */
 void
 Oracle::markInstructionUndemotable(jsbytecode* pc)
 {
-    _pcDontDemote.set(&gc, pcHash(pc));
+    _pcDontDemote.set(&gc, PCHash(pc));
 }
 
 /* Consult with the oracle whether we shouldn't demote a certain bytecode location. */
 bool
 Oracle::isInstructionUndemotable(jsbytecode* pc) const
 {
-    return _pcDontDemote.get(pcHash(pc));
+    return _pcDontDemote.get(PCHash(pc));
 }
 
 void
 Oracle::clearDemotability()
 {
     _stackDontDemote.reset();
     _globalDontDemote.reset();
     _pcDontDemote.reset();
 }
 
-
 struct PCHashEntry : public JSDHashEntryStub {
     size_t          count;
 };
 
 #define PC_HASH_COUNT 1024
 
 static void
-js_Blacklist(jsbytecode* pc)
+Blacklist(jsbytecode* pc)
 {
     AUDIT(blacklisted);
     JS_ASSERT(*pc == JSOP_LOOP || *pc == JSOP_NOP);
     *pc = JSOP_NOP;
 }
 
 static void
-js_Backoff(JSContext *cx, jsbytecode* pc, Fragment* tree=NULL)
+Backoff(JSContext *cx, jsbytecode* pc, Fragment* tree = NULL)
 {
     JSDHashTable *table = &JS_TRACE_MONITOR(cx).recordAttempts;
 
     if (table->ops) {
         PCHashEntry *entry = (PCHashEntry *)
             JS_DHashTableOperate(table, pc, JS_DHASH_ADD);
 
         if (entry) {
             if (!entry->key) {
                 entry->key = pc;
                 JS_ASSERT(entry->count == 0);
             }
             JS_ASSERT(JS_DHASH_ENTRY_IS_LIVE(&(entry->hdr)));
             if (entry->count++ > (BL_ATTEMPTS * MAXPEERS)) {
                 entry->count = 0;
-                js_Blacklist(pc);
+                Blacklist(pc);
                 return;
             }
         }
     }
 
     if (tree) {
         tree->hits() -= BL_BACKOFF;
 
         /*
          * In case there is no entry or no table (due to OOM) or some
          * serious imbalance in the recording-attempt distribution on a
          * multitree, give each tree another chance to blacklist here as
          * well.
          */
         if (++tree->recordAttempts > BL_ATTEMPTS)
-            js_Blacklist(pc);
+            Blacklist(pc);
     }
 }
 
 static void
-js_resetRecordingAttempts(JSContext *cx, jsbytecode* pc)
+ResetRecordingAttempts(JSContext *cx, jsbytecode* pc)
 {
     JSDHashTable *table = &JS_TRACE_MONITOR(cx).recordAttempts;
     if (table->ops) {
         PCHashEntry *entry = (PCHashEntry *)
             JS_DHashTableOperate(table, pc, JS_DHASH_LOOKUP);
 
         if (JS_DHASH_ENTRY_IS_FREE(&(entry->hdr)))
             return;
         JS_ASSERT(JS_DHASH_ENTRY_IS_LIVE(&(entry->hdr)));
         entry->count = 0;
     }
 }
 
 static inline size_t
-fragmentHash(const void *ip, JSObject* globalObj, uint32 globalShape, uint32 argc)
+FragmentHash(const void *ip, JSObject* globalObj, uint32 globalShape, uint32 argc)
 {
     uintptr_t h = HASH_SEED;
-    hash_accum(h, uintptr_t(ip), FRAGMENT_TABLE_MASK);
-    hash_accum(h, uintptr_t(globalObj), FRAGMENT_TABLE_MASK);
-    hash_accum(h, uintptr_t(globalShape), FRAGMENT_TABLE_MASK);
-    hash_accum(h, uintptr_t(argc), FRAGMENT_TABLE_MASK);
+    HashAccum(h, uintptr_t(ip), FRAGMENT_TABLE_MASK);
+    HashAccum(h, uintptr_t(globalObj), FRAGMENT_TABLE_MASK);
+    HashAccum(h, uintptr_t(globalShape), FRAGMENT_TABLE_MASK);
+    HashAccum(h, uintptr_t(argc), FRAGMENT_TABLE_MASK);
     return size_t(h);
 }
 
 /*
  * argc is cx->fp->argc at the trace loop header, i.e., the number of arguments
  * pushed for the innermost JS frame. This is required as part of the fragment
  * key because the fragment will write those arguments back to the interpreter
- * stack when it exits, using its typemap, which implicitly incorporates a given
- * value of argc. Without this feature, a fragment could be called as an inner
- * tree with two different values of argc, and entry type checking or exit
- * frame synthesis could crash.
+ * stack when it exits, using its typemap, which implicitly incorporates a
+ * given value of argc. Without this feature, a fragment could be called as an
+ * inner tree with two different values of argc, and entry type checking or
+ * exit frame synthesis could crash.
  */
 struct VMFragment : public Fragment
 {
     VMFragment(const void* _ip, JSObject* _globalObj, uint32 _globalShape, uint32 _argc) :
         Fragment(_ip),
         next(NULL),
         globalObj(_globalObj),
         globalShape(_globalShape),
@@ -746,69 +768,68 @@ struct VMFragment : public Fragment
     uint32 globalShape;
     uint32 argc;
 };
 
 static VMFragment*
 getVMFragment(JSTraceMonitor* tm, const void *ip, JSObject* globalObj, uint32 globalShape,
               uint32 argc)
 {
-    size_t h = fragmentHash(ip, globalObj, globalShape, argc);
+    size_t h = FragmentHash(ip, globalObj, globalShape, argc);
     VMFragment* vf = tm->vmfragments[h];
     while (vf &&
            ! (vf->globalObj == globalObj &&
               vf->globalShape == globalShape &&
               vf->ip == ip &&
               vf->argc == argc)) {
         vf = vf->next;
     }
     return vf;
 }
 
 static VMFragment*
-getLoop(JSTraceMonitor* tm, const void *ip, JSObject* globalObj, uint32 globalShape,
-        uint32 argc)
+getLoop(JSTraceMonitor* tm, const void *ip, JSObject* globalObj, uint32 globalShape, uint32 argc)
 {
     return getVMFragment(tm, ip, globalObj, globalShape, argc);
 }
 
 static Fragment*
-getAnchor(JSTraceMonitor* tm, const void *ip, JSObject* globalObj, uint32 globalShape,
-          uint32 argc)
+getAnchor(JSTraceMonitor* tm, const void *ip, JSObject* globalObj, uint32 globalShape, uint32 argc)
 {
     VMFragment *f = new (&gc) VMFragment(ip, globalObj, globalShape, argc);
     JS_ASSERT(f);
 
     Fragment *p = getVMFragment(tm, ip, globalObj, globalShape, argc);
 
     if (p) {
         f->first = p;
         /* append at the end of the peer list */
         Fragment* next;
         while ((next = p->peer) != NULL)
             p = next;
         p->peer = f;
     } else {
         /* this is the first fragment */
         f->first = f;
-        size_t h = fragmentHash(ip, globalObj, globalShape, argc);
+        size_t h = FragmentHash(ip, globalObj, globalShape, argc);
         f->next = tm->vmfragments[h];
         tm->vmfragments[h] = f;
     }
     f->anchor = f;
     f->root = f;
     f->kind = LoopTrace;
     return f;
 }
 
 #ifdef DEBUG
 static void
-ensureTreeIsUnique(JSTraceMonitor* tm, VMFragment* f, TreeInfo* ti)
+AssertTreeIsUnique(JSTraceMonitor* tm, VMFragment* f, TreeInfo* ti)
 {
     JS_ASSERT(f->root == f);
+
     /*
      * Check for duplicate entry type maps.  This is always wrong and hints at
      * trace explosion since we are trying to stabilize something without
      * properly connecting peer edges.
      */
     TreeInfo* ti_other;
     for (Fragment* peer = getLoop(tm, f->ip, f->globalObj, f->globalShape, f->argc);
          peer != NULL;
@@ -818,31 +839,26 @@ ensureTreeIsUnique(JSTraceMonitor* tm, V
         ti_other = (TreeInfo*)peer->vmprivate;
         JS_ASSERT(ti_other);
         JS_ASSERT(!ti->typeMap.matches(ti_other->typeMap));
     }
 }
 #endif
 
 static void
-js_AttemptCompilation(JSContext *cx, JSTraceMonitor* tm, JSObject* globalObj, jsbytecode* pc,
-                      uint32 argc)
-{
-    /*
-     * If we already permanently blacklisted the location, undo that.
-     */
+AttemptCompilation(JSContext *cx, JSTraceMonitor* tm, JSObject* globalObj, jsbytecode* pc,
+                   uint32 argc)
+{
+    /* If we already permanently blacklisted the location, undo that. */
     JS_ASSERT(*(jsbytecode*)pc == JSOP_NOP || *(jsbytecode*)pc == JSOP_LOOP);
     *(jsbytecode*)pc = JSOP_LOOP;
-    js_resetRecordingAttempts(cx, pc);
-
-    /*
-     * Breath new live into all peer fragments at the designated loop header.
-     */
-    Fragment* f = (VMFragment*)getLoop(tm, pc, globalObj, OBJ_SHAPE(globalObj),
-                                       argc);
+    ResetRecordingAttempts(cx, pc);
+
+    /* Breathe new life into all peer fragments at the designated loop header. */
+    Fragment* f = (VMFragment*)getLoop(tm, pc, globalObj, OBJ_SHAPE(globalObj), argc);
     if (!f) {
         /*
          * If the global object's shape changed, we can't easily find the
          * corresponding loop header via a hash table lookup. In this
          * we simply bail here and hope that the fragment has another
          * outstanding compilation attempt. This case is extremely rare.
          */
         return;
@@ -856,111 +872,116 @@ js_AttemptCompilation(JSContext *cx, JST
         f = f->peer;
     }
 }
 
 // Forward declarations.
 JS_DEFINE_CALLINFO_1(static, DOUBLE, i2f,  INT32, 1, 1)
 JS_DEFINE_CALLINFO_1(static, DOUBLE, u2f, UINT32, 1, 1)
 
-static bool isi2f(LInsp i)
+static bool
+isi2f(LIns* i)
 {
     if (i->isop(LIR_i2f))
         return true;
 
     if (nanojit::AvmCore::config.soft_float &&
         i->isop(LIR_qjoin) &&
         i->oprnd1()->isop(LIR_call) &&
-        i->oprnd2()->isop(LIR_callh))
-    {
+        i->oprnd2()->isop(LIR_callh)) {
         if (i->oprnd1()->callInfo() == &i2f_ci)
             return true;
     }
 
     return false;
 }
 
-static bool isu2f(LInsp i)
+static bool
+isu2f(LIns* i)
 {
     if (i->isop(LIR_u2f))
         return true;
 
     if (nanojit::AvmCore::config.soft_float &&
         i->isop(LIR_qjoin) &&
         i->oprnd1()->isop(LIR_call) &&
-        i->oprnd2()->isop(LIR_callh))
-    {
+        i->oprnd2()->isop(LIR_callh)) {
         if (i->oprnd1()->callInfo() == &u2f_ci)
             return true;
     }
 
     return false;
 }
 
-static LInsp iu2fArg(LInsp i)
+static LIns*
+iu2fArg(LIns* i)
 {
     if (nanojit::AvmCore::config.soft_float &&
-        i->isop(LIR_qjoin))
-    {
+        i->isop(LIR_qjoin)) {
         return i->oprnd1()->arg(0);
     }
 
     return i->oprnd1();
 }
 
-
-static LIns* demote(LirWriter *out, LInsp i)
+static LIns*
+demote(LirWriter *out, LIns* i)
 {
     if (i->isCall())
         return callArgN(i, 0);
     if (isi2f(i) || isu2f(i))
         return iu2fArg(i);
     if (i->isconst())
         return i;
     AvmAssert(i->isconstq());
     double cf = i->imm64f();
     int32_t ci = cf > 0x7fffffff ? uint32_t(cf) : int32_t(cf);
     return out->insImm(ci);
 }
 
-static bool isPromoteInt(LIns* i)
+static bool
+isPromoteInt(LIns* i)
 {
     if (isi2f(i) || i->isconst())
         return true;
     if (!i->isconstq())
         return false;
     jsdouble d = i->imm64f();
     return d == jsdouble(jsint(d)) && !JSDOUBLE_IS_NEGZERO(d);
 }
 
-static bool isPromoteUint(LIns* i)
+static bool
+isPromoteUint(LIns* i)
 {
     if (isu2f(i) || i->isconst())
         return true;
     if (!i->isconstq())
         return false;
     jsdouble d = i->imm64f();
     return d == jsdouble(jsuint(d)) && !JSDOUBLE_IS_NEGZERO(d);
 }
 
-static bool isPromote(LIns* i)
+static bool
+isPromote(LIns* i)
 {
     return isPromoteInt(i) || isPromoteUint(i);
 }
 
-static bool isconst(LIns* i, int32_t c)
+static bool
+IsConst(LIns* i, int32_t c)
 {
     return i->isconst() && i->imm32() == c;
 }
 
 /*
  * Determine whether this operand is guaranteed to not overflow the specified
  * integer operation.
  */
-static bool overflowSafe(LOpcode op, LIns* i)
+static bool
+IsOverflowSafe(LOpcode op, LIns* i)
 {
     LIns* c;
     switch (op) {
       case LIR_add:
       case LIR_sub:
           return (i->isop(LIR_and) && ((c = i->oprnd2())->isconst()) &&
                   ((c->imm32() & 0xc0000000) == 0)) ||
                  (i->isop(LIR_rsh) && ((c = i->oprnd2())->isconst()) &&
@@ -1061,42 +1082,42 @@ JS_DEFINE_CALLINFO_2(static, DOUBLE, fsu
 class SoftFloatFilter: public LirWriter
 {
 public:
     SoftFloatFilter(LirWriter* out):
         LirWriter(out)
     {
     }
 
-    LInsp quadCall(const CallInfo *ci, LInsp args[]) {
+    LIns* quadCall(const CallInfo *ci, LIns* args[]) {
         LInsp qlo, qhi;
 
         qlo = out->insCall(ci, args);
         qhi = out->ins1(LIR_callh, qlo);
         return out->qjoin(qlo, qhi);
     }
 
-    LInsp ins1(LOpcode v, LInsp s0)
+    LIns* ins1(LOpcode v, LIns* s0)
     {
         if (v == LIR_fneg)
             return quadCall(&fneg_ci, &s0);
 
         if (v == LIR_i2f)
             return quadCall(&i2f_ci, &s0);
 
         if (v == LIR_u2f)
             return quadCall(&u2f_ci, &s0);
 
         return out->ins1(v, s0);
     }
 
-    LInsp ins2(LOpcode v, LInsp s0, LInsp s1)
+    LIns* ins2(LOpcode v, LIns* s0, LIns* s1)
     {
-        LInsp args[2];
-        LInsp bv;
+        LIns* args[2];
+        LIns* bv;
 
         // change the numeric value and order of these LIR opcodes and die
         if (LIR_fadd <= v && v <= LIR_fdiv) {
             static const CallInfo *fmap[] = { &fadd_ci, &fsub_ci, &fmul_ci, &fdiv_ci };
 
             args[0] = s1;
             args[1] = s0;
 
@@ -1111,45 +1132,45 @@ public:
 
             bv = out->insCall(fmap[v - LIR_feq], args);
             return out->ins2(LIR_eq, bv, out->insImm(1));
         }
 
         return out->ins2(v, s0, s1);
     }
 
-    LInsp insCall(const CallInfo *ci, LInsp args[])
+    LIns* insCall(const CallInfo *ci, LIns* args[])
     {
         // if the return type is ARGSIZE_F, we have
-        // to do a quadCall ( qjoin(call,callh) )
+        // to do a quadCall(qjoin(call,callh))
         if ((ci->_argtypes & 3) == ARGSIZE_F)
             return quadCall(ci, args);
 
         return out->insCall(ci, args);
     }
 };
 
 class FuncFilter: public LirWriter
 {
 public:
     FuncFilter(LirWriter* out):
         LirWriter(out)
     {
     }
 
-    LInsp ins2(LOpcode v, LInsp s0, LInsp s1)
+    LIns* ins2(LOpcode v, LIns* s0, LIns* s1)
     {
         if (s0 == s1 && v == LIR_feq) {
             if (isPromote(s0)) {
                 // double(int) and double(uint) cannot be nan
                 return insImm(1);
             }
             if (s0->isop(LIR_fmul) || s0->isop(LIR_fsub) || s0->isop(LIR_fadd)) {
-                LInsp lhs = s0->oprnd1();
-                LInsp rhs = s0->oprnd2();
+                LIns* lhs = s0->oprnd1();
+                LIns* rhs = s0->oprnd2();
                 if (isPromote(lhs) && isPromote(rhs)) {
                     // add/sub/mul promoted ints can't be nan
                     return insImm(1);
                 }
             }
         } else if (LIR_feq <= v && v <= LIR_fge) {
             if (isPromoteInt(s0) && isPromoteInt(s1)) {
                 // demote fcmp to cmp
@@ -1158,67 +1179,68 @@ public:
             } else if (isPromoteUint(s0) && isPromoteUint(s1)) {
                 // uint compare
                 v = LOpcode(v + (LIR_eq - LIR_feq));
                 if (v != LIR_eq)
                     v = LOpcode(v + (LIR_ult - LIR_lt)); // cmp -> ucmp
                 return out->ins2(v, demote(out, s0), demote(out, s1));
             }
         } else if (v == LIR_or &&
-                   s0->isop(LIR_lsh) && isconst(s0->oprnd2(), 16) &&
-                   s1->isop(LIR_and) && isconst(s1->oprnd2(), 0xffff)) {
+                   s0->isop(LIR_lsh) && IsConst(s0->oprnd2(), 16) &&
+                   s1->isop(LIR_and) && IsConst(s1->oprnd2(), 0xffff)) {
             LIns* msw = s0->oprnd1();
             LIns* lsw = s1->oprnd1();
             LIns* x;
             LIns* y;
             if (lsw->isop(LIR_add) &&
                 lsw->oprnd1()->isop(LIR_and) &&
                 lsw->oprnd2()->isop(LIR_and) &&
-                isconst(lsw->oprnd1()->oprnd2(), 0xffff) &&
-                isconst(lsw->oprnd2()->oprnd2(), 0xffff) &&
+                IsConst(lsw->oprnd1()->oprnd2(), 0xffff) &&
+                IsConst(lsw->oprnd2()->oprnd2(), 0xffff) &&
                 msw->isop(LIR_add) &&
                 msw->oprnd1()->isop(LIR_add) &&
                 msw->oprnd2()->isop(LIR_rsh) &&
                 msw->oprnd1()->oprnd1()->isop(LIR_rsh) &&
                 msw->oprnd1()->oprnd2()->isop(LIR_rsh) &&
-                isconst(msw->oprnd2()->oprnd2(), 16) &&
-                isconst(msw->oprnd1()->oprnd1()->oprnd2(), 16) &&
-                isconst(msw->oprnd1()->oprnd2()->oprnd2(), 16) &&
+                IsConst(msw->oprnd2()->oprnd2(), 16) &&
+                IsConst(msw->oprnd1()->oprnd1()->oprnd2(), 16) &&
+                IsConst(msw->oprnd1()->oprnd2()->oprnd2(), 16) &&
                 (x = lsw->oprnd1()->oprnd1()) == msw->oprnd1()->oprnd1()->oprnd1() &&
                 (y = lsw->oprnd2()->oprnd1()) == msw->oprnd1()->oprnd2()->oprnd1() &&
                 lsw == msw->oprnd2()->oprnd1()) {
                 return out->ins2(LIR_add, x, y);
             }
         }
 
         return out->ins2(v, s0, s1);
     }
 
-    LInsp insCall(const CallInfo *ci, LInsp args[])
+    LIns* insCall(const CallInfo *ci, LIns* args[])
     {
         if (ci == &js_DoubleToUint32_ci) {
-            LInsp s0 = args[0];
+            LIns* s0 = args[0];
             if (s0->isconstq())
                 return out->insImm(js_DoubleToECMAUint32(s0->imm64f()));
             if (isi2f(s0) || isu2f(s0))
                 return iu2fArg(s0);
         } else if (ci == &js_DoubleToInt32_ci) {
-            LInsp s0 = args[0];
+            LIns* s0 = args[0];
             if (s0->isconstq())
                 return out->insImm(js_DoubleToECMAInt32(s0->imm64f()));
             if (s0->isop(LIR_fadd) || s0->isop(LIR_fsub)) {
-                LInsp lhs = s0->oprnd1();
-                LInsp rhs = s0->oprnd2();
+                LIns* lhs = s0->oprnd1();
+                LIns* rhs = s0->oprnd2();
                 if (isPromote(lhs) && isPromote(rhs)) {
                     LOpcode op = LOpcode(s0->opcode() & ~LIR64);
                     return out->ins2(op, demote(out, lhs), demote(out, rhs));
                 }
             }
             if (isi2f(s0) || isu2f(s0))
                 return iu2fArg(s0);
+
             // XXX ARM -- check for qjoin(call(UnboxDouble),call(UnboxDouble))
             if (s0->isCall()) {
                 const CallInfo* ci2 = s0->callInfo();
                 if (ci2 == &js_UnboxDouble_ci) {
                     LIns* args2[] = { callArgN(s0, 0) };
                     return out->insCall(&js_UnboxInt32_ci, args2);
                 } else if (ci2 == &js_StringToNumber_ci) {
                     // callArgN's ordering is that as seen by the builtin, not as stored in
@@ -1235,39 +1257,39 @@ public:
                     idx = isPromote(idx)
                         ? demote(out, idx)
                         : out->insCall(&js_DoubleToInt32_ci, &idx);
                     LIns* args2[] = { idx, callArgN(s0, 0) };
                     return out->insCall(&js_String_p_charCodeAt_int_ci, args2);
                 }
             }
         } else if (ci == &js_BoxDouble_ci) {
-            LInsp s0 = args[0];
+            LIns* s0 = args[0];
             JS_ASSERT(s0->isQuad());
             if (isPromoteInt(s0)) {
                 LIns* args2[] = { demote(out, s0), args[1] };
                 return out->insCall(&js_BoxInt32_ci, args2);
             }
             if (s0->isCall() && s0->callInfo() == &js_UnboxDouble_ci)
                 return callArgN(s0, 0);
         }
         return out->insCall(ci, args);
     }
 };
 
 /*
- * Visit the values in the given JSStackFrame that the tracer cares about. This visitor
- * function is (implicitly) the primary definition of the native stack area layout. There
- * are a few other independent pieces of code that must be maintained to assume the same
- * layout. They are marked like this:
+ * Visit the values in the given JSStackFrame that the tracer cares about. This
+ * visitor function is (implicitly) the primary definition of the native stack
+ * area layout. There are a few other independent pieces of code that must be
+ * maintained to assume the same layout. They are marked like this:
  *
  *   Duplicate native stack layout computation: see VisitFrameSlots header comment.
  */
 template <typename Visitor>
-JS_REQUIRES_STACK static bool
+static JS_REQUIRES_STACK bool
 VisitFrameSlots(Visitor &visitor, unsigned depth, JSStackFrame *fp,
                 JSStackFrame *up)
 {
     if (depth > 0 && !VisitFrameSlots(visitor, depth-1, fp->down, fp))
         return false;
 
     if (fp->callee) {
         if (depth == 0) {
@@ -1296,73 +1318,73 @@ VisitFrameSlots(Visitor &visitor, unsign
             if (!visitor.visitStackSlots(fp->regs->sp, size_t(missing), fp))
                 return false;
         }
     }
     return true;
 }
 
 template <typename Visitor>
-JS_REQUIRES_STACK static JS_ALWAYS_INLINE bool
+static JS_REQUIRES_STACK JS_ALWAYS_INLINE bool
 VisitStackSlots(Visitor &visitor, JSContext *cx, unsigned callDepth)
 {
     return VisitFrameSlots(visitor, callDepth, cx->fp, NULL);
 }
 
 template <typename Visitor>
-JS_REQUIRES_STACK static JS_ALWAYS_INLINE void
+static JS_REQUIRES_STACK JS_ALWAYS_INLINE void
 VisitGlobalSlots(Visitor &visitor, JSContext *cx, JSObject *globalObj,
                  unsigned ngslots, uint16 *gslots)
 {
     for (unsigned n = 0; n < ngslots; ++n) {
         unsigned slot = gslots[n];
         visitor.visitGlobalSlot(&STOBJ_GET_SLOT(globalObj, slot), n, slot);
     }
 }
 
 class AdjustCallerTypeVisitor;
 
 template <typename Visitor>
-JS_REQUIRES_STACK static JS_ALWAYS_INLINE void
+static JS_REQUIRES_STACK JS_ALWAYS_INLINE void
 VisitGlobalSlots(Visitor &visitor, JSContext *cx, SlotList &gslots)
 {
     VisitGlobalSlots(visitor, cx, JS_GetGlobalForObject(cx, cx->fp->scopeChain),
                      gslots.length(), gslots.data());
 }
 
 
 template <typename Visitor>
-JS_REQUIRES_STACK static JS_ALWAYS_INLINE void
+static JS_REQUIRES_STACK JS_ALWAYS_INLINE void
 VisitSlots(Visitor& visitor, JSContext* cx, JSObject* globalObj,
            unsigned callDepth, unsigned ngslots, uint16* gslots)
 {
     if (VisitStackSlots(visitor, cx, callDepth))
         VisitGlobalSlots(visitor, cx, globalObj, ngslots, gslots);
 }
 
 template <typename Visitor>
-JS_REQUIRES_STACK static JS_ALWAYS_INLINE void
+static JS_REQUIRES_STACK JS_ALWAYS_INLINE void
 VisitSlots(Visitor& visitor, JSContext* cx, unsigned callDepth,
            unsigned ngslots, uint16* gslots)
 {
     VisitSlots(visitor, cx, JS_GetGlobalForObject(cx, cx->fp->scopeChain),
                callDepth, ngslots, gslots);
 }
 
 template <typename Visitor>
-JS_REQUIRES_STACK static JS_ALWAYS_INLINE void
+static JS_REQUIRES_STACK JS_ALWAYS_INLINE void
 VisitSlots(Visitor &visitor, JSContext *cx, JSObject *globalObj,
            unsigned callDepth, const SlotList& slots)
 {
     VisitSlots(visitor, cx, globalObj, callDepth, slots.length(),
                slots.data());
 }
 
 template <typename Visitor>
-JS_REQUIRES_STACK static JS_ALWAYS_INLINE void
+static JS_REQUIRES_STACK JS_ALWAYS_INLINE void
 VisitSlots(Visitor &visitor, JSContext *cx, unsigned callDepth,
            const SlotList& slots)
 {
     VisitSlots(visitor, cx, JS_GetGlobalForObject(cx, cx->fp->scopeChain),
                callDepth, slots.length(), slots.data());
 }
 
 
@@ -1412,26 +1434,31 @@ public:
         return mCount;
     }
 
     JS_ALWAYS_INLINE bool stopped() {
         return mDone;
     }
 };
 
-/* Calculate the total number of native frame slots we need from this frame
-   all the way back to the entry frame, including the current stack usage. */
+/*
+ * Calculate the total number of native frame slots we need from this frame all
+ * the way back to the entry frame, including the current stack usage.
+ */
 JS_REQUIRES_STACK unsigned
-js_NativeStackSlots(JSContext *cx, unsigned callDepth)
+NativeStackSlots(JSContext *cx, unsigned callDepth)
 {
     JSStackFrame* fp = cx->fp;
     unsigned slots = 0;
     unsigned depth = callDepth;
     for (;;) {
-        /* Duplicate native stack layout computation: see VisitFrameSlots header comment. */
+        /*
+         * Duplicate native stack layout computation: see VisitFrameSlots
+         * header comment.
+         */
         unsigned operands = fp->regs->sp - StackBase(fp);
         slots += operands;
         if (fp->callee)
             slots += fp->script->nfixed + 1 /*argsobj*/;
         if (depth-- == 0) {
             if (fp->callee)
                 slots += 2/*callee,this*/ + argSlots(fp);
 #ifdef DEBUG
@@ -1442,17 +1469,17 @@ js_NativeStackSlots(JSContext *cx, unsig
             return slots;
         }
         JSStackFrame* fp2 = fp;
         fp = fp->down;
         int missing = fp2->fun->nargs - fp2->argc;
         if (missing > 0)
             slots += missing;
     }
-    JS_NOT_REACHED("js_NativeStackSlots");
+    JS_NOT_REACHED("NativeStackSlots");
 }
 
 class CaptureTypesVisitor : public SlotVisitorBase
 {
     JSContext* mCx;
     JSTraceType* mTypeMap;
     JSTraceType* mPtr;
 
@@ -1499,17 +1526,17 @@ public:
 
 /*
  * Capture the type map for the selected slots of the global object and currently pending
  * stack frames.
  */
 JS_REQUIRES_STACK void
 TypeMap::captureTypes(JSContext* cx, JSObject* globalObj, SlotList& slots, unsigned callDepth)
 {
-    setLength(js_NativeStackSlots(cx, callDepth) + slots.length());
+    setLength(NativeStackSlots(cx, callDepth) + slots.length());
     CaptureTypesVisitor visitor(cx, data());
     VisitSlots(visitor, cx, globalObj, callDepth, slots);
     JS_ASSERT(visitor.length() == length());
 }
 
 JS_REQUIRES_STACK void
 TypeMap::captureMissingGlobalTypes(JSContext* cx, JSObject* globalObj, SlotList& slots, unsigned stackSlots)
 {
@@ -1525,53 +1552,75 @@ TypeMap::captureMissingGlobalTypes(JSCon
 bool
 TypeMap::matches(TypeMap& other) const
 {
     if (length() != other.length())
         return false;
     return !memcmp(data(), other.data(), length());
 }
 
-/* Use the provided storage area to create a new type map that contains the partial type map
-   with the rest of it filled up from the complete type map. */
+/*
+ * Use the provided storage area to create a new type map that contains the
+ * partial type map with the rest of it filled up from the complete type
+ * map.
+ */
 static void
-mergeTypeMaps(JSTraceType** partial, unsigned* plength, JSTraceType* complete, unsigned clength, JSTraceType* mem)
+MergeTypeMaps(JSTraceType** partial, unsigned* plength, JSTraceType* complete, unsigned clength, JSTraceType* mem)
 {
     unsigned l = *plength;
     JS_ASSERT(l < clength);
     memcpy(mem, *partial, l * sizeof(JSTraceType));
     memcpy(mem + l, complete + l, (clength - l) * sizeof(JSTraceType));
     *partial = mem;
     *plength = clength;
 }
 
 /* Specializes a tree to any missing globals, including any dependent trees. */
 static JS_REQUIRES_STACK void
-specializeTreesToMissingGlobals(JSContext* cx, JSObject* globalObj, TreeInfo* root)
+SpecializeTreesToMissingGlobals(JSContext* cx, JSObject* globalObj, TreeInfo* root)
 {
     TreeInfo* ti = root;
 
     ti->typeMap.captureMissingGlobalTypes(cx, globalObj, *ti->globalSlots, ti->nStackTypes);
     JS_ASSERT(ti->globalSlots->length() == ti->typeMap.length() - ti->nStackTypes);
 
     for (unsigned i = 0; i < root->dependentTrees.length(); i++) {
         ti = (TreeInfo*)root->dependentTrees[i]->vmprivate;
+
         /* ti can be NULL if we hit the recording tree in emitTreeCall; this is harmless. */
         if (ti && ti->nGlobalTypes() < ti->globalSlots->length())
-            specializeTreesToMissingGlobals(cx, globalObj, ti);
+            SpecializeTreesToMissingGlobals(cx, globalObj, ti);
     }
     for (unsigned i = 0; i < root->linkedTrees.length(); i++) {
         ti = (TreeInfo*)root->linkedTrees[i]->vmprivate;
         if (ti && ti->nGlobalTypes() < ti->globalSlots->length())
-            specializeTreesToMissingGlobals(cx, globalObj, ti);
-    }
+            SpecializeTreesToMissingGlobals(cx, globalObj, ti);
+    }
+}
+
+static inline JSTraceType*
+GetStackTypeMap(nanojit::SideExit* exit)
+{
+    return (JSTraceType*)(((VMSideExit*)exit) + 1);
+}
+
+static inline JSTraceType*
+GetGlobalTypeMap(nanojit::SideExit* exit)
+{
+    return GetStackTypeMap(exit) + ((VMSideExit*)exit)->numStackSlots;
+}
+
+static inline JSTraceType*
+GetFullTypeMap(nanojit::SideExit* exit)
+{
+    return GetStackTypeMap(exit);
 }
 
 static void
-js_TrashTree(JSContext* cx, Fragment* f);
+TrashTree(JSContext* cx, Fragment* f);
 
 JS_REQUIRES_STACK
 TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* _anchor, Fragment* _fragment,
         TreeInfo* ti, unsigned stackSlots, unsigned ngslots, JSTraceType* typeMap,
         VMSideExit* innermostNestedGuard, jsbytecode* outer, uint32 outerArgc)
 {
     JS_ASSERT(!_fragment->vmprivate && ti && cx->fp->regs->pc == (jsbytecode*)_fragment->ip);
 
@@ -1631,32 +1680,34 @@ TraceRecorder::TraceRecorder(JSContext* 
     lirbuf->sp = addName(lir->insLoad(LIR_ldp, lirbuf->state, (int)offsetof(InterpState, sp)), "sp");
     lirbuf->rp = addName(lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, rp)), "rp");
     cx_ins = addName(lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, cx)), "cx");
     eos_ins = addName(lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, eos)), "eos");
     eor_ins = addName(lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, eor)), "eor");
 
     /* If we came from exit, we might not have enough global types. */
     if (ti->globalSlots->length() > ti->nGlobalTypes())
-        specializeTreesToMissingGlobals(cx, globalObj, ti);
+        SpecializeTreesToMissingGlobals(cx, globalObj, ti);
 
     /* read into registers all values on the stack and all globals we know so far */
     import(treeInfo, lirbuf->sp, stackSlots, ngslots, callDepth, typeMap);
 
     if (fragment == fragment->root) {
         /*
          * We poll the operation callback request flag. It is updated asynchronously whenever
          * the callback is to be invoked.
          */
         LIns* x = lir->insLoad(LIR_ld, cx_ins, offsetof(JSContext, operationCallbackFlag));
         guard(true, lir->ins_eq0(x), snapshot(TIMEOUT_EXIT));
     }
 
-    /* If we are attached to a tree call guard, make sure the guard the inner tree exited from
-       is what we expect it to be. */
+    /*
+     * If we are attached to a tree call guard, make sure the guard the inner
+     * tree exited from is what we expect it to be.
+     */
     if (_anchor && _anchor->exitType == NESTED_EXIT) {
         LIns* nested_ins = addName(lir->insLoad(LIR_ldp, lirbuf->state,
                                                 offsetof(InterpState, lastTreeExitGuard)),
                                                 "lastTreeExitGuard");
         guard(true, lir->ins2(LIR_eq, nested_ins, INS_CONSTPTR(innermostNestedGuard)), NESTED_EXIT);
     }
 }
 
@@ -1685,173 +1736,186 @@ TraceRecorder::~TraceRecorder()
 #endif
     if (fragment) {
         if (wasRootFragment && !fragment->root->code()) {
             JS_ASSERT(!fragment->root->vmprivate);
             delete treeInfo;
         }
 
         if (trashSelf)
-            js_TrashTree(cx, fragment->root);
+            TrashTree(cx, fragment->root);
 
         for (unsigned int i = 0; i < whichTreesToTrash.length(); i++)
-            js_TrashTree(cx, whichTreesToTrash[i]);
+            TrashTree(cx, whichTreesToTrash[i]);
     } else if (wasRootFragment) {
         delete treeInfo;
     }
 #ifdef DEBUG
     debug_only_stmt( delete verbose_filter; )
 #endif
     delete cse_filter;
     delete expr_filter;
     delete func_filter;
     delete float_filter;
     delete lir_buf_writer;
     delete generatedTraceableNative;
 }
 
-void TraceRecorder::removeFragmentoReferences()
+void
+TraceRecorder::removeFragmentoReferences()
 {
     fragment = NULL;
 }
 
-void TraceRecorder::deepAbort()
+void
+TraceRecorder::deepAbort()
 {
     debug_only_print0(LC_TMTracer|LC_TMAbort, "deep abort");
     deepAborted = true;
 }
 
 /* Add debug information to a LIR instruction as we emit it. */
 inline LIns*
 TraceRecorder::addName(LIns* ins, const char* name)
 {
 #ifdef JS_JIT_SPEW
-    /* We'll only ask for verbose Nanojit when .lcbits > 0, so
-       there's no point in adding names otherwise. */
+    /*
+     * We'll only ask for verbose Nanojit when .lcbits > 0, so there's no point
+     * in adding names otherwise.
+     */
     if (js_LogController.lcbits > 0)
         lirbuf->names->addName(ins, name);
 #endif
     return ins;
 }
 
 /* Determine the current call depth (starting with the entry frame.) */
 unsigned
 TraceRecorder::getCallDepth() const
 {
     return callDepth;
 }
 
-/* Determine the offset in the native global frame for a jsval we track */
+/* Determine the offset in the native global frame for a jsval we track. */
 ptrdiff_t
 TraceRecorder::nativeGlobalOffset(jsval* p) const
 {
     JS_ASSERT(isGlobal(p));
     if (size_t(p - globalObj->fslots) < JS_INITIAL_NSLOTS)
         return sizeof(InterpState) + size_t(p - globalObj->fslots) * sizeof(double);
     return sizeof(InterpState) + ((p - globalObj->dslots) + JS_INITIAL_NSLOTS) * sizeof(double);
 }
 
-/* Determine whether a value is a global stack slot */
+/* Determine whether a value is a global stack slot. */
 bool
 TraceRecorder::isGlobal(jsval* p) const
 {
     return ((size_t(p - globalObj->fslots) < JS_INITIAL_NSLOTS) ||
             (size_t(p - globalObj->dslots) < (STOBJ_NSLOTS(globalObj) - JS_INITIAL_NSLOTS)));
 }
 
-/* 
+/*
  * Return the offset in the native stack for the given jsval. More formally,
  * |p| must be the address of a jsval that is represented in the native stack
  * area. The return value is the offset, from InterpState::stackBase, in bytes,
- * where the native representation of |*p| is stored. To get the offset relative
- * to InterpState::sp, subtract TreeInfo::nativeStackBase.
+ * where the native representation of |*p| is stored. To get the offset
+ * relative to InterpState::sp, subtract TreeInfo::nativeStackBase.
  */
 JS_REQUIRES_STACK ptrdiff_t
 TraceRecorder::nativeStackOffset(jsval* p) const
 {
     CountSlotsVisitor visitor(p);
     VisitStackSlots(visitor, cx, callDepth);
     size_t offset = visitor.count() * sizeof(double);
-    /*
-     * If it's not in a pending frame, it must be on the stack of the current frame above
-     * sp but below fp->slots + script->nslots.
+
+    /*
+     * If it's not in a pending frame, it must be on the stack of the current
+     * frame above sp but below fp->slots + script->nslots.
      */
     if (!visitor.stopped()) {
         JS_ASSERT(size_t(p - cx->fp->slots) < cx->fp->script->nslots);
         offset += size_t(p - cx->fp->regs->sp) * sizeof(double);
     }
     return offset;
 }
 
-/* Track the maximum number of native frame slots we need during
-   execution. */
+/* Track the maximum number of native frame slots we need during execution. */
 void
 TraceRecorder::trackNativeStackUse(unsigned slots)
 {
     if (slots > treeInfo->maxNativeStackSlots)
         treeInfo->maxNativeStackSlots = slots;
 }
 
-/* Unbox a jsval into a slot. Slots are wide enough to hold double values directly (instead of
-   storing a pointer to them). We now assert instead of type checking, the caller must ensure the
-   types are compatible. */
+/*
+ * Unbox a jsval into a slot. Slots are wide enough to hold double values
+ * directly (instead of storing a pointer to them). We assert instead of
+ * type checking. The caller must ensure the types are compatible.
+ */
 static void
 ValueToNative(JSContext* cx, jsval v, JSTraceType type, double* slot)
 {
     uint8_t tag = JSVAL_TAG(v);
     switch (type) {
       case TT_OBJECT:
         JS_ASSERT(tag == JSVAL_OBJECT);
         JS_ASSERT(!JSVAL_IS_NULL(v) && !HAS_FUNCTION_CLASS(JSVAL_TO_OBJECT(v)));
         *(JSObject**)slot = JSVAL_TO_OBJECT(v);
         debug_only_printf(LC_TMTracer,
                           "object<%p:%s> ", (void*)JSVAL_TO_OBJECT(v),
                           JSVAL_IS_NULL(v)
                           ? "null"
                           : STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v))->name);
         return;
+
       case TT_INT32:
         jsint i;
         if (JSVAL_IS_INT(v))
             *(jsint*)slot = JSVAL_TO_INT(v);
         else if (tag == JSVAL_DOUBLE && JSDOUBLE_IS_INT(*JSVAL_TO_DOUBLE(v), i))
             *(jsint*)slot = i;
         else
             JS_ASSERT(JSVAL_IS_INT(v));
         debug_only_printf(LC_TMTracer, "int<%d> ", *(jsint*)slot);
         return;
+
       case TT_DOUBLE:
         jsdouble d;
         if (JSVAL_IS_INT(v))
             d = JSVAL_TO_INT(v);
         else
             d = *JSVAL_TO_DOUBLE(v);
         JS_ASSERT(JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v));
         *(jsdouble*)slot = d;
         debug_only_printf(LC_TMTracer, "double<%g> ", d);
         return;
+
       case TT_JSVAL:
         JS_NOT_REACHED("found jsval type in an entry type map");
         return;
+
       case TT_STRING:
         JS_ASSERT(tag == JSVAL_STRING);
         *(JSString**)slot = JSVAL_TO_STRING(v);
         debug_only_printf(LC_TMTracer, "string<%p> ", (void*)(*(JSString**)slot));
         return;
+
       case TT_NULL:
         JS_ASSERT(tag == JSVAL_OBJECT);
         *(JSObject**)slot = NULL;
         debug_only_print0(LC_TMTracer, "null ");
         return;
+
       case TT_PSEUDOBOOLEAN:
         /* Watch out for pseudo-booleans. */
         JS_ASSERT(tag == JSVAL_BOOLEAN);
         *(JSBool*)slot = JSVAL_TO_PSEUDO_BOOLEAN(v);
         debug_only_printf(LC_TMTracer, "pseudoboolean<%d> ", *(JSBool*)slot);
         return;
+
       case TT_FUNCTION: {
         JS_ASSERT(tag == JSVAL_OBJECT);
         JSObject* obj = JSVAL_TO_OBJECT(v);
         *(JSObject**)slot = obj;
 #ifdef DEBUG
         JSFunction* fun = GET_FUNCTION_PRIVATE(cx, obj);
         debug_only_printf(LC_TMTracer,
                           "function<%p:%s> ", (void*) obj,
@@ -1861,28 +1925,30 @@ ValueToNative(JSContext* cx, jsval v, JS
 #endif
         return;
       }
     }
 
     JS_NOT_REACHED("unexpected type");
 }
 
-/* We maintain an emergency pool of doubles so we can recover safely if a trace runs
-   out of memory (doubles or objects). */
+/*
+ * We maintain an emergency pool of doubles so we can recover safely if a trace
+ * runs out of memory (doubles or objects).
+ */
 static jsval
 AllocateDoubleFromReservedPool(JSContext* cx)
 {
     JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
     JS_ASSERT(tm->reservedDoublePoolPtr > tm->reservedDoublePool);
     return *--tm->reservedDoublePoolPtr;
 }
 
 static bool
-js_ReplenishReservedPool(JSContext* cx, JSTraceMonitor* tm)
+ReplenishReservedPool(JSContext* cx, JSTraceMonitor* tm)
 {
     /* We should not be called with a full pool. */
     JS_ASSERT((size_t) (tm->reservedDoublePoolPtr - tm->reservedDoublePool) <
               MAX_NATIVE_STACK_SLOTS);
 
     /*
      * When the GC runs in js_NewDoubleInRootedValue, it resets
      * tm->reservedDoublePoolPtr back to tm->reservedDoublePool.
@@ -1918,84 +1984,94 @@ oom:
     /*
      * Already massive GC pressure, no need to hold doubles back.
      * We won't run any native code anyway.
      */
     tm->reservedDoublePoolPtr = tm->reservedDoublePool;
     return false;
 }
 
-/* Box a value from the native stack back into the jsval format. Integers
-   that are too large to fit into a jsval are automatically boxed into
-   heap-allocated doubles. */
+/*
+ * Box a value from the native stack back into the jsval format. Integers that
+ * are too large to fit into a jsval are automatically boxed into
+ * heap-allocated doubles.
+ */
 static void
 NativeToValue(JSContext* cx, jsval& v, JSTraceType type, double* slot)
 {
     jsint i;
     jsdouble d;
     switch (type) {
       case TT_OBJECT:
         v = OBJECT_TO_JSVAL(*(JSObject**)slot);
         JS_ASSERT(v != JSVAL_ERROR_COOKIE); /* don't leak JSVAL_ERROR_COOKIE */
         debug_only_printf(LC_TMTracer,
                           "object<%p:%s> ", (void*)JSVAL_TO_OBJECT(v),
                           JSVAL_IS_NULL(v)
                           ? "null"
                           : STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v))->name);
         break;
+
       case TT_INT32:
         i = *(jsint*)slot;
         debug_only_printf(LC_TMTracer, "int<%d> ", i);
       store_int:
         if (INT_FITS_IN_JSVAL(i)) {
             v = INT_TO_JSVAL(i);
             break;
         }
         d = (jsdouble)i;
         goto store_double;
       case TT_DOUBLE:
         d = *slot;
         debug_only_printf(LC_TMTracer, "double<%g> ", d);
         if (JSDOUBLE_IS_INT(d, i))
             goto store_int;
       store_double: {
-        /* Its not safe to trigger the GC here, so use an emergency heap if we are out of
-           double boxes. */
+        /*
+         * It's not safe to trigger the GC here, so use an emergency heap if we
+         * are out of double boxes.
+         */
         if (cx->doubleFreeList) {
 #ifdef DEBUG
             JSBool ok =
 #endif
                 js_NewDoubleInRootedValue(cx, d, &v);
             JS_ASSERT(ok);
             return;
         }
         v = AllocateDoubleFromReservedPool(cx);
         JS_ASSERT(JSVAL_IS_DOUBLE(v) && *JSVAL_TO_DOUBLE(v) == 0.0);
         *JSVAL_TO_DOUBLE(v) = d;
         return;
       }
+
       case TT_JSVAL:
         v = *(jsval*)slot;
         JS_ASSERT(v != JSVAL_ERROR_COOKIE); /* don't leak JSVAL_ERROR_COOKIE */
         debug_only_printf(LC_TMTracer, "box<%p> ", (void*)v);
         break;
+
       case TT_STRING:
         v = STRING_TO_JSVAL(*(JSString**)slot);
         debug_only_printf(LC_TMTracer, "string<%p> ", (void*)(*(JSString**)slot));
         break;
+
       case TT_NULL:
         JS_ASSERT(*(JSObject**)slot == NULL);
         v = JSVAL_NULL;
         debug_only_printf(LC_TMTracer, "null<%p> ", (void*)(*(JSObject**)slot));
         break;
+
       case TT_PSEUDOBOOLEAN:
         /* Watch out for pseudo-booleans. */
         v = PSEUDO_BOOLEAN_TO_JSVAL(*(JSBool*)slot);
         debug_only_printf(LC_TMTracer, "boolean<%d> ", *(JSBool*)slot);
         break;
+
       case TT_FUNCTION: {
         JS_ASSERT(HAS_FUNCTION_CLASS(*(JSObject**)slot));
         v = OBJECT_TO_JSVAL(*(JSObject**)slot);
 #ifdef DEBUG
         JSFunction* fun = GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(v));
         debug_only_printf(LC_TMTracer,
                           "function<%p:%s> ", (void*)JSVAL_TO_OBJECT(v),
                           fun->atom
@@ -2123,18 +2199,18 @@ FlushNativeGlobalFrame(JSContext *cx, do
  *             native_slot(argc, slot)  Return the position of the desired value in the on-trace
  *                                      stack frame (with position 0 being callee).
  *
  *     upvarLevel  Static level of the function containing the upvar definition
  *     slot        Identifies the value to get. The meaning is defined by the traits type.
  *     callDepth   Call depth of current point relative to trace entry
  */
 template<typename T>
-JSTraceType JS_INLINE
-js_GetUpvarOnTrace(JSContext* cx, uint32 upvarLevel, int32 slot, uint32 callDepth, double* result)
+inline JSTraceType
+GetUpvarOnTrace(JSContext* cx, uint32 upvarLevel, int32 slot, uint32 callDepth, double* result)
 {
     InterpState* state = cx->interpState;
     FrameInfo** fip = state->rp + callDepth;
 
     /*
      * First search the FrameInfo call stack for an entry containing
      * our upvar, namely one with level == upvarLevel.
      */
@@ -2186,76 +2262,76 @@ struct UpvarArgTraits {
     }
 
     static uint32 native_slot(uint32 argc, int32 slot) {
         return 2 /*callee,this*/ + slot;
     }
 };
 
 uint32 JS_FASTCALL
-js_GetUpvarArgOnTrace(JSContext* cx, uint32 upvarLevel, int32 slot, uint32 callDepth, double* result)
-{
-    return js_GetUpvarOnTrace<UpvarArgTraits>(cx, upvarLevel, slot, callDepth, result);
+GetUpvarArgOnTrace(JSContext* cx, uint32 upvarLevel, int32 slot, uint32 callDepth, double* result)
+{
+    return GetUpvarOnTrace<UpvarArgTraits>(cx, upvarLevel, slot, callDepth, result);
 }
 
 // For this traits type, 'slot' is an index into the local slots array.
 struct UpvarVarTraits {
     static jsval interp_get(JSStackFrame* fp, int32 slot) {
         return fp->slots[slot];
     }
 
     static uint32 native_slot(uint32 argc, int32 slot) {
         return 3 /*callee,this,arguments*/ + argc + slot;
     }
 };
 
 uint32 JS_FASTCALL
-js_GetUpvarVarOnTrace(JSContext* cx, uint32 upvarLevel, int32 slot, uint32 callDepth, double* result)
-{
-    return js_GetUpvarOnTrace<UpvarVarTraits>(cx, upvarLevel, slot, callDepth, result);
+GetUpvarVarOnTrace(JSContext* cx, uint32 upvarLevel, int32 slot, uint32 callDepth, double* result)
+{
+    return GetUpvarOnTrace<UpvarVarTraits>(cx, upvarLevel, slot, callDepth, result);
 }
 
 /*
- * For this traits type, 'slot' is an index into the stack area (within slots, after nfixed)
- * of a frame with no function. (On trace, the top-level frame is the only one that can have
- * no function.)
+ * For this traits type, 'slot' is an index into the stack area (within slots,
+ * after nfixed) of a frame with no function. (On trace, the top-level frame is
+ * the only one that can have no function.)
  */
 struct UpvarStackTraits {
     static jsval interp_get(JSStackFrame* fp, int32 slot) {
         return fp->slots[slot + fp->script->nfixed];
     }
 
     static uint32 native_slot(uint32 argc, int32 slot) {
         /*
-         * Locals are not imported by the tracer when the frame has no function, so
-         * we do not add fp->script->nfixed.
+         * Locals are not imported by the tracer when the frame has no
+         * function, so we do not add fp->script->nfixed.
          */
         JS_ASSERT(argc == 0);
         return slot;
     }
 };
 
 uint32 JS_FASTCALL
-js_GetUpvarStackOnTrace(JSContext* cx, uint32 upvarLevel, int32 slot, uint32 callDepth, double* result)
-{
-    return js_GetUpvarOnTrace<UpvarStackTraits>(cx, upvarLevel, slot, callDepth, result);
+GetUpvarStackOnTrace(JSContext* cx, uint32 upvarLevel, int32 slot, uint32 callDepth, double* result)
+{
+    return GetUpvarOnTrace<UpvarStackTraits>(cx, upvarLevel, slot, callDepth, result);
 }
 
 /*
- * Generic function to read upvars from Call objects of active heavyweight functions. 
+ * Generic function to read upvars from Call objects of active heavyweight functions.
  *     callee       Callee Function object in which the upvar is accessed.
  *     scopeIndex   Number of parent steps to make from |callee| to find upvar definition.
  *                  This must be at least 1 because |callee| is a Function and we must reach a Call.
  *     slot         Slot in Call object to read.
  *     callDepth    callDepth of current point relative to trace entry.
  */
 template<typename T>
-uint32 JS_INLINE
-js_GetFromClosure(JSContext* cx, JSObject* callee, uint32 scopeIndex, uint32 slot, uint32 callDepth, 
-                  double* result)
+inline uint32
+GetFromClosure(JSContext* cx, JSObject* callee, uint32 scopeIndex, uint32 slot, uint32 callDepth,
+               double* result)
 {
     JS_ASSERT(scopeIndex >= 1);
     JS_ASSERT(OBJ_GET_CLASS(cx, callee) == &js_FunctionClass);
     JSObject* call = callee;
 
     for (uint32 i = 0; i < scopeIndex; ++i)
         call = OBJ_GET_PARENT(cx, call);
 
@@ -2293,42 +2369,42 @@ js_GetFromClosure(JSContext* cx, JSObjec
     jsval v = T::slots(fp)[slot];
     JSTraceType type = getCoercedType(v);
     ValueToNative(cx, v, type, result);
     return type;
 }
 
 struct ArgClosureTraits
 {
-    static JS_INLINE uint32 adj_slot(JSStackFrame* fp, uint32 slot) { return fp->argc + slot; }
-    static JS_INLINE jsval* slots(JSStackFrame* fp) { return fp->argv; }
+    static inline uint32 adj_slot(JSStackFrame* fp, uint32 slot) { return fp->argc + slot; }
+    static inline jsval* slots(JSStackFrame* fp) { return fp->argv; }
 private:
     ArgClosureTraits();
 };
 
 uint32 JS_FASTCALL
-js_GetClosureArg(JSContext* cx, JSObject* callee, uint32 scopeIndex, uint32 slot, uint32 callDepth, 
-                 double* result)
-{
-    return js_GetFromClosure<ArgClosureTraits>(cx, callee, scopeIndex, slot, callDepth, result);
+GetClosureArg(JSContext* cx, JSObject* callee, uint32 scopeIndex, uint32 slot, uint32 callDepth,
+              double* result)
+{
+    return GetFromClosure<ArgClosureTraits>(cx, callee, scopeIndex, slot, callDepth, result);
 }
 
 struct VarClosureTraits
 {
-    static JS_INLINE uint32 adj_slot(JSStackFrame* fp, uint32 slot) { return slot; }
-    static JS_INLINE jsval* slots(JSStackFrame* fp) { return fp->slots; }
+    static inline uint32 adj_slot(JSStackFrame* fp, uint32 slot) { return slot; }
+    static inline jsval* slots(JSStackFrame* fp) { return fp->slots; }
 private:
     VarClosureTraits();
 };
 
 uint32 JS_FASTCALL
-js_GetClosureVar(JSContext* cx, JSObject* callee, uint32 scopeIndex, uint32 slot, uint32 callDepth, 
-                 double* result)
-{
-    return js_GetFromClosure<VarClosureTraits>(cx, callee, scopeIndex, slot, callDepth, result);
+GetClosureVar(JSContext* cx, JSObject* callee, uint32 scopeIndex, uint32 slot, uint32 callDepth,
+              double* result)
+{
+    return GetFromClosure<VarClosureTraits>(cx, callee, scopeIndex, slot, callDepth, result);
 }
 
 /**
  * Box the given native stack frame into the virtual machine stack. This
  * is infallible.
  *
  * @param callDepth the distance between the entry frame into our trace and
  *                  cx->fp when we make this call.  If this is not called as a
@@ -2357,16 +2433,17 @@ FlushNativeStackFrame(JSContext* cx, uns
     {
         unsigned n = callDepth+1; // +1 to make sure we restore the entry frame
         JSStackFrame* fp = cx->fp;
         if (stopFrame) {
             for (; fp != stopFrame; fp = fp->down) {
                 JS_ASSERT(n != 0);
                 --n;
             }
+
             // Skip over stopFrame itself.
             JS_ASSERT(n != 0);
             --n;
             fp = fp->down;
         }
         for (; n != 0; fp = fp->down) {
             --n;
             if (fp->callee) {
@@ -2392,17 +2469,17 @@ FlushNativeStackFrame(JSContext* cx, uns
                 if (!fp->scopeChain) {
                     fp->scopeChain = OBJ_GET_PARENT(cx, fp->callee);
                     if (fp->fun->flags & JSFUN_HEAVYWEIGHT) {
                         /*
                          * Set hookData to null because the failure case for js_GetCallObject
                          * involves it calling the debugger hook.
                          *
                          * Allocating the Call object must not fail, so use an object
-                         * previously reserved by js_ExecuteTree if needed.
+                         * previously reserved by ExecuteTree if needed.
                          */
                         void* hookData = ((JSInlineFrame*)fp)->hookData;
                         ((JSInlineFrame*)fp)->hookData = NULL;
                         JS_ASSERT(!JS_TRACE_MONITOR(cx).useReservedObjects);
                         JS_TRACE_MONITOR(cx).useReservedObjects = JS_TRUE;
 #ifdef DEBUG
                         JSObject *obj =
 #endif
@@ -2425,20 +2502,23 @@ FlushNativeStackFrame(JSContext* cx, uns
 /* Emit load instructions onto the trace that read the initial stack state. */
 JS_REQUIRES_STACK void
 TraceRecorder::import(LIns* base, ptrdiff_t offset, jsval* p, JSTraceType t,
                       const char *prefix, uintN index, JSStackFrame *fp)
 {
     LIns* ins;
     if (t == TT_INT32) { /* demoted */
         JS_ASSERT(isInt32(*p));
-        /* Ok, we have a valid demotion attempt pending, so insert an integer
-           read and promote it to double since all arithmetic operations expect
-           to see doubles on entry. The first op to use this slot will emit a
-           f2i cast which will cancel out the i2f we insert here. */
+
+        /*
+         * Ok, we have a valid demotion attempt pending, so insert an integer
+         * read and promote it to double since all arithmetic operations expect
+         * to see doubles on entry. The first op to use this slot will emit a
+         * f2i cast which will cancel out the i2f we insert here.
+         */
         ins = lir->insLoad(LIR_ld, base, offset);
         ins = lir->ins1(LIR_i2f, ins);
     } else {
         JS_ASSERT_IF(t != TT_JSVAL, isNumber(*p) == (t == TT_DOUBLE));
         if (t == TT_DOUBLE) {
             ins = lir->insLoad(LIR_ldq, base, offset);
         } else if (t == TT_PSEUDOBOOLEAN) {
             ins = lir->insLoad(LIR_ld, base, offset);
@@ -2577,46 +2657,49 @@ public:
         return true;
     }
 };
 
 JS_REQUIRES_STACK void
 TraceRecorder::import(TreeInfo* treeInfo, LIns* sp, unsigned stackSlots, unsigned ngslots,
                       unsigned callDepth, JSTraceType* typeMap)
 {
-    /* If we get a partial list that doesn't have all the types (i.e. recording from a side
-       exit that was recorded but we added more global slots later), merge the missing types
-       from the entry type map. This is safe because at the loop edge we verify that we
-       have compatible types for all globals (entry type and loop edge type match). While
-       a different trace of the tree might have had a guard with a different type map for
-       these slots we just filled in here (the guard we continue from didn't know about them),
-       since we didn't take that particular guard the only way we could have ended up here
-       is if that other trace had at its end a compatible type distribution with the entry
-       map. Since thats exactly what we used to fill in the types our current side exit
-       didn't provide, this is always safe to do. */
+    /*
+     * If we get a partial list that doesn't have all the types (i.e. recording
+     * from a side exit that was recorded but we added more global slots
+     * later), merge the missing types from the entry type map. This is safe
+     * because at the loop edge we verify that we have compatible types for all
+     * globals (entry type and loop edge type match). While a different trace
+     * of the tree might have had a guard with a different type map for these
+     * slots we just filled in here (the guard we continue from didn't know
+     * about them), since we didn't take that particular guard the only way we
+     * could have ended up here is if that other trace had at its end a
+     * compatible type distribution with the entry map. Since that's exactly
+     * what we used to fill in the types our current side exit didn't provide,
+     * this is always safe to do.
+     */
 
     JSTraceType* globalTypeMap = typeMap + stackSlots;
     unsigned length = treeInfo->nGlobalTypes();
 
     /*
-     * This is potentially the typemap of the side exit and thus shorter than the tree's
-     * global type map.
+     * This is potentially the typemap of the side exit and thus shorter than
+     * the tree's global type map.
      */
     if (ngslots < length) {
-        mergeTypeMaps(&globalTypeMap/*out param*/, &ngslots/*out param*/,
+        MergeTypeMaps(&globalTypeMap /* out param */, &ngslots /* out param */,
                       treeInfo->globalTypeMap(), length,
                       (JSTraceType*)alloca(sizeof(JSTraceType) * length));
     }
     JS_ASSERT(ngslots == treeInfo->nGlobalTypes());
     ptrdiff_t offset = -treeInfo->nativeStackBase;
 
     /*
-     * Check whether there are any values on the stack we have to unbox and
-     * do that first before we waste any time fetching the state from the
-     * stack.
+     * Check whether there are any values on the stack we have to unbox and do
+     * that first before we waste any time fetching the state from the stack.
      */
     ImportBoxedStackSlotVisitor boxedStackVisitor(*this, sp, offset, typeMap);
     VisitStackSlots(boxedStackVisitor, cx, callDepth);
 
     ImportGlobalSlotVisitor globalVisitor(*this, lirbuf->state, globalTypeMap);
     VisitGlobalSlots(globalVisitor, cx, globalObj, ngslots,
                      treeInfo->globalSlots->data());
 
@@ -2631,78 +2714,87 @@ TraceRecorder::isValidSlot(JSScope* scop
     uint32 setflags = (js_CodeSpec[*cx->fp->regs->pc].format & (JOF_SET | JOF_INCDEC | JOF_FOR));
 
     if (setflags) {
         if (!SPROP_HAS_STUB_SETTER(sprop))
             ABORT_TRACE_RV("non-stub setter", false);
         if (sprop->attrs & JSPROP_READONLY)
             ABORT_TRACE_RV("writing to a read-only property", false);
     }
+
     /* This check applies even when setflags == 0. */
     if (setflags != JOF_SET && !SPROP_HAS_STUB_GETTER(sprop))
         ABORT_TRACE_RV("non-stub getter", false);
 
     if (!SPROP_HAS_VALID_SLOT(sprop, scope))
         ABORT_TRACE_RV("slotless obj property", false);
 
     return true;
 }
 
 /* Lazily import a global slot if we don't already have it in the tracker. */
 JS_REQUIRES_STACK bool
 TraceRecorder::lazilyImportGlobalSlot(unsigned slot)
 {
     if (slot != uint16(slot)) /* we use a table of 16-bit ints, bail out if that's not enough */
         return false;
-    /*
-     * If the global object grows too large, alloca in js_ExecuteTree might fail, so
-     * abort tracing on global objects with unreasonably many slots.
+
+    /*
+     * If the global object grows too large, alloca in ExecuteTree might fail,
+     * so abort tracing on global objects with unreasonably many slots.
      */
     if (STOBJ_NSLOTS(globalObj) > MAX_GLOBAL_SLOTS)
         return false;
     jsval* vp = &STOBJ_GET_SLOT(globalObj, slot);
     if (known(vp))
         return true; /* we already have it */
     unsigned index = treeInfo->globalSlots->length();
+
     /* Add the slot to the list of interned global slots. */
     JS_ASSERT(treeInfo->nGlobalTypes() == treeInfo->globalSlots->length());
     treeInfo->globalSlots->add(slot);
     JSTraceType type = getCoercedType(*vp);
     if (type == TT_INT32 && oracle.isGlobalSlotUndemotable(cx, slot))
         type = TT_DOUBLE;
     treeInfo->typeMap.add(type);
     import(lirbuf->state, sizeof(struct InterpState) + slot*sizeof(double),
            vp, type, "global", index, NULL);
-    specializeTreesToMissingGlobals(cx, globalObj, treeInfo);
+    SpecializeTreesToMissingGlobals(cx, globalObj, treeInfo);
     return true;
 }
 
 /* Write back a value onto the stack or global frames. */
 LIns*
 TraceRecorder::writeBack(LIns* i, LIns* base, ptrdiff_t offset)
 {
-    /* Sink all type casts targeting the stack into the side exit by simply storing the original
-       (uncasted) value. Each guard generates the side exit map based on the types of the
-       last stores to every stack location, so its safe to not perform them on-trace. */
+    /*
+     * Sink all type casts targeting the stack into the side exit by simply storing the original
+     * (uncasted) value. Each guard generates the side exit map based on the types of the
+     * last stores to every stack location, so it's safe to not perform them on-trace.
+     */
     if (isPromoteInt(i))
         i = ::demote(lir, i);
     return lir->insStorei(i, base, offset);
 }
 
 /* Update the tracker, then issue a write back store. */
 JS_REQUIRES_STACK void
 TraceRecorder::set(jsval* p, LIns* i, bool initializing)
 {
     JS_ASSERT(i != NULL);
     JS_ASSERT(initializing || known(p));
     checkForGlobalObjectReallocation();
     tracker.set(p, i);
-    /* If we are writing to this location for the first time, calculate the offset into the
-       native frame manually, otherwise just look up the last load or store associated with
-       the same source address (p) and use the same offset/base. */
+
+    /*
+     * If we are writing to this location for the first time, calculate the
+     * offset into the native frame manually. Otherwise just look up the last
+     * load or store associated with the same source address (p) and use the
+     * same offset/base.
+     */
     LIns* x = nativeFrameTracker.get(p);
     if (!x) {
         if (isGlobal(p))
             x = writeBack(i, lirbuf->state, nativeGlobalOffset(p));
         else
             x = writeBack(i, lirbuf->sp, -treeInfo->nativeStackBase + nativeStackOffset(p));
         nativeFrameTracker.set(p, x);
     } else {
@@ -2755,17 +2847,17 @@ TraceRecorder::checkForGlobalObjectReall
         for (jsuint n = 0; n < length; ++n)
             tracker.set(dst++, map[n]);
         global_dslots = globalObj->dslots;
     }
 }
 
 /* Determine whether the current branch is a loop edge (taken or not taken). */
 static JS_REQUIRES_STACK bool
-js_IsLoopEdge(jsbytecode* pc, jsbytecode* header)
+IsLoopEdge(jsbytecode* pc, jsbytecode* header)
 {
     switch (*pc) {
       case JSOP_IFEQ:
       case JSOP_IFNE:
         return ((pc + GET_JUMP_OFFSET(pc)) == header);
       case JSOP_IFEQX:
       case JSOP_IFNEX:
         return ((pc + GET_JUMPX_OFFSET(pc)) == header);
@@ -2800,18 +2892,21 @@ public:
 
     JS_REQUIRES_STACK JS_ALWAYS_INLINE void
     visitGlobalSlot(jsval *vp, unsigned n, unsigned slot) {
         LIns *ins = mRecorder.get(vp);
         bool isPromote = isPromoteInt(ins);
         if (isPromote && *mTypeMap == TT_DOUBLE) {
             mLir->insStorei(mRecorder.get(vp), mLirbuf->state,
                             mRecorder.nativeGlobalOffset(vp));
-            /* Aggressively undo speculation so the inner tree will compile
-               if this fails. */
+
+            /*
+             * Aggressively undo speculation so the inner tree will compile
+             * if this fails.
+             */
             oracle.markGlobalSlotUndemotable(mCx, slot);
         }
         JS_ASSERT(!(!isPromote && *mTypeMap == TT_INT32));
         ++mTypeMap;
     }
 };
 
 class AdjustCallerStackTypesVisitor : public SlotVisitorBase
@@ -2842,33 +2937,36 @@ public:
     visitStackSlots(jsval *vp, size_t count, JSStackFrame* fp) {
         for (size_t i = 0; i < count; ++i) {
             LIns *ins = mRecorder.get(vp);
             bool isPromote = isPromoteInt(ins);
             if (isPromote && *mTypeMap == TT_DOUBLE) {
                 mLir->insStorei(mRecorder.get(vp), mLirbuf->sp,
                                 -mRecorder.treeInfo->nativeStackBase +
                                 mRecorder.nativeStackOffset(vp));
-                /* Aggressively undo speculation so the inner tree will
-                   compile if this fails. */
+
+                /*
+                 * Aggressively undo speculation so the inner tree will compile
+                 * if this fails.
+                 */
                 oracle.markStackSlotUndemotable(mCx, mSlotnum);
             }
             JS_ASSERT(!(!isPromote && *mTypeMap == TT_INT32));
             ++vp;
             ++mTypeMap;
             ++mSlotnum;
         }
         return true;
     }
 };
 
 /*
- * Promote slots if necessary to match the called tree's type map. This function is
- * infallible and must only be called if we are certain that it is possible to
- * reconcile the types for each slot in the inner and outer trees.
+ * Promote slots if necessary to match the called tree's type map. This
+ * function is infallible and must only be called if we are certain that it is
+ * possible to reconcile the types for each slot in the inner and outer trees.
  */
 JS_REQUIRES_STACK void
 TraceRecorder::adjustCallerTypes(Fragment* f)
 {
     TreeInfo* ti = (TreeInfo*)f->vmprivate;
 
     AdjustCallerGlobalTypesVisitor globalVisitor(*this, ti->globalTypeMap());
     VisitGlobalSlots(globalVisitor, cx, *treeInfo->globalSlots);
@@ -2890,18 +2988,18 @@ TraceRecorder::determineSlotType(jsval* 
         if (JSVAL_IS_NULL(*vp))
             m = TT_NULL;
         else if (HAS_FUNCTION_CLASS(JSVAL_TO_OBJECT(*vp)))
             m = TT_FUNCTION;
         else
             m = TT_OBJECT;
     } else {
         JS_ASSERT(JSVAL_TAG(*vp) == JSVAL_STRING || JSVAL_TAG(*vp) == JSVAL_BOOLEAN);
-        JS_STATIC_ASSERT(TT_STRING == JSVAL_STRING);
-        JS_STATIC_ASSERT(TT_PSEUDOBOOLEAN == JSVAL_BOOLEAN);
+        JS_STATIC_ASSERT(static_cast<jsvaltag>(TT_STRING) == JSVAL_STRING);
+        JS_STATIC_ASSERT(static_cast<jsvaltag>(TT_PSEUDOBOOLEAN) == JSVAL_BOOLEAN);
         m = JSTraceType(JSVAL_TAG(*vp));
     }
     JS_ASSERT(m != TT_INT32 || isInt32(*vp));
     return m;
 }
 
 class DetermineTypesVisitor : public SlotVisitorBase
 {
@@ -2934,74 +3032,86 @@ public:
 
 JS_REQUIRES_STACK VMSideExit*
 TraceRecorder::snapshot(ExitType exitType)
 {
     JSStackFrame* fp = cx->fp;
     JSFrameRegs* regs = fp->regs;
     jsbytecode* pc = regs->pc;
 
-    /* Check for a return-value opcode that needs to restart at the next instruction. */
+    /*
+     * Check for a return-value opcode that needs to restart at the next
+     * instruction.
+     */
     const JSCodeSpec& cs = js_CodeSpec[*pc];
 
     /*
      * When calling a _FAIL native, make the snapshot's pc point to the next
-     * instruction after the CALL or APPLY. Even on failure, a _FAIL native must not
-     * be called again from the interpreter.
+     * instruction after the CALL or APPLY. Even on failure, a _FAIL native
+     * must not be called again from the interpreter.
      */
     bool resumeAfter = (pendingTraceableNative &&
                         JSTN_ERRTYPE(pendingTraceableNative) == FAIL_STATUS);
     if (resumeAfter) {
-        JS_ASSERT(*pc == JSOP_CALL || *pc == JSOP_APPLY || *pc == JSOP_NEW);
+        JS_ASSERT(*pc == JSOP_CALL || *pc == JSOP_APPLY || *pc == JSOP_NEW ||
+                  *pc == JSOP_SETPROP || *pc == JSOP_SETNAME);
         pc += cs.length;
         regs->pc = pc;
         MUST_FLOW_THROUGH("restore_pc");
     }
 
-    /* Generate the entry map for the (possibly advanced) pc and stash it in the trace. */
-    unsigned stackSlots = js_NativeStackSlots(cx, callDepth);
-
-    /* It's sufficient to track the native stack use here since all stores above the
-       stack watermark defined by guards are killed. */
+    /*
+     * Generate the entry map for the (possibly advanced) pc and stash it in
+     * the trace.
+     */
+    unsigned stackSlots = NativeStackSlots(cx, callDepth);
+
+    /*
+     * It's sufficient to track the native stack use here since all stores
+     * above the stack watermark defined by guards are killed.
+     */
     trackNativeStackUse(stackSlots + 1);
 
     /* Capture the type map into a temporary location. */
     unsigned ngslots = treeInfo->globalSlots->length();
     unsigned typemap_size = (stackSlots + ngslots) * sizeof(JSTraceType);
     void *mark = JS_ARENA_MARK(&cx->tempPool);
     JSTraceType* typemap;
     JS_ARENA_ALLOCATE_CAST(typemap, JSTraceType*, &cx->tempPool, typemap_size);
 
     /*
      * Determine the type of a store by looking at the current type of the
-     * actual value the interpreter is using. For numbers we have to check
-     * what kind of store we used last (integer or double) to figure out
-     * what the side exit show reflect in its typemap.
+     * actual value the interpreter is using. For numbers we have to check what
+     * kind of store we used last (integer or double) to figure out what the
+     * side exit show reflect in its typemap.
      */
     DetermineTypesVisitor detVisitor(*this, typemap);
     VisitSlots(detVisitor, cx, callDepth, ngslots,
                treeInfo->globalSlots->data());
     JS_ASSERT(unsigned(detVisitor.getTypeMap() - typemap) ==
               ngslots + stackSlots);
 
     /*
-     * If we are currently executing a traceable native or we are attaching a second trace
-     * to it, the value on top of the stack is a jsval. Make a note of this in the typemap.
+     * If we are currently executing a traceable native or we are attaching a
+     * second trace to it, the value on top of the stack is a jsval. Make a
+     * note of this in the typemap.
      */
     if (pendingTraceableNative && (pendingTraceableNative->flags & JSTN_UNBOX_AFTER))
         typemap[stackSlots - 1] = TT_JSVAL;
 
     /* Now restore the the original pc (after which early returns are ok). */
     if (resumeAfter) {
         MUST_FLOW_LABEL(restore_pc);
         regs->pc = pc - cs.length;
     } else {
-        /* If we take a snapshot on a goto, advance to the target address. This avoids inner
-           trees returning on a break goto, which the outer recorder then would confuse with
-           a break in the outer tree. */
+        /*
+         * If we take a snapshot on a goto, advance to the target address. This
+         * avoids inner trees returning on a break goto, which the outer
+         * recorder then would confuse with a break in the outer tree.
+         */
         if (*pc == JSOP_GOTO)
             pc += GET_JUMP_OFFSET(pc);
         else if (*pc == JSOP_GOTOX)
             pc += GET_JUMPX_OFFSET(pc);
     }
 
     /*
      * Check if we already have a matching side exit; if so we can return that
@@ -3009,17 +3119,17 @@ TraceRecorder::snapshot(ExitType exitTyp
      */
     VMSideExit** exits = treeInfo->sideExits.data();
     unsigned nexits = treeInfo->sideExits.length();
     if (exitType == LOOP_EXIT) {
         for (unsigned n = 0; n < nexits; ++n) {
             VMSideExit* e = exits[n];
             if (e->pc == pc && e->imacpc == fp->imacpc &&
                 ngslots == e->numGlobalSlots &&
-                !memcmp(getFullTypeMap(exits[n]), typemap, typemap_size)) {
+                !memcmp(GetFullTypeMap(exits[n]), typemap, typemap_size)) {
                 AUDIT(mergedLoopExits);
                 JS_ARENA_RELEASE(&cx->tempPool, mark);
                 return e;
             }
         }
     }
 
     if (sizeof(VMSideExit) + (stackSlots + ngslots) * sizeof(JSTraceType) >= NJ_MAX_SKIP_PAYLOAD_SZB) {
@@ -3053,17 +3163,17 @@ TraceRecorder::snapshot(ExitType exitTyp
     exit->exitType = exitType;
     exit->block = fp->blockChain;
     exit->pc = pc;
     exit->imacpc = fp->imacpc;
     exit->sp_adj = (stackSlots * sizeof(double)) - treeInfo->nativeStackBase;
     exit->rp_adj = exit->calldepth * sizeof(FrameInfo*);
     exit->nativeCalleeWord = 0;
     exit->lookupFlags = js_InferFlags(cx, 0);
-    memcpy(getFullTypeMap(exit), typemap, typemap_size);
+    memcpy(GetFullTypeMap(exit), typemap, typemap_size);
 
     JS_ARENA_RELEASE(&cx->tempPool, mark);
     return exit;
 }
 
 JS_REQUIRES_STACK LIns*
 TraceRecorder::createGuardRecord(VMSideExit* exit)
 {
@@ -3132,26 +3242,31 @@ TraceRecorder::copy(VMSideExit* copy)
      * rewinding those lirbufs, we have to make sure we purge the side exits
      * that then no longer will be in valid memory.
      */
     if (exit->exitType == LOOP_EXIT)
         treeInfo->sideExits.add(exit);
     return exit;
 }
 
-/* Emit a guard for condition (cond), expecting to evaluate to boolean result (expected)
-   and generate a side exit with type exitType to jump to if the condition does not hold. */
+/*
+ * Emit a guard for condition (cond), expecting to evaluate to boolean result
+ * (expected) and generate a side exit with type exitType to jump to if the
+ * condition does not hold.
+ */
 JS_REQUIRES_STACK void
 TraceRecorder::guard(bool expected, LIns* cond, ExitType exitType)
 {
     guard(expected, cond, snapshot(exitType));
 }
 
-/* Try to match the type of a slot to type t. checkType is used to verify that the type of
- * values flowing into the loop edge is compatible with the type we expect in the loop header.
+/*
+ * Try to match the type of a slot to type t. checkType is used to verify that
+ * the type of each value flowing into the loop edge is compatible with the
+ * type we expect in the loop header.
  *
  * @param v             Value.
  * @param t             Typemap entry for value.
  * @param stage_val     Outparam for set() address.
  * @param stage_ins     Outparam for set() instruction.
  * @param stage_count   Outparam for set() buffer count.
  * @return              True if types are compatible, false otherwise.
  */
@@ -3163,39 +3278,46 @@ TraceRecorder::checkType(jsval& v, JSTra
         debug_only_printf(LC_TMTracer, "checkType(tag=1, t=%d, isnum=%d, i2f=%d) stage_count=%d\n",
                           t,
                           isNumber(v),
                           isPromoteInt(get(&v)),
                           stage_count);
         if (!isNumber(v))
             return false; /* not a number? type mismatch */
         LIns* i = get(&v);
+
         /* This is always a type mismatch, we can't close a double to an int. */
         if (!isPromoteInt(i))
             return false;
+
         /* Looks good, slot is an int32, the last instruction should be promotable. */
         JS_ASSERT(isInt32(v) && isPromoteInt(i));
+
         /* Overwrite the value in this slot with the argument promoted back to an integer. */
         stage_val = &v;
         stage_ins = f2i(i);
         stage_count++;
         return true;
     }
     if (t == TT_DOUBLE) {
         debug_only_printf(LC_TMTracer,
                           "checkType(tag=2, t=%d, isnum=%d, promote=%d) stage_count=%d\n",
                           t,
                           isNumber(v),
                           isPromoteInt(get(&v)),
                           stage_count);
         if (!isNumber(v))
             return false; /* not a number? type mismatch */
         LIns* i = get(&v);
-        /* We sink i2f conversions into the side exit, but at the loop edge we have to make
-           sure we promote back to double if at loop entry we want a double. */
+
+        /*
+         * We sink i2f conversions into the side exit, but at the loop edge we
+         * have to make sure we promote back to double if at loop entry we want
+         * a double.
+         */
         if (isPromoteInt(i)) {
             stage_val = &v;
             stage_ins = lir->ins1(LIR_i2f, i);
             stage_count++;
         }
         return true;
     }
     if (t == TT_NULL)
@@ -3411,36 +3533,37 @@ public:
             mTypeMap++;
             vp++;
         }
         return true;
     }
 };
 
 /**
- * Make sure that the current values in the given stack frame and all stack frames
- * up and including entryFrame are type-compatible with the entry map.
+ * Make sure that the current values in the given stack frame and all stack
+ * frames up to and including entryFrame are type-compatible with the entry
+ * map.
  *
  * @param root_peer         First fragment in peer list.
  * @param stable_peer       Outparam for first type stable peer.
  * @param demote            True if stability was achieved through demotion.
  * @return                  True if type stable, false otherwise.
  */
 JS_REQUIRES_STACK bool
 TraceRecorder::deduceTypeStability(Fragment* root_peer, Fragment** stable_peer, bool& demote)
 {
-    JS_ASSERT(treeInfo->globalSlots->length() ==
-              treeInfo->nGlobalTypes());
+    JS_ASSERT(treeInfo->globalSlots->length() == treeInfo->nGlobalTypes());
 
     if (stable_peer)
         *stable_peer = NULL;
 
     /*
-     * Rather than calculate all of this stuff twice, it gets cached locally.  The "stage" buffers
-     * are for calls to set() that will change the exit types.
+     * Rather than calculate all of this stuff twice, it gets cached locally.
+     * The "stage" buffers are for calls to set() that will change the exit
+     * types.
      */
     bool success;
     unsigned stage_count;
     jsval** stage_vals = (jsval**)alloca(sizeof(jsval*) * (treeInfo->typeMap.length()));
     LIns** stage_ins = (LIns**)alloca(sizeof(LIns*) * (treeInfo->typeMap.length()));
 
     /* First run through and see if we can close ourselves - best case! */
     stage_count = 0;
@@ -3459,68 +3582,69 @@ TraceRecorder::deduceTypeStability(Fragm
         return true;
     /* If we need to trash, don't bother checking peers. */
     } else if (trashSelf) {
         return false;
     }
 
     demote = false;
 
-    /* At this point the tree is about to be incomplete, so let's see if we can connect to any
-     * peer fragment that is type stable.
+    /*
+     * At this point the tree is about to be incomplete, so let's see if we can
+     * connect to any peer fragment that is type stable.
      */
     Fragment* f;
     TreeInfo* ti;
     for (f = root_peer; f != NULL; f = f->peer) {
         debug_only_printf(LC_TMTracer,
                           "Checking type stability against peer=%p (code=%p)\n",
                           (void*)f, f->code());
         if (!f->code())
             continue;
         ti = (TreeInfo*)f->vmprivate;
+
         /* Don't allow varying stack depths */
         if ((ti->nStackTypes != treeInfo->nStackTypes) ||
             (ti->typeMap.length() != treeInfo->typeMap.length()) ||
             (ti->globalSlots->length() != treeInfo->globalSlots->length()))
             continue;
         stage_count = 0;
         success = false;
 
         PeerTypeStabilityVisitor peerVisitor(*this, ti->stackTypeMap(),
                                              stage_vals, stage_ins, stage_count);
         VisitSlots(peerVisitor, cx, 0, *treeInfo->globalSlots);
         success = peerVisitor.isOk();
 
         if (success) {
             /*
-             * There was a successful match.  We don't care about restoring the saved staging, but
-             * we do need to clear the original undemote list.
+             * There was a successful match.  We don't care about restoring the
+             * saved staging, but we do need to clear the original undemote
+             * list.
              */
             for (unsigned i = 0; i < stage_count; i++)
                 set(stage_vals[i], stage_ins[i]);
             if (stable_peer)
                 *stable_peer = f;
             demote = false;
             return false;
         }
     }
 
     /*
-     * If this is a loop trace and it would be stable with demotions, build an undemote list
-     * and return true.  Our caller should sniff this and trash the tree, recording a new one
-     * that will assumedly stabilize.
+     * If this is a loop trace and it would be stable with demotions, build an
+     * undemote list and return true.  Our caller should sniff this and trash
+     * the tree, recording a new one that will assumedly stabilize.
      */
     if (demote && fragment->kind == LoopTrace) {
         UndemoteVisitor visitor(*this, treeInfo->stackTypeMap());
         VisitSlots(visitor, cx, 0, *treeInfo->globalSlots);
         return true;
-    } else {
-        demote = false;
-    }
-
+    }
+    demote = false;
     return false;
 }
 
 static JS_REQUIRES_STACK void
 FlushJITCache(JSContext* cx)
 {
     if (!TRACING_ENABLED(cx))
         return;
@@ -3532,18 +3656,17 @@ FlushJITCache(JSContext* cx)
     while ((tr = tm->abortStack) != NULL) {
         tr->removeFragmentoReferences();
         tr->deepAbort();
         tr->popAbortStack();
     }
     Fragmento* fragmento = tm->fragmento;
     if (fragmento) {
         if (tm->prohibitFlush) {
-            debug_only_print0(LC_TMTracer,
-                              "Deferring fragmento flush due to deep bail.\n");
+            debug_only_print0(LC_TMTracer, "Deferring fragmento flush due to deep bail.\n");
             tm->needFlush = JS_TRUE;
             return;
         }
 
         fragmento->clearFrags();
 #ifdef DEBUG
         JS_ASSERT(fragmento->labels);
         fragmento->labels->clear();
@@ -3576,68 +3699,69 @@ TraceRecorder::compile(JSTraceMonitor* t
 
     if (tm->needFlush) {
         FlushJITCache(cx);
         return;
     }
     Fragmento* fragmento = tm->fragmento;
     if (treeInfo->maxNativeStackSlots >= MAX_NATIVE_STACK_SLOTS) {
         debug_only_print0(LC_TMTracer, "Blacklist: excessive stack use.\n");
-        js_Blacklist((jsbytecode*) fragment->root->ip);
+        Blacklist((jsbytecode*) fragment->root->ip);
         return;
     }
     if (anchor && anchor->exitType != CASE_EXIT)
         ++treeInfo->branchCount;
     if (lirbuf->outOMem()) {
         fragmento->assm()->setError(nanojit::OutOMem);
         return;
     }
     ::compile(fragmento->assm(), fragment);
     if (fragmento->assm()->error() == nanojit::OutOMem)
         return;
     if (fragmento->assm()->error() != nanojit::None) {
         debug_only_print0(LC_TMTracer, "Blacklisted: error during compilation\n");
-        js_Blacklist((jsbytecode*) fragment->root->ip);
+        Blacklist((jsbytecode*) fragment->root->ip);
         return;
     }
-    js_resetRecordingAttempts(cx, (jsbytecode*) fragment->ip);
-    js_resetRecordingAttempts(cx, (jsbytecode*) fragment->root->ip);
+    ResetRecordingAttempts(cx, (jsbytecode*) fragment->ip);
+    ResetRecordingAttempts(cx, (jsbytecode*) fragment->root->ip);
     if (anchor) {
 #ifdef NANOJIT_IA32
         if (anchor->exitType == CASE_EXIT)
             fragmento->assm()->patch(anchor, anchor->switchInfo);
         else
 #endif
             fragmento->assm()->patch(anchor);
     }
     JS_ASSERT(fragment->code());
     JS_ASSERT(!fragment->vmprivate);
     if (fragment == fragment->root)
         fragment->vmprivate = treeInfo;
+
     /* :TODO: windows support */
 #if defined DEBUG && !defined WIN32
     const char* filename = cx->fp->script->filename;
-    char* label = (char*)malloc((filename ? strlen(filename) : 7) + 16);
+    char* label = (char*)js_malloc((filename ? strlen(filename) : 7) + 16);
     sprintf(label, "%s:%u", filename ? filename : "<stdin>",
             js_FramePCToLineNumber(cx, cx->fp));
     fragmento->labels->add(fragment, sizeof(Fragment), 0, label);
-    free(label);
+    js_free(label);
 #endif
     AUDIT(traceCompleted);
 }
 
 static bool
-js_JoinPeersIfCompatible(Fragmento* frago, Fragment* stableFrag, TreeInfo* stableTree,
-                         VMSideExit* exit)
+JoinPeersIfCompatible(Fragmento* frago, Fragment* stableFrag, TreeInfo* stableTree,
+                      VMSideExit* exit)
 {
     JS_ASSERT(exit->numStackSlots == stableTree->nStackTypes);
 
     /* Must have a matching type unstable exit. */
     if ((exit->numGlobalSlots + exit->numStackSlots != stableTree->typeMap.length()) ||
-        memcmp(getFullTypeMap(exit), stableTree->typeMap.data(), stableTree->typeMap.length())) {
+        memcmp(GetFullTypeMap(exit), stableTree->typeMap.data(), stableTree->typeMap.length())) {
        return false;
     }
 
     exit->target = stableFrag;
     frago->assm()->patch(exit);
 
     stableTree->dependentTrees.addUnique(exit->from->root);
     ((TreeInfo*)exit->from->root->vmprivate)->linkedTrees.addUnique(stableFrag);
@@ -3645,31 +3769,31 @@ js_JoinPeersIfCompatible(Fragmento* frag
     return true;
 }
 
 /* Complete and compile a trace and link it to the existing tree if appropriate. */
 JS_REQUIRES_STACK void
 TraceRecorder::closeLoop(JSTraceMonitor* tm, bool& demote)
 {
     /*
-     * We should have arrived back at the loop header, and hence we don't want to be in an imacro
-     * here and the opcode should be either JSOP_LOOP, or in case this loop was blacklisted in the
-     * meantime JSOP_NOP.
+     * We should have arrived back at the loop header, and hence we don't want
+     * to be in an imacro here and the opcode should be either JSOP_LOOP or, in
+     * case this loop was blacklisted in the meantime, JSOP_NOP.
      */
     JS_ASSERT((*cx->fp->regs->pc == JSOP_LOOP || *cx->fp->regs->pc == JSOP_NOP) && !cx->fp->imacpc);
 
     bool stable;
     Fragment* peer;
     VMFragment* peer_root;
     Fragmento* fragmento = tm->fragmento;
 
     if (callDepth != 0) {
         debug_only_print0(LC_TMTracer,
                           "Blacklisted: stack depth mismatch, possible recursion.\n");
-        js_Blacklist((jsbytecode*) fragment->root->ip);
+        Blacklist((jsbytecode*) fragment->root->ip);
         trashSelf = true;
         return;
     }
 
     VMSideExit* exit = snapshot(UNSTABLE_LOOP_EXIT);
     JS_ASSERT(exit->numStackSlots == treeInfo->nStackTypes);
 
     VMFragment* root = (VMFragment*)fragment->root;
@@ -3733,24 +3857,24 @@ TraceRecorder::closeLoop(JSTraceMonitor*
     if (fragmento->assm()->error() != nanojit::None)
         return;
 
     joinEdgesToEntry(fragmento, peer_root);
 
     debug_only_print0(LC_TMTracer,
                       "updating specializations on dependent and linked trees\n");
     if (fragment->root->vmprivate)
-        specializeTreesToMissingGlobals(cx, globalObj, (TreeInfo*)fragment->root->vmprivate);
+        SpecializeTreesToMissingGlobals(cx, globalObj, (TreeInfo*)fragment->root->vmprivate);
 
     /*
      * If this is a newly formed tree, and the outer tree has not been compiled yet, we
      * should try to compile the outer tree again.
      */
     if (outer)
-        js_AttemptCompilation(cx, tm, globalObj, outer, outerArgc);
+        AttemptCompilation(cx, tm, globalObj, outer, outerArgc);
 #ifdef JS_JIT_SPEW
     debug_only_printf(LC_TMMinimal,
                       "recording completed at  %s:%u@%u via closeLoop\n",
                       cx->fp->script->filename,
                       js_FramePCToLineNumber(cx, cx->fp),
                       FramePCOffset(cx->fp));
     debug_only_print0(LC_TMMinimal, "\n");
 #endif