Bug 787246 - rm OffTheBooks/Foreground/UnwantedForeground gunk (r=billm)
authorLuke Wagner <luke@mozilla.com>
Fri, 31 Aug 2012 15:01:33 -0700
changeset 104066 d0789db68c77ada4f7fdf1ca8db213a3e003cf44
parent 104064 7a9f9c67c0f2fd75be9beab0461ddc1c262f0934
child 104067 949ade2a2ea186f431cb629d8f8281c1a91b488e
push id1053
push uservporof@mozilla.com
push dateMon, 03 Sep 2012 10:27:19 +0000
treeherderfx-team@2e5e12afabde [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs787246
milestone18.0a1
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();