Bug 787246 - rm OffTheBooks/Foreground/UnwantedForeground gunk (r=billm)
authorLuke Wagner <luke@mozilla.com>
Fri, 31 Aug 2012 15:01:33 -0700
changeset 104060 d0789db68c77ada4f7fdf1ca8db213a3e003cf44
parent 104059 7a9f9c67c0f2fd75be9beab0461ddc1c262f0934
child 104061 949ade2a2ea186f431cb629d8f8281c1a91b488e
push id14319
push userlwagner@mozilla.com
push dateFri, 31 Aug 2012 22:25:50 +0000
treeherdermozilla-inbound@949ade2a2ea1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs787246
milestone18.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 787246 - rm OffTheBooks/Foreground/UnwantedForeground gunk (r=billm)
js/jsd/jshash.cpp
js/public/Utility.h
js/src/Makefile.in
js/src/assembler/jit/ExecutableAllocator.h
js/src/builtin/MapObject.cpp
js/src/ctypes/CTypes.cpp
js/src/ctypes/CTypes.h
js/src/ds/LifoAlloc.h
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/FoldConstants.cpp
js/src/frontend/ParseMaps.cpp
js/src/frontend/Parser-inl.h
js/src/frontend/Parser.h
js/src/frontend/TokenStream.cpp
js/src/jsanalyze.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsatom.cpp
js/src/jsclone.cpp
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jscntxtinlines.h
js/src/jscompartment.cpp
js/src/jsdbgapi.cpp
js/src/jsdhash.cpp
js/src/jsdtoa.cpp
js/src/jsdtoa.h
js/src/jsexn.cpp
js/src/jsgc.cpp
js/src/jsgc.h
js/src/jsinfer.cpp
js/src/jsiter.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsopcode.cpp
js/src/jsprf.cpp
js/src/jspropertytree.cpp
js/src/jsreflect.cpp
js/src/jsscope.cpp
js/src/jsscope.h
js/src/jsscript.cpp
js/src/jsstr.cpp
js/src/jstypedarray.cpp
js/src/jsutil.cpp
js/src/jsweakmap.cpp
js/src/jsxml.cpp
js/src/methodjit/Compiler.cpp
js/src/methodjit/FrameState.cpp
js/src/methodjit/ImmutableSync.cpp
js/src/methodjit/LoopState.cpp
js/src/methodjit/MethodJIT.cpp
js/src/methodjit/PolyIC.cpp
js/src/methodjit/PolyIC.h
js/src/perf/pm_linux.cpp
js/src/shell/jsheaptools.cpp
js/src/shell/jsoptparse.cpp
js/src/vm/Debugger.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/RegExpObject.cpp
js/src/vm/RegExpObject.h
js/src/vm/SPSProfiler.cpp
js/src/vm/String.cpp
js/src/vm/StringBuffer.cpp
js/src/vm/Xdr.cpp
js/src/yarr/RegExpJitTables.h
js/src/yarr/YarrInterpreter.cpp
js/src/yarr/YarrPattern.cpp
js/src/yarr/YarrPattern.h
js/src/yarr/wtfbridge.h
--- a/js/jsd/jshash.cpp
+++ b/js/jsd/jshash.cpp
@@ -29,36 +29,36 @@ using namespace js;
 #define UNDERLOADED(n)  (((n) > MINBUCKETS) ? ((n) >> 2) : 0)
 
 /*
 ** Stubs for default hash allocator ops.
 */
 static void *
 DefaultAllocTable(void *pool, size_t size)
 {
-    return OffTheBooks::malloc_(size);
+    return js_malloc(size);
 }
 
 static void
 DefaultFreeTable(void *pool, void *item, size_t size)
 {
-    UnwantedForeground::free_(item);
+    js_free(item);
 }
 
 static JSHashEntry *
 DefaultAllocEntry(void *pool, const void *key)
 {
-    return (JSHashEntry*) OffTheBooks::malloc_(sizeof(JSHashEntry));
+    return (JSHashEntry*) js_malloc(sizeof(JSHashEntry));
 }
 
 static void
 DefaultFreeEntry(void *pool, JSHashEntry *he, unsigned flag)
 {
     if (flag == HT_FREE_ENTRY)
-        UnwantedForeground::free_(he);
+        js_free(he);
 }
 
 static JSHashAllocOps defaultHashAllocOps = {
     DefaultAllocTable, DefaultFreeTable,
     DefaultAllocEntry, DefaultFreeEntry
 };
 
 JSHashTable *
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -141,21 +141,16 @@ PrintBacktrace()
         } \
     } while (0)
 
 # else
 #  define JS_OOM_POSSIBLY_FAIL() do {} while(0)
 #  define JS_OOM_POSSIBLY_FAIL_REPORT(cx) do {} while(0)
 # endif /* DEBUG */
 
-/*
- * SpiderMonkey code should not be calling these allocation functions directly.
- * Instead, all calls should go through JSRuntime, JSContext or OffTheBooks.
- * However, js_free() can be called directly.
- */
 static JS_INLINE void* js_malloc(size_t bytes)
 {
     JS_OOM_POSSIBLY_FAIL();
     return malloc(bytes);
 }
 
 static JS_INLINE void* js_calloc(size_t bytes)
 {
@@ -376,284 +371,169 @@ JS_FLOOR_LOG2W(size_t n)
 #endif
 
 JS_END_EXTERN_C
 
 #ifdef __cplusplus
 #include <new>
 
 /*
- * User guide to memory management within SpiderMonkey:
- *
- * Quick tips:
+ * Low-level memory management in SpiderMonkey:
  *
- *   Allocation:
- *   - Prefer to allocate using JSContext:
- *       cx->{malloc_,realloc_,calloc_,new_,array_new}
+ *  ** Do not use the standard malloc/free/realloc: SpiderMonkey allows these
+ *     to be redefined (via JS_USE_CUSTOM_ALLOCATOR) and Gecko even #define's
+ *     these symbols.
  *
- *   - If no JSContext is available, use a JSRuntime:
- *       rt->{malloc_,realloc_,calloc_,new_,array_new}
- *
- *   - As a last resort, use unaccounted allocation ("OffTheBooks"):
- *       js::OffTheBooks::{malloc_,realloc_,calloc_,new_,array_new}
+ *  ** Do not use the builtin C++ operator new and delete: these throw on
+ *     error and we cannot override them not to.
  *
- *   Deallocation:
- *   - When the deallocation occurs on a slow path, use:
- *       Foreground::{free_,delete_,array_delete}
- *
- *   - Otherwise deallocate on a background thread using a JSContext:
- *       cx->{free_,delete_,array_delete}
- *
- *   - If no JSContext is available, use a JSRuntime:
- *       rt->{free_,delete_,array_delete}
+ * Allocation:
  *
- *   - As a last resort, use UnwantedForeground deallocation:
- *       js::UnwantedForeground::{free_,delete_,array_delete}
- *
- * General tips:
+ * - If the lifetime of the allocation is tied to the lifetime of a GC-thing
+ *   (that is, finalizing the GC-thing will free the allocation), call one of
+ *   the following functions:
  *
- *   - Mixing and matching these allocators is allowed (you may free memory
- *     allocated by any allocator, with any deallocator).
- *
- *   - Never, ever use normal C/C++ memory management:
- *       malloc, free, new, new[], delete, operator new, etc.
+ *     JSContext::{malloc_,realloc_,calloc_,new_}
+ *     JSRuntime::{malloc_,realloc_,calloc_,new_}
  *
- *   - Never, ever use low-level SpiderMonkey allocators:
- *       js_malloc(), js_free(), js_calloc(), js_realloc()
- *     Their use is reserved for the other memory managers.
- *
- *   - Classes which have private constructors or destructors should have
- *     JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR added to their
- *     declaration.
+ *   These functions accumulate the number of bytes allocated which is used as
+ *   part of the GC-triggering heuristic.
  *
- * Details:
+ *   The difference between the JSContext and JSRuntime versions is that the
+ *   cx version reports an out-of-memory error on OOM. (This follows from the
+ *   general SpiderMonkey idiom that a JSContext-taking function reports its
+ *   own errors.)
  *
- *   Using vanilla new/new[] is unsafe in SpiderMonkey because they throw on
- *   failure instead of returning NULL, which is what SpiderMonkey expects.
- *   (Even overriding them is unsafe, as the system's C++ runtime library may
- *   throw, which we do not support. We also can't just use the 'nothrow'
- *   variant of new/new[], because we want to mediate *all* allocations
- *   within SpiderMonkey, to satisfy any embedders using
- *   JS_USE_CUSTOM_ALLOCATOR.)
+ * - Otherwise, use js_malloc/js_realloc/js_calloc/js_free/js_new
  *
- *   JSContexts and JSRuntimes keep track of memory allocated, and use this
- *   accounting to schedule GC. OffTheBooks does not. We'd like to remove
- *   OffTheBooks allocations as much as possible (bug 636558).
+ * Deallocation:
  *
- *   On allocation failure, a JSContext correctly reports an error, which a
- *   JSRuntime and OffTheBooks does not.
+ * - Ordinarily, use js_free/js_delete.
  *
- *   A JSContext deallocates in a background thread. A JSRuntime might
- *   deallocate in the background in the future, but does not now. Foreground
- *   deallocation is preferable on slow paths. UnwantedForeground deallocations
- *   occur where we have no JSContext or JSRuntime, and the deallocation is not
- *   on a slow path. We want to remove UnwantedForeground deallocations (bug
- *   636561).
+ * - For deallocations during GC finalization, use one of the following
+ *   operations on the FreeOp provided to the finalizer:
  *
- *   JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR makes the allocation
- *   classes friends with your class, giving them access to private
- *   constructors and destructors.
+ *     FreeOp::{free_,delete_}
  *
- *   |make check| does a source level check on the number of uses OffTheBooks,
- *   UnwantedForeground, js_malloc, js_free etc, to prevent regressions. If you
- *   really must add one, update Makefile.in, and run |make check|.
- *
- *   |make check| also statically prevents the use of vanilla new/new[].
+ *   The advantage of these operations is that the memory is batched and freed
+ *   on another thread.
  */
 
 #define JS_NEW_BODY(allocator, t, parms)                                       \
     void *memory = allocator(sizeof(t));                                       \
     return memory ? new(memory) t parms : NULL;
 
 /*
- * Given a class which should provide new_() methods, add
+ * Given a class which should provide 'new' methods, add
  * JS_DECLARE_NEW_METHODS (see JSContext for a usage example). This
- * adds new_()s with up to 12 parameters. Add more versions of new_ below if
+ * adds news with up to 12 parameters. Add more versions of new below if
  * you need more than 12 parameters.
  *
  * Note: Do not add a ; at the end of a use of JS_DECLARE_NEW_METHODS,
  * or the build will break.
  */
-#define JS_DECLARE_NEW_METHODS(ALLOCATOR, QUALIFIERS)\
+#define JS_DECLARE_NEW_METHODS(NEWNAME, ALLOCATOR, QUALIFIERS)\
     template <class T>\
-    QUALIFIERS T *new_() {\
+    QUALIFIERS T *NEWNAME() {\
         JS_NEW_BODY(ALLOCATOR, T, ())\
     }\
 \
     template <class T, class P1>\
-    QUALIFIERS T *new_(P1 p1) {\
+    QUALIFIERS T *NEWNAME(P1 p1) {\
         JS_NEW_BODY(ALLOCATOR, T, (p1))\
     }\
 \
     template <class T, class P1, class P2>\
-    QUALIFIERS T *new_(P1 p1, P2 p2) {\
+    QUALIFIERS T *NEWNAME(P1 p1, P2 p2) {\
         JS_NEW_BODY(ALLOCATOR, T, (p1, p2))\
     }\
 \
     template <class T, class P1, class P2, class P3>\
-    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3) {\
+    QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3) {\
         JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3))\
     }\
 \
     template <class T, class P1, class P2, class P3, class P4>\
-    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4) {\
+    QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4) {\
         JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4))\
     }\
 \
     template <class T, class P1, class P2, class P3, class P4, class P5>\
-    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {\
+    QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {\
         JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5))\
     }\
 \
     template <class T, class P1, class P2, class P3, class P4, class P5, class P6>\
-    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {\
+    QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {\
         JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6))\
     }\
 \
     template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7>\
-    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {\
+    QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {\
         JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7))\
     }\
 \
     template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>\
-    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {\
+    QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {\
         JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8))\
     }\
 \
     template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>\
-    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9) {\
+    QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9) {\
         JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8, p9))\
     }\
 \
     template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10>\
-    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10) {\
+    QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10) {\
         JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10))\
     }\
 \
     template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11>\
-    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11) {\
+    QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11) {\
         JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11))\
     }\
 \
     template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11, class P12>\
-    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11, P12 p12) {\
+    QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11, P12 p12) {\
         JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12))\
     }\
-    static const int JSMinAlignment = 8;\
-    template <class T>\
-    QUALIFIERS T *array_new(size_t n) {\
-        /* The length is stored just before the vector memory. */\
-        uint64_t numBytes64 = uint64_t(JSMinAlignment) + uint64_t(sizeof(T)) * uint64_t(n);\
-        size_t numBytes = size_t(numBytes64);\
-        if (numBytes64 != numBytes) {\
-            JS_ASSERT(0);   /* we want to know if this happens in debug builds */\
-            return NULL;\
-        }\
-        void *memory = ALLOCATOR(numBytes);\
-        if (!memory)\
-            return NULL;\
-        *(size_t *)memory = n;\
-        memory = (void*)(uintptr_t(memory) + JSMinAlignment);\
-        return new(memory) T[n];\
-    }\
 
-
-#define JS_DECLARE_DELETE_METHODS(DEALLOCATOR, QUALIFIERS)\
-    template <class T>\
-    QUALIFIERS void delete_(T *p) {\
-        if (p) {\
-            p->~T();\
-            DEALLOCATOR(p);\
-        }\
-    }\
-\
-    template <class T>\
-    QUALIFIERS void array_delete(T *p) {\
-        if (p) {\
-            void* p0 = (void *)(uintptr_t(p) - js::OffTheBooks::JSMinAlignment);\
-            size_t n = *(size_t *)p0;\
-            for (size_t i = 0; i < n; i++)\
-                (p + i)->~T();\
-            DEALLOCATOR(p0);\
-        }\
-    }
-
-
-/*
- * In general, all allocations should go through a JSContext or JSRuntime, so
- * that the garbage collector knows how much memory has been allocated. In
- * cases where it is difficult to use a JSContext or JSRuntime, OffTheBooks can
- * be used, though this is undesirable.
- */
-namespace js {
+JS_DECLARE_NEW_METHODS(js_new, js_malloc, static JS_ALWAYS_INLINE)
 
-class OffTheBooks {
-public:
-    JS_DECLARE_NEW_METHODS(::js_malloc, JS_ALWAYS_INLINE static)
-
-    static JS_INLINE void* malloc_(size_t bytes) {
-        return ::js_malloc(bytes);
+template <class T>
+static JS_ALWAYS_INLINE void
+js_delete(T *p)
+{
+    if (p) {
+        p->~T();
+        js_free(p);
     }
-
-    static JS_INLINE void* calloc_(size_t bytes) {
-        return ::js_calloc(bytes);
-    }
-
-    static JS_INLINE void* realloc_(void* p, size_t bytes) {
-        return ::js_realloc(p, bytes);
-    }
-};
+}
 
-/*
- * We generally prefer deallocating using JSContext because it can happen in
- * the background. On slow paths, we may prefer foreground allocation.
- */
-class Foreground {
-public:
-    /* See parentheses comment above. */
-    static JS_ALWAYS_INLINE void free_(void* p) {
-        ::js_free(p);
-    }
-
-    JS_DECLARE_DELETE_METHODS(::js_free, JS_ALWAYS_INLINE static)
-};
-
-class UnwantedForeground : public Foreground {
-};
+namespace js {
 
 template<typename T>
 struct ScopedFreePtrTraits
 {
     typedef T* type;
     static T* empty() { return NULL; }
-    static void release(T* ptr) { Foreground::free_(ptr); }
+    static void release(T* ptr) { js_free(ptr); }
 };
 SCOPED_TEMPLATE(ScopedFreePtr, ScopedFreePtrTraits)
 
 template <typename T>
 struct ScopedDeletePtrTraits : public ScopedFreePtrTraits<T>
 {
-    static void release(T *ptr) { Foreground::delete_(ptr); }
+    static void release(T *ptr) { js_delete(ptr); }
 };
 SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits)
 
 } /* namespace js */
 
 /*
- * Note lack of ; in JSRuntime below. This is intentional so "calling" this
- * looks "normal".
- */
-#define JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR \
-    friend class js::OffTheBooks;\
-    friend class js::Foreground;\
-    friend class js::UnwantedForeground;\
-    friend struct ::JSContext;\
-    friend struct ::JSRuntime
-
-/*
  * The following classes are designed to cause assertions to detect
  * inadvertent use of guard objects as temporaries.  In other words,
  * when we have a guard object whose only purpose is its constructor and
  * destructor (and is never otherwise referenced), the intended use
  * might be:
  *     JSAutoTempValueRooter tvr(cx, 1, &val);
  * but is is easy to accidentally write:
  *     JSAutoTempValueRooter(cx, 1, &val);
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -507,47 +507,16 @@ endif
 # number to go down over time, by fixing OOMs.
 check-ooms:
 	$(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/config/find_OOM_errors.py --regression 125
 
 ifeq ($(MOZ_DEBUG),1)
 #check:: check-ooms
 endif
 
-## Prevent regressing in our deprecation of non-preferred memory management functions.
-# We use all the files in the distribution so that different configurations
-# don't give different results. We skip the contents of objdirs using |find|
-# (it can't be done with %-expansion, because the files we want to skip aren't
-# in the vpath).
-ALL_FILES=$(shell find $(srcdir) \( -name "*.cpp" -o -name "*.h" \) ! -path "*/dist/*" ! -path "*/config/*")
-check-malloc-function-usage: $(filter-out %jsalloc.h %jscntxt.h %jsutil.h, $(ALL_FILES))
-
-	# js_malloc and friends are only used by other memory managers, and should
-	# never be used elsewhere directly.
-	$(srcdir)/config/check_source_count.py "\bjs_malloc\b" 0 \
-		"in Makefile.in" "cx->malloc_ or rt->malloc_" $^
-	$(srcdir)/config/check_source_count.py "\bjs_calloc\b" 0 \
-		"in Makefile.in" "cx->calloc_ or rt->calloc_" $^
-	$(srcdir)/config/check_source_count.py "\bjs_realloc\b" 0 \
-		"in Makefile.in" "cx->realloc_ or rt->realloc_" $^
-	$(srcdir)/config/check_source_count.py "\bjs_free\b" 0 \
-		"in Makefile.in" "cx->free_" $^
-
-	# We desire these numbers to go down, not up. See "User guide to memory
-	# management within SpiderMonkey" in jsutil.h.
-	$(srcdir)/config/check_source_count.py OffTheBooks:: 71 \
-		"in Makefile.in" "{cx,rt}->{new_,array_new,malloc_,calloc_,realloc_}" $^
-	# This should go to zero, if possible.
-	$(srcdir)/config/check_source_count.py UnwantedForeground:: 31 \
-		"in Makefile.in" "{cx,rt}->{free_,delete_,array_delete}" $^
-
-ifneq ($(OS_ARCH),WINNT) # FIXME: this should be made work on Windows too.
-#check:: check-malloc-function-usage FIXME: disable on JM until closer to merge time.
-endif
-
 ifdef MOZ_VALGRIND
 ifndef MOZ_ASAN
 JITTEST_VALGRIND_FLAG = --valgrind
 endif
 endif
 
 JITFLAGS = ,m,am,amd,n,mn,amn,amdn,mdn
 check-jit-test::
--- a/js/src/assembler/jit/ExecutableAllocator.h
+++ b/js/src/assembler/jit/ExecutableAllocator.h
@@ -82,17 +82,16 @@ namespace JSC {
 
   class ExecutableAllocator;
 
   enum CodeKind { METHOD_CODE, REGEXP_CODE };
 
   // These are reference-counted. A new one starts with a count of 1. 
   class ExecutablePool {
 
-    JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR;
     friend class ExecutableAllocator;
 private:
     struct Allocation {
         char* pages;
         size_t size;
 #if WTF_OS_SYMBIAN
         RChunk* chunk;
 #endif
@@ -118,38 +117,37 @@ public:
     // remember whether m_destroy was computed for the currently active GC.
     size_t m_gcNumber;
 
     void release(bool willDestroy = false)
     { 
         JS_ASSERT(m_refCount != 0);
         // XXX: disabled, see bug 654820.
         //JS_ASSERT_IF(willDestroy, m_refCount == 1);
-        if (--m_refCount == 0) {
-            js::UnwantedForeground::delete_(this);
-        }
+        if (--m_refCount == 0)
+            js_delete(this);
     }
 
+    ExecutablePool(ExecutableAllocator* allocator, Allocation a)
+      : m_allocator(allocator), m_freePtr(a.pages), m_end(m_freePtr + a.size), m_allocation(a),
+        m_refCount(1), m_mjitCodeMethod(0), m_mjitCodeRegexp(0), m_destroy(false), m_gcNumber(0)
+    { }
+
+    ~ExecutablePool();
+
 private:
     // It should be impossible for us to roll over, because only small
     // pools have multiple holders, and they have one holder per chunk
     // of generated code, and they only hold 16KB or so of code.
     void addRef()
     {
         JS_ASSERT(m_refCount);
         ++m_refCount;
     }
 
-    ExecutablePool(ExecutableAllocator* allocator, Allocation a)
-      : m_allocator(allocator), m_freePtr(a.pages), m_end(m_freePtr + a.size), m_allocation(a),
-        m_refCount(1), m_mjitCodeMethod(0), m_mjitCodeRegexp(0), m_destroy(false), m_gcNumber(0)
-    { }
-
-    ~ExecutablePool();
-
     void* alloc(size_t n, CodeKind kind)
     {
         JS_ASSERT(n <= available());
         void *result = m_freePtr;
         m_freePtr += n;
 
         if ( kind == REGEXP_CODE )
             m_mjitCodeRegexp += n;
@@ -299,17 +297,17 @@ private:
 #ifdef DEBUG_STRESS_JSC_ALLOCATOR
         ExecutablePool::Allocation a = systemAlloc(size_t(4294967291));
 #else
         ExecutablePool::Allocation a = systemAlloc(allocSize);
 #endif
         if (!a.pages)
             return NULL;
 
-        ExecutablePool *pool = js::OffTheBooks::new_<ExecutablePool>(this, a);
+        ExecutablePool *pool = js_new<ExecutablePool>(this, a);
         if (!pool) {
             systemRelease(a);
             return NULL;
         }
         m_pools.put(pool);
         return pool;
     }
 
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -784,17 +784,17 @@ MapIteratorObject::create(JSContext *cx,
         return NULL;
 
     ValueMap::Range *range = cx->new_<ValueMap::Range>(data->all());
     if (!range)
         return NULL;
 
     JSObject *iterobj = NewObjectWithGivenProto(cx, &MapIteratorClass, proto, global);
     if (!iterobj) {
-        cx->delete_(range);
+        js_delete(range);
         return NULL;
     }
     iterobj->setSlot(TargetSlot, ObjectValue(*mapobj));
     iterobj->setSlot(RangeSlot, PrivateValue(range));
     return static_cast<MapIteratorObject *>(iterobj);
 }
 
 void
@@ -812,17 +812,17 @@ MapIteratorObject::is(const Value &v)
 bool
 MapIteratorObject::next_impl(JSContext *cx, CallArgs args)
 {
     MapIteratorObject &thisobj = args.thisv().toObject().asMapIterator();
     ValueMap::Range *range = thisobj.range();
     if (!range)
         return js_ThrowStopIteration(cx);
     if (range->empty()) {
-        cx->delete_(range);
+        js_delete(range);
         thisobj.setReservedSlot(RangeSlot, PrivateValue(NULL));
         return js_ThrowStopIteration(cx);
     }
 
     Value pair[2] = { range->front().key.get(), range->front().value };
     AutoValueArray root(cx, pair, 2);
 
     JSObject *pairobj = NewDenseCopiedArray(cx, 2, pair);
@@ -1231,17 +1231,17 @@ SetIteratorObject::create(JSContext *cx,
         return NULL;
 
     ValueSet::Range *range = cx->new_<ValueSet::Range>(data->all());
     if (!range)
         return NULL;
 
     JSObject *iterobj = NewObjectWithGivenProto(cx, &SetIteratorClass, proto, global);
     if (!iterobj) {
-        cx->delete_(range);
+        js_delete(range);
         return NULL;
     }
     iterobj->setSlot(TargetSlot, ObjectValue(*setobj));
     iterobj->setSlot(RangeSlot, PrivateValue(range));
     return static_cast<SetIteratorObject *>(iterobj);
 }
 
 void
@@ -1259,17 +1259,17 @@ SetIteratorObject::is(const Value &v)
 bool
 SetIteratorObject::next_impl(JSContext *cx, CallArgs args)
 {
     SetIteratorObject &thisobj = args.thisv().toObject().asSetIterator();
     ValueSet::Range *range = thisobj.range();
     if (!range)
         return js_ThrowStopIteration(cx);
     if (range->empty()) {
-        cx->delete_(range);
+        js_delete(range);
         thisobj.setReservedSlot(RangeSlot, PrivateValue(NULL));
         return js_ThrowStopIteration(cx);
     }
 
     args.rval().set(range->front().get());
     range->popFront();
     return true;
 }
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -2144,34 +2144,34 @@ ImplicitConvert(JSContext* cx,
       case TYPE_unsigned_char: {
         // Convert from UTF-16 to UTF-8.
         size_t nbytes =
           GetDeflatedUTF8StringLength(cx, sourceChars, sourceLength);
         if (nbytes == (size_t) -1)
           return false;
 
         char** charBuffer = static_cast<char**>(buffer);
-        *charBuffer = cx->array_new<char>(nbytes + 1);
+        *charBuffer = (char*)cx->malloc_(nbytes + 1);
         if (!*charBuffer) {
           JS_ReportAllocationOverflow(cx);
           return false;
         }
 
         ASSERT_OK(DeflateStringToUTF8Buffer(cx, sourceChars, sourceLength,
                     *charBuffer, &nbytes));
         (*charBuffer)[nbytes] = 0;
         *freePointer = true;
         break;
       }
       case TYPE_jschar: {
         // Copy the jschar string data. (We could provide direct access to the
         // JSString's buffer, but this approach is safer if the caller happens
         // to modify the string.)
         jschar** jscharBuffer = static_cast<jschar**>(buffer);
-        *jscharBuffer = cx->array_new<jschar>(sourceLength + 1);
+        *jscharBuffer = (jschar*)cx->malloc_((sourceLength + 1) * sizeof(jschar));
         if (!*jscharBuffer) {
           JS_ReportAllocationOverflow(cx);
           return false;
         }
 
         *freePointer = true;
         memcpy(*jscharBuffer, sourceChars, sourceLength * sizeof(jschar));
         (*jscharBuffer)[sourceLength] = 0;
@@ -2250,17 +2250,17 @@ ImplicitConvert(JSContext* cx,
           targetLength != size_t(sourceLength)) {
         JS_ReportError(cx, "ArrayType length does not match source array length");
         return false;
       }
 
       // Convert into an intermediate, in case of failure.
       size_t elementSize = CType::GetSize(baseType);
       size_t arraySize = elementSize * targetLength;
-      AutoPtr<char>::Array intermediate(cx->array_new<char>(arraySize));
+      AutoPtr<char> intermediate((char*)cx->malloc_(arraySize));
       if (!intermediate) {
         JS_ReportAllocationOverflow(cx);
         return false;
       }
 
       for (uint32_t i = 0; i < sourceLength; ++i) {
         js::AutoValueRooter item(cx);
         if (!JS_GetElement(cx, valObj, i, item.jsval_addr()))
@@ -2301,17 +2301,17 @@ ImplicitConvert(JSContext* cx,
       // Enumerate the properties of the object; if they match the struct
       // specification, convert the fields.
       RootedObject iter(cx, JS_NewPropertyIterator(cx, valObj));
       if (!iter)
         return false;
 
       // Convert into an intermediate, in case of failure.
       size_t structSize = CType::GetSize(targetType);
-      AutoPtr<char>::Array intermediate(cx->array_new<char>(structSize));
+      AutoPtr<char> intermediate((char*)cx->malloc_(structSize));
       if (!intermediate) {
         JS_ReportAllocationOverflow(cx);
         return false;
       }
 
       jsid id;
       size_t i = 0;
       while (1) {
@@ -3062,17 +3062,17 @@ CType::Finalize(JSFreeOp *fop, JSObject*
   }
 
     // Fall through.
   case TYPE_array: {
     // Free the ffi_type info.
     slot = JS_GetReservedSlot(obj, SLOT_FFITYPE);
     if (!JSVAL_IS_VOID(slot)) {
       ffi_type* ffiType = static_cast<ffi_type*>(JSVAL_TO_PRIVATE(slot));
-      FreeOp::get(fop)->array_delete(ffiType->elements);
+      FreeOp::get(fop)->free_(ffiType->elements);
       FreeOp::get(fop)->delete_(ffiType);
     }
 
     break;
   }
   default:
     // Nothing to do here.
     break;
@@ -4197,17 +4197,17 @@ ArrayType::BuildFFIType(JSContext* cx, J
   if (!ffiType) {
     JS_ReportOutOfMemory(cx);
     return NULL;
   }
 
   ffiType->type = FFI_TYPE_STRUCT;
   ffiType->size = CType::GetSize(obj);
   ffiType->alignment = CType::GetAlignment(obj);
-  ffiType->elements = cx->array_new<ffi_type*>(length + 1);
+  ffiType->elements = (ffi_type**)cx->malloc_((length + 1) * sizeof(ffi_type*));
   if (!ffiType->elements) {
     JS_ReportAllocationOverflow(cx);
     return NULL;
   }
 
   for (size_t i = 0; i < length; ++i)
     ffiType->elements[i] = ffiBaseType;
   ffiType->elements[length] = NULL;
@@ -4639,19 +4639,19 @@ StructType::BuildFFIType(JSContext* cx, 
 
   AutoPtr<ffi_type> ffiType(cx->new_<ffi_type>());
   if (!ffiType) {
     JS_ReportOutOfMemory(cx);
     return NULL;
   }
   ffiType->type = FFI_TYPE_STRUCT;
 
-  AutoPtr<ffi_type*>::Array elements;
+  AutoPtr<ffi_type*> elements;
   if (len != 0) {
-    elements = cx->array_new<ffi_type*>(len + 1);
+    elements = (ffi_type**)cx->malloc_((len + 1) * sizeof(ffi_type*));
     if (!elements) {
       JS_ReportOutOfMemory(cx);
       return NULL;
     }
     elements[len] = NULL;
 
     for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) {
       const FieldInfoHash::Entry& entry = r.front();
@@ -4660,17 +4660,17 @@ StructType::BuildFFIType(JSContext* cx, 
         return NULL;
       elements[entry.value.mIndex] = fieldType;
     }
 
   } else {
     // Represent an empty struct as having a size of 1 byte, just like C++.
     JS_ASSERT(structSize == 1);
     JS_ASSERT(structAlign == 1);
-    elements = cx->array_new<ffi_type*>(2);
+    elements = (ffi_type**)cx->malloc_(2 * sizeof(ffi_type*));
     if (!elements) {
       JS_ReportOutOfMemory(cx);
       return NULL;
     }
     elements[0] = &ffi_type_uint8;
     elements[1] = NULL;
   }
 
@@ -5007,24 +5007,24 @@ StructType::AddressOfField(JSContext* cx
 
 // Helper class for handling allocation of function arguments.
 struct AutoValue
 {
   AutoValue() : mData(NULL) { }
 
   ~AutoValue()
   {
-    UnwantedForeground::array_delete(static_cast<char*>(mData));
+    js_free(mData);
   }
 
   bool SizeToType(JSContext* cx, JSObject* type)
   {
     // Allocate a minimum of sizeof(ffi_arg) to handle small integers.
     size_t size = Align(CType::GetSize(type), sizeof(ffi_arg));
-    mData = cx->array_new<char>(size);
+    mData = js_malloc(size);
     if (mData)
       memset(mData, 0, size);
     return mData != NULL;
   }
 
   void* mData;
 };
 
@@ -6063,21 +6063,21 @@ CData::Create(JSContext* cx,
   }
 
   char* data;
   if (!ownResult) {
     data = static_cast<char*>(source);
   } else {
     // Initialize our own buffer.
     size_t size = CType::GetSize(typeObj);
-    data = cx->array_new<char>(size);
+    data = (char*)cx->malloc_(size);
     if (!data) {
       // Report a catchable allocation error.
       JS_ReportAllocationOverflow(cx);
-      Foreground::delete_(buffer);
+      js_free(buffer);
       return NULL;
     }
 
     if (!source)
       memset(data, 0, size);
     else
       memcpy(data, source, size);
   }
@@ -6099,17 +6099,17 @@ CData::Finalize(JSFreeOp *fop, JSObject*
   JSBool owns = JSVAL_TO_BOOLEAN(slot);
 
   slot = JS_GetReservedSlot(obj, SLOT_DATA);
   if (JSVAL_IS_VOID(slot))
     return;
   char** buffer = static_cast<char**>(JSVAL_TO_PRIVATE(slot));
 
   if (owns)
-    FreeOp::get(fop)->array_delete(*buffer);
+    FreeOp::get(fop)->free_(*buffer);
   FreeOp::get(fop)->delete_(buffer);
 }
 
 JSObject*
 CData::GetCType(JSObject* dataObj)
 {
   JS_ASSERT(CData::IsCData(dataObj));
 
--- a/js/src/ctypes/CTypes.h
+++ b/js/src/ctypes/CTypes.h
@@ -15,62 +15,45 @@
 
 namespace js {
 namespace ctypes {
 
 /*******************************************************************************
 ** Utility classes
 *******************************************************************************/
 
-template<class T>
-class OperatorDelete
-{
-public:
-  static void destroy(T* ptr) { UnwantedForeground::delete_(ptr); }
-};
-
-template<class T>
-class OperatorArrayDelete
-{
-public:
-  static void destroy(T* ptr) { UnwantedForeground::array_delete(ptr); }
-};
-
 // Class that takes ownership of a pointer T*, and calls cx->delete_() or
 // cx->array_delete() upon destruction.
-template<class T, class DeleteTraits = OperatorDelete<T> >
+template<class T>
 class AutoPtr {
 private:
-  typedef AutoPtr<T, DeleteTraits> self_type;
+  typedef AutoPtr<T> self_type;
 
 public:
-  // An AutoPtr variant that calls js_array_delete() instead.
-  typedef AutoPtr<T, OperatorArrayDelete<T> > Array;
-
   AutoPtr() : mPtr(NULL) { }
   explicit AutoPtr(T* ptr) : mPtr(ptr) { }
-  ~AutoPtr() { DeleteTraits::destroy(mPtr); }
+  ~AutoPtr() { js_delete(mPtr); }
 
   T*   operator->()         { return mPtr; }
   bool operator!()          { return mPtr == NULL; }
   T&   operator[](size_t i) { return *(mPtr + i); }
   // Note: we cannot safely provide an 'operator T*()', since this would allow
   // the compiler to perform implicit conversion from one AutoPtr to another
   // via the constructor AutoPtr(T*).
 
   T*   get()         { return mPtr; }
   void set(T* other) { JS_ASSERT(mPtr == NULL); mPtr = other; }
   T*   forget()      { T* result = mPtr; mPtr = NULL; return result; }
 
   self_type& operator=(T* rhs) { mPtr = rhs; return *this; }
 
 private:
   // Do not allow copy construction or assignment from another AutoPtr.
-  template<class U> AutoPtr(AutoPtr<T, U>&);
-  template<class U> self_type& operator=(AutoPtr<T, U>& rhs);
+  AutoPtr(AutoPtr<T>&);
+  self_type& operator=(AutoPtr<T>& rhs);
 
   T* mPtr;
 };
 
 // Container class for Vector, using SystemAllocPolicy.
 template<class T, size_t N = 0>
 class Array : public Vector<T, N, SystemAllocPolicy>
 {
@@ -306,17 +289,17 @@ struct ClosureInfo
     , errResult(NULL)
     , closure(NULL)
   {}
 
   ~ClosureInfo() {
     if (closure)
       ffi_closure_free(closure);
     if (errResult)
-      rt->free_(errResult);
+      js_free(errResult);
   };
 };
 
 bool IsCTypesGlobal(JSObject* obj);
 
 JSCTypesCallbacks* GetCallbacks(JSObject* obj);
 
 JSBool InitTypeClasses(JSContext* cx, JSHandleObject parent);
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -301,17 +301,17 @@ class LifoAlloc
 
     /* Doesn't perform construction; useful for lazily-initialized POD types. */
     template <typename T>
     JS_ALWAYS_INLINE
     T *newPod() {
         return static_cast<T *>(alloc(sizeof(T)));
     }
 
-    JS_DECLARE_NEW_METHODS(alloc, JS_ALWAYS_INLINE)
+    JS_DECLARE_NEW_METHODS(new_, alloc, JS_ALWAYS_INLINE)
 };
 
 class LifoAllocScope
 {
     LifoAlloc   *lifoAlloc;
     void        *mark;
     bool        shouldRelease;
     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -134,22 +134,20 @@ BytecodeEmitter::BytecodeEmitter(Bytecod
 bool
 BytecodeEmitter::init()
 {
     return constMap.init() && atomIndices.ensureMap(sc->context);
 }
 
 BytecodeEmitter::~BytecodeEmitter()
 {
-    JSContext *cx = sc->context;
-
-    cx->free_(prolog.base);
-    cx->free_(prolog.notes);
-    cx->free_(main.base);
-    cx->free_(main.notes);
+    js_free(prolog.base);
+    js_free(prolog.notes);
+    js_free(main.base);
+    js_free(main.notes);
 }
 
 static ptrdiff_t
 EmitCheck(JSContext *cx, BytecodeEmitter *bce, ptrdiff_t delta)
 {
     jsbytecode *base = bce->base();
     jsbytecode *newbase;
     jsbytecode *next = bce->next();
@@ -2386,17 +2384,17 @@ EmitSwitch(JSContext *cx, BytecodeEmitte
                 switchOp = JSOP_LOOKUPSWITCH;
                 continue;
             }
             JS_SET_BIT(intmap, i);
         }
 
       release:
         if (intmap && intmap != intmap_space)
-            cx->free_(intmap);
+            js_free(intmap);
         if (!ok)
             return false;
 
         /*
          * Compute table length and select lookup instead if overlarge or
          * more than half-sparse.
          */
         if (switchOp == JSOP_TABLESWITCH) {
--- a/js/src/frontend/FoldConstants.cpp
+++ b/js/src/frontend/FoldConstants.cpp
@@ -673,17 +673,17 @@ frontend::FoldConstants(JSContext *cx, P
 
             /* Allocate a new buffer and string descriptor for the result. */
             jschar *chars = (jschar *) cx->malloc_((length + 1) * sizeof(jschar));
             if (!chars)
                 return false;
             chars[length] = 0;
             JSString *str = js_NewString(cx, chars, length);
             if (!str) {
-                cx->free_(chars);
+                js_free(chars);
                 return false;
             }
 
             /* Fill the buffer, advancing chars and recycling kids as we go. */
             for (pn2 = pn1; pn2; pn2 = parser->freeTree(pn2)) {
                 JSAtom *atom = pn2->pn_atom;
                 size_t length2 = atom->length();
                 js_strncpy(chars, atom->chars(), length2);
--- a/js/src/frontend/ParseMaps.cpp
+++ b/js/src/frontend/ParseMaps.cpp
@@ -31,17 +31,17 @@ ParseMapPool::checkInvariants()
     JS_STATIC_ASSERT(tl::IsPodType<AtomDefnListMap::WordMap::Entry>::result);
     JS_STATIC_ASSERT(tl::IsPodType<AtomDefnMap::WordMap::Entry>::result);
 }
 
 void
 ParseMapPool::purgeAll()
 {
     for (void **it = all.begin(), **end = all.end(); it != end; ++it)
-        cx->delete_<AtomMapT>(asAtomMap(*it));
+        js_delete<AtomMapT>(asAtomMap(*it));
 
     all.clearAndFree();
     recyclable.clearAndFree();
 }
 
 void *
 ParseMapPool::allocateFresh()
 {
--- a/js/src/frontend/Parser-inl.h
+++ b/js/src/frontend/Parser-inl.h
@@ -74,25 +74,25 @@ ParseContext::setQueuedStrictModeError(C
 
 inline
 ParseContext::~ParseContext()
 {
     // |*parserPC| pointed to this object.  Now that this object is about to
     // die, make |*parserPC| point to this object's parent.
     JS_ASSERT(*parserPC == this);
     *parserPC = this->parent;
-    sc->context->delete_(funcStmts);
+    js_delete(funcStmts);
     if (queuedStrictModeError) {
         // If the parent context is looking for strict mode violations, pass
         // ours up. Otherwise, free it.
         if (parent && parent->sc->strictModeState == StrictMode::UNKNOWN &&
             !parent->queuedStrictModeError)
             parent->queuedStrictModeError = queuedStrictModeError;
         else
-            sc->context->delete_(queuedStrictModeError);
+            js_delete(queuedStrictModeError);
     }
 }
 
 } // namespace frontend
 } // namespace js
 
 #endif // Parser_inl_h__
 
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -337,17 +337,17 @@ struct Parser : private AutoGCRooter
      */
     ParseNode *atomNode(ParseNodeKind kind, JSOp op);
 
   public:
     ParseNode *freeTree(ParseNode *pn) { return allocator.freeTree(pn); }
     void prepareNodeForMutation(ParseNode *pn) { return allocator.prepareNodeForMutation(pn); }
 
     /* new_ methods for creating parse nodes. These report OOM on context. */
-    JS_DECLARE_NEW_METHODS(allocParseNode, inline)
+    JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline)
 
     ParseNode *cloneNode(const ParseNode &other) {
         ParseNode *node = allocParseNode(sizeof(ParseNode));
         if (!node)
             return NULL;
         PodAssign(node, &other);
         return node;
     }
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -213,19 +213,19 @@ TokenStream::TokenStream(JSContext *cx, 
 
 #ifdef _MSC_VER
 #pragma warning(pop)
 #endif
 
 TokenStream::~TokenStream()
 {
     if (flags & TSF_OWNFILENAME)
-        cx->free_((void *) filename);
+        js_free((void *) filename);
     if (sourceMap)
-        cx->free_(sourceMap);
+        js_free(sourceMap);
     if (originPrincipals)
         JS_DropPrincipals(cx->runtime, originPrincipals);
 }
 
 /* Use the fastest available getc. */
 #if defined(HAVE_GETC_UNLOCKED)
 # define fast_getc getc_unlocked
 #elif defined(HAVE__GETC_NOLOCK)
@@ -436,29 +436,29 @@ CompileError::throwError()
         /* Report the error */
         if (reportError && cx->errorReporter)
             cx->errorReporter(cx, message, &report);
     }
 }
 
 CompileError::~CompileError()
 {
-    cx->free_((void*)report.uclinebuf);
-    cx->free_((void*)report.linebuf);
-    cx->free_((void*)report.ucmessage);
-    cx->free_(message);
+    js_free((void*)report.uclinebuf);
+    js_free((void*)report.linebuf);
+    js_free((void*)report.ucmessage);
+    js_free(message);
     message = NULL;
 
     if (report.messageArgs) {
         if (hasCharArgs) {
             unsigned i = 0;
             while (report.messageArgs[i])
-                cx->free_((void*)report.messageArgs[i++]);
+                js_free((void*)report.messageArgs[i++]);
         }
-        cx->free_(report.messageArgs);
+        js_free(report.messageArgs);
     }
 
     PodZero(&report);
 }
 
 bool
 TokenStream::reportCompileErrorNumberVA(ParseNode *pn, unsigned flags, unsigned errorNumber,
                                         va_list args)
@@ -720,17 +720,17 @@ TokenStream::getXMLEntity()
   badncr:
     msg = JSMSG_BAD_XML_NCR;
   bad:
     /* No match: throw a TypeError per ECMA-357 10.3.2.1 step 8(a). */
     JS_ASSERT((tb.end() - bp) >= 1);
     bytes = DeflateString(cx, bp + 1, (tb.end() - bp) - 1);
     if (bytes) {
         reportError(msg, bytes);
-        cx->free_(bytes);
+        js_free(bytes);
     }
     return false;
 }
 
 bool
 TokenStream::getXMLTextOrTag(TokenKind *ttp, Token **tpp)
 {
     TokenKind tt;
@@ -1206,17 +1206,17 @@ TokenStream::getAtLine()
                     while ((c = getChar()) != '\n' && c != EOF && IsSpaceOrBOM2(c))
                         continue;
                 }
             }
             filenameBuf[i] = '\0';
             if (c == EOF || c == '\n') {
                 if (i > 0) {
                     if (flags & TSF_OWNFILENAME)
-                        cx->free_((void *) filename);
+                        js_free((void *) filename);
                     filename = JS_strdup(cx, filenameBuf);
                     if (!filename)
                         return false;
                     flags |= TSF_OWNFILENAME;
                 }
                 lineno = line;
             }
         }
@@ -1245,17 +1245,17 @@ TokenStream::getAtSourceMappingURL()
         if (tokenbuf.empty())
             /* The source map's URL was missing, but not quite an exception that
              * we should stop and drop everything for, though. */
             return true;
 
         size_t sourceMapLength = tokenbuf.length();
 
         if (sourceMap)
-            cx->free_(sourceMap);
+            js_free(sourceMap);
         sourceMap = static_cast<jschar *>(cx->malloc_(sizeof(jschar) * (sourceMapLength + 1)));
         if (!sourceMap)
             return false;
 
         PodCopy(sourceMap, tokenbuf.begin(), sourceMapLength);
         sourceMap[sourceMapLength] = '\0';
     }
     return true;
--- a/js/src/jsanalyze.cpp
+++ b/js/src/jsanalyze.cpp
@@ -794,17 +794,17 @@ ScriptAnalysis::analyzeLifetimes(JSConte
 
           case JSOP_LOOKUPSWITCH:
           case JSOP_TABLESWITCH:
             /* Restore all saved variables. :FIXME: maybe do this precisely. */
             for (unsigned i = 0; i < savedCount; i++) {
                 LifetimeVariable &var = *saved[i];
                 var.lifetime = alloc.new_<Lifetime>(offset, var.savedEnd, var.saved);
                 if (!var.lifetime) {
-                    cx->free_(saved);
+                    js_free(saved);
                     setOOM(cx);
                     return;
                 }
                 var.saved = NULL;
                 saved[i--] = saved[--savedCount];
             }
             savedCount = 0;
             break;
@@ -861,17 +861,17 @@ ScriptAnalysis::analyzeLifetimes(JSConte
                  * need to prune the last block in the loop --- we do not
                  * track 'continue' statements for outer loops.
                  */
                 if (loop && loop->entry > loop->lastBlock)
                     loop->lastBlock = loop->entry;
 
                 LoopAnalysis *nloop = alloc.new_<LoopAnalysis>();
                 if (!nloop) {
-                    cx->free_(saved);
+                    js_free(saved);
                     setOOM(cx);
                     return;
                 }
                 PodZero(nloop);
 
                 if (loop)
                     loop->hasCallsLoops = true;
 
@@ -911,17 +911,17 @@ ScriptAnalysis::analyzeLifetimes(JSConte
                     JS_ASSERT(!var.lifetime && var.saved);
                     if (var.live(targetOffset)) {
                         /*
                          * Jumping to a place where this variable is live. Make a new
                          * lifetime segment for the variable.
                          */
                         var.lifetime = alloc.new_<Lifetime>(offset, var.savedEnd, var.saved);
                         if (!var.lifetime) {
-                            cx->free_(saved);
+                            js_free(saved);
                             setOOM(cx);
                             return;
                         }
                         var.saved = NULL;
                         saved[i--] = saved[--savedCount];
                     } else if (loop && !var.savedEnd) {
                         /*
                          * This jump precedes the basic block which killed the variable,
@@ -934,17 +934,17 @@ ScriptAnalysis::analyzeLifetimes(JSConte
                     }
                 }
             }
         }
 
         offset--;
     }
 
-    cx->free_(saved);
+    js_free(saved);
 
     ranLifetimes_ = true;
 }
 
 #ifdef JS_METHODJIT_SPEW
 void
 LifetimeVariable::print() const
 {
@@ -1202,17 +1202,17 @@ ScriptAnalysis::analyzeSSA(JSContext *cx
     if (!values) {
         setOOM(cx);
         return;
     }
     struct FreeSSAValues {
         JSContext *cx;
         SSAValueInfo *values;
         FreeSSAValues(JSContext *cx, SSAValueInfo *values) : cx(cx), values(values) {}
-        ~FreeSSAValues() { cx->free_(values); }
+        ~FreeSSAValues() { js_free(values); }
     } free(cx, values);
 
     SSAValueInfo *stack = values + numSlots;
     uint32_t stackDepth = 0;
 
     for (uint32_t slot = ArgSlot(0); slot < numSlots; slot++) {
         if (trackSlot(slot))
             values[slot].v.initInitial(slot);
@@ -1848,32 +1848,32 @@ ScriptAnalysis::freezeNewValues(JSContex
 {
     Bytecode &code = getCode(offset);
 
     Vector<SlotValue> *pending = code.pendingValues;
     code.pendingValues = NULL;
 
     unsigned count = pending->length();
     if (count == 0) {
-        cx->delete_(pending);
+        js_delete(pending);
         return;
     }
 
     code.newValues = cx->analysisLifoAlloc().newArray<SlotValue>(count + 1);
     if (!code.newValues) {
         setOOM(cx);
         return;
     }
 
     for (unsigned i = 0; i < count; i++)
         code.newValues[i] = (*pending)[i];
     code.newValues[count].slot = 0;
     code.newValues[count].value.clear();
 
-    cx->delete_(pending);
+    js_delete(pending);
 }
 
 bool
 ScriptAnalysis::needsArgsObj(JSContext *cx, SeenVector &seen, const SSAValue &v)
 {
     /*
      * trackUseChain is false for initial values of variables, which
      * cannot hold the script's arguments object.
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -431,17 +431,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;
-            cx->free_(map);
+            js_free(map);
             return;
         }
         mpp = &map->next;
     }
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
@@ -900,17 +900,17 @@ JSRuntime::init(uint32_t maxbytes)
     const char *size = getenv("JSGC_MARK_STACK_LIMIT");
     if (size)
         SetMarkStackLimit(this, atoi(size));
 
     if (!(atomsCompartment = this->new_<JSCompartment>(this)) ||
         !atomsCompartment->init(NULL) ||
         !compartments.append(atomsCompartment))
     {
-        Foreground::delete_(atomsCompartment);
+        js_delete(atomsCompartment);
         return false;
     }
 
     atomsCompartment->isSystemCompartment = true;
     atomsCompartment->setGCLastBytes(8192, 8192, GC_NORMAL);
 
     if (!InitAtomState(this))
         return false;
@@ -933,31 +933,31 @@ JSRuntime::init(uint32_t maxbytes)
         return false;
 #endif
 
     if (!evalCache.init())
         return false;
 
     debugScopes = this->new_<DebugScopes>(this);
     if (!debugScopes || !debugScopes->init()) {
-        Foreground::delete_(debugScopes);
+        js_delete(debugScopes);
         return false;
     }
 
     nativeStackBase = GetNativeStackBase();
     return true;
 }
 
 JSRuntime::~JSRuntime()
 {
 #ifdef JS_THREADSAFE
     clearOwnerThread();
 #endif
 
-    delete_(debugScopes);
+    js_delete(debugScopes);
 
     /*
      * Even though all objects in the compartment are dead, we may have keep
      * some filenames around because of gcKeepAtoms.
      */
     FreeScriptFilenames(this);
 
 #ifdef JS_THREADSAFE
@@ -987,22 +987,22 @@ JSRuntime::~JSRuntime()
         js_DestroyDtoaState(dtoaState);
 
     js_FinishGC(this);
 #ifdef JS_THREADSAFE
     if (gcLock)
         PR_DestroyLock(gcLock);
 #endif
 
-    delete_(bumpAlloc_);
-    delete_(mathCache_);
+    js_delete(bumpAlloc_);
+    js_delete(mathCache_);
 #ifdef JS_METHODJIT
-    delete_(jaegerRuntime_);
+    js_delete(jaegerRuntime_);
 #endif
-    delete_(execAlloc_);  /* Delete after jaegerRuntime_. */
+    js_delete(execAlloc_);  /* Delete after jaegerRuntime_. */
 }
 
 #ifdef JS_THREADSAFE
 void
 JSRuntime::setOwnerThread()
 {
     JS_ASSERT(ownerThread_ == (void *)0xc1ea12);  /* "clear" */
     JS_ASSERT(requestDepth == 0);
@@ -1082,34 +1082,34 @@ JS_NewRuntime(uint32_t maxbytes)
         InitMemorySubsystem();
 
         if (!JS::TlsRuntime.init())
             return NULL;
 
         js_NewRuntimeWasCalled = JS_TRUE;
     }
 
-    JSRuntime *rt = OffTheBooks::new_<JSRuntime>();
+    JSRuntime *rt = js_new<JSRuntime>();
     if (!rt)
         return NULL;
 
     if (!rt->init(maxbytes)) {
         JS_DestroyRuntime(rt);
         return NULL;
     }
 
     Probes::createRuntime(rt);
     return rt;
 }
 
 JS_PUBLIC_API(void)
 JS_DestroyRuntime(JSRuntime *rt)
 {
     Probes::destroyRuntime(rt);
-    Foreground::delete_(rt);
+    js_delete(rt);
 }
 
 JS_PUBLIC_API(void)
 JS_ShutDown(void)
 {
     Probes::shutdown();
     PRMJ_NowShutdown();
 }
@@ -2305,17 +2305,17 @@ JS_realloc(JSContext *cx, void *p, size_
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     return cx->realloc_(p, nbytes);
 }
 
 JS_PUBLIC_API(void)
 JS_free(JSContext *cx, void *p)
 {
-    return cx->free_(p);
+    return js_free(p);
 }
 
 JS_PUBLIC_API(void)
 JS_freeop(JSFreeOp *fop, void *p)
 {
     return FreeOp::get(fop)->free_(p);
 }
 
@@ -2767,17 +2767,17 @@ DumpNotify(JSTracer *trc, void **thingp,
             dtrc->ok = false;
             return;
         }
     }
 
     const char *edgeName = JS_GetTraceEdgeName(&dtrc->base, dtrc->buffer, sizeof(dtrc->buffer));
     size_t edgeNameSize = strlen(edgeName) + 1;
     size_t bytes = offsetof(JSHeapDumpNode, edgeName) + edgeNameSize;
-    JSHeapDumpNode *node = (JSHeapDumpNode *) OffTheBooks::malloc_(bytes);
+    JSHeapDumpNode *node = (JSHeapDumpNode *) js_malloc(bytes);
     if (!node) {
         dtrc->ok = false;
         return;
     }
 
     node->thing = thing;
     node->kind = kind;
     node->next = NULL;
@@ -2911,17 +2911,17 @@ JS_DumpHeap(JSRuntime *rt, FILE *fp, voi
                 }
             }
         }
 
         /* Move to next or parents next and free the node. */
         for (;;) {
             next = node->next;
             parent = node->parent;
-            Foreground::free_(node);
+            js_free(node);
             node = next;
             if (node)
                 break;
             if (!parent)
                 return dtrc.ok;
             JS_ASSERT(depth > 1);
             --depth;
             node = parent;
@@ -5222,17 +5222,17 @@ JS::Compile(JSContext *cx, HandleObject 
     if (options.utf8)
         chars = InflateString(cx, bytes, &length, CESU8Encoding);
     else
         chars = InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
 
     JSScript *script = Compile(cx, obj, options, chars, length);
-    cx->free_(chars);
+    js_free(chars);
     return script;
 }
 
 JSScript *
 JS::Compile(JSContext *cx, HandleObject obj, CompileOptions options, FILE *fp)
 {
     FileContents buffer(cx);
     if (!ReadCompleteFile(cx, fp, buffer))
@@ -5390,17 +5390,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);
         }
     }
-    cx->free_(chars);
+    js_free(chars);
     JS_RestoreExceptionState(cx, exnState);
     return result;
 }
 
 JS_PUBLIC_API(JSScript *)
 JS_CompileUTF8File(JSContext *cx, JSObject *objArg, const char *filename)
 {
     RootedObject obj(cx, objArg);
@@ -5514,17 +5514,17 @@ JS::CompileFunction(JSContext *cx, Handl
     if (options.utf8)
         chars = InflateString(cx, bytes, &length, CESU8Encoding);
     else
         chars = InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
 
     JSFunction *fun = CompileFunction(cx, obj, options, name, nargs, argnames, chars, length);
-    cx->free_(chars);
+    js_free(chars);
     return fun;
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_CompileUCFunctionForPrincipalsVersion(JSContext *cx, JSObject *obj_,
                                          JSPrincipals *principals, const char *name,
                                          unsigned nargs, const char **argnames,
                                          const jschar *chars, size_t length,
@@ -5710,17 +5710,17 @@ JS::Evaluate(JSContext *cx, HandleObject
     if (options.utf8)
         chars = InflateString(cx, bytes, &length, CESU8Encoding);
     else
         chars = InflateString(cx, bytes, &length);
     if (!chars)
         return false;
 
     bool ok = Evaluate(cx, obj, options, chars, length, rval);
-    cx->free_(chars);
+    js_free(chars);
     return ok;
 }
 
 extern JS_PUBLIC_API(bool)
 JS::Evaluate(JSContext *cx, HandleObject obj, CompileOptions options,
              const char *filename, jsval *rval)
 {
     FileContents buffer(cx);
@@ -6015,17 +6015,17 @@ JS_NewStringCopyZ(JSContext *cx, const c
     if (!s || !*s)
         return cx->runtime->emptyString;
     n = strlen(s);
     js = InflateString(cx, s, &n);
     if (!js)
         return NULL;
     str = js_NewString(cx, js, n);
     if (!str)
-        cx->free_(js);
+        js_free(js);
     return str;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_StringHasBeenInterned(JSContext *cx, JSString *str)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
@@ -6456,17 +6456,17 @@ JS_StructuredClone(JSContext *cx, jsval 
     return buf.write(cx, v, callbacks, closure) &&
            buf.read(cx, vp, callbacks, closure);
 }
 
 void
 JSAutoStructuredCloneBuffer::clear()
 {
     if (data_) {
-        Foreground::free_(data_);
+        js_free(data_);
         data_ = NULL;
         nbytes_ = 0;
         version_ = 0;
     }
 }
 
 void
 JSAutoStructuredCloneBuffer::adopt(uint64_t *data, size_t nbytes, uint32_t version)
@@ -6475,17 +6475,17 @@ JSAutoStructuredCloneBuffer::adopt(uint6
     data_ = data;
     nbytes_ = nbytes;
     version_ = version;
 }
 
 bool
 JSAutoStructuredCloneBuffer::copy(const uint64_t *srcData, size_t nbytes, uint32_t version)
 {
-    uint64_t *newData = static_cast<uint64_t *>(OffTheBooks::malloc_(nbytes));
+    uint64_t *newData = static_cast<uint64_t *>(js_malloc(nbytes));
     if (!newData)
         return false;
 
     js_memcpy(newData, srcData, nbytes);
 
     clear();
     data_ = newData;
     nbytes_ = nbytes;
@@ -6771,17 +6771,17 @@ JS_NewRegExpObject(JSContext *cx, JSObje
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     jschar *chars = InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
 
     RegExpStatics *res = obj->asGlobal().getRegExpStatics();
     RegExpObject *reobj = RegExpObject::create(cx, res, chars, length, RegExpFlag(flags), NULL);
-    cx->free_(chars);
+    js_free(chars);
     return reobj;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_NewUCRegExpObject(JSContext *cx, JSObject *objArg, jschar *chars, size_t length, unsigned flags)
 {
     RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
@@ -6830,17 +6830,17 @@ JS_PUBLIC_API(JSObject *)
 JS_NewRegExpObjectNoStatics(JSContext *cx, char *bytes, size_t length, unsigned flags)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     jschar *chars = InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
     RegExpObject *reobj = RegExpObject::createNoStatics(cx, chars, length, RegExpFlag(flags), NULL);
-    cx->free_(chars);
+    js_free(chars);
     return reobj;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_NewUCRegExpObjectNoStatics(JSContext *cx, jschar *chars, size_t length, unsigned flags)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
@@ -6990,17 +6990,17 @@ JS_DropExceptionState(JSContext *cx, JSE
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     if (state) {
         if (state->throwing && JSVAL_IS_GCTHING(state->exception)) {
             assertSameCompartment(cx, state->exception);
             JS_RemoveValueRoot(cx, &state->exception);
         }
-        cx->free_(state);
+        js_free(state);
     }
 }
 
 JS_PUBLIC_API(JSErrorReport *)
 JS_ErrorFromException(JSContext *cx, jsval v)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -5757,34 +5757,34 @@ class JSAutoByteString {
     }
 
     JSAutoByteString(JS_GUARD_OBJECT_NOTIFIER_PARAM0)
       : mBytes(NULL) {
         JS_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
     ~JSAutoByteString() {
-        js::UnwantedForeground::free_(mBytes);
+        js_free(mBytes);
     }
 
     /* Take ownership of the given byte array. */
     void initBytes(char *bytes) {
         JS_ASSERT(!mBytes);
         mBytes = bytes;
     }
 
     char *encode(JSContext *cx, JSString *str) {
         JS_ASSERT(!mBytes);
         JS_ASSERT(cx);
         mBytes = JS_EncodeString(cx, str);
         return mBytes;
     }
 
     void clear() {
-        js::UnwantedForeground::free_(mBytes);
+        js_free(mBytes);
         mBytes = NULL;
     }
 
     char *ptr() const {
         return mBytes;
     }
 
     bool operator!() const {
@@ -6033,27 +6033,27 @@ JS_ReportOutOfMemory(JSContext *cx);
  * Complain when an allocation size overflows the maximum supported limit.
  */
 extern JS_PUBLIC_API(void)
 JS_ReportAllocationOverflow(JSContext *cx);
 
 struct JSErrorReport {
     const char      *filename;      /* source file name, URL, etc., or null */
     JSPrincipals    *originPrincipals; /* see 'originPrincipals' comment above */
-    unsigned           lineno;         /* source line number */
+    unsigned        lineno;         /* source line number */
     const char      *linebuf;       /* offending source line without final \n */
     const char      *tokenptr;      /* pointer to error token in linebuf */
     const jschar    *uclinebuf;     /* unicode (original) line buffer */
     const jschar    *uctokenptr;    /* unicode (original) token pointer */
-    unsigned           flags;          /* error/warning, etc. */
-    unsigned           errorNumber;    /* the error number, e.g. see js.msg */
+    unsigned        flags;          /* error/warning, etc. */
+    unsigned        errorNumber;    /* the error number, e.g. see js.msg */
     const jschar    *ucmessage;     /* the (default) error message */
     const jschar    **messageArgs;  /* arguments for the error message */
     int16_t         exnType;        /* One of the JSExnType constants */
-    unsigned           column;         /* zero-based column index in line */
+    unsigned        column;         /* zero-based column index in line */
 };
 
 /*
  * JSErrorReport flag values.  These may be freely composed.
  */
 #define JSREPORT_ERROR      0x0     /* pseudo-flag for default case */
 #define JSREPORT_WARNING    0x1     /* reported via JS_ReportWarning */
 #define JSREPORT_EXCEPTION  0x2     /* exception was thrown */
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1320,17 +1320,17 @@ JSObject::makeDenseArraySlow(JSContext *
 
     /*
      * Begin with the length property to share more of the property tree.
      * The getter/setter here will directly access the object's private value.
      */
     if (!AddLengthProperty(cx, obj)) {
         obj->shape_ = oldShape;
         if (obj->elements != emptyObjectElements)
-            cx->free_(obj->getElementsHeader());
+            js_free(obj->getElementsHeader());
         obj->elements = elems;
         return false;
     }
 
     /*
      * Create new properties pointing to existing elements. Pack the array to
      * remove holes, so that shapes use successive slots (as for other objects).
      */
@@ -1340,30 +1340,30 @@ JSObject::makeDenseArraySlow(JSContext *
         jsid id;
         JS_ALWAYS_TRUE(ValueToId(cx, Int32Value(i), &id));
 
         if (elems[i].isMagic(JS_ARRAY_HOLE))
             continue;
 
         if (!obj->addDataProperty(cx, id, next, JSPROP_ENUMERATE)) {
             obj->shape_ = oldShape;
-            cx->free_(obj->getElementsHeader());
+            js_free(obj->getElementsHeader());
             obj->elements = elems;
             return false;
         }
 
         obj->initSlot(next, elems[i]);
 
         next++;
     }
 
     ObjectElements *oldheader = ObjectElements::fromElements(elems);
 
     obj->getElementsHeader()->length = oldheader->length;
-    cx->free_(oldheader);
+    js_free(oldheader);
 
     return true;
 }
 
 #if JS_HAS_TOSOURCE
 JS_ALWAYS_INLINE bool
 IsArray(const Value &v)
 {
@@ -3732,26 +3732,26 @@ js_ArrayInfo(JSContext *cx, unsigned arg
         RootedValue arg(cx, args[i]);
 
         char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, arg, NullPtr());
         if (!bytes)
             return JS_FALSE;
         if (arg.isPrimitive() ||
             !(array = arg.toObjectOrNull())->isArray()) {
             fprintf(stderr, "%s: not array\n", bytes);
-            cx->free_(bytes);
+            js_free(bytes);
             continue;
         }
         fprintf(stderr, "%s: %s (len %u", bytes,
                 array->isDenseArray() ? "dense" : "sparse",
                 array->getArrayLength());
         if (array->isDenseArray()) {
             fprintf(stderr, ", capacity %u",
                     array->getDenseArrayCapacity());
         }
         fputs(")\n", stderr);
-        cx->free_(bytes);
+        js_free(bytes);
     }
 
     args.rval().setUndefined();
     return true;
 }
 #endif
--- a/js/src/jsatom.cpp
+++ b/js/src/jsatom.cpp
@@ -379,17 +379,17 @@ js::Atomize(JSContext *cx, const char *b
         chars = InflateString(cx, bytes, &inflatedLength, fc);
         if (!chars)
             return NULL;
         ocb = TakeCharOwnership;
     }
 
     JSAtom *atom = AtomizeInline(cx, &chars, inflatedLength, ib, ocb);
     if (ocb == TakeCharOwnership && chars)
-        cx->free_((void *)chars);
+        js_free((void *)chars);
     return atom;
 }
 
 JSAtom *
 js::AtomizeChars(JSContext *cx, const jschar *chars, size_t length, InternBehavior ib)
 {
     CHECK_REQUEST(cx);
 
@@ -501,17 +501,17 @@ js::XDRAtom(XDRState<mode> *xdr, JSAtom 
         chars = static_cast<jschar *>(cx->runtime->malloc_(nchars * sizeof(jschar)));
         if (!chars)
             return false;
     }
 
     JS_ALWAYS_TRUE(xdr->codeChars(chars, nchars));
     atom = AtomizeChars(cx, chars, nchars);
     if (chars != stackChars)
-        Foreground::free_(chars);
+        js_free(chars);
 #endif /* !IS_LITTLE_ENDIAN */
 
     if (!atom)
         return false;
     *atomp = atom;
     return true;
 }
 
--- a/js/src/jsclone.cpp
+++ b/js/src/jsclone.cpp
@@ -602,17 +602,17 @@ JSStructuredCloneReader::checkDouble(dou
     return true;
 }
 
 class Chars {
     JSContext *cx;
     jschar *p;
   public:
     Chars(JSContext *cx) : cx(cx), p(NULL) {}
-    ~Chars() { if (p) cx->free_(p); }
+    ~Chars() { if (p) js_free(p); }
 
     bool allocate(size_t len) {
         JS_ASSERT(!p);
         // We're going to null-terminate!
         p = (jschar *) cx->malloc_((len + 1) * sizeof(jschar));
         if (p) {
             p[len] = jschar(0);
             return true;
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -180,61 +180,61 @@ JSRuntime::setJitHardening(bool enabled)
 JSC::ExecutableAllocator *
 JSRuntime::createExecutableAllocator(JSContext *cx)
 {
     JS_ASSERT(!execAlloc_);
     JS_ASSERT(cx->runtime == this);
 
     JSC::AllocationBehavior randomize =
         jitHardening ? JSC::AllocationCanRandomize : JSC::AllocationDeterministic;
-    execAlloc_ = new_<JSC::ExecutableAllocator>(randomize);
+    execAlloc_ = js_new<JSC::ExecutableAllocator>(randomize);
     if (!execAlloc_)
         js_ReportOutOfMemory(cx);
     return execAlloc_;
 }
 
 WTF::BumpPointerAllocator *
 JSRuntime::createBumpPointerAllocator(JSContext *cx)
 {
     JS_ASSERT(!bumpAlloc_);
     JS_ASSERT(cx->runtime == this);
 
-    bumpAlloc_ = new_<WTF::BumpPointerAllocator>();
+    bumpAlloc_ = js_new<WTF::BumpPointerAllocator>();
     if (!bumpAlloc_)
         js_ReportOutOfMemory(cx);
     return bumpAlloc_;
 }
 
 MathCache *
 JSRuntime::createMathCache(JSContext *cx)
 {
     JS_ASSERT(!mathCache_);
     JS_ASSERT(cx->runtime == this);
 
-    MathCache *newMathCache = new_<MathCache>();
+    MathCache *newMathCache = js_new<MathCache>();
     if (!newMathCache) {
         js_ReportOutOfMemory(cx);
         return NULL;
     }
 
     mathCache_ = newMathCache;
     return mathCache_;
 }
 
 #ifdef JS_METHODJIT
 mjit::JaegerRuntime *
 JSRuntime::createJaegerRuntime(JSContext *cx)
 {
     JS_ASSERT(!jaegerRuntime_);
     JS_ASSERT(cx->runtime == this);
 
-    mjit::JaegerRuntime *jr = new_<mjit::JaegerRuntime>();
+    mjit::JaegerRuntime *jr = js_new<mjit::JaegerRuntime>();
     if (!jr || !jr->init(cx)) {
         js_ReportOutOfMemory(cx);
-        delete_(jr);
+        js_delete(jr);
         return NULL;
     }
 
     jaegerRuntime_ = jr;
     return jaegerRuntime_;
 }
 #endif
 
@@ -329,24 +329,24 @@ JSRuntime::cloneSelfHostedValueById(JSCo
     return true;
 }
 
 JSContext *
 js::NewContext(JSRuntime *rt, size_t stackChunkSize)
 {
     JS_AbortIfWrongThread(rt);
 
-    JSContext *cx = OffTheBooks::new_<JSContext>(rt);
+    JSContext *cx = js_new<JSContext>(rt);
     if (!cx)
         return NULL;
 
     JS_ASSERT(cx->findVersion() == JSVERSION_DEFAULT);
 
     if (!cx->cycleDetectorSet.init()) {
-        Foreground::delete_(cx);
+        js_delete(cx);
         return NULL;
     }
 
     /*
      * Here the GC lock is still held after js_InitContextThreadAndLockGC took it and
      * the GC is not running on another thread.
      */
     bool first = JS_CLIST_IS_EMPTY(&rt->contextList);
@@ -434,17 +434,17 @@ js::DestroyContext(JSContext *cx, Destro
 
         PrepareForFullGC(rt);
         GC(rt, GC_NORMAL, gcreason::LAST_CONTEXT);
     } else if (mode == DCM_FORCE_GC) {
         JS_ASSERT(!rt->isHeapBusy());
         PrepareForFullGC(rt);
         GC(rt, GC_NORMAL, gcreason::DESTROY_CONTEXT);
     }
-    Foreground::delete_(cx);
+    js_delete(cx);
 }
 
 namespace js {
 
 bool
 AutoResolving::alreadyStartedSlow() const
 {
     JS_ASSERT(link);
@@ -648,18 +648,18 @@ js_ReportErrorVA(JSContext *cx, unsigned
     report.flags = flags;
     report.errorNumber = JSMSG_USER_DEFINED_ERROR;
     report.ucmessage = ucmessage = InflateString(cx, message, &messagelen);
     PopulateReportBlame(cx, &report);
 
     warning = JSREPORT_IS_WARNING(report.flags);
 
     ReportError(cx, message, &report, NULL, NULL);
-    Foreground::free_(message);
-    Foreground::free_(ucmessage);
+    js_free(message);
+    js_free(ucmessage);
     return warning;
 }
 
 namespace js {
 
 /* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */
 void
 ReportUsageError(JSContext *cx, HandleObject callee, const char *msg)
@@ -844,17 +844,17 @@ js_ExpandErrorArguments(JSContext *cx, J
 
                 /*
                 * Note - the above calculation assumes that each argument
                 * is used once and only once in the expansion !!!
                 */
                 reportp->ucmessage = out = (jschar *)
                     cx->malloc_((expandedLength + 1) * sizeof(jschar));
                 if (!out) {
-                    cx->free_(buffer);
+                    js_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],
@@ -864,17 +864,17 @@ js_ExpandErrorArguments(JSContext *cx, J
                             expandedArgs++;
                             continue;
                         }
                     }
                     *out++ = *fmt++;
                 }
                 JS_ASSERT(expandedArgs == argCount);
                 *out = 0;
-                cx->free_(buffer);
+                js_free(buffer);
                 *messagep = DeflateString(cx, reportp->ucmessage,
                                           size_t(out - reportp->ucmessage));
                 if (!*messagep)
                     goto error;
             }
         } else {
             /*
              * Zero arguments: the format string (if it exists) is the
@@ -905,27 +905,27 @@ js_ExpandErrorArguments(JSContext *cx, J
     return JS_TRUE;
 
 error:
     if (reportp->messageArgs) {
         /* free the arguments only if we allocated them */
         if (charArgs) {
             i = 0;
             while (reportp->messageArgs[i])
-                cx->free_((void *)reportp->messageArgs[i++]);
+                js_free((void *)reportp->messageArgs[i++]);
         }
-        cx->free_((void *)reportp->messageArgs);
+        js_free((void *)reportp->messageArgs);
         reportp->messageArgs = NULL;
     }
     if (reportp->ucmessage) {
-        cx->free_((void *)reportp->ucmessage);
+        js_free((void *)reportp->ucmessage);
         reportp->ucmessage = NULL;
     }
     if (*messagep) {
-        cx->free_((void *)*messagep);
+        js_free((void *)*messagep);
         *messagep = NULL;
     }
     return JS_FALSE;
 }
 
 JSBool
 js_ReportErrorNumberVA(JSContext *cx, unsigned flags, JSErrorCallback callback,
                        void *userRef, const unsigned errorNumber,
@@ -947,45 +947,45 @@ js_ReportErrorNumberVA(JSContext *cx, un
     if (!js_ExpandErrorArguments(cx, callback, userRef, errorNumber,
                                  &message, &report, !!charArgs, ap)) {
         return JS_FALSE;
     }
 
     ReportError(cx, message, &report, callback, userRef);
 
     if (message)
-        cx->free_(message);
+        js_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])
-                cx->free_((void *)report.messageArgs[i++]);
+                js_free((void *)report.messageArgs[i++]);
         }
-        cx->free_((void *)report.messageArgs);
+        js_free((void *)report.messageArgs);
     }
     if (report.ucmessage)
-        cx->free_((void *)report.ucmessage);
+        js_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)
-        Foreground::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.
@@ -1030,17 +1030,17 @@ js_ReportIsNullOrUndefined(JSContext *cx
     } else {
         JS_ASSERT(v.isNull());
         ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
                                           js_GetErrorMessage, NULL,
                                           JSMSG_UNEXPECTED_TYPE, bytes,
                                           js_null_str, NULL);
     }
 
-    cx->free_(bytes);
+    js_free(bytes);
     return ok;
 }
 
 void
 js_ReportMissingArg(JSContext *cx, HandleValue v, unsigned arg)
 {
     char argbuf[11];
     char *bytes;
@@ -1053,17 +1053,17 @@ js_ReportMissingArg(JSContext *cx, Handl
         bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK,
                                         v, atom);
         if (!bytes)
             return;
     }
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                          JSMSG_MISSING_FUN_ARG, argbuf,
                          bytes ? bytes : "");
-    cx->free_(bytes);
+    js_free(bytes);
 }
 
 JSBool
 js_ReportValueErrorFlags(JSContext *cx, unsigned flags, const unsigned errorNumber,
                          int spindex, HandleValue v, HandleString fallback,
                          const char *arg1, const char *arg2)
 {
     char *bytes;
@@ -1072,17 +1072,17 @@ js_ReportValueErrorFlags(JSContext *cx, 
     JS_ASSERT(js_ErrorFormatString[errorNumber].argCount >= 1);
     JS_ASSERT(js_ErrorFormatString[errorNumber].argCount <= 3);
     bytes = DecompileValueGenerator(cx, spindex, v, fallback);
     if (!bytes)
         return JS_FALSE;
 
     ok = JS_ReportErrorFlagsAndNumber(cx, flags, js_GetErrorMessage,
                                       NULL, errorNumber, bytes, arg1, arg2);
-    cx->free_(bytes);
+    js_free(bytes);
     return ok;
 }
 
 JSErrorFormatString js_ErrorFormatString[JSErr_Limit] = {
 #define MSG_DEF(name, number, count, exception, format) \
     { format, count, exception } ,
 #include "js.msg"
 #undef MSG_DEF
@@ -1219,27 +1219,27 @@ JSContext::JSContext(JSRuntime *rt)
 #endif
 #endif
 }
 
 JSContext::~JSContext()
 {
     /* Free the stuff hanging off of cx. */
     if (parseMapPool_)
-        Foreground::delete_(parseMapPool_);
+        js_delete(parseMapPool_);
 
     if (lastMessage)
-        Foreground::free_(lastMessage);
+        js_free(lastMessage);
 
     /* Remove any argument formatters. */
     JSArgumentFormatMap *map = argumentFormatMap;
     while (map) {
         JSArgumentFormatMap *temp = map;
         map = map->next;
-        Foreground::free_(temp);
+        js_free(temp);
     }
 
     JS_ASSERT(!resolvingList);
 }
 
 #ifdef DEBUG
 namespace JS {
 
@@ -1377,33 +1377,33 @@ JSRuntime::onOutOfMemory(void *p, size_t
 
     /*
      * Retry when we are done with the background sweeping and have stopped
      * all the allocations and released the empty GC chunks.
      */
     ShrinkGCBuffers(this);
     gcHelperThread.waitBackgroundSweepOrAllocEnd();
     if (!p)
-        p = OffTheBooks::malloc_(nbytes);
+        p = js_malloc(nbytes);
     else if (p == reinterpret_cast<void *>(1))
-        p = OffTheBooks::calloc_(nbytes);
+        p = js_calloc(nbytes);
     else
-      p = OffTheBooks::realloc_(p, nbytes);
+      p = js_realloc(p, nbytes);
     if (p)
         return p;
     if (cx)
         js_ReportOutOfMemory(cx);
     return NULL;
 }
 
 void
 JSContext::purge()
 {
     if (!activeCompilations) {
-        Foreground::delete_(parseMapPool_);
+        js_delete(parseMapPool_);
         parseMapPool_ = NULL;
     }
 }
 
 #if defined(JS_METHODJIT)
 static bool
 ComputeIsJITBroken()
 {
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -336,17 +336,23 @@ class FreeOp : public JSFreeOp {
     }
 
     bool shouldFreeLater() const {
         return shouldFreeLater_;
     }
 
     inline void free_(void* p);
 
-    JS_DECLARE_DELETE_METHODS(free_, inline)
+    template <class T>
+    inline void delete_(T *p) {
+        if (p) {
+            p->~T();
+            free_(p);
+        }
+    }
 
     static void staticAsserts() {
         /*
          * Check that JSFreeOp is the first base class for FreeOp and we can
          * reinterpret a pointer to JSFreeOp as a pointer to FreeOp without
          * any offset adjustments. JSClass::finalize <-> Class::finalize depends
          * on this.
          */
@@ -929,23 +935,17 @@ struct JSRuntime : js::RuntimeFriendFiel
          * previously allocated memory.
          */
         if (!p)
             updateMallocCounter(cx, bytes);
         void *p2 = ::js_realloc(p, bytes);
         return JS_LIKELY(!!p2) ? p2 : onOutOfMemory(p, bytes, cx);
     }
 
-    inline void free_(void* p) {
-        /* FIXME: Making this free in the background is buggy. Can it work? */
-        js::Foreground::free_(p);
-    }
-
-    JS_DECLARE_NEW_METHODS(malloc_, JS_ALWAYS_INLINE)
-    JS_DECLARE_DELETE_METHODS(free_, JS_ALWAYS_INLINE)
+    JS_DECLARE_NEW_METHODS(new_, malloc_, JS_ALWAYS_INLINE)
 
     void setGCMaxMallocBytes(size_t value);
 
     void resetGCMallocBytes() { gcMallocBytes = ptrdiff_t(gcMaxMallocBytes); }
 
     /*
      * Call this after allocating memory held by GC things, to update memory
      * pressure counters or report the OOM error if necessary. If oomError and
@@ -1115,17 +1115,17 @@ VersionIsKnown(JSVersion version)
 }
 
 inline void
 FreeOp::free_(void* p) {
     if (shouldFreeLater()) {
         runtime()->gcHelperThread.freeLater(p);
         return;
     }
-    runtime()->free_(p);
+    js_free(p);
 }
 
 } /* namespace js */
 
 struct JSContext : js::ContextFriendFields
 {
     explicit JSContext(JSRuntime *rt);
     JSContext *thisDuringConstruction() { return this; }
@@ -1411,22 +1411,17 @@ struct JSContext : js::ContextFriendFiel
     inline void* realloc_(void* p, size_t bytes) {
         return runtime->realloc_(p, bytes, this);
     }
 
     inline void* realloc_(void* p, size_t oldBytes, size_t newBytes) {
         return runtime->realloc_(p, oldBytes, newBytes, this);
     }
 
-    inline void free_(void* p) {
-        runtime->free_(p);
-    }
-
-    JS_DECLARE_NEW_METHODS(malloc_, inline)
-    JS_DECLARE_DELETE_METHODS(free_, inline)
+    JS_DECLARE_NEW_METHODS(new_, malloc_, JS_ALWAYS_INLINE)
 
     void purge();
 
     bool isExceptionPending() {
         return throwing;
     }
 
     js::Value getPendingException() {
@@ -1612,57 +1607,56 @@ class AutoKeepAtoms {
     {
         JS_GUARD_OBJECT_NOTIFIER_INIT;
         JS_KEEP_ATOMS(rt);
     }
     ~AutoKeepAtoms() { JS_UNKEEP_ATOMS(rt); }
 };
 
 class AutoReleasePtr {
-    JSContext   *cx;
     void        *ptr;
     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
 
     AutoReleasePtr(const AutoReleasePtr &other) MOZ_DELETE;
     AutoReleasePtr operator=(const AutoReleasePtr &other) MOZ_DELETE;
 
   public:
-    explicit AutoReleasePtr(JSContext *cx, void *ptr
+    explicit AutoReleasePtr(void *ptr
                             JS_GUARD_OBJECT_NOTIFIER_PARAM)
-      : cx(cx), ptr(ptr)
+      : ptr(ptr)
     {
         JS_GUARD_OBJECT_NOTIFIER_INIT;
     }
-    ~AutoReleasePtr() { cx->free_(ptr); }
+    void forget() { ptr = NULL; }
+    ~AutoReleasePtr() { js_free(ptr); }
 };
 
 /*
  * FIXME: bug 602774: cleaner API for AutoReleaseNullablePtr
  */
 class AutoReleaseNullablePtr {
-    JSContext   *cx;
     void        *ptr;
     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
 
     AutoReleaseNullablePtr(const AutoReleaseNullablePtr &other) MOZ_DELETE;
     AutoReleaseNullablePtr operator=(const AutoReleaseNullablePtr &other) MOZ_DELETE;
 
   public:
-    explicit AutoReleaseNullablePtr(JSContext *cx, void *ptr
+    explicit AutoReleaseNullablePtr(void *ptr
                                     JS_GUARD_OBJECT_NOTIFIER_PARAM)
-      : cx(cx), ptr(ptr)
+      : ptr(ptr)
     {
         JS_GUARD_OBJECT_NOTIFIER_INIT;
     }
     void reset(void *ptr2) {
         if (ptr)
-            cx->free_(ptr);
+            js_free(ptr);
         ptr = ptr2;
     }
-    ~AutoReleaseNullablePtr() { if (ptr) cx->free_(ptr); }
+    ~AutoReleaseNullablePtr() { if (ptr) js_free(ptr); }
 };
 
 } /* namespace js */
 
 class JSAutoResolveFlags
 {
   public:
     JSAutoResolveFlags(JSContext *cx, unsigned flags
@@ -2008,33 +2002,33 @@ class RuntimeAllocPolicy
 {
     JSRuntime *const runtime;
 
   public:
     RuntimeAllocPolicy(JSRuntime *rt) : runtime(rt) {}
     RuntimeAllocPolicy(JSContext *cx) : runtime(cx->runtime) {}
     void *malloc_(size_t bytes) { return runtime->malloc_(bytes); }
     void *realloc_(void *p, size_t bytes) { return runtime->realloc_(p, bytes); }
-    void free_(void *p) { runtime->free_(p); }
+    void free_(void *p) { js_free(p); }
     void reportAllocOverflow() const {}
 };
 
 /*
  * FIXME bug 647103 - replace these *AllocPolicy names.
  */
 class ContextAllocPolicy
 {
     JSContext *const cx;
 
   public:
     ContextAllocPolicy(JSContext *cx) : cx(cx) {}
     JSContext *context() const { return cx; }
     void *malloc_(size_t bytes) { return cx->malloc_(bytes); }
     void *realloc_(void *p, size_t oldBytes, size_t bytes) { return cx->realloc_(p, oldBytes, bytes); }
-    void free_(void *p) { cx->free_(p); }
+    void free_(void *p) { js_free(p); }
     void reportAllocOverflow() const { js_ReportAllocationOverflow(cx); }
 };
 
 } /* namespace js */
 
 #ifdef _MSC_VER
 #pragma warning(pop)
 #pragma warning(pop)
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -171,17 +171,17 @@ class AutoPtr
     JSContext *cx;
     T *value;
 
     AutoPtr(const AutoPtr &other) MOZ_DELETE;
 
   public:
     explicit AutoPtr(JSContext *cx) : cx(cx), value(NULL) {}
     ~AutoPtr() {
-        cx->delete_<T>(value);
+        js_delete<T>(value);
     }
 
     void operator=(T *ptr) { value = ptr; }
 
     typedef void ***** ConvertibleToBool;
     operator ConvertibleToBool() const { return (ConvertibleToBool) value; }
 
     const T *operator->() const { return value; }
@@ -546,17 +546,17 @@ JSContext::setPendingException(js::Value
     js::assertSameCompartment(this, v);
 }
 
 inline bool
 JSContext::ensureParseMapPool()
 {
     if (parseMapPool_)
         return true;
-    parseMapPool_ = js::OffTheBooks::new_<js::frontend::ParseMapPool>(this);
+    parseMapPool_ = js_new<js::frontend::ParseMapPool>(this);
     return parseMapPool_;
 }
 
 inline js::PropertyTree&
 JSContext::propertyTree()
 {
     return compartment->propertyTree;
 }
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -71,19 +71,19 @@ JSCompartment::JSCompartment(JSRuntime *
     scriptCountsMap(NULL),
     debugScriptMap(NULL)
 {
     setGCMaxMallocBytes(rt->gcMaxMallocBytes);
 }
 
 JSCompartment::~JSCompartment()
 {
-    Foreground::delete_(watchpointMap);
-    Foreground::delete_(scriptCountsMap);
-    Foreground::delete_(debugScriptMap);
+    js_delete(watchpointMap);
+    js_delete(scriptCountsMap);
+    js_delete(debugScriptMap);
 }
 
 bool
 JSCompartment::init(JSContext *cx)
 {
     activeAnalysis = activeInference = false;
     types.init(cx);
 
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -357,17 +357,17 @@ JS_GetLinePCs(JSContext *cx, JSScript *s
     jsbytecode** pcs;
     size_t len = (script->length > maxLines ? maxLines : script->length);
     lines = (unsigned*) cx->malloc_(len * sizeof(unsigned));
     if (!lines)
         return JS_FALSE;
 
     pcs = (jsbytecode**) cx->malloc_(len * sizeof(jsbytecode*));
     if (!pcs) {
-        cx->free_(lines);
+        js_free(lines);
         return JS_FALSE;
     }
 
     unsigned lineno = script->lineno;
     unsigned offset = 0;
     unsigned i = 0;
     for (jssrcnote *sn = script->notes(); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
         offset += SN_DELTA(sn);
@@ -386,22 +386,22 @@ JS_GetLinePCs(JSContext *cx, JSScript *s
             }
         }
     }
 
     *count = i;
     if (retLines)
         *retLines = lines;
     else
-        cx->free_(lines);
+        js_free(lines);
 
     if (retPCs)
         *retPCs = pcs;
     else
-        cx->free_(pcs);
+        js_free(pcs);
 
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(unsigned)
 JS_GetFunctionArgumentCount(JSContext *cx, JSFunction *fun)
 {
     return fun->nargs;
@@ -746,17 +746,17 @@ JS_EvaluateInStackFrame(JSContext *cx, J
         return JS_FALSE;
 
     chars = InflateString(cx, bytes, &len);
     if (!chars)
         return JS_FALSE;
     length = (unsigned) len;
     ok = JS_EvaluateUCInStackFrame(cx, fp, chars, length, filename, lineno,
                                    rval);
-    cx->free_(chars);
+    js_free(chars);
 
     return ok;
 }
 
 /************************************************************************/
 
 /* This all should be reworked to avoid requiring JSScopeProperty types. */
 
@@ -891,17 +891,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);
     }
-    cx->free_(pd);
+    js_free(pd);
     pda->array = NULL;
     pda->length = 0;
 }
 
 /************************************************************************/
 
 JS_PUBLIC_API(JSBool)
 JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler handler, void *closure)
@@ -1222,17 +1222,17 @@ struct RequiredStringArg {
             mBytes = JS_EncodeString(cx, JSVAL_TO_STRING(JS_ARGV(cx, vp)[argi]));
         }
     }
     operator void*() {
         return (void*) mBytes;
     }
     ~RequiredStringArg() {
         if (mBytes)
-            mCx->free_(mBytes);
+            js_free(mBytes);
     }
 };
 
 static JSBool
 StartProfiling(JSContext *cx, unsigned argc, jsval *vp)
 {
     if (argc == 0) {
         JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_StartProfiling(NULL)));
@@ -1531,17 +1531,17 @@ js_StartVtune(const char *profileName)
         char filename[strlen(profileName) + strlen("-vtune.tb5") + 1];
         snprintf(filename, sizeof(filename), "%s-vtune.tb5", profileName);
         params.tb5Filename = filename;
     }
 
     status = VTStartSampling(&params);
 
     if (params.tb5Filename != default_filename)
-        Foreground::free_(params.tb5Filename);
+        js_free(params.tb5Filename);
 
     if (status != 0) {
         if (status == VTAPI_MULTIPLE_RUNS)
             VTStopSampling(0);
         if (status < sizeof(vtuneErrorMessages))
             UnsafeError("Vtune setup error: %s", vtuneErrorMessages[status]);
         else
             UnsafeError("Vtune setup error: %d", status);
--- a/js/src/jsdhash.cpp
+++ b/js/src/jsdhash.cpp
@@ -73,23 +73,23 @@ using namespace js;
 #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_t nbytes)
 {
-    return OffTheBooks::malloc_(nbytes);
+    return js_malloc(nbytes);
 }
 
 JS_PUBLIC_API(void)
 JS_DHashFreeTable(JSDHashTable *table, void *ptr)
 {
-    UnwantedForeground::free_(ptr);
+    js_free(ptr);
 }
 
 JS_PUBLIC_API(JSDHashNumber)
 JS_DHashStringKey(JSDHashTable *table, const void *key)
 {
     JSDHashNumber h;
     const unsigned char *s;
 
@@ -142,17 +142,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;
 
-    UnwantedForeground::free_((void *) stub->key);
+    js_free((void *) stub->key);
     memset(entry, 0, table->entrySize);
 }
 
 JS_PUBLIC_API(void)
 JS_DHashFinalizeStub(JSDHashTable *table)
 {
 }
 
@@ -174,31 +174,31 @@ JS_DHashGetStubOps(void)
 }
 
 JS_PUBLIC_API(JSDHashTable *)
 JS_NewDHashTable(const JSDHashTableOps *ops, void *data, uint32_t entrySize,
                  uint32_t capacity)
 {
     JSDHashTable *table;
 
-    table = (JSDHashTable *) OffTheBooks::malloc_(sizeof *table);
+    table = (JSDHashTable *) js_malloc(sizeof *table);
     if (!table)
         return NULL;
     if (!JS_DHashTableInit(table, ops, data, entrySize, capacity)) {
-        Foreground::free_(table);
+        js_free(table);
         return NULL;
     }
     return table;
 }
 
 JS_PUBLIC_API(void)
 JS_DHashTableDestroy(JSDHashTable *table)
 {
     JS_DHashTableFinish(table);
-    UnwantedForeground::free_(table);
+    js_free(table);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DHashTableInit(JSDHashTable *table, const JSDHashTableOps *ops, void *data,
                   uint32_t entrySize, uint32_t capacity)
 {
     int log2;
     uint32_t nbytes;
--- a/js/src/jsdtoa.cpp
+++ b/js/src/jsdtoa.cpp
@@ -43,18 +43,18 @@ using namespace js;
 #define ULlong uint64_t
 #endif
 */
 
 /*
  * MALLOC gets declared external, and that doesn't work for class members, so
  * wrap.
  */
-inline void* dtoa_malloc(size_t size) { return OffTheBooks::malloc_(size); }
-inline void dtoa_free(void* p) { return UnwantedForeground::free_(p); }
+inline void* dtoa_malloc(size_t size) { return js_malloc(size); }
+inline void dtoa_free(void* p) { return js_free(p); }
 
 #define NO_GLOBAL_STATE
 #define MALLOC dtoa_malloc
 #define FREE dtoa_free
 #include "dtoa.c"
 
 /* Mapping of JSDToStrMode -> js_dtoa mode */
 static const uint8_t dtoaModes[] = {
@@ -296,17 +296,17 @@ js_dtobasestr(DtoaState *state, int base
     char *q;
     uint32_t 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*) OffTheBooks::malloc_(DTOBASESTR_BUFFER_SIZE);
+    buffer = (char*) js_malloc(DTOBASESTR_BUFFER_SIZE);
     if (!buffer)
         return NULL;
     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
@@ -340,17 +340,17 @@ js_dtobasestr(DtoaState *state, int base
         int bits;  /* Number of significant bits in di; not used. */
         Bigint *b = d2b(PASS_STATE di, &e, &bits);
         if (!b)
             goto nomem1;
         b = lshift(PASS_STATE b, e);
         if (!b) {
           nomem1:
             Bfree(PASS_STATE b);
-            UnwantedForeground::free_(buffer);
+            js_free(buffer);
             return NULL;
         }
         do {
             digit = divrem(b, base);
             JS_ASSERT(digit < (uint32_t)base);
             *p++ = BASEDIGIT(digit);
         } while (b->wds);
         Bfree(PASS_STATE b);
@@ -376,17 +376,17 @@ js_dtobasestr(DtoaState *state, int base
         b = d2b(PASS_STATE df, &e, &bbits);
         if (!b) {
           nomem2:
             Bfree(PASS_STATE b);
             Bfree(PASS_STATE s);
             if (mlo != mhi)
                 Bfree(PASS_STATE mlo);
             Bfree(PASS_STATE mhi);
-            UnwantedForeground::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_t)(word0(d) >> Exp_shift1 & Exp_mask>>Exp_shift1);
 #ifndef Sudden_Underflow
         if (!s2)
--- a/js/src/jsdtoa.h
+++ b/js/src/jsdtoa.h
@@ -98,16 +98,16 @@ js_dtostr(DtoaState *state, char *buffer
  * round-trip property (analogous to that of printing decimal numbers).  In
  * other words, if one were to read the resulting string in via a hypothetical
  * base-number-reading routine that rounds to the nearest IEEE double (and to
  * an even significand if there are two equally near doubles), then the result
  * would equal d (except for -0.0, which converts to "0", and NaN, which is
  * not equal to itself).
  *
  * Return NULL if out of memory.  If the result is not NULL, it must be
- * released via cx->free_().
+ * released via js_free().
  */
 char *
 js_dtobasestr(DtoaState *state, int base, double d);
 
 JS_END_EXTERN_C
 
 #endif /* jsdtoa_h___ */
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -316,17 +316,17 @@ InitExnPrivate(JSContext *cx, HandleObje
         /*
          * Construct a new copy of the error report struct. We can't use the
          * error report struct that was passed in, because it's allocated on
          * the stack, and also because it may point to transient data in the
          * TokenStream.
          */
         priv->errorReport = CopyErrorReport(cx, report);
         if (!priv->errorReport) {
-            cx->free_(priv);
+            js_free(priv);
             return false;
         }
     } else {
         priv->errorReport = NULL;
     }
 
     priv->message.init(message);
     priv->filename.init(filename);
@@ -1174,36 +1174,27 @@ js_CopyErrorObject(JSContext *cx, Handle
     JSExnPrivate *priv = GetExnPrivate(errobj);
 
     size_t size = offsetof(JSExnPrivate, stackElems) +
                   priv->stackDepth * sizeof(JSStackTraceElem);
 
     JSExnPrivate *copy = (JSExnPrivate *)cx->malloc_(size);
     if (!copy)
         return NULL;
+    AutoReleasePtr autoFreePrivate(copy);
 
-    struct AutoFree {
-        JSContext *cx;
-        JSExnPrivate *p;
-        ~AutoFree() {
-            if (p) {
-                cx->free_(p->errorReport);
-                cx->free_(p);
-            }
-        }
-    } autoFree = {cx, copy};
-
-    // Copy each field. Don't bother copying the stack elements.
     if (priv->errorReport) {
         copy->errorReport = CopyErrorReport(cx, priv->errorReport);
         if (!copy->errorReport)
             return NULL;
     } else {
         copy->errorReport = NULL;
     }
+    AutoReleasePtr autoFreeErrorReport(copy->errorReport);
+
     copy->message.init(priv->message);
     if (!cx->compartment->wrap(cx, &copy->message))
         return NULL;
     JS::Anchor<JSString *> messageAnchor(copy->message);
     copy->filename.init(priv->filename);
     if (!cx->compartment->wrap(cx, &copy->filename))
         return NULL;
     JS::Anchor<JSString *> filenameAnchor(copy->filename);
@@ -1215,11 +1206,12 @@ js_CopyErrorObject(JSContext *cx, Handle
     // Create the Error object.
     JSObject *proto = scope->global().getOrCreateCustomErrorPrototype(cx, copy->exnType);
     if (!proto)
         return NULL;
     JSObject *copyobj = NewObjectWithGivenProto(cx, &ErrorClass, proto, NULL);
     if (!copyobj)
         return NULL;
     SetExnPrivate(cx, copyobj, copy);
-    autoFree.p = NULL;
+    autoFreePrivate.forget();
+    autoFreeErrorReport.forget();
     return copyobj;
 }
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -1268,17 +1268,17 @@ js_FinishGC(JSRuntime *rt)
 
 #ifdef JS_GC_ZEAL
     /* Free memory associated with GC verification. */
     FinishVerifier(rt);
 #endif
 
     /* Delete all remaining Compartments. */
     for (CompartmentsIter c(rt); !c.done(); c.next())
-        Foreground::delete_(c.get());
+        js_delete(c.get());
     rt->compartments.clear();
     rt->atomsCompartment = NULL;
 
     rt->gcSystemAvailableChunkListHead = NULL;
     rt->gcUserAvailableChunkListHead = NULL;
     for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront())
         Chunk::release(rt, r.front());
     rt->gcChunkSet.clear();
@@ -3078,26 +3078,26 @@ GCHelperThread::startBackgroundAllocatio
 
 JS_FRIEND_API(void)
 GCHelperThread::replenishAndFreeLater(void *ptr)
 {
     JS_ASSERT(freeCursor == freeCursorEnd);
     do {
         if (freeCursor && !freeVector.append(freeCursorEnd - FREE_ARRAY_LENGTH))
             break;
-        freeCursor = (void **) OffTheBooks::malloc_(FREE_ARRAY_SIZE);
+        freeCursor = (void **) js_malloc(FREE_ARRAY_SIZE);
         if (!freeCursor) {
             freeCursorEnd = NULL;
             break;
         }
         freeCursorEnd = freeCursor + FREE_ARRAY_LENGTH;
         *freeCursor++ = ptr;
         return;
     } while (false);
-    Foreground::free_(ptr);
+    js_free(ptr);
 }
 
 #ifdef JS_THREADSAFE
 /* Must be called with the GC lock taken. */
 void
 GCHelperThread::doSweep()
 {
     if (sweepFlag) {
@@ -4743,17 +4743,17 @@ NewCompartment(JSContext *cx, JSPrincipa
         {
             AutoLockGC lock(rt);
             if (rt->compartments.append(compartment))
                 return compartment;
         }
 
         js_ReportOutOfMemory(cx);
     }
-    Foreground::delete_(compartment);
+    js_delete(compartment);
     return NULL;
 }
 
 void
 RunDebugGC(JSContext *cx)
 {
 #ifdef JS_GC_ZEAL
     JSRuntime *rt = cx->runtime;
@@ -4937,17 +4937,17 @@ JS::CheckStackRoots(JSContext *cx)
     uintptr_t *&oldStackData = cgcd->oldStackData;
     uintptr_t &oldStackCapacity = cgcd->oldStackCapacity;
 
     /*
      * Adjust the stack to remove regions which have not changed since the
      * stack was last scanned, and update the last scanned state.
      */
     if (stackEnd != oldStackEnd) {
-        rt->free_(oldStackData);
+        js_free(oldStackData);
         oldStackCapacity = rt->nativeStackQuota / sizeof(uintptr_t);
         oldStackData = (uintptr_t *) rt->malloc_(oldStackCapacity * sizeof(uintptr_t));
         if (!oldStackData) {
             oldStackCapacity = 0;
         } else {
             uintptr_t *existing = stackEnd - 1, *copy = oldStackData;
             while (existing >= stackMin && size_t(copy - oldStackData) < oldStackCapacity)
                 *copy++ = *existing--;
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -628,18 +628,18 @@ class GCHelperThread {
     friend struct js::gc::ArenaLists;
 
     JS_FRIEND_API(void)
     replenishAndFreeLater(void *ptr);
 
     static void freeElementsAndArray(void **array, void **end) {
         JS_ASSERT(array <= end);
         for (void **p = array; p != end; ++p)
-            js::Foreground::free_(*p);
-        js::Foreground::free_(array);
+            js_free(*p);
+        js_free(array);
     }
 
     static void threadMain(void* arg);
     void threadLoop();
 
     /* Must be called with the GC lock taken. */
     void doSweep();
 
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -2160,24 +2160,24 @@ types::ArrayPrototypeHasIndexedProperty(
 
     return false;
 }
 
 bool
 TypeCompartment::growPendingArray(JSContext *cx)
 {
     unsigned newCapacity = js::Max(unsigned(100), pendingCapacity * 2);
-    PendingWork *newArray = (PendingWork *) OffTheBooks::calloc_(newCapacity * sizeof(PendingWork));
+    PendingWork *newArray = (PendingWork *) js_calloc(newCapacity * sizeof(PendingWork));
     if (!newArray) {
         cx->compartment->types.setPendingNukeTypes(cx);
         return false;
     }
 
     PodCopy(newArray, pendingArray, pendingCount);
-    cx->free_(pendingArray);
+    js_free(pendingArray);
 
     pendingArray = newArray;
     pendingCapacity = newCapacity;
 
     return true;
 }
 
 void
@@ -3236,17 +3236,17 @@ TypeObject::clearNewScript(JSContext *cx
             if (!finished)
                 obj->rollbackProperties(cx, numProperties);
         }
     }
 
     /* We NULL out newScript *before* freeing it so the write barrier works. */
     TypeNewScript *savedNewScript = newScript;
     newScript = NULL;
-    cx->free_(savedNewScript);
+    js_free(savedNewScript);
 
     markStateChange(cx);
 }
 
 void
 TypeObject::print(JSContext *cx)
 {
     printf("%s : %s",
@@ -5925,18 +5925,18 @@ TypeCompartment::sweep(FreeOp *fop)
                     JS_ASSERT(AtomToId((JSAtom *)str) == key.ids[i]);
                 }
                 JS_ASSERT(!entry.types[i].isSingleObject());
                 if (entry.types[i].isTypeObject() && !entry.types[i].typeObject()->isMarked())
                     remove = true;
             }
 
             if (remove) {
-                Foreground::free_(key.ids);
-                Foreground::free_(entry.types);
+                js_free(key.ids);
+                js_free(entry.types);
                 e.removeFront();
             }
         }
     }
 
     if (allocationSiteTable) {
         for (AllocationSiteTable::Enum e(*allocationSiteTable); !e.empty(); e.popFront()) {
             AllocationSiteKey key = e.front().key;
@@ -6010,26 +6010,26 @@ JSCompartment::sweepNewTypeObjectTable(T
                 e.removeFront();
         }
     }
 }
 
 TypeCompartment::~TypeCompartment()
 {
     if (pendingArray)
-        Foreground::free_(pendingArray);
+        js_free(pendingArray);
 
     if (arrayTypeTable)
-        Foreground::delete_(arrayTypeTable);
+        js_delete(arrayTypeTable);
 
     if (objectTypeTable)
-        Foreground::delete_(objectTypeTable);
+        js_delete(objectTypeTable);
 
     if (allocationSiteTable)
-        Foreground::delete_(allocationSiteTable);
+        js_delete(allocationSiteTable);
 }
 
 /* static */ void
 TypeScript::Sweep(FreeOp *fop, JSScript *script)
 {
     JSCompartment *compartment = script->compartment();
     JS_ASSERT(compartment->types.inferenceEnabled);
 
@@ -6062,21 +6062,21 @@ TypeScript::Sweep(FreeOp *fop, JSScript 
     script->hasFreezeConstraints = false;
 }
 
 void
 TypeScript::destroy()
 {
     while (dynamicList) {
         TypeResult *next = dynamicList->next;
-        Foreground::delete_(dynamicList);
+        js_delete(dynamicList);
         dynamicList = next;
     }
 
-    Foreground::free_(this);
+    js_free(this);
 }
 
 /* static */ void
 TypeScript::AddFreezeConstraints(JSContext *cx, JSScript *script)
 {
     /*
      * Adding freeze constraints to a script ensures that code for the script
      * will be recompiled any time any type set for stack values in the script
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -590,17 +590,17 @@ GetIterator(JSContext *cx, HandleObject 
         // for this kind of error anyway, but it would throw an inscrutable
         // error message about |method| rather than this nice one about |obj|.
         if (!method.isObject() || !method.toObject().isCallable()) {
             RootedValue val(cx, ObjectOrNullValue(obj));
             char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, val, NullPtr());
             if (!bytes)
                 return false;
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_ITERABLE, bytes);
-            cx->free_(bytes);
+            js_free(bytes);
             return false;
         }
 
         if (!Invoke(cx, ObjectOrNullValue(obj), method, 0, NULL, vp.address()))
             return false;
 
         JSObject *obj = ToObject(cx, vp);
         if (!obj)
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -78,22 +78,22 @@ ComputeAccurateDecimalInteger(JSContext 
     }
     cstr[length] = 0;
 
     char *estr;
     int err = 0;
     *dp = js_strtod_harder(cx->runtime->dtoaState, cstr, &estr, &err);
     if (err == JS_DTOA_ENOMEM) {
         JS_ReportOutOfMemory(cx);
-        cx->free_(cstr);
+        js_free(cstr);
         return false;
     }
     if (err == JS_DTOA_ERANGE && *dp == HUGE_VAL)
         *dp = js_PositiveInfinity;
-    cx->free_(cstr);
+    js_free(cstr);
     return true;
 }
 
 class BinaryDigitReader
 {
     const int base;      /* Base of number; must be a power of 2 */
     int digit;           /* Current digit value in radix given by base */
     int digitMask;       /* Mask to extract the next bit from digit */
@@ -509,17 +509,17 @@ num_toSource(JSContext *cx, unsigned arg
 ToCStringBuf::ToCStringBuf() :dbuf(NULL)
 {
     JS_STATIC_ASSERT(sbufSize >= DTOSTR_STANDARD_BUFFER_SIZE);
 }
 
 ToCStringBuf::~ToCStringBuf()
 {
     if (dbuf)
-        UnwantedForeground::free_(dbuf);
+        js_free(dbuf);
 }
 
 JSFixedString *
 js::Int32ToString(JSContext *cx, int32_t si)
 {
     uint32_t ui;
     if (si >= 0) {
         if (StaticStrings::hasInt(si))
@@ -736,22 +736,22 @@ num_toLocaleString_impl(JSContext *cx, C
         strcpy(tmpDest, nint);
     }
 
     if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode) {
         Rooted<Value> v(cx, StringValue(str));
         bool ok = !!cx->localeCallbacks->localeToUnicode(cx, buf, v.address());
         if (ok)
             args.rval().set(v);
-        cx->free_(buf);
+        js_free(buf);
         return ok;
     }
 
     str = js_NewStringCopyN(cx, buf, buflen);
-    cx->free_(buf);
+    js_free(buf);
     if (!str)
         return false;
 
     args.rval().setString(str);
     return true;
 }
 
 JSBool
@@ -1084,19 +1084,19 @@ InitRuntimeNumberState(JSRuntime *rt)
     /*
      * We use single malloc to get the memory for all separator and grouping
      * strings.
      */
     size_t thousandsSeparatorSize = strlen(thousandsSeparator) + 1;
     size_t decimalPointSize = strlen(decimalPoint) + 1;
     size_t groupingSize = strlen(grouping) + 1;
 
-    char *storage = static_cast<char *>(OffTheBooks::malloc_(thousandsSeparatorSize +
-                                                             decimalPointSize +
-                                                             groupingSize));
+    char *storage = static_cast<char *>(js_malloc(thousandsSeparatorSize +
+                                                  decimalPointSize +
+                                                  groupingSize));
     if (!storage)
         return false;
 
     js_memcpy(storage, thousandsSeparator, thousandsSeparatorSize);
     rt->thousandsSeparator = storage;
     storage += thousandsSeparatorSize;
 
     js_memcpy(storage, decimalPoint, decimalPointSize);
@@ -1111,17 +1111,17 @@ InitRuntimeNumberState(JSRuntime *rt)
 void
 FinishRuntimeNumberState(JSRuntime *rt)
 {
     /*
      * The free also releases the memory for decimalSeparator and numGrouping
      * strings.
      */
     char *storage = const_cast<char *>(rt->thousandsSeparator);
-    Foreground::free_(storage);
+    js_free(storage);
 }
 
 } /* namespace js */
 
 JSObject *
 js_InitNumberClass(JSContext *cx, JSObject *obj)
 {
     JS_ASSERT(obj->isNative());
@@ -1542,13 +1542,13 @@ js_strtod(JSContext *cx, const jschar *s
         if (d == HUGE_VAL)
             d = js_PositiveInfinity;
         else if (d == -HUGE_VAL)
             d = js_NegativeInfinity;
     }
 
     i = estr - cstr;
     if (cstr != cbuf)
-        cx->free_(cstr);
+        js_free(cstr);
     *ep = i ? s1 + i : s;
     *dp = d;
     return JS_TRUE;
 }
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2121,17 +2121,17 @@ NewObject(JSContext *cx, Class *clasp, t
         return NULL;
 
     HeapSlot *slots;
     if (!PreallocateObjectDynamicSlots(cx, shape, &slots))
         return NULL;
 
     JSObject *obj = JSObject::create(cx, kind, shape, type, slots);
     if (!obj) {
-        cx->free_(slots);
+        js_free(slots);
         return NULL;
     }
 
     /*
      * This will cancel an already-running incremental GC from doing any more
      * slices, and it will prevent any future incremental GCs.
      */
     if (clasp->trace && !(clasp->flags & JSCLASS_IMPLEMENTS_BARRIERS))
@@ -2645,19 +2645,19 @@ struct JSObject::TradeGutsReserved {
           newafixed(0), newbfixed(0),
           newashape(NULL), newbshape(NULL),
           newaslots(NULL), newbslots(NULL)
     {}
 
     ~TradeGutsReserved()
     {
         if (newaslots)
-            cx->free_(newaslots);
+            js_free(newaslots);
         if (newbslots)
-            cx->free_(newbslots);
+            js_free(newbslots);
     }
 };
 
 bool
 JSObject::ReserveForTradeGuts(JSContext *cx, JSObject *a, JSObject *b,
                               TradeGutsReserved &reserved)
 {
     /*
@@ -2835,19 +2835,19 @@ JSObject::TradeGuts(JSContext *cx, JSObj
         for (size_t i = 0; i < acap; i++)
             reserved.avals.infallibleAppend(a->getSlot(i));
 
         for (size_t i = 0; i < bcap; i++)
             reserved.bvals.infallibleAppend(b->getSlot(i));
 
         /* Done with the dynamic slots. */
         if (a->hasDynamicSlots())
-            cx->free_(a->slots);
+            js_free(a->slots);
         if (b->hasDynamicSlots())
-            cx->free_(b->slots);
+            js_free(b->slots);
 
         void *apriv = a->hasPrivate() ? a->getPrivate() : NULL;
         void *bpriv = b->hasPrivate() ? b->getPrivate() : NULL;
 
         char tmp[sizeof(JSObject)];
         js_memcpy(&tmp, a, sizeof tmp);
         js_memcpy(a, b, sizeof tmp);
         js_memcpy(b, &tmp, sizeof tmp);
@@ -3370,17 +3370,17 @@ JSObject::shrinkSlots(JSContext *cx, uin
      */
     if (isCall())
         return;
 
     size_t oldSize = Probes::objectResizeActive() ? computedSizeOfThisSlotsElements() : 0;
     size_t newSize = oldSize - (oldCount - newCount) * sizeof(Value);
 
     if (newCount == 0) {
-        cx->free_(slots);
+        js_free(slots);
         slots = NULL;
         if (Probes::objectResizeActive())
             Probes::resizeObject(cx, this, oldSize, newSize);
         return;
     }
 
     JS_ASSERT(newCount >= SLOT_CAPACITY_MIN);
 
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -708,17 +708,17 @@ Sprinter::Sprinter(JSContext *cx)
 { }
 
 Sprinter::~Sprinter()
 {
 #ifdef DEBUG
     if (initialized)
         checkInvariants();
 #endif
-    context->free_(base);
+    js_free(base);
 }
 
 bool
 Sprinter::init()
 {
     JS_ASSERT(!initialized);
     base = (char *) context->malloc_(DefaultSize);
     if (!base)
@@ -910,17 +910,17 @@ js::Sprint(Sprinter *sp, const char *for
     va_start(ap, format);
     bp = JS_vsmprintf(format, ap);      /* XXX vsaprintf */
     va_end(ap);
     if (!bp) {
         JS_ReportOutOfMemory(sp->context);
         return -1;
     }
     offset = sp->put(bp);
-    sp->context->free_(bp);
+    js_free(bp);
     return offset;
 }
 
 const char js_EscapeMap[] = {
     '\b', 'b',
     '\f', 'f',
     '\n', 'n',
     '\r', 'r',
@@ -1101,21 +1101,20 @@ js_NewPrinter(JSContext *cx, const char 
         }
     }
     return jp;
 }
 
 void
 js_DestroyPrinter(JSPrinter *jp)
 {
-    JSContext *cx = jp->sprinter.context;
     jp->pool.freeAll();
-    Foreground::delete_(jp->localNames);
+    js_delete(jp->localNames);
     jp->sprinter.Sprinter::~Sprinter();
-    cx->free_(jp);
+    js_free(jp);
 }
 
 JSString *
 js_GetPrinterOutput(JSPrinter *jp)
 {
     JSContext *cx = jp->sprinter.context;
     return JS_NewStringCopyZ(cx, jp->sprinter.string());
 }
@@ -1177,29 +1176,29 @@ js_printf(JSPrinter *jp, const char *for
         }
         fp[cc] = '\0';
         format = fp;
     }
 
     /* Allocate temp space, convert format, and put. */
     bp = JS_vsmprintf(format, ap);      /* XXX vsaprintf */
     if (fp) {
-        jp->sprinter.context->free_(fp);
+        js_free(fp);
         format = NULL;
     }
     if (!bp) {
         JS_ReportOutOfMemory(jp->sprinter.context);
         va_end(ap);
         return -1;
     }
 
     cc = strlen(bp);
     if (jp->sprinter.put(bp, (size_t)cc) < 0)
         cc = -1;
-    jp->sprinter.context->free_(bp);
+    js_free(bp);
 
     va_end(ap);
     return cc;
 }
 
 JSBool
 js_puts(JSPrinter *jp, const char *s)
 {
@@ -1374,17 +1373,17 @@ GetOff(SprintStack *ss, unsigned i)
                                     ss->printer->fun, pc);
         if (!bytes)
             return 0;
         if (bytes != FAILED_EXPRESSION_DECOMPILER) {
             off = ss->sprinter.put(bytes);
             if (off < 0)
                 off = 0;
             ss->offsets[i] = off;
-            ss->sprinter.context->free_(bytes);
+            js_free(bytes);
             return off;
         }
 
         if (!*ss->sprinter.string()) {
             memset(ss->sprinter.stringAt(0), 0, ss->sprinter.getOffset());
             ss->offsets[i] = -1;
         }
     }
@@ -4285,17 +4284,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                 argc = GET_ARGC(pc);
                 const char **argv = (const char **)
                     cx->malloc_((size_t)(argc + 1) * sizeof *argv);
                 if (!argv)
                     return NULL;
                 jsbytecode **argbytecodes = (jsbytecode **)
                     cx->malloc_((size_t)(argc + 1) * sizeof *argbytecodes);
                 if (!argbytecodes) {
-                    cx->free_(argv);
+                    js_free(argv);
                     return NULL;
                 }
 
                 op = JSOP_SETNAME;
                 for (i = argc; i > 0; i--)
                     argv[i] = PopStrDupe(ss, op, &argbytecodes[i]);
 
                 /* Skip the JSOP_PUSHOBJ-created empty string. */
@@ -4333,18 +4332,18 @@ Decompile(SprintStack *ss, jsbytecode *p
 
                 for (i = 1; i <= argc; i++) {
                     SprintOpcode(ss, argv[i], argbytecodes[i], pc, todo);
                     if (i < argc)
                         ss->sprinter.put(", ");
                 }
                 ss->sprinter.put(rval);
 
-                cx->free_(argv);
-                cx->free_(argbytecodes);
+                js_free(argv);
+                js_free(argbytecodes);
 
                 break;
               }
 
               case JSOP_SETCALL:
                 todo = Sprint(&ss->sprinter, "");
                 break;
 
@@ -4801,17 +4800,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                      * top of ss2 because both ss and ss2 arena-allocate from
                      * cx's tempLifoAlloc
                      */
                     rval = JS_strdup(cx, PopStr(&ss2, op));
                     las.releaseEarly();
                     if (!rval)
                         return NULL;
                     todo = ss->sprinter.put(rval);
-                    cx->free_((void *)rval);
+                    js_free((void *)rval);
                     break;
                 }
 #endif /* JS_HAS_GENERATOR_EXPRS */
                 else if (sn && SN_TYPE(sn) == SRC_CONTINUE) {
                     /*
                      * Local function definitions have a lambda;setlocal;pop
                      * triple (annotated with SRC_CONTINUE) in the function
                      * prologue and a nop (annotated with SRC_FUNCDEF) at the
@@ -4923,26 +4922,26 @@ Decompile(SprintStack *ss, jsbytecode *p
                             j++;
                         }
                         pc2 += JUMP_OFFSET_LEN;
                     }
                     tmp = (TableEntry *)
                           cx->malloc_((size_t)j * sizeof *table);
                     if (tmp) {
                         MergeSort(table, size_t(j), tmp, CompareTableEntries);
-                        Foreground::free_(tmp);
+                        js_free(tmp);
                         ok = true;
                     } else {
                         ok = false;
                     }
                 }
 
                 if (ok)
                     ok = DecompileSwitch(ss, table, (unsigned)j, pc, len, off, false);
-                cx->free_(table);
+                js_free(table);
                 if (!ok)
                     return NULL;
                 todo = -2;
                 break;
               }
 
               case JSOP_LOOKUPSWITCH:
               {
@@ -4975,17 +4974,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                     off2 = GET_JUMP_OFFSET(pc2);
                     pc2 += JUMP_OFFSET_LEN;
                     table[k].key = jp->script->getConst(constIndex);
                     table[k].offset = off2;
                 }
 
                 ok = DecompileSwitch(ss, table, (unsigned)npairs, pc, len, off,
                                      JS_FALSE);
-                cx->free_(table);
+                js_free(table);
                 if (!ok)
                     return NULL;
                 todo = -2;
                 break;
               }
 
               case JSOP_CONDSWITCH:
               {
@@ -5047,17 +5046,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                  * case at the end.
                  */
                 off = JSVAL_TO_INT(table[ncases-1].key);
                 pc2 = pc + off;
                 off += GET_JUMP_OFFSET(pc2);
 
                 ok = DecompileSwitch(ss, table, (unsigned)ncases, pc, len, off,
                                      JS_TRUE);
-                cx->free_(table);
+                js_free(table);
                 if (!ok)
                     return NULL;
                 todo = -2;
                 break;
               }
 
               case JSOP_CASE:
               {
@@ -5366,17 +5365,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                 rval = JS_strdup(cx, POP_STR());
                 if (!rval)
                     return NULL;
                 todo = ss->sprinter.put("<?", 2);
                 ok = QuoteString(&ss->sprinter, atom, 0) &&
                      (*rval == '\0' ||
                       (ss->sprinter.put(" ", 1) >= 0 &&
                        ss->sprinter.put(rval)));
-                cx->free_((char *)rval);
+                js_free((char *)rval);
                 if (!ok)
                     return NULL;
                 ss->sprinter.put("?>", 2);
                 break;
 
               case JSOP_GETFUNNS:
                 todo = ss->sprinter.put(js_function_str, 8);
                 break;
@@ -5792,17 +5791,17 @@ class PCStack
     ~PCStack();
     bool init(JSContext *cx, JSScript *script, jsbytecode *pc);
     int depth() const { return depth_; }
     jsbytecode *operator[](int i) const;
 };
 
 PCStack::~PCStack()
 {
-    cx->free_(stack);
+    js_free(stack);
 }
 
 bool
 PCStack::init(JSContext *cx, JSScript *script, jsbytecode *pc)
 {
     stack = static_cast<jsbytecode **>(cx->malloc_(StackDepth(script) * sizeof(*stack)));
     if (!stack)
         return false;
@@ -6029,17 +6028,17 @@ ExpressionDecompiler::decompilePC(jsbyte
       default:
         break;
     }
     return write("(intermediate value)");
 }
 
 ExpressionDecompiler::~ExpressionDecompiler()
 {
-    cx->delete_<BindingVector>(localNames);
+    js_delete<BindingVector>(localNames);
 }
 
 bool
 ExpressionDecompiler::init()
 {
     if (!sprinter.init())
         return false;
 
@@ -6208,17 +6207,17 @@ js::DecompileValueGenerator(JSContext *c
     RootedString fallback(cx, fallbackArg);
     {
         char *result;
         if (!DecompileExpressionFromStack(cx, spindex, skipStackHits, v, &result))
             return NULL;
         if (result) {
             if (strcmp(result, "(intermediate value)"))
                 return result;
-            cx->free_(result);
+            js_free(result);
         }
     }
     if (!fallback) {
         if (v.isUndefined())
             return JS_strdup(cx, js_undefined_str); // Prevent users from seeing "(void 0)"
         fallback = js_ValueToSource(cx, v);
         if (!fallback)
             return NULL;
@@ -6300,21 +6299,21 @@ DecompileExpression(JSContext *cx, JSScr
 
     struct Guard {
         jsbytecode **pcstack;
         JSPrinter *printer;
         Guard() : pcstack(NULL), printer(NULL) {}
         ~Guard() {
             if (printer)
                 js_DestroyPrinter(printer);
-            Foreground::free_(pcstack);
+            js_free(pcstack);
         }
     } g;
 
-    g.pcstack = (jsbytecode **)OffTheBooks::malloc_(StackDepth(script) * sizeof *g.pcstack);
+    g.pcstack = (jsbytecode **)js_malloc(StackDepth(script) * sizeof *g.pcstack);
     if (!g.pcstack)
         return NULL;
 
     int pcdepth = ReconstructPCStack(cx, script, begin, g.pcstack);
     if (pcdepth < 0)
          return FAILED_EXPRESSION_DECOMPILER;
 
     g.printer = js_NewPrinter(cx, "js_DecompileValueGenerator", fun, 0, false, false, false);
--- a/js/src/jsprf.cpp
+++ b/js/src/jsprf.cpp
@@ -369,17 +369,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 = DeflateString(NULL, ws, slen);
         if (!s)
             return -1; /* JSStuffFunc error indicator. */
         result = cvt_s(ss, s, width, prec, flags);
-        UnwantedForeground::free_(s);
+        js_free(s);
     } else {
         result = cvt_s(ss, NULL, width, prec, flags);
     }
     return result;
 }
 
 /*
 ** BuildArgArray stands for Numbered Argument list Sprintf
@@ -587,17 +587,17 @@ static struct NumArgState* BuildArgArray
 
     /*
     ** third pass
     ** fill the nas[cn].ap
     */
 
     if( *rv < 0 ){
         if( nas != nasArray )
-            UnwantedForeground::free_( nas );
+            js_free( nas );
         return NULL;
     }
 
     cn = 0;
     while( cn < number ){
         if( nas[cn].type == TYPE_UNKNOWN ){
             cn++;
             continue;
@@ -624,17 +624,17 @@ static struct NumArgState* BuildArgArray
         case TYPE_WSTRING:      (void)va_arg( ap, jschar* );            break;
 
         case TYPE_INTSTR:       (void)va_arg( ap, int* );            break;
 
         case TYPE_DOUBLE:       (void)va_arg( ap, double );             break;
 
         default:
             if( nas != nasArray )
-                UnwantedForeground::free_( nas );
+                js_free( nas );
             *rv = -1;
             return NULL;
         }
 
         cn++;
     }
 
 
@@ -713,17 +713,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 ) )
-                    UnwantedForeground::free_( nas );
+                    js_free( nas );
                 return -1;
             }
 
             ap = nas[i-1].ap;
             dolPt = fmt;
             c = *fmt++;
         }
 
@@ -994,17 +994,17 @@ static int dosprintf(SprintfState *ss, c
             }
         }
     }
 
     /* Stuff trailing NUL */
     rv = (*ss->stuff)(ss, "\0", 1);
 
     if( nas && ( nas != nasArray ) ){
-        UnwantedForeground::free_( nas );
+        js_free( nas );
     }
 
     return rv;
 }
 
 /************************************************************************/
 
 static int FuncStuff(SprintfState *ss, const char *sp, uint32_t len)
@@ -1055,19 +1055,19 @@ static int GrowStuff(SprintfState *ss, c
     char *newbase;
     uint32_t 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*) OffTheBooks::realloc_(ss->base, newlen);
+            newbase = (char*) js_realloc(ss->base, newlen);
         } else {
-            newbase = (char*) OffTheBooks::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;
@@ -1096,32 +1096,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)
 {
-        Foreground::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) {
-            Foreground::free_(ss.base);
+            js_free(ss.base);
         }
         return 0;
     }
     return ss.base;
 }
 
 /*
 ** Stuff routine that discards overflow data
@@ -1210,15 +1210,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) {
-            Foreground::free_(ss.base);
+            js_free(ss.base);
         }
         return 0;
     }
     return ss.base;
 }
 
--- a/js/src/jspropertytree.cpp
+++ b/js/src/jspropertytree.cpp
@@ -41,19 +41,19 @@ PropertyTree::newShape(JSContext *cx)
         return NULL;
     }
     return shape;
 }
 
 static KidsHash *
 HashChildren(Shape *kid1, Shape *kid2)
 {
-    KidsHash *hash = OffTheBooks::new_<KidsHash>();
+    KidsHash *hash = js_new<KidsHash>();
     if (!hash || !hash->init(2)) {
-        Foreground::delete_(hash);
+        js_delete(hash);
         return NULL;
     }
 
     JS_ALWAYS_TRUE(hash->putNew(kid1, kid1));
     JS_ALWAYS_TRUE(hash->putNew(kid2, kid2));
     return hash;
 }
 
@@ -120,17 +120,17 @@ Shape::removeChild(Shape *child)
     child->parent = NULL;
 
     if (hash->count() == 1) {
         /* Convert from HASH form back to SHAPE form. */
         KidsHash::Range r = hash->all();
         Shape *otherChild = r.front();
         JS_ASSERT((r.popFront(), r.empty()));    /* No more elements! */
         kidp->setShape(otherChild);
-        js::UnwantedForeground::delete_(hash);
+        js_delete(hash);
     }
 }
 
 Shape *
 PropertyTree::getChild(JSContext *cx, Shape *parent_, uint32_t nfixed, const StackShape &child)
 {
     Shape *shape = NULL;
 
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -3280,17 +3280,17 @@ reflect_parse(JSContext *cx, uint32_t ar
         return JS_FALSE;
     }
 
     JSString *src = ToString(cx, JS_ARGV(cx, vp)[0]);
     if (!src)
         return JS_FALSE;
 
     char *filename = NULL;
-    AutoReleaseNullablePtr filenamep(cx, filename);
+    AutoReleaseNullablePtr filenamep(filename);
     uint32_t lineno = 1;
     bool loc = true;
 
     JSObject *builder = NULL;
 
     RootedValue arg(cx, argc > 1 ? JS_ARGV(cx, vp)[1] : UndefinedValue());
 
     if (!arg.isNullOrUndefined()) {
--- a/js/src/jsscope.cpp
+++ b/js/src/jsscope.cpp
@@ -123,17 +123,17 @@ Shape::hashify(JSContext *cx)
         return false;
 
     JSRuntime *rt = cx->runtime;
     ShapeTable *table = rt->new_<ShapeTable>(self->entryCount());
     if (!table)
         return false;
 
     if (!table->init(rt, self)) {
-        rt->free_(table);
+        js_free(table);
         return false;
     }
 
     self->base()->setTable(table);
     return true;
 }
 
 /*
@@ -250,17 +250,17 @@ ShapeTable::change(int log2Delta, JSCont
             Shape **spp = search(shape->propid(), true);
             JS_ASSERT(SHAPE_IS_FREE(*spp));
             *spp = shape;
         }
         oldsize--;
     }
 
     /* Finally, free the old entries storage. */
-    cx->free_(oldTable);
+    js_free(oldTable);
     return true;
 }
 
 bool
 ShapeTable::grow(JSContext *cx)
 {
     JS_ASSERT(needsToGrow());
 
--- a/js/src/jsscope.h
+++ b/js/src/jsscope.h
@@ -125,17 +125,17 @@ struct ShapeTable {
         entryCount(nentries),
         removedCount(0),
         freelist(SHAPE_INVALID_SLOT)
     {
         /* NB: entries is set by init, which must be called. */
     }
 
     ~ShapeTable() {
-        js::UnwantedForeground::free_(entries);
+        js_free(entries);
     }
 
     /* By definition, hashShift = HASH_BITS - log2(capacity). */
     uint32_t capacity() const { return JS_BIT(HASH_BITS - hashShift); }
 
     /* Computes the size of the entries array for a given capacity. */
     static size_t sizeOfEntries(size_t cap) { return cap * sizeof(Shape *); }
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -772,18 +772,18 @@ JSScript::initScriptCounts(JSContext *cx
     if (!cursor)
         return false;
 
     /* Create compartment's scriptCountsMap if necessary. */
     ScriptCountsMap *map = compartment()->scriptCountsMap;
     if (!map) {
         map = cx->new_<ScriptCountsMap>();
         if (!map || !map->init()) {
-            cx->free_(cursor);
-            cx->delete_(map);
+            js_free(cursor);
+            js_delete(map);
             return false;
         }
         compartment()->scriptCountsMap = map;
     }
 
     DebugOnly<char *> base = cursor;
 
     ScriptCounts scriptCounts;
@@ -797,18 +797,18 @@ JSScript::initScriptCounts(JSContext *cx
 #ifdef DEBUG
         scriptCounts.pcCountsVector[pc - code].capacity = capacity;
 #endif
         cursor += capacity * sizeof(double);
         next = pc + GetBytecodeLength(pc);
     }
 
     if (!map->putNew(this, scriptCounts)) {
-        cx->free_(cursor);
-        cx->delete_(map);
+        js_free(cursor);
+        js_delete(map);
         return false;
     }
     hasScriptCounts = true; // safe to set this;  we can't fail after this point
 
     JS_ASSERT(size_t(cursor - base) == bytes);
 
     /* Enable interrupts in any interpreter frames running on this script. */
     InterpreterFrames *frames;
@@ -1052,32 +1052,32 @@ SourceDataCache::lookup(ScriptSource *ss
         return p->value;
     return NULL;
 }
 
 void
 SourceDataCache::put(ScriptSource *ss, JSFixedString *str)
 {
     if (!map_) {
-        map_ = OffTheBooks::new_<Map>();
+        map_ = js_new<Map>();
         if (!map_)
             return;
         if (!map_->init()) {
             purge();
             return;
         }
     }
 
     (void) map_->put(ss, str);
 }
 
 void
 SourceDataCache::purge()
 {
-    Foreground::delete_(map_);
+    js_delete(map_);
     map_ = NULL;
 }
 
 JSFixedString *
 ScriptSource::substring(JSContext *cx, uint32_t start, uint32_t stop)
 {
     JS_ASSERT(ready());
     const jschar *chars;
@@ -1088,23 +1088,23 @@ ScriptSource::substring(JSContext *cx, u
         if (!cached) {
             const size_t nbytes = sizeof(jschar) * (length_ + 1);
             jschar *decompressed = static_cast<jschar *>(cx->malloc_(nbytes));
             if (!decompressed)
                 return NULL;
             if (!DecompressString(data.compressed, compressedLength_,
                                   reinterpret_cast<unsigned char *>(decompressed), nbytes)) {
                 JS_ReportOutOfMemory(cx);
-                cx->free_(decompressed);
+                js_free(decompressed);
                 return NULL;
             }
             decompressed[length_] = 0;
             cached = js_NewString(cx, decompressed, length_);
             if (!cached) {
-                cx->free_(decompressed);
+                js_free(decompressed);
                 return NULL;
             }
             cx->runtime->sourceDataCache.put(this, cached);
         }
         chars = cached->getChars(cx);
         JS_ASSERT(chars);
     } else {
         chars = data.source;
@@ -1168,22 +1168,22 @@ SourceCompressionToken::abort()
     cx->runtime->sourceCompressorThread.abort(this);
 #endif
 }
 
 void
 ScriptSource::destroy(JSRuntime *rt)
 {
     JS_ASSERT(ready());
-    rt->free_(data.compressed);
-    rt->free_(sourceMap_);
+    js_free(data.compressed);
+    js_free(sourceMap_);
 #ifdef DEBUG
     ready_ = false;
 #endif
-    rt->free_(this);
+    js_free(this);
 }
 
 size_t
 ScriptSource::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf)
 {
     JS_ASSERT(ready());
 
     // data is a union, but both members are pointers to allocated memory or
@@ -1222,17 +1222,17 @@ ScriptSource::performXDR(XDRState<mode> 
         size_t byteLen = compressedLength ? compressedLength : (length * sizeof(jschar));
         if (mode == XDR_DECODE) {
             data.compressed = static_cast<unsigned char *>(xdr->cx()->malloc_(byteLen));
             if (!data.compressed)
                 return false;
         }
         if (!xdr->codeBytes(data.compressed, byteLen)) {
             if (mode == XDR_DECODE) {
-                xdr->cx()->free_(data.compressed);
+                js_free(data.compressed);
                 data.compressed = NULL;
             }
             return false;
         }
         length_ = length;
         compressedLength_ = compressedLength;
         argumentsNotIncluded_ = argumentsNotIncluded;
     }
@@ -1249,17 +1249,17 @@ ScriptSource::performXDR(XDRState<mode> 
         if (mode == XDR_DECODE) {
             size_t byteLen = (sourceMapLen + 1) * sizeof(jschar);
             sourceMap_ = static_cast<jschar *>(xdr->cx()->malloc_(byteLen));
             if (!sourceMap_)
                 return false;
         }
         if (!xdr->codeChars(sourceMap_, sourceMapLen)) {
             if (mode == XDR_DECODE) {
-                xdr->cx()->free_(sourceMap_);
+                js_free(sourceMap_);
                 sourceMap_ = NULL;
             }
             return false;
         }
         sourceMap_[sourceMapLen] = '\0';
     }
 
 #ifdef DEBUG
@@ -1272,17 +1272,17 @@ ScriptSource::performXDR(XDRState<mode> 
 
 bool
 ScriptSource::setSourceMap(JSContext *cx, jschar *sourceMapURL, const char *filename)
 {
     JS_ASSERT(sourceMapURL);
     if (hasSourceMap()) {
         if (!JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING, js_GetErrorMessage, NULL,
                                           JSMSG_ALREADY_HAS_SOURCEMAP, filename)) {
-            cx->free_(sourceMapURL);
+            js_free(sourceMapURL);
             return false;
         }
     }
     sourceMap_ = sourceMapURL;
     return true;
 }
 
 const jschar *
@@ -1309,17 +1309,17 @@ js::SaveScriptFilename(JSContext *cx, co
         size_t size = offsetof(ScriptFilenameEntry, filename) + strlen(filename) + 1;
         ScriptFilenameEntry *entry = (ScriptFilenameEntry *) cx->malloc_(size);
         if (!entry)
             return NULL;
         entry->marked = false;
         strcpy(entry->filename, filename);
 
         if (!rt->scriptFilenameTable.add(p, entry)) {
-            Foreground::free_(entry);
+            js_free(entry);
             JS_ReportOutOfMemory(cx);
             return NULL;
         }
     }
 
     ScriptFilenameEntry *sfe = *p;
 #ifdef JSGC_INCREMENTAL
     /*
@@ -1340,28 +1340,28 @@ js::SweepScriptFilenames(JSRuntime *rt)
 {
     JS_ASSERT(rt->gcIsFull);
     ScriptFilenameTable &table = rt->scriptFilenameTable;
     for (ScriptFilenameTable::Enum e(table); !e.empty(); e.popFront()) {
         ScriptFilenameEntry *entry = e.front();
         if (entry->marked) {
             entry->marked = false;
         } else if (!rt->gcKeepAtoms) {
-            Foreground::free_(entry);
+            js_free(entry);
             e.removeFront();
         }
     }
 }
 
 void
 js::FreeScriptFilenames(JSRuntime *rt)
 {
     ScriptFilenameTable &table = rt->scriptFilenameTable;
     for (ScriptFilenameTable::Enum e(table); !e.empty(); e.popFront())
-        Foreground::free_(e.front());
+        js_free(e.front());
 
     table.clear();
 }
 
 /*
  * JSScript::data has a complex, manually-controlled, memory layout.
  *
  * First are some optional array headers.  They are optional because they
@@ -2121,17 +2121,17 @@ js::CloneScript(JSContext *cx, HandleObj
            .setOriginPrincipals(src->originPrincipals)
            .setCompileAndGo(src->compileAndGo)
            .setNoScriptRval(src->noScriptRval)
            .setVersion(src->getVersion());
     JSScript *dst = JSScript::Create(cx, enclosingScope, src->savedCallerFun,
                                      options, src->staticLevel,
                                      src->scriptSource(), src->sourceStart, src->sourceEnd);
     if (!dst) {
-        Foreground::free_(data);
+        js_free(data);
         return NULL;
     }
 
     dst->bindings = bindings;
 
     /* This assignment must occur before all the Rebase calls. */
     dst->data = data;
     memcpy(data, src->data, size);
@@ -2251,26 +2251,26 @@ JSScript::ensureHasDebugScript(JSContext
     if (!debug)
         return false;
 
     /* Create compartment's debugScriptMap if necessary. */
     DebugScriptMap *map = compartment()->debugScriptMap;
     if (!map) {
         map = cx->new_<DebugScriptMap>();
         if (!map || !map->init()) {
-            cx->free_(debug);
-            cx->delete_(map);
+            js_free(debug);
+            js_delete(map);
             return false;
         }
         compartment()->debugScriptMap = map;
     }
 
     if (!map->putNew(this, debug)) {
-        cx->free_(debug);
-        cx->delete_(map);
+        js_free(debug);
+        js_delete(map);
         return false;
     }
     hasDebugScript = true; // safe to set this;  we can't fail after this point
 
     /*
      * Ensure that any Interpret() instances running on this script have
      * interrupts enabled. The interrupts must stay enabled until the
      * debug state is destroyed.
@@ -2302,17 +2302,17 @@ JSScript::tryNewStepMode(JSContext *cx, 
     uint32_t prior = debug->stepMode;
     debug->stepMode = newValue;
 
     if (!prior != !newValue) {
         /* Step mode has been enabled or disabled. Alert the methodjit. */
         recompileForStepMode(cx->runtime->defaultFreeOp());
 
         if (!stepModeEnabled() && !debug->numSites)
-            cx->free_(releaseDebugScript());
+            js_free(releaseDebugScript());
     }
 
     return true;
 }
 
 bool
 JSScript::setStepModeFlag(JSContext *cx, bool step)
 {
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -187,17 +187,17 @@ str_escape(JSContext *cx, unsigned argc,
             newchars[ni++] = digits[ch & 0xF];
         }
     }
     JS_ASSERT(ni == newlength);
     newchars[newlength] = 0;
 
     JSString *retstr = js_NewString(cx, newchars, newlength);
     if (!retstr) {
-        cx->free_(newchars);
+        js_free(newchars);
         return false;
     }
 
     args.rval().setString(retstr);
     return true;
 }
 
 static inline bool
@@ -619,17 +619,17 @@ js_toLowerCase(JSContext *cx, JSString *
     jschar *news = (jschar *) cx->malloc_((n + 1) * sizeof(jschar));
     if (!news)
         return NULL;
     for (size_t i = 0; i < n; i++)
         news[i] = unicode::ToLowerCase(s[i]);
     news[n] = 0;
     str = js_NewString(cx, news, n);
     if (!str) {
-        cx->free_(news);
+        js_free(news);
         return NULL;
     }
     return str;
 }
 
 static inline bool
 ToLowerCaseHelper(JSContext *cx, CallReceiver call)
 {
@@ -686,17 +686,17 @@ js_toUpperCase(JSContext *cx, JSString *
     jschar *news = (jschar *) cx->malloc_((n + 1) * sizeof(jschar));
     if (!news)
         return NULL;
     for (size_t i = 0; i < n; i++)
         news[i] = unicode::ToUpperCase(s[i]);
     news[n] = 0;
     str = js_NewString(cx, news, n);
     if (!str) {
-        cx->free_(news);
+        js_free(news);
         return NULL;
     }
     return str;
 }
 
 static JSBool
 ToUpperCaseHelper(JSContext *cx, CallReceiver call)
 {
@@ -3187,25 +3187,25 @@ js::str_fromCharCode(JSContext *cx, unsi
         args[0].setInt32(code);
     }
     jschar *chars = (jschar *) cx->malloc_((args.length() + 1) * sizeof(jschar));
     if (!chars)
         return JS_FALSE;
     for (unsigned i = 0; i < args.length(); i++) {
         uint16_t code;
         if (!ToUint16(cx, args[i], &code)) {
-            cx->free_(chars);
+            js_free(chars);
             return JS_FALSE;
         }
         chars[i] = (jschar)code;
     }
     chars[args.length()] = 0;
     JSString *str = js_NewString(cx, chars, args.length());
     if (!str) {
-        cx->free_(chars);
+        js_free(chars);
         return JS_FALSE;
     }
 
     args.rval().setString(str);
     return JS_TRUE;
 }
 
 static JSFunctionSpec string_static_methods[] = {
@@ -3338,32 +3338,32 @@ js_NewStringCopyN(JSContext *cx, const j
 
     jschar *news = (jschar *) cx->malloc_((n + 1) * sizeof(jschar));
     if (!news)
         return NULL;
     js_strncpy(news, s, n);
     news[n] = 0;
     JSFixedString *str = js_NewString(cx, news, n);
     if (!str)
-        cx->free_(news);
+        js_free(news);
     return str;
 }
 
 JSFixedString *
 js_NewStringCopyN(JSContext *cx, const char *s, size_t n)
 {
     if (JSShortString::lengthFits(n))
         return NewShortString(cx, s, n);
 
     jschar *chars = InflateString(cx, s, &n);
     if (!chars)
         return NULL;
     JSFixedString *str = js_NewString(cx, chars, n);
     if (!str)
-        cx->free_(chars);
+        js_free(chars);
     return str;
 }
 
 JSFixedString *
 js_NewStringCopyZ(JSContext *cx, const jschar *s)
 {
     size_t n = js_strlen(s);
     if (JSShortString::lengthFits(n))
@@ -3371,17 +3371,17 @@ js_NewStringCopyZ(JSContext *cx, const j
 
     size_t m = (n + 1) * sizeof(jschar);
     jschar *news = (jschar *) cx->malloc_(m);
     if (!news)
         return NULL;
     js_memcpy(news, s, m);
     JSFixedString *str = js_NewString(cx, news, n);
     if (!str)
-        cx->free_(news);
+        js_free(news);
     return str;
 }
 
 JSFixedString *
 js_NewStringCopyZ(JSContext *cx, const char *s)
 {
     return js_NewStringCopyN(cx, s, strlen(s));
 }
@@ -3649,23 +3649,23 @@ DeflateString(JSContext *cx, const jscha
 {
     size_t nbytes, i;
     char *bytes;
 
     if (js_CStringsAreUTF8) {
         nbytes = GetDeflatedStringLength(cx, chars, nchars);
         if (nbytes == (size_t) -1)
             return NULL;
-        bytes = (char *) (cx ? cx->malloc_(nbytes + 1) : OffTheBooks::malloc_(nbytes + 1));
+        bytes = (char *) (cx ? cx->malloc_(nbytes + 1) : js_malloc(nbytes + 1));
         if (!bytes)
             return NULL;
         JS_ALWAYS_TRUE(DeflateStringToBuffer(cx, chars, nchars, bytes, &nbytes));
     } else {
         nbytes = nchars;
-        bytes = (char *) (cx ? cx->malloc_(nbytes + 1) : OffTheBooks::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;
 }
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -206,17 +206,17 @@ ArrayBufferObject::class_constructor(JSC
  * Note that some callers are allowed to pass in a NULL cx, so we allocate with
  * the cx if available and fall back to the runtime.
  */
 static ObjectElements *
 AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes, uint8_t *contents)
 {
     uint32_t size = nbytes + sizeof(ObjectElements);
     ObjectElements *newheader =
-        static_cast<ObjectElements *>(maybecx ? maybecx->calloc_(size) : OffTheBooks::calloc_(size));
+        static_cast<ObjectElements *>(maybecx ? maybecx->calloc_(size) : js_calloc(size));
     if (!newheader) {
         if (maybecx)
             js_ReportOutOfMemory(maybecx);
         return NULL;
     }
     if (contents)
         memcpy(newheader->elements(), contents, nbytes);
     return newheader;
@@ -2176,17 +2176,17 @@ class TypedArrayTemplate
                 *dest++ = NativeType(*src++);
             break;
           }
           default:
             JS_NOT_REACHED("copyFromWithOverlap with a TypedArray of unknown type");
             break;
         }
 
-        UnwantedForeground::free_(srcbuf);
+        js_free(srcbuf);
         return true;
     }
 
     static JSObject *
     createBufferWithSizeAndCount(JSContext *cx, uint32_t count)
     {
         size_t size = sizeof(NativeType);
         if (size != 0 && count >= INT32_MAX / size) {
--- a/js/src/jsutil.cpp
+++ b/js/src/jsutil.cpp
@@ -28,23 +28,23 @@
 #endif
 
 using namespace js;
 
 #if USE_ZLIB
 static void *
 zlib_alloc(void *cx, uInt items, uInt size)
 {
-    return OffTheBooks::malloc_(items * size);
+    return js_malloc(items * size);
 }
 
 static void
 zlib_free(void *cx, void *addr)
 {
-    Foreground::free_(addr);
+    js_free(addr);
 }
 
 bool
 Compressor::init()
 {
     if (inplen >= UINT32_MAX)
         return false;
     zs.zalloc = zlib_alloc;
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -237,17 +237,17 @@ WeakMap_set_impl(JSContext *cx, CallArgs
 
     Value value = (args.length() > 1) ? args[1] : UndefinedValue();
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     ObjectValueMap *map = GetObjectMap(thisObj);
     if (!map) {
         map = cx->new_<ObjectValueMap>(cx, thisObj.get());
         if (!map->init()) {
-            cx->delete_(map);
+            js_delete(map);
             JS_ReportOutOfMemory(cx);
             return false;
         }
         thisObj->setPrivate(map);
     }
 
     // Preserve wrapped native keys to prevent wrapper optimization.
     if (key->getClass()->ext.isWrappedNative) {
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -373,24 +373,24 @@ ConvertQNameToString(JSContext *cx, JSOb
         JS::Anchor<JSString *> anchor(str);
         size_t length = str->length();
         jschar *chars = (jschar *) cx->malloc_((length + 2) * sizeof(jschar));
         if (!chars)
             return NULL;
         *chars = '@';
         const jschar *strChars = str->getChars(cx);
         if (!strChars) {
-            cx->free_(chars);
+            js_free(chars);
             return NULL;
         }
         js_strncpy(chars + 1, strChars, length);
         chars[++length] = 0;
         str = js_NewString(cx, chars, length);
         if (!str) {
-            cx->free_(chars);
+            js_free(chars);
             return NULL;
         }
     }
     return str;
 }
 
 static JSBool
 qname_toString(JSContext *cx, unsigned argc, Value *vp)
@@ -857,31 +857,31 @@ static HeapPtr<T> *
 ReallocateVector(HeapPtr<T> *vector, size_t count)
 {
 #if JS_BITS_PER_WORD == 32
     if (count > ~(size_t)0 / sizeof(HeapPtr<T>))
         return NULL;
 #endif
 
     size_t size = count * sizeof(HeapPtr<T>);
-    return (HeapPtr<T> *) OffTheBooks::realloc_(vector, size);
+    return (HeapPtr<T> *) js_realloc(vector, size);
 }
 
 /* NB: called with null cx from the GC, via xml_trace => JSXMLArray::trim. */
 template<class T>
 bool
 JSXMLArray<T>::setCapacity(JSContext *cx, uint32_t newCapacity)
 {
     if (newCapacity == 0) {
         /* We could let realloc(p, 0) free this, but purify gets confused. */
         if (vector) {
             if (cx)
-                cx->free_(vector);
+                js_free(vector);
             else
-                Foreground::free_(vector);
+                js_free(vector);
         }
         vector = NULL;
     } else {
         HeapPtr<T> *tmp = ReallocateVector(vector, newCapacity);
         if (!tmp) {
             if (cx)
                 JS_ReportOutOfMemory(cx);
             return false;
@@ -1057,17 +1057,17 @@ XMLArrayTruncate(JSContext *cx, JSXMLArr
     if (length >= array->length)
         return;
 
     for (uint32_t i = length; i < array->length; i++)
         array->vector[i].~HeapPtr<T>();
 
     if (length == 0) {
         if (array->vector)
-            cx->free_(array->vector);
+            js_free(array->vector);
         vector = NULL;
     } else {
         vector = ReallocateVector(array->vector, length);
         if (!vector)
             return;
     }
 
     if (array->length > length)
@@ -1728,17 +1728,17 @@ ParseXMLSource(JSContext *cx, HandleStri
     offset = dstlen;
     js_strncpy(chars + offset, uri->chars(), urilen);
     offset += urilen;
     dstlen = length - offset + 1;
     InflateStringToBuffer(cx, middle, constrlen(middle), chars + offset, &dstlen);
     offset += dstlen;
     srcp = src->getChars(cx);
     if (!srcp) {
-        cx->free_(chars);
+        js_free(chars);
         return NULL;
     }
     js_strncpy(chars + offset, srcp, srclen);
     offset += srclen;
     dstlen = length - offset + 1;
     InflateStringToBuffer(cx, suffix, constrlen(suffix), chars + offset, &dstlen);
     chars [offset + dstlen] = 0;
 
@@ -1760,31 +1760,31 @@ ParseXMLSource(JSContext *cx, HandleStri
 
     {
         CompileOptions options(cx);
         options.setFileAndLine(filename, lineno);
         Parser parser(cx, options, chars, length, /* foldConstants = */ true);
         if (parser.init()) {
             JSObject *scopeChain = GetCurrentScopeChain(cx);
             if (!scopeChain) {
-                cx->free_(chars);
+                js_free(chars);
                 return NULL;
             }
 
             ParseNode *pn = parser.parseXMLText(scopeChain, false);
             unsigned flags;
             if (pn && GetXMLSettingFlags(cx, &flags)) {
                 AutoNamespaceArray namespaces(cx);
                 if (namespaces.array.setCapacity(cx, 1))
                     xml = ParseNodeToXML(&parser, pn, &namespaces.array, flags);
             }
         }
     }
 
-    cx->free_(chars);
+    js_free(chars);
     return xml;
 
 #undef constrlen
 }
 
 /*
  * Errata in 10.3.1, 10.4.1, and 13.4.4.24 (at least).
  *
@@ -2355,17 +2355,17 @@ GeneratePrefix(JSContext *cx, JSLinearSt
     } while (!done);
 
     if (bp == cp) {
         offset = cp - start;
         prefix = js_NewDependentString(cx, uri, offset, length);
     } else {
         prefix = js_NewString(cx, bp, newlength);
         if (!prefix)
-            cx->free_(bp);
+            js_free(bp);
     }
     return prefix;
 }
 
 static JSBool
 namespace_match(const JSObject *nsa, const JSObject *nsb)
 {
     JSLinearString *prefixa, *prefixb = nsb->getNamePrefix();
@@ -5097,17 +5097,17 @@ xml_enumerate(JSContext *cx, HandleObjec
             break;
         }
         /* FALL THROUGH */
 
       case JSENUMERATE_DESTROY:
         if (!statep->isInt32(0)) {
             cursor = (JSXMLArrayCursor<JSXML> *) statep->toPrivate();
             if (cursor)
-                cx->delete_(cursor);
+                js_delete(cursor);
         }
         statep->setNull();
         break;
     }
     return JS_TRUE;
 }
 
 static JSType
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -379,17 +379,17 @@ mjit::Compiler::scanInlineCalls(uint32_t
 }
 
 CompileStatus
 mjit::Compiler::pushActiveFrame(JSScript *script, uint32_t argc)
 {
     if (cx->runtime->profilingScripts && !script->hasScriptCounts)
         script->initScriptCounts(cx);
 
-    ActiveFrame *newa = OffTheBooks::new_<ActiveFrame>(cx);
+    ActiveFrame *newa = js_new<ActiveFrame>(cx);
     if (!newa) {
         js_ReportOutOfMemory(cx);
         return Compile_Error;
     }
 
     newa->parent = a;
     if (a)
         newa->parentPC = PC;
@@ -430,17 +430,17 @@ mjit::Compiler::pushActiveFrame(JSScript
     }
 #endif
 
     if (!frame.pushActiveFrame(script, argc)) {
         js_ReportOutOfMemory(cx);
         return Compile_Error;
     }
 
-    newa->jumpMap = (Label *)OffTheBooks::malloc_(sizeof(Label) * script->length);
+    newa->jumpMap = (Label *)js_malloc(sizeof(Label) * script->length);
     if (!newa->jumpMap) {
         js_ReportOutOfMemory(cx);
         return Compile_Error;
     }
 #ifdef DEBUG
     for (uint32_t i = 0; i < script->length; i++)
         newa->jumpMap[i] = Label();
 #endif
@@ -520,17 +520,17 @@ mjit::Compiler::performCompilation()
 
         CHECK_STATUS(checkAnalysis(outerScript));
         if (inlining())
             CHECK_STATUS(scanInlineCalls(CrossScriptSSA::OUTER_FRAME, 0));
         CHECK_STATUS(pushActiveFrame(outerScript, 0));
 
         if (outerScript->hasScriptCounts || Probes::wantNativeAddressInfo(cx)) {
             size_t length = ssa.frameLength(ssa.numFrames() - 1);
-            pcLengths = (PCLengthEntry *) OffTheBooks::calloc_(sizeof(pcLengths[0]) * length);
+            pcLengths = (PCLengthEntry *) js_calloc(sizeof(pcLengths[0]) * length);
             if (!pcLengths)
                 return Compile_Error;
         }
 
         if (chunkIndex == 0)
             CHECK_STATUS(generatePrologue());
         else
             sps.setPushed();
@@ -563,30 +563,30 @@ mjit::Compiler::ActiveFrame::ActiveFrame
     : jumpMap(NULL),
       varTypes(NULL), needReturnValue(false),
       syncReturnValue(false), returnValueDouble(false), returnSet(false),
       returnEntry(NULL), returnJumps(NULL), exitState(NULL)
 {}
 
 mjit::Compiler::ActiveFrame::~ActiveFrame()
 {
-    js::Foreground::free_(jumpMap);
+    js_free(jumpMap);
     if (varTypes)
-        js::Foreground::free_(varTypes);
+        js_free(varTypes);
 }
 
 mjit::Compiler::~Compiler()
 {
     if (outer)
-        cx->delete_(outer);
+        js_delete(outer);
     for (unsigned i = 0; i < inlineFrames.length(); i++)
-        cx->delete_(inlineFrames[i]);
+        js_delete(inlineFrames[i]);
     while (loop) {
         LoopState *nloop = loop->outer;
-        cx->delete_(loop);
+        js_delete(loop);
         loop = nloop;
     }
 }
 
 CompileStatus
 mjit::Compiler::prepareInferenceTypes(JSScript *script, ActiveFrame *a)
 {
     /*
@@ -606,18 +606,17 @@ mjit::Compiler::prepareInferenceTypes(JS
      * vars (updateVarTypes) and new phi nodes at join points.
      *
      * When we get to a branch and need to know a variable's value at the
      * branch target, we know it will either be a phi node at the target or
      * the variable's current value, as no phi node is created at the target
      * only if a variable has the same value on all incoming edges.
      */
 
-    a->varTypes = (VarType *)
-        OffTheBooks::calloc_(TotalSlots(script) * sizeof(VarType));
+    a->varTypes = (VarType *)js_calloc(TotalSlots(script) * sizeof(VarType));
     if (!a->varTypes) {
         js_ReportOutOfMemory(cx);
         return Compile_Error;
     }
 
     for (uint32_t slot = ArgSlot(0); slot < TotalSlots(script); slot++) {
         VarType &vt = a->varTypes[slot];
         vt.setTypes(types::TypeScript::SlotTypes(script, slot));
@@ -852,17 +851,17 @@ MakeJITScript(JSContext *cx, JSScript *s
             if (!chunks.append(desc))
                 return NULL;
         }
     }
 
     size_t dataSize = sizeof(JITScript)
         + (chunks.length() * sizeof(ChunkDescriptor))
         + (edges.length() * sizeof(CrossChunkEdge));
-    uint8_t *cursor = (uint8_t *) OffTheBooks::calloc_(dataSize);
+    uint8_t *cursor = (uint8_t *) js_calloc(dataSize);
     if (!cursor)
         return NULL;
 
     JITScript *jit = (JITScript *) cursor;
     cursor += sizeof(JITScript);
 
     jit->script = script;
     JS_INIT_CLIST(&jit->callers);
@@ -1350,17 +1349,17 @@ mjit::Compiler::finishThisUp()
 #endif
 #if defined JS_POLYIC
                       sizeof(ic::PICInfo) * pics.length() +
                       sizeof(ic::GetElementIC) * getElemICs.length() +
                       sizeof(ic::SetElementIC) * setElemICs.length() +
 #endif
                       0;
 
-    uint8_t *cursor = (uint8_t *)OffTheBooks::calloc_(dataSize);
+    uint8_t *cursor = (uint8_t *)js_calloc(dataSize);
     if (!cursor) {
         execPool->release();
         js_ReportOutOfMemory(cx);
         return Compile_Error;
     }
 
     JITChunk *chunk = new(cursor) JITChunk;
     cursor += sizeof(JITChunk);
@@ -1803,17 +1802,17 @@ mjit::Compiler::finishThisUp()
 
     a->mainCodeStart = size_t(result);
     a->mainCodeEnd   = size_t(result + masm.size());
     a->stubCodeStart = a->mainCodeEnd;
     a->stubCodeEnd   = a->mainCodeEnd + stubcc.size();
     if (!Probes::registerMJITCode(cx, chunk,
                                   a, (JSActiveFrame**) inlineFrames.begin())) {
         execPool->release();
-        cx->free_(chunk);
+        js_free(chunk);
         js_ReportOutOfMemory(cx);
         return Compile_Error;
     }
 
     outerChunkRef().chunk = chunk;
 
     /* Patch all incoming and outgoing cross-chunk jumps. */
     CrossChunkEdge *crossEdges = jit->edges();
@@ -1821,35 +1820,35 @@ mjit::Compiler::finishThisUp()
         CrossChunkEdge &edge = crossEdges[i];
         if (bytecodeInChunk(outerScript->code + edge.source)) {
             JS_ASSERT(!edge.sourceJump1 && !edge.sourceJump2);
             void *label = edge.targetLabel ? edge.targetLabel : edge.shimLabel;
             CodeLocationLabel targetLabel(label);
             JSOp op = JSOp(script->code[edge.source]);
             if (op == JSOP_TABLESWITCH) {
                 if (edge.jumpTableEntries)
-                    cx->free_(edge.jumpTableEntries);
+                    js_free(edge.jumpTableEntries);
                 CrossChunkEdge::JumpTableEntryVector *jumpTableEntries = NULL;
                 bool failed = false;
                 for (unsigned j = 0; j < chunkJumps.length(); j++) {
                     ChunkJumpTableEdge nedge = chunkJumps[j];
                     if (nedge.edge.source == edge.source && nedge.edge.target == edge.target) {
                         if (!jumpTableEntries) {
-                            jumpTableEntries = OffTheBooks::new_<CrossChunkEdge::JumpTableEntryVector>();
+                            jumpTableEntries = js_new<CrossChunkEdge::JumpTableEntryVector>();
                             if (!jumpTableEntries)
                                 failed = true;
                         }
                         if (!jumpTableEntries->append(nedge.jumpTableEntry))
                             failed = true;
                         *nedge.jumpTableEntry = label;
                     }
                 }
                 if (failed) {
                     execPool->release();
-                    cx->free_(chunk);
+                    js_free(chunk);
                     js_ReportOutOfMemory(cx);
                     return Compile_Error;
                 }
                 edge.jumpTableEntries = jumpTableEntries;
             }
             for (unsigned j = 0; j < chunkEdges.length(); j++) {
                 const OutgoingChunkEdge &oedge = chunkEdges[j];
                 if (oedge.source == edge.source && oedge.target == edge.target) {
@@ -4613,17 +4612,17 @@ mjit::Compiler::inlineScriptedFunction(u
     }
 
     for (unsigned i = 0; i < returnJumps.length(); i++)
         returnJumps[i].linkTo(masm.label(), &masm);
 
     frame.popn(argc + 2);
 
     if (entrySnapshot)
-        cx->array_delete(entrySnapshot);
+        js_free(entrySnapshot);
 
     if (exitState)
         frame.discardForJoin(exitState, analysis->getCode(PC).stackDepth - (argc + 2));
 
     if (returnSet) {
         frame.takeReg(returnRegister);
         if (returnRegister.isReg())
             frame.pushTypedPayload(returnType, returnRegister.reg());
@@ -6890,17 +6889,17 @@ mjit::Compiler::startLoop(jsbytecode *he
          * Convert all loop registers in the outer loop into unassigned registers.
          * We don't keep track of which registers the inner loop uses, so the only
          * registers that can be carried in the outer loop must be mentioned before
          * the inner loop starts.
          */
         loop->clearLoopRegisters();
     }
 
-    LoopState *nloop = OffTheBooks::new_<LoopState>(cx, &ssa, this, &frame);
+    LoopState *nloop = js_new<LoopState>(cx, &ssa, this, &frame);
     if (!nloop || !nloop->init(head, entry, entryTarget)) {
         js_ReportOutOfMemory(cx);
         return false;
     }
 
     nloop->outer = loop;
     loop = nloop;
     frame.setLoop(loop);
@@ -7027,17 +7026,17 @@ mjit::Compiler::finishLoop(jsbytecode *h
         loopEntries.append(entry);
     }
     PC = oldPC;
 
     /* Write out loads and tests of loop invariants at all calls in the loop body. */
     loop->flushLoop(stubcc);
 
     LoopState *nloop = loop->outer;
-    cx->delete_(loop);
+    js_delete(loop);
     loop = nloop;
     frame.setLoop(loop);
 
     fallthrough.linkTo(masm.label(), &masm);
 
     /*
      * Clear all registers used for loop temporaries. In the case of loop
      * nesting, we do not allocate temporaries for the outer loop.
--- a/js/src/methodjit/FrameState.cpp
+++ b/js/src/methodjit/FrameState.cpp
@@ -26,20 +26,20 @@ FrameState::FrameState(JSContext *cx, mj
 }
 
 FrameState::~FrameState()
 {
     while (a) {
         ActiveFrame *parent = a->parent;
         if (a->script->hasAnalysis())
             a->script->analysis()->clearAllocations();
-        cx->free_(a);
+        js_free(a);
         a = parent;
     }
-    cx->free_(entries);
+    js_free(entries);
 }
 
 void
 FrameState::pruneDeadEntries()
 {
     unsigned shift = 0;
     for (unsigned i = 0; i < tracker.nentries; i++) {
         FrameEntry *fe = tracker[i];
@@ -58,17 +58,17 @@ bool
 FrameState::pushActiveFrame(JSScript *script, uint32_t argc)
 {
     if (!a) {
         this->nentries = analyze::TotalSlots(script) + (script->nslots - script->nfixed) +
             StackSpace::STACK_JIT_EXTRA - VALUES_PER_STACK_FRAME;
         size_t totalBytes = sizeof(FrameEntry) * nentries +       // entries[]
                             sizeof(FrameEntry *) * nentries +     // tracker.entries
                             sizeof(StackEntryExtra) * nentries;   // extraArray
-        uint8_t *cursor = (uint8_t *)OffTheBooks::calloc_(totalBytes);
+        uint8_t *cursor = (uint8_t *)js_calloc(totalBytes);
         if (!cursor)
             return false;
 
         this->entries = (FrameEntry *) cursor;
         cursor += sizeof(FrameEntry) * nentries;
 
         this->tracker.entries = (FrameEntry **)cursor;
         cursor += sizeof(FrameEntry *) * nentries;
@@ -84,17 +84,17 @@ FrameState::pushActiveFrame(JSScript *sc
 #endif
 
         this->temporaries = this->temporariesTop = this->entries + nentries - TEMPORARY_LIMIT;
     }
 
     /* We should have already checked that argc == nargs */
     JS_ASSERT_IF(a, argc == script->function()->nargs);
 
-    ActiveFrame *newa = OffTheBooks::new_<ActiveFrame>();
+    ActiveFrame *newa = js_new<ActiveFrame>();
     if (!newa)
         return false;
 
     newa->parent = a;
     newa->depth = a ? (totalDepth() + VALUES_PER_STACK_FRAME) : 0;
 
     newa->script = script;
     newa->PC = script->code;
@@ -142,17 +142,17 @@ FrameState::popActiveFrame()
             if (!fe->isTracked())
                 continue;
             forgetAllRegs(fe);
             fe->clear();
         }
     }
 
     ActiveFrame *parent = a->parent;
-    cx->delete_(a);
+    js_delete(a);
     a = parent;
 }
 
 void
 FrameState::takeReg(AnyRegisterID reg)
 {
     modifyReg(reg);
     if (freeRegs.hasReg(reg)) {
@@ -469,17 +469,17 @@ FrameState::discardFrame()
     resetInternalState();
     PodArrayZero(regstate_);
 }
 
 FrameEntry *
 FrameState::snapshotState()
 {
     /* Everything can be recovered from a copy of the frame entries. */
-    FrameEntry *snapshot = cx->array_new<FrameEntry>(nentries);
+    FrameEntry *snapshot = (FrameEntry *)js_malloc(nentries * sizeof(FrameEntry));
     if (!snapshot)
         return NULL;
     PodCopy(snapshot, entries, nentries);
     return snapshot;
 }
 
 void
 FrameState::restoreFromSnapshot(FrameEntry *snapshot)
@@ -2853,17 +2853,17 @@ FrameState::getTemporaryCopies(Uses uses
     for (FrameEntry *fe = temporaries; fe < temporariesTop; fe++) {
         if (!fe->isTracked())
             continue;
         if (fe->isCopied()) {
             for (uint32_t i = fe->trackerIndex() + 1; i < tracker.nentries; i++) {
                 FrameEntry *nfe = tracker[i];
                 if (!deadEntry(nfe, uses.nuses) && nfe->isCopy() && nfe->copyOf() == fe) {
                     if (!res)
-                        res = OffTheBooks::new_< Vector<TemporaryCopy> >(cx);
+                        res = js_new< Vector<TemporaryCopy> >(cx);
                     res->append(TemporaryCopy(addressOf(nfe), addressOf(fe)));
                 }
             }
         }
     }
 
     return res;
 }
--- a/js/src/methodjit/ImmutableSync.cpp
+++ b/js/src/methodjit/ImmutableSync.cpp
@@ -18,26 +18,26 @@ using namespace js::mjit;
 ImmutableSync::ImmutableSync()
   : cx(NULL), entries(NULL), frame(NULL), avail(Registers::AvailRegs), generation(0)
 {
 }
 
 ImmutableSync::~ImmutableSync()
 {
     if (cx)
-        cx->free_(entries);
+        js_free(entries);
 }
 
 bool
 ImmutableSync::init(JSContext *cx, const FrameState &frame, uint32_t nentries)
 {
     this->cx = cx;
     this->frame = &frame;
 
-    entries = (SyncEntry *)OffTheBooks::calloc_(sizeof(SyncEntry) * nentries);
+    entries = (SyncEntry *)js_calloc(sizeof(SyncEntry) * nentries);
     return !!entries;
 }
 
 void
 ImmutableSync::reset(Assembler *masm, Registers avail, FrameEntry *top, FrameEntry *bottom)
 {
     this->avail = avail;
     this->masm = masm;
--- a/js/src/methodjit/LoopState.cpp
+++ b/js/src/methodjit/LoopState.cpp
@@ -1433,17 +1433,17 @@ LoopState::restoreInvariants(jsbytecode 
      */
 
     for (unsigned i = 0; temporaryCopies && i < temporaryCopies->length(); i++) {
         const TemporaryCopy &copy = (*temporaryCopies)[i];
         masm.compareValue(copy.copy, copy.temporary, T0, T1, jumps);
     }
 
     if (temporaryCopies)
-        cx->delete_(temporaryCopies);
+        js_delete(temporaryCopies);
 }
 
 /* Loop analysis methods. */
 
 /*
  * Get any slot/constant accessed by a loop test operand, in terms of its value
  * at the start of the next loop iteration.
  */
--- a/js/src/methodjit/MethodJIT.cpp
+++ b/js/src/methodjit/MethodJIT.cpp
@@ -1255,17 +1255,17 @@ JITChunk::~JITChunk()
 {
     purgeCaches();
     code.release();
 
     for (size_t i = 0; i < nRootedRegExps; i++)
         rootedRegExps()[i]->decRef();
 
     if (pcLengths)
-        Foreground::free_(pcLengths);
+        js_free(pcLengths);
 }
 
 void
 JITScript::destroy(FreeOp *fop)
 {
     for (unsigned i = 0; i < nchunks; i++)
         destroyChunk(fop, i);
 
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -2372,17 +2372,17 @@ GetElementIC::attachGetProp(VMFrame &f, 
     buffer.link(done, fastPathRejoin);
 
     CodeLocationLabel cs = buffer.finalize(f);
 #if DEBUG
     char *chars = DeflateString(cx, v.toString()->getChars(cx), v.toString()->length());
     JaegerSpew(JSpew_PICs, "generated %s stub at %p for atom %p (\"%s\") shape %p (%s: %d)\n",
                js_CodeName[JSOp(*f.pc())], cs.executableAddress(), (void*)name, chars,
                (void*)holder->lastProperty(), cx->fp()->script()->filename, CurrentLine(cx));
-    cx->free_(chars);
+    js_free(chars);
 #endif
 
     // Update the inline guards, if needed.
     if (shouldPatchInlineTypeGuard() || shouldPatchUnconditionalShapeGuard()) {
         Repatcher repatcher(f.chunk());
 
         if (shouldPatchInlineTypeGuard()) {
             // A type guard is present in the inline path, and this is the
--- a/js/src/methodjit/PolyIC.h
+++ b/js/src/methodjit/PolyIC.h
@@ -124,21 +124,21 @@ class BasePolyIC : public BaseIC {
     bool addPool(JSContext *cx, JSC::ExecutablePool *pool) {
         if (areZeroPools()) {
             u.execPool = pool;
             return true;
         }
         if (isOnePool()) {
             JSC::ExecutablePool *oldPool = u.execPool;
             JS_ASSERT(!isTagged(oldPool));
-            ExecPoolVector *execPools = OffTheBooks::new_<ExecPoolVector>(SystemAllocPolicy());
+            ExecPoolVector *execPools = js_new<ExecPoolVector>(SystemAllocPolicy());
             if (!execPools)
                 return false;
             if (!execPools->append(oldPool) || !execPools->append(pool)) {
-                Foreground::delete_(execPools);
+                js_delete(execPools);
                 return false;
             }
             u.taggedExecPools = tag(execPools);
             return true;
         }
         return multiplePools()->append(pool);
     }
 
@@ -149,17 +149,17 @@ class BasePolyIC : public BaseIC {
             // Common case:  do nothing.
         } else if (isOnePool()) {
             u.execPool->release();
             u.execPool = NULL;
         } else {
             ExecPoolVector *execPools = multiplePools();
             for (size_t i = 0; i < execPools->length(); i++)
                 (*execPools)[i]->release();
-            Foreground::delete_(execPools);
+            js_delete(execPools);
             u.execPool = NULL;
         }
         JS_ASSERT(areZeroPools());
     }
 };
 
 struct GetElementIC : public BasePolyIC {
 
--- a/js/src/perf/pm_linux.cpp
+++ b/js/src/perf/pm_linux.cpp
@@ -229,17 +229,17 @@ Impl::stop(PerfMeasurement* counters)
 } // anonymous namespace
 
 
 namespace JS {
 
 #define initCtr(flag) ((eventsMeasured & flag) ? 0 : -1)
 
 PerfMeasurement::PerfMeasurement(PerfMeasurement::EventMask toMeasure)
-  : impl(OffTheBooks::new_<Impl>()),
+  : impl(js_new<Impl>()),
     eventsMeasured(impl ? static_cast<Impl*>(impl)->init(toMeasure)
                    : EventMask(0)),
     cpu_cycles(initCtr(CPU_CYCLES)),
     instructions(initCtr(INSTRUCTIONS)),
     cache_references(initCtr(CACHE_REFERENCES)),
     cache_misses(initCtr(CACHE_MISSES)),
     branch_instructions(initCtr(BRANCH_INSTRUCTIONS)),
     branch_misses(initCtr(BRANCH_MISSES)),
@@ -250,17 +250,17 @@ PerfMeasurement::PerfMeasurement(PerfMea
     cpu_migrations(initCtr(CPU_MIGRATIONS))
 {
 }
 
 #undef initCtr
 
 PerfMeasurement::~PerfMeasurement()
 {
-    js::Foreground::delete_(static_cast<Impl*>(impl));
+    js_delete(static_cast<Impl*>(impl));
 }
 
 void
 PerfMeasurement::start()
 {
     if (impl)
         static_cast<Impl*>(impl)->start();
 }
--- a/js/src/shell/jsheaptools.cpp
+++ b/js/src/shell/jsheaptools.cpp
@@ -486,17 +486,17 @@ ReferenceFinder::addReferrer(jsval refer
     Rooted<jsval> referrer(context, referrer_);
 
     if (!context->compartment->wrap(context, referrer.address()))
         return false;
 
     char *pathName = path->computeName(context);
     if (!pathName)
         return false;
-    AutoReleasePtr releasePathName(context, pathName);
+    AutoReleasePtr releasePathName(pathName);
 
     /* Find the property of the results object named |pathName|. */
     JS::RootedValue valRoot(context);
     Value &v = valRoot.get();
 
     if (!JS_GetProperty(context, result, pathName, &v))
         return false;
     if (v.isUndefined()) {
--- a/js/src/shell/jsoptparse.cpp
+++ b/js/src/shell/jsoptparse.cpp
@@ -437,19 +437,19 @@ OptionParser::getMultiStringOption(const
 {
     const MultiStringOption *mso = findOption(longflag)->asMultiStringOption();
     return MultiStringRange(mso->strings.begin(), mso->strings.end());
 }
 
 OptionParser::~OptionParser()
 {
     for (Option **it = options.begin(), **end = options.end(); it != end; ++it)
-        Foreground::delete_<Option>(*it);
+        js_delete<Option>(*it);
     for (Option **it = arguments.begin(), **end = arguments.end(); it != end; ++it)
-        Foreground::delete_<Option>(*it);
+        js_delete<Option>(*it);
 }
 
 Option *
 OptionParser::findOption(char shortflag)
 {
     for (Option **it = options.begin(), **end = options.end(); it != end; ++it) {
         if ((*it)->shortflag == shortflag)
             return *it;
@@ -529,82 +529,79 @@ OptionParser::getMultiStringArg(const ch
 /* Option builders */
 
 bool
 OptionParser::addIntOption(char shortflag, const char *longflag, const char *metavar,
                            const char *help, int defaultValue)
 {
     if (!options.reserve(options.length() + 1))
         return false;
-    IntOption *io = OffTheBooks::new_<IntOption>(shortflag, longflag, help, metavar,
-                                                 defaultValue);
+    IntOption *io = js_new<IntOption>(shortflag, longflag, help, metavar, defaultValue);
     if (!io)
         return false;
     options.infallibleAppend(io);
     return true;
 }
 
 bool
 OptionParser::addBoolOption(char shortflag, const char *longflag, const char *help)
 {
     if (!options.reserve(options.length() + 1))
         return false;
-    BoolOption *bo = OffTheBooks::new_<BoolOption>(shortflag, longflag, help);
+    BoolOption *bo = js_new<BoolOption>(shortflag, longflag, help);
     if (!bo)
         return false;
     options.infallibleAppend(bo);
     return true;
 }
 
 bool
 OptionParser::addStringOption(char shortflag, const char *longflag, const char *metavar,
                               const char *help)
 {
     if (!options.reserve(options.length() + 1))
         return false;
-    StringOption *so = OffTheBooks::new_<StringOption>(shortflag, longflag, help, metavar);
+    StringOption *so = js_new<StringOption>(shortflag, longflag, help, metavar);
     if (!so)
         return false;
     options.infallibleAppend(so);
     return true;
 }
 
 bool
 OptionParser::addMultiStringOption(char shortflag, const char *longflag, const char *metavar,
                                    const char *help)
 {
     if (!options.reserve(options.length() + 1))
         return false;
-    MultiStringOption *mso = OffTheBooks::new_<MultiStringOption>(shortflag, longflag, help,
-                                                                  metavar);
+    MultiStringOption *mso = js_new<MultiStringOption>(shortflag, longflag, help, metavar);
     if (!mso)
         return false;
     options.infallibleAppend(mso);
     return true;
 }
 
 /* Argument builders */
 
 bool
 OptionParser::addOptionalStringArg(const char *name, const char *help)
 {
     if (!arguments.reserve(arguments.length() + 1))
         return false;
-    StringOption *so = OffTheBooks::new_<StringOption>(1, name, help, (const char *) NULL);
+    StringOption *so = js_new<StringOption>(1, name, help, (const char *) NULL);
     if (!so)
         return false;
     arguments.infallibleAppend(so);
     return true;
 }
 
 bool
 OptionParser::addOptionalMultiStringArg(const char *name, const char *help)
 {
     JS_ASSERT_IF(!arguments.empty(), !arguments.back()->isVariadic());
     if (!arguments.reserve(arguments.length() + 1))
         return false;
-    MultiStringOption *mso = OffTheBooks::new_<MultiStringOption>(1, name, help,
-                                                                  (const char *) NULL);
+    MultiStringOption *mso = js_new<MultiStringOption>(1, name, help, (const char *) NULL);
     if (!mso)
         return false;
     arguments.infallibleAppend(mso);
     return true;
 }
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -1814,17 +1814,17 @@ Debugger::construct(JSContext *cx, unsig
     for (unsigned slot = JSSLOT_DEBUG_PROTO_START; slot < JSSLOT_DEBUG_PROTO_STOP; slot++)
         obj->setReservedSlot(slot, proto->getReservedSlot(slot));
 
     Debugger *dbg = cx->new_<Debugger>(cx, obj.get());
     if (!dbg)
         return false;
     obj->setPrivate(dbg);
     if (!dbg->init(cx)) {
-        cx->delete_(dbg);
+        js_delete(dbg);
         return false;
     }
 
     /* Add the initial debuggees, if any. */
     for (unsigned i = 0; i < argc; i++) {
         Rooted<GlobalObject*> debuggee(cx, &GetProxyPrivate(&args[i].toObject()).toObject().global());
         if (!dbg->addDebuggeeGlobal(cx, debuggee))
             return false;
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -222,17 +222,17 @@ intrinsic_ThrowError(JSContext *cx, unsi
             ptrdiff_t spIndex = cx->stack.spIndexOf(val.address());
             errorArgs[i - 1] = DecompileValueGenerator(cx, spIndex, val, NullPtr(), 1);
         }
     }
 
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, errorNumber,
                          errorArgs[0], errorArgs[1], errorArgs[2]);
     for (unsigned i = 0; i < 3; i++)
-        cx->free_(errorArgs[i]);
+        js_free(errorArgs[i]);
     return false;
 }
 
 static JSBool
 intrinsic_MakeConstructible(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     JS_ASSERT(args.length() >= 1);
@@ -300,17 +300,17 @@ GlobalObject::initFunctionAndObjectClass
 
         const char *rawSource = "() {\n}";
         size_t sourceLen = strlen(rawSource);
         jschar *source = InflateString(cx, rawSource, &sourceLen);
         if (!source)
             return NULL;
         ScriptSource *ss = cx->new_<ScriptSource>();
         if (!ss) {
-            cx->free_(source);
+            js_free(source);
             return NULL;
         }
         ScriptSourceHolder ssh(cx->runtime, ss);
         ss->setSource(source, sourceLen);
 
         CompileOptions options(cx);
         options.setNoScriptRval(true)
                .setVersion(JSVERSION_DEFAULT);
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -541,17 +541,17 @@ RegExpCompartment::init(JSContext *cx)
 
 void
 RegExpCompartment::sweep(JSRuntime *rt)
 {
     for (Map::Enum e(map_); !e.empty(); e.popFront()) {
         /* See the comment on RegExpShared lifetime in RegExpObject.h. */
         RegExpShared *shared = e.front().value;
         if (shared->activeUseCount == 0 && shared->gcNumberWhenUsed < rt->gcStartNumber) {
-            Foreground::delete_(shared);
+            js_delete(shared);
             e.removeFront();
         }
     }
 }
 
 inline bool
 RegExpCompartment::get(JSContext *cx, JSAtom *keyAtom, JSAtom *source, RegExpFlag flags, Type type,
                        RegExpGuard *g)
--- a/js/src/vm/RegExpObject.h
+++ b/js/src/vm/RegExpObject.h
@@ -99,17 +99,17 @@ class RegExpCode
         byteCode(NULL)
     { }
 
     ~RegExpCode() {
 #if ENABLE_YARR_JIT
         codeBlock.release();
 #endif
         if (byteCode)
-            Foreground::delete_<BytecodePattern>(byteCode);
+            js_delete<BytecodePattern>(byteCode);
     }
 
     static bool checkSyntax(JSContext *cx, frontend::TokenStream *tokenStream,
                             JSLinearString *source)
     {
         ErrorCode error = JSC::Yarr::checkSyntax(*source);
         if (error == JSC::Yarr::NoError)
             return true;
@@ -162,27 +162,25 @@ class RegExpCode
  * conditions.
  */
 class RegExpShared
 {
     friend class RegExpCompartment;
     friend class RegExpGuard;
 
     detail::RegExpCode code;
-    unsigned              parenCount;
+    unsigned           parenCount;
     RegExpFlag         flags;
     size_t             activeUseCount;   /* See comment above. */
     uint64_t           gcNumberWhenUsed; /* See comment above. */
 
     bool compile(JSContext *cx, JSAtom *source);
 
+  public:
     RegExpShared(JSRuntime *rt, RegExpFlag flags);
-    JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR;
-
-  public:
 
     /* Called when a RegExpShared is installed into a RegExpObject. */
     inline void prepareForUse(JSContext *cx);
 
     /* Primary interface: run this regular expression on the given string. */
 
     RegExpRunStatus
     execute(JSContext *cx, const jschar *chars, size_t length, size_t *lastIndex,
--- a/js/src/vm/SPSProfiler.cpp
+++ b/js/src/vm/SPSProfiler.cpp
@@ -26,22 +26,22 @@ SPSProfiler::SPSProfiler(JSRuntime *rt)
 {
     JS_ASSERT(rt != NULL);
 }
 
 SPSProfiler::~SPSProfiler()
 {
     if (strings.initialized()) {
         for (ProfileStringMap::Enum e(strings); !e.empty(); e.popFront())
-            rt->array_delete(e.front().value);
+            js_free(const_cast<char *>(e.front().value));
     }
 #ifdef JS_METHODJIT
     if (jminfo.initialized()) {
         for (JITInfoMap::Enum e(jminfo); !e.empty(); e.popFront())
-            rt->delete_(e.front().value);
+            js_delete(e.front().value);
     }
 #endif
 }
 
 void
 SPSProfiler::setProfilingStack(ProfileEntry *stack, uint32_t *size, uint32_t max)
 {
     JS_ASSERT(!enabled());
@@ -71,17 +71,17 @@ SPSProfiler::profileString(JSContext *cx
     JS_ASSERT(strings.initialized());
     ProfileStringMap::AddPtr s = strings.lookupForAdd(script);
     if (s)
         return s->value;
     const char *str = allocProfileString(cx, script, maybeFun);
     if (str == NULL)
         return NULL;
     if (!strings.add(s, script, str)) {
-        rt->array_delete(str);
+        js_free(const_cast<char *>(str));
         return NULL;
     }
     return str;
 }
 
 void
 SPSProfiler::onScriptFinalized(JSScript *script)
 {
@@ -92,17 +92,17 @@ SPSProfiler::onScriptFinalized(JSScript 
      * off, we still want to remove the string, so no check of enabled() is
      * done.
      */
     if (!strings.initialized())
         return;
     if (ProfileStringMap::Ptr entry = strings.lookup(script)) {
         const char *tofree = entry->value;
         strings.remove(entry);
-        rt->array_delete(tofree);
+        js_free(const_cast<char *>(tofree));
     }
 }
 
 bool
 SPSProfiler::enter(JSContext *cx, JSScript *script, JSFunction *maybeFun)
 {
     const char *str = profileString(cx, script, maybeFun);
     if (str == NULL)
@@ -186,17 +186,17 @@ SPSProfiler::allocProfileString(JSContex
     if (!buf.append(":"))
         return NULL;
     if (!NumberValueToStringBuffer(cx, NumberValue(script->lineno), buf))
         return NULL;
     if (hasAtom && !buf.append(")"))
         return NULL;
 
     size_t len = buf.length();
-    char *cstr = rt->array_new<char>(len + 1);
+    char *cstr = (char *)js_malloc((len + 1) * sizeof(char));
     if (cstr == NULL)
         return NULL;
 
     const jschar *ptr = buf.begin();
     for (size_t i = 0; i < len; i++)
         cstr[i] = ptr[i];
     cstr[len] = 0;
 
@@ -374,17 +374,17 @@ SPSProfiler::unregisterScript(JSScript *
     for (unsigned i = 0; i < info->chunks.length(); i++) {
         if (info->chunks[i].chunk == chunk) {
             info->chunks.erase(&info->chunks[i]);
             break;
         }
     }
     if (info->chunks.length() == 0) {
         jminfo.remove(ptr);
-        rt->delete_(info);
+        js_delete(info);
     }
 }
 #endif
 
 SPSEntryMarker::SPSEntryMarker(JSRuntime *rt JS_GUARD_OBJECT_NOTIFIER_PARAM_NO_INIT)
     : profiler(&rt->spsProfiler)
 {
     JS_GUARD_OBJECT_NOTIFIER_INIT;
--- a/js/src/vm/String.cpp
+++ b/js/src/vm/String.cpp
@@ -125,17 +125,17 @@ AllocChars(JSContext *maybecx, size_t le
     static const size_t DOUBLING_MAX = 1024 * 1024;
     numChars = numChars > DOUBLING_MAX ? numChars + (numChars / 8) : RoundUpPow2(numChars);
 
     /* Like length, capacity does not include the null char, so take it out. */
     *capacity = numChars - 1;
 
     JS_STATIC_ASSERT(JSString::MAX_LENGTH * sizeof(jschar) < UINT32_MAX);
     size_t bytes = numChars * sizeof(jschar);
-    *chars = (jschar *)(maybecx ? maybecx->malloc_(bytes) : OffTheBooks::malloc_(bytes));
+    *chars = (jschar *)(maybecx ? maybecx->malloc_(bytes) : js_malloc(bytes));
     return *chars != NULL;
 }
 
 template<JSRope::UsingBarrier b>
 JSFlatString *
 JSRope::flattenInternal(JSContext *maybecx)
 {
     /*
--- a/js/src/vm/StringBuffer.cpp
+++ b/js/src/vm/StringBuffer.cpp
@@ -24,17 +24,17 @@ StringBuffer::extractWellSized()
 
     /* For medium/big buffers, avoid wasting more than 1/4 of the memory. */
     JS_ASSERT(capacity >= length);
     if (length > CharBuffer::sMaxInlineStorage && capacity - length > length / 4) {
         size_t bytes = sizeof(jschar) * (length + 1);
         JSContext *cx = context();
         jschar *tmp = (jschar *)cx->realloc_(buf, bytes);
         if (!tmp) {
-            cx->free_(buf);
+            js_free(buf);
             return NULL;
         }
         buf = tmp;
     }
 
     return buf;
 }
 
@@ -57,17 +57,17 @@ StringBuffer::finishString()
         return NULL;
 
     jschar *buf = extractWellSized();
     if (!buf)
         return NULL;
 
     JSFixedString *str = js_NewString(cx, buf, length);
     if (!str)
-        cx->free_(buf);
+        js_free(buf);
     return str;
 }
 
 JSAtom *
 StringBuffer::finishAtom()
 {
     JSContext *cx = context();
 
--- a/js/src/vm/Xdr.cpp
+++ b/js/src/vm/Xdr.cpp
@@ -27,17 +27,17 @@
 using namespace mozilla;
 using namespace js;
 
 namespace js {
 
 void
 XDRBuffer::freeBuffer()
 {
-    Foreground::free_(base);
+    js_free(base);
 #ifdef DEBUG
     memset(this, 0xe2, sizeof *this);
 #endif
 }
 
 bool
 XDRBuffer::grow(size_t n)
 {
@@ -46,17 +46,17 @@ XDRBuffer::grow(size_t n)
     const size_t MEM_BLOCK = 8192;
     size_t offset = cursor - base;
     size_t newCapacity = JS_ROUNDUP(offset + n, MEM_BLOCK);
     if (isUint32Overflow(newCapacity)) {
         JS_ReportErrorNumber(cx(), js_GetErrorMessage, NULL, JSMSG_TOO_BIG_TO_ENCODE);
         return false;
     }
 
-    void *data = OffTheBooks::realloc_(base, newCapacity);
+    void *data = js_realloc(base, newCapacity);
     if (!data) {
         js_ReportOutOfMemory(cx());
         return false;
     }
     base = static_cast<uint8_t *>(data);
     cursor = base + offset;
     limit = base + newCapacity;
     return true;
--- a/js/src/yarr/RegExpJitTables.h
+++ b/js/src/yarr/RegExpJitTables.h
@@ -2625,46 +2625,46 @@ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 };
 
 
 CharacterClass* digitsCreate()
 {
     // FIXME: bug 574459 -- no NULL check
-    CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>((CharacterClassTable*)NULL);
+    CharacterClass* characterClass = js_new<CharacterClass>((CharacterClassTable*)NULL);
     characterClass->m_ranges.append(CharacterRange(0x30, 0x39));
     return characterClass;
 }
 
 CharacterClass* nondigitsCreate()
 {
     // FIXME: bug 574459 -- no NULL check
-    CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>((CharacterClassTable*)NULL);
+    CharacterClass* characterClass = js_new<CharacterClass>((CharacterClassTable*)NULL);
     characterClass->m_ranges.append(CharacterRange(0x00, 0x2f));
     characterClass->m_ranges.append(CharacterRange(0x3a, 0x7f));
     characterClass->m_rangesUnicode.append(CharacterRange(0x0080, 0xffff));
     return characterClass;
 }
 
 CharacterClass* newlineCreate()
 {
     // FIXME: bug 574459 -- no NULL check
-    CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>((CharacterClassTable*)NULL);
+    CharacterClass* characterClass = js_new<CharacterClass>((CharacterClassTable*)NULL);
     characterClass->m_matches.append(0x0a);
     characterClass->m_matches.append(0x0d);
     characterClass->m_matchesUnicode.append(0x2028);
     characterClass->m_matchesUnicode.append(0x2029);
     return characterClass;
 }
 
 CharacterClass* spacesCreate()
 {
     // FIXME: bug 574459 -- no NULL check
-    CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>(CharacterClassTable::create(_spacesData, false));
+    CharacterClass* characterClass = js_new<CharacterClass>(CharacterClassTable::create(_spacesData, false));
     characterClass->m_ranges.append(CharacterRange(0x09, 0x0d));
     characterClass->m_matches.append(0x20);
     characterClass->m_matchesUnicode.append(0x00a0);
     characterClass->m_matchesUnicode.append(0x1680);
     characterClass->m_matchesUnicode.append(0x180e);
     characterClass->m_rangesUnicode.append(CharacterRange(0x2000, 0x200a));
     characterClass->m_matchesUnicode.append(0x2028);
     characterClass->m_matchesUnicode.append(0x2029);
@@ -2672,17 +2672,17 @@ CharacterClass* spacesCreate()
     characterClass->m_matchesUnicode.append(0x205f);
     characterClass->m_matchesUnicode.append(0x3000);
     return characterClass;
 }
 
 CharacterClass* nonspacesCreate()
 {
     // FIXME: bug 574459 -- no NULL check
-    CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>(CharacterClassTable::create(_spacesData, true));
+    CharacterClass* characterClass = js_new<CharacterClass>(CharacterClassTable::create(_spacesData, true));
     characterClass->m_ranges.append(CharacterRange(0x00, 0x08));
     characterClass->m_ranges.append(CharacterRange(0x0e, 0x1f));
     characterClass->m_ranges.append(CharacterRange(0x21, 0x7f));
     characterClass->m_rangesUnicode.append(CharacterRange(0x0080, 0x009f));
     characterClass->m_rangesUnicode.append(CharacterRange(0x00a1, 0x167f));
     characterClass->m_rangesUnicode.append(CharacterRange(0x1681, 0x180d));
     characterClass->m_rangesUnicode.append(CharacterRange(0x180f, 0x1fff));
     characterClass->m_rangesUnicode.append(CharacterRange(0x200b, 0x2027));
@@ -2691,30 +2691,30 @@ CharacterClass* nonspacesCreate()
     characterClass->m_rangesUnicode.append(CharacterRange(0x2060, 0x2fff));
     characterClass->m_rangesUnicode.append(CharacterRange(0x3001, 0xffff));
     return characterClass;
 }
 
 CharacterClass* nonwordcharCreate()
 {
     // FIXME: bug 574459 -- no NULL check
-    CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>(CharacterClassTable::create(_wordcharData, true));
+    CharacterClass* characterClass = js_new<CharacterClass>(CharacterClassTable::create(_wordcharData, true));
     characterClass->m_ranges.append(CharacterRange(0x00, 0x2f));
     characterClass->m_ranges.append(CharacterRange(0x3a, 0x40));
     characterClass->m_ranges.append(CharacterRange(0x5b, 0x5e));
     characterClass->m_matches.append(0x60);
     characterClass->m_ranges.append(CharacterRange(0x7b, 0x7f));
     characterClass->m_rangesUnicode.append(CharacterRange(0x0080, 0xffff));
     return characterClass;
 }
 
 CharacterClass* wordcharCreate()
 {
     // FIXME: bug 574459 -- no NULL check
-    CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>(CharacterClassTable::create(_wordcharData, false));
+    CharacterClass* characterClass = js_new<CharacterClass>(CharacterClassTable::create(_wordcharData, false));
     characterClass->m_ranges.append(CharacterRange(0x30, 0x39));
     characterClass->m_ranges.append(CharacterRange(0x41, 0x5a));
     characterClass->m_matches.append(0x5f);
     characterClass->m_ranges.append(CharacterRange(0x61, 0x7a));
     return characterClass;
 }
 
 
--- a/js/src/yarr/YarrInterpreter.cpp
+++ b/js/src/yarr/YarrInterpreter.cpp
@@ -1417,17 +1417,17 @@ public:
     }
 
     PassOwnPtr<BytecodePattern> compile(BumpPointerAllocator* allocator)
     {
         regexBegin(m_pattern.m_numSubpatterns, m_pattern.m_body->m_callFrameSize, m_pattern.m_body->m_alternatives[0]->onceThrough());
         emitDisjunction(m_pattern.m_body);
         regexEnd();
 
-        return adoptPtr(js::OffTheBooks::new_<BytecodePattern>(m_bodyDisjunction.release(), m_allParenthesesInfo, Ref<YarrPattern>(m_pattern), allocator));
+        return adoptPtr(js_new<BytecodePattern>(m_bodyDisjunction.release(), m_allParenthesesInfo, Ref<YarrPattern>(m_pattern), allocator));
     }
 
     void checkInput(unsigned count)
     {
         m_bodyDisjunction->terms.append(ByteTerm::CheckInput(count));
     }
 
     void uncheckInput(unsigned count)
@@ -1643,17 +1643,17 @@ public:
         ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeParenthesesSubpatternOnceBegin);
 
         ByteTerm& parenthesesBegin = m_bodyDisjunction->terms[beginTerm];
 
         bool capture = parenthesesBegin.capture();
         unsigned subpatternId = parenthesesBegin.atom.subpatternId;
 
         unsigned numSubpatterns = lastSubpatternId - subpatternId + 1;
-        ByteDisjunction* parenthesesDisjunction = js::OffTheBooks::new_<ByteDisjunction>(numSubpatterns, callFrameSize);
+        ByteDisjunction* parenthesesDisjunction = js_new<ByteDisjunction>(numSubpatterns, callFrameSize);
 
         parenthesesDisjunction->terms.append(ByteTerm::SubpatternBegin());
         for (unsigned termInParentheses = beginTerm + 1; termInParentheses < endTerm; ++termInParentheses)
             parenthesesDisjunction->terms.append(m_bodyDisjunction->terms[termInParentheses]);
         parenthesesDisjunction->terms.append(ByteTerm::SubpatternEnd());
 
         m_bodyDisjunction->terms.shrink(beginTerm);
 
@@ -1706,17 +1706,17 @@ public:
         m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount;
         m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType;
         m_bodyDisjunction->terms[endTerm].atom.quantityCount = quantityCount;
         m_bodyDisjunction->terms[endTerm].atom.quantityType = quantityType;
     }
 
     void regexBegin(unsigned numSubpatterns, unsigned callFrameSize, bool onceThrough)
     {
-        m_bodyDisjunction = adoptPtr(js::OffTheBooks::new_<ByteDisjunction>(numSubpatterns, callFrameSize));
+        m_bodyDisjunction = adoptPtr(js_new<ByteDisjunction>(numSubpatterns, callFrameSize));
         m_bodyDisjunction->terms.append(ByteTerm::BodyAlternativeBegin(onceThrough));
         m_bodyDisjunction->terms[0].frameLocation = 0;
         m_currentAlternativeIndex = 0;
     }
 
     void regexEnd()
     {
         closeBodyAlternative();
--- a/js/src/yarr/YarrPattern.cpp
+++ b/js/src/yarr/YarrPattern.cpp
@@ -145,17 +145,17 @@ public:
                         ++unicodeCurr;
                 }
             }
         }
     }
 
     CharacterClass* charClass()
     {
-        CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>(PassRefPtr<CharacterClassTable>(0));
+        CharacterClass* characterClass = js_new<CharacterClass>(PassRefPtr<CharacterClassTable>(0));
 
         characterClass->m_matches.append(m_matches);
         characterClass->m_ranges.append(m_ranges);
         characterClass->m_matchesUnicode.append(m_matchesUnicode);
         characterClass->m_rangesUnicode.append(m_rangesUnicode);
 
         reset();
 
@@ -244,31 +244,31 @@ private:
 
 class YarrPatternConstructor {
 public:
     YarrPatternConstructor(YarrPattern& pattern)
         : m_pattern(pattern)
         , m_characterClassConstructor(pattern.m_ignoreCase)
         , m_invertParentheticalAssertion(false)
     {
-        m_pattern.m_body = js::OffTheBooks::new_<PatternDisjunction>();
+        m_pattern.m_body = js_new<PatternDisjunction>();
         m_alternative = m_pattern.m_body->addNewAlternative();
         m_pattern.m_disjunctions.append(m_pattern.m_body);
     }
 
     ~YarrPatternConstructor()
     {
     }
 
     void reset()
     {
         m_pattern.reset();
         m_characterClassConstructor.reset();
 
-        m_pattern.m_body = js::OffTheBooks::new_<PatternDisjunction>();
+        m_pattern.m_body = js_new<PatternDisjunction>();
         m_alternative = m_pattern.m_body->addNewAlternative();
         m_pattern.m_disjunctions.append(m_pattern.m_body);
     }
     
     void assertionBOL()
     {
         if (!m_alternative->m_terms.size() & !m_invertParentheticalAssertion) {
             m_alternative->m_startsWithBOL = true;
@@ -361,25 +361,25 @@ public:
     }
 
     void atomParenthesesSubpatternBegin(bool capture = true)
     {
         unsigned subpatternId = m_pattern.m_numSubpatterns + 1;
         if (capture)
             m_pattern.m_numSubpatterns++;
 
-        PatternDisjunction* parenthesesDisjunction = js::OffTheBooks::new_<PatternDisjunction>(m_alternative);
+        PatternDisjunction* parenthesesDisjunction = js_new<PatternDisjunction>(m_alternative);
         m_pattern.m_disjunctions.append(parenthesesDisjunction);
         m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, capture, false));
         m_alternative = parenthesesDisjunction->addNewAlternative();
     }
 
     void atomParentheticalAssertionBegin(bool invert = false)
     {
-        PatternDisjunction* parenthesesDisjunction = js::OffTheBooks::new_<PatternDisjunction>(m_alternative);
+        PatternDisjunction* parenthesesDisjunction = js_new<PatternDisjunction>(m_alternative);
         m_pattern.m_disjunctions.append(parenthesesDisjunction);
         m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParentheticalAssertion, m_pattern.m_numSubpatterns + 1, parenthesesDisjunction, false, invert));
         m_alternative = parenthesesDisjunction->addNewAlternative();
         m_invertParentheticalAssertion = invert;
     }
 
     void atomParenthesesEnd()
     {
@@ -443,17 +443,17 @@ public:
     // skip alternatives with m_startsWithBOL set true.
     PatternDisjunction* copyDisjunction(PatternDisjunction* disjunction, bool filterStartsWithBOL = false)
     {
         PatternDisjunction* newDisjunction = 0;
         for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
             PatternAlternative* alternative = disjunction->m_alternatives[alt];
             if (!filterStartsWithBOL || !alternative->m_startsWithBOL) {
                 if (!newDisjunction) {
-                    newDisjunction = js::OffTheBooks::new_<PatternDisjunction>();
+                    newDisjunction = js_new<PatternDisjunction>();
                     newDisjunction->m_parent = disjunction->m_parent;
                 }
                 PatternAlternative* newAlternative = newDisjunction->addNewAlternative();
                 for (unsigned i = 0; i < alternative->m_terms.size(); ++i)
                     newAlternative->m_terms.append(copyTerm(alternative->m_terms[i], filterStartsWithBOL));
             }
         }
         
--- a/js/src/yarr/YarrPattern.h
+++ b/js/src/yarr/YarrPattern.h
@@ -61,25 +61,23 @@ struct CharacterRange {
     CharacterRange(UChar begin, UChar end)
         : begin(begin)
         , end(end)
     {
     }
 };
 
 struct CharacterClassTable : RefCounted<CharacterClassTable> {
-    friend class js::OffTheBooks;
     const char* m_table;
     bool m_inverted;
     static PassRefPtr<CharacterClassTable> create(const char* table, bool inverted)
     {
-        return adoptRef(js::OffTheBooks::new_<CharacterClassTable>(table, inverted));
+        return adoptRef(js_new<CharacterClassTable>(table, inverted));
     }
 
-private:
     CharacterClassTable(const char* table, bool inverted)
         : m_table(table)
         , m_inverted(inverted)
     {
     }
 };
 
 struct CharacterClass {
@@ -89,17 +87,17 @@ public:
     // they may have an optional table for faster lookups (which must match the
     // specified matches and ranges)
     CharacterClass(PassRefPtr<CharacterClassTable> table)
         : m_table(table)
     {
     }
     ~CharacterClass()
     {
-        js::Foreground::delete_(m_table.get());
+        js_delete(m_table.get());
     }
     Vector<UChar> m_matches;
     Vector<CharacterRange> m_ranges;
     Vector<UChar> m_matchesUnicode;
     Vector<CharacterRange> m_rangesUnicode;
     RefPtr<CharacterClassTable> m_table;
 };
 
@@ -294,17 +292,17 @@ public:
     
     ~PatternDisjunction()
     {
         deleteAllValues(m_alternatives);
     }
 
     PatternAlternative* addNewAlternative()
     {
-        PatternAlternative* alternative = js::OffTheBooks::new_<PatternAlternative>(this);
+        PatternAlternative* alternative = js_new<PatternAlternative>(this);
         m_alternatives.append(alternative);
         return alternative;
     }
 
     Vector<PatternAlternative*> m_alternatives;
     PatternAlternative* m_parent;
     unsigned m_minimumSize;
     unsigned m_callFrameSize;
--- a/js/src/yarr/wtfbridge.h
+++ b/js/src/yarr/wtfbridge.h
@@ -75,17 +75,17 @@ template<typename T>
 class OwnPtr {
     T *ptr;
   public:
     OwnPtr() : ptr(NULL) { }
     OwnPtr(PassOwnPtr<T> p) : ptr(p.get()) { }
 
     ~OwnPtr() {
         if (ptr)
-            js::Foreground::delete_(ptr);
+            js_delete(ptr);
     }
 
     OwnPtr<T> &operator=(PassOwnPtr<T> p) {
         ptr = p.get();
         return *this;
     }
 
     T *operator ->() { return ptr; }
@@ -187,17 +187,17 @@ class Vector {
     void shrink(size_t newLength) {
         // XXX yarr-oom
         JS_ASSERT(newLength <= impl.length());
         (void) impl.resize(newLength);
     }
 
     void deleteAllValues() {
         for (T *p = impl.begin(); p != impl.end(); ++p)
-            js::Foreground::delete_(*p);
+            js_delete(*p);
     }
 };
 
 template<typename T>
 class Vector<OwnPtr<T> > {
   public:
     js::Vector<T *, 0, js::SystemAllocPolicy> impl;
   public:
@@ -213,17 +213,17 @@ class Vector<OwnPtr<T> > {
     }
 
     PassOwnPtr<T> operator[](size_t i) {
         return PassOwnPtr<T>(impl[i]);
     }
 
     void clear() {
         for (T **p = impl.begin(); p != impl.end(); ++p)
-            js::Foreground::delete_(*p);
+            delete_(*p);
         return impl.clear();
     }
 };
 
 template <typename T, size_t N>
 inline void
 deleteAllValues(Vector<T, N> &v) {
     v.deleteAllValues();