bug 736978 - remove JS_FinalizeStub. r=:billm
authorIgor Bukanov <igor@mir2.org>
Mon, 19 Mar 2012 15:27:58 +0100
changeset 89777 ca0782c1f3d5deb2986793580662a11e07935dd7
parent 89776 d548cc64e028fd4afd549d44cdacd4dda27ae0a5
child 89778 af19e5ada310814ad206fadcf1e32e77ffbbbe37
push id22282
push usermlamouri@mozilla.com
push dateTue, 20 Mar 2012 10:40:32 +0000
treeherdermozilla-central@ee554888d071 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs736978
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 736978 - remove JS_FinalizeStub. r=:billm Currently the GC finalizes on the background thread only objects with null JSClass::finalize. However, this implies that any object that uses JS_FinalizeStub for the finalizer would be prevented from the background finalization. To fix this the patch removes JS_FinalizeStub replacing it with NULL in all cases when the class has no custom finalizer. For style consistency the patch also removed the usage of JSCLASS_NO_OPTIONAL_MEMBERS in the static declarations as the compiler fills the missing fields with null in any cases.
dom/indexedDB/IDBObjectStore.cpp
dom/workers/EventTarget.cpp
dom/workers/Events.cpp
dom/workers/Exceptions.cpp
dom/workers/File.cpp
dom/workers/FileReaderSync.cpp
dom/workers/Location.cpp
dom/workers/Navigator.cpp
dom/workers/WorkerScope.cpp
gfx/skia/src/xml/SkJS.cpp
js/ipc/ObjectWrapperChild.cpp
js/jsd/jsd_high.c
js/src/ctypes/CTypes.cpp
js/src/ctypes/Library.cpp
js/src/jsapi-tests/testChromeBuffer.cpp
js/src/jsapi-tests/testClassGetter.cpp
js/src/jsapi-tests/testLookup.cpp
js/src/jsapi-tests/testOps.cpp
js/src/jsapi-tests/testPropCache.cpp
js/src/jsapi-tests/testResolveRecursion.cpp
js/src/jsapi-tests/tests.h
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jstypedarray.cpp
js/src/jsxml.cpp
js/src/perf/jsperf.cpp
js/src/shell/js.cpp
js/xpconnect/src/XPCQuickStubs.cpp
js/xpconnect/src/dombindingsgen.py
js/xpconnect/wrappers/XrayWrapper.cpp
startupcache/test/TestStartupCache.cpp
toolkit/components/telemetry/Telemetry.cpp
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -511,18 +511,17 @@ GenerateRequest(IDBObjectStore* aObjectS
                             aObjectStore->Transaction());
 }
 
 JSClass gDummyPropClass = {
   "dummy", 0,
   JS_PropertyStub,  JS_PropertyStub,
   JS_PropertyStub,  JS_StrictPropertyStub,
   JS_EnumerateStub, JS_ResolveStub,
-  JS_ConvertStub, JS_FinalizeStub,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_ConvertStub
 };
 
 } // anonymous namespace
 
 // static
 already_AddRefed<IDBObjectStore>
 IDBObjectStore::Create(IDBTransaction* aTransaction,
                        ObjectStoreInfo* aStoreInfo,
@@ -2471,17 +2470,17 @@ class ThreadLocalJSRuntime
     }
   }
 };
 
 JSClass ThreadLocalJSRuntime::sGlobalClass = {
   "IndexedDBTransactionThreadGlobal",
   JSCLASS_GLOBAL_FLAGS,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
 };
 
 CreateIndexHelper::CreateIndexHelper(IDBTransaction* aTransaction,
                                      IDBIndex* aIndex)
   : AsyncConnectionHelper(aTransaction, nsnull), mIndex(aIndex)
 {
   if (sTLSIndex == BAD_TLS_INDEX) {
     PR_NewThreadPrivateIndex(&sTLSIndex, DestroyTLSEntry);
--- a/dom/workers/EventTarget.cpp
+++ b/dom/workers/EventTarget.cpp
@@ -54,18 +54,17 @@ USING_WORKERS_NAMESPACE
 using mozilla::dom::workers::events::EventTarget;
 
 namespace {
 
 #define DECL_EVENTTARGET_CLASS(_varname, _name) \
   JSClass _varname = { \
     _name, 0, \
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub, \
-    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, \
-    JSCLASS_NO_OPTIONAL_MEMBERS \
+    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub \
   };
 
 DECL_EVENTTARGET_CLASS(gClass, "EventTarget")
 DECL_EVENTTARGET_CLASS(gMainThreadClass, "WorkerEventTarget")
 
 #undef DECL_EVENTTARGET_CLASS
 
 inline
--- a/dom/workers/Events.cpp
+++ b/dom/workers/Events.cpp
@@ -360,18 +360,17 @@ private:
   }
 };
 
 #define DECL_EVENT_CLASS(_varname, _name) \
   JSClass _varname = { \
     _name, \
     JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT), \
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub, \
-    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize, \
-    JSCLASS_NO_OPTIONAL_MEMBERS \
+    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize \
   };
 
 DECL_EVENT_CLASS(Event::sClass, "Event")
 DECL_EVENT_CLASS(Event::sMainRuntimeClass, "WorkerEvent")
 
 #undef DECL_EVENT_CLASS
 
 JSPropertySpec Event::sProperties[] = {
@@ -613,18 +612,17 @@ private:
   }
 };
 
 #define DECL_MESSAGEEVENT_CLASS(_varname, _name) \
   JSClass _varname = { \
     _name, \
     JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT), \
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub, \
-    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize, \
-    JSCLASS_NO_OPTIONAL_MEMBERS \
+    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize \
   };
 
 DECL_MESSAGEEVENT_CLASS(MessageEvent::sClass, "MessageEvent")
 DECL_MESSAGEEVENT_CLASS(MessageEvent::sMainRuntimeClass, "WorkerMessageEvent")
 
 #undef DECL_MESSAGEEVENT_CLASS
 
 JSPropertySpec MessageEvent::sProperties[] = {
@@ -799,18 +797,17 @@ private:
   }
 };
 
 #define DECL_ERROREVENT_CLASS(_varname, _name) \
   JSClass _varname = { \
     _name, \
     JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT), \
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub, \
-    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize, \
-    JSCLASS_NO_OPTIONAL_MEMBERS \
+    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize \
   };
 
 DECL_ERROREVENT_CLASS(ErrorEvent::sClass, "ErrorEvent")
 DECL_ERROREVENT_CLASS(ErrorEvent::sMainRuntimeClass, "WorkerErrorEvent")
 
 #undef DECL_ERROREVENT_CLASS
 
 JSPropertySpec ErrorEvent::sProperties[] = {
@@ -979,18 +976,17 @@ private:
     return true;
   }
 };
 
 JSClass ProgressEvent::sClass = {
   "ProgressEvent",
   JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
 };
 
 JSPropertySpec ProgressEvent::sProperties[] = {
   { "lengthComputable", SLOT_lengthComputable, PROPERTY_FLAGS, GetProperty,
     js_GetterOnlyPropertyStub },
   { "loaded", SLOT_loaded, PROPERTY_FLAGS, GetProperty, 
     js_GetterOnlyPropertyStub },
   { "total", SLOT_total, PROPERTY_FLAGS, GetProperty, 
--- a/dom/workers/Exceptions.cpp
+++ b/dom/workers/Exceptions.cpp
@@ -181,18 +181,17 @@ private:
     return true;
   }
 };
 
 JSClass DOMException::sClass = {
   "DOMException",
   JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
 };
 
 JSPropertySpec DOMException::sProperties[] = {
   { "code", SLOT_code, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
   { "name", SLOT_name, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
   { 0, 0, 0, NULL, NULL }
 };
 
@@ -353,18 +352,17 @@ private:
     return true;
   }
 };
 
 JSClass FileException::sClass = {
   "FileException",
   JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
 };
 
 JSPropertySpec FileException::sProperties[] = {
   { "code", SLOT_code, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
   { "name", SLOT_name, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
   { 0, 0, 0, NULL, NULL }
 };
 
--- a/dom/workers/File.cpp
+++ b/dom/workers/File.cpp
@@ -214,18 +214,17 @@ private:
     return true;
   }
 };
 
 JSClass Blob::sClass = {
   "Blob",
   JSCLASS_HAS_PRIVATE,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
 };
 
 JSPropertySpec Blob::sProperties[] = {
   { "size", 0, PROPERTY_FLAGS, GetSize, js_GetterOnlyPropertyStub },
   { "type", 0, PROPERTY_FLAGS, GetType, js_GetterOnlyPropertyStub },
   { 0, 0, 0, NULL, NULL }
 };
 
@@ -365,18 +364,17 @@ private:
     return true;
   }
 };
 
 JSClass File::sClass = {
   "File",
   JSCLASS_HAS_PRIVATE,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
 };
 
 JSPropertySpec File::sProperties[] = {
   { "name", 0, PROPERTY_FLAGS, GetName, js_GetterOnlyPropertyStub },
   { "mozFullPath", 0, PROPERTY_FLAGS, GetMozFullPath,
     js_GetterOnlyPropertyStub },
   { 0, 0, 0, NULL, NULL }
 };
--- a/dom/workers/FileReaderSync.cpp
+++ b/dom/workers/FileReaderSync.cpp
@@ -338,18 +338,17 @@ private:
     return true;
   }
 };
 
 JSClass FileReaderSync::sClass = {
   "FileReaderSync",
   JSCLASS_HAS_PRIVATE,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
 };
 
 JSFunctionSpec FileReaderSync::sFunctions[] = {
   JS_FN("readAsArrayBuffer", ReadAsArrayBuffer, 1, FUNCTION_FLAGS),
   JS_FN("readAsBinaryString", ReadAsBinaryString, 1, FUNCTION_FLAGS),
   JS_FN("readAsText", ReadAsText, 1, FUNCTION_FLAGS),
   JS_FN("readAsDataURL", ReadAsDataURL, 1, FUNCTION_FLAGS),
   JS_FS_END
--- a/dom/workers/Location.cpp
+++ b/dom/workers/Location.cpp
@@ -178,18 +178,17 @@ private:
     return true;
   }
 };
 
 JSClass Location::sClass = {
   "WorkerLocation",
   JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
 };
 
 JSPropertySpec Location::sProperties[] = {
   { "href", SLOT_href, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
   { "protocol", SLOT_protocol, PROPERTY_FLAGS, GetProperty, 
     js_GetterOnlyPropertyStub },
   { "host", SLOT_host, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
   { "hostname", SLOT_hostname, PROPERTY_FLAGS, GetProperty, 
--- a/dom/workers/Navigator.cpp
+++ b/dom/workers/Navigator.cpp
@@ -167,18 +167,17 @@ private:
     return true;
   }
 };
 
 JSClass Navigator::sClass = {
   "WorkerNavigator",
   JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
 };
 
 JSPropertySpec Navigator::sProperties[] = {
   { "appName", SLOT_appName, PROPERTY_FLAGS, GetProperty, 
     js_GetterOnlyPropertyStub },
   { "appVersion", SLOT_appVersion, PROPERTY_FLAGS, GetProperty, 
     js_GetterOnlyPropertyStub },
   { "platform", SLOT_platform, PROPERTY_FLAGS, GetProperty, 
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -587,18 +587,17 @@ private:
     return true;
   }
 };
 
 JSClass WorkerGlobalScope::sClass = {
   "WorkerGlobalScope",
   0,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
 };
 
 JSPropertySpec WorkerGlobalScope::sProperties[] = {
   { "location", SLOT_location, PROPERTY_FLAGS, GetLocation, 
     js_GetterOnlyPropertyStub },
   { sEventStrings[STRING_onerror], STRING_onerror, PROPERTY_FLAGS,
     GetOnErrorListener, SetOnErrorListener },
   { sEventStrings[STRING_onclose], STRING_onclose, PROPERTY_FLAGS,
--- a/gfx/skia/src/xml/SkJS.cpp
+++ b/gfx/skia/src/xml/SkJS.cpp
@@ -150,17 +150,17 @@ global_resolve(JSContext *cx, JSObject *
 #endif
 }
 
 JSClass global_class = {
     "global", JSCLASS_NEW_RESOLVE,
     JS_PropertyStub,  JS_PropertyStub,
     JS_PropertyStub,  JS_PropertyStub,
     global_enumerate, (JSResolveOp) global_resolve,
-    JS_ConvertStub,   JS_FinalizeStub
+    JS_ConvertStub
 };
 
 SkJS::SkJS(void* hwnd) : SkOSWindow(hwnd) {
     if ((fRuntime = JS_NewRuntime(0x100000)) == NULL) {
         SkASSERT(0);
         return;
     }
     if ((fContext = JS_NewContext(fRuntime, 0x1000)) == NULL) {
--- a/js/ipc/ObjectWrapperChild.cpp
+++ b/js/ipc/ObjectWrapperChild.cpp
@@ -425,18 +425,17 @@ CPOW_NewEnumerateState_Finalize(JSContex
 // Similar to IteratorClass in XPCWrapper.cpp
 static const JSClass sCPOW_NewEnumerateState_JSClass = {
     "CPOW NewEnumerate State",
     JSCLASS_HAS_PRIVATE |
     JSCLASS_HAS_RESERVED_SLOTS(sNumNewEnumerateStateSlots),
     JS_PropertyStub,  JS_PropertyStub,
     JS_PropertyStub,  JS_StrictPropertyStub,
     JS_EnumerateStub, JS_ResolveStub,
-    JS_ConvertStub,   CPOW_NewEnumerateState_Finalize,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_ConvertStub,   CPOW_NewEnumerateState_Finalize
 };
 
 bool
 ObjectWrapperChild::AnswerNewEnumerateInit(/* no in-parameters */
                                            OperationStatus* status, JSVariant* statep, int* idp)
 {
     *idp = 0;
 
--- a/js/jsd/jsd_high.c
+++ b/js/jsd/jsd_high.c
@@ -67,18 +67,17 @@ void JSD_ASSERT_VALID_CONTEXT(JSDContext
     JS_ASSERT(jsdc->dumbContext);
     JS_ASSERT(jsdc->glob);
 }
 #endif
 
 static JSClass global_class = {
     "JSDGlobal", JSCLASS_GLOBAL_FLAGS,
     JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_StrictPropertyStub,
-    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   JS_FinalizeStub,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub
 };
 
 static JSBool
 _validateUserCallbacks(JSD_UserCallbacks* callbacks)
 {
     return !callbacks ||
            (callbacks->size && callbacks->size <= sizeof(JSD_UserCallbacks));
 }    
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -215,26 +215,24 @@ namespace UInt64 {
 *******************************************************************************/
 
 // Class representing the 'ctypes' object itself. This exists to contain the
 // JSCTypesCallbacks set of function pointers.
 static JSClass sCTypesGlobalClass = {
   "ctypes",
   JSCLASS_HAS_RESERVED_SLOTS(CTYPESGLOBAL_SLOTS),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
 };
 
 static JSClass sCABIClass = {
   "CABI",
   JSCLASS_HAS_RESERVED_SLOTS(CABI_SLOTS),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
 };
 
 // Class representing ctypes.{C,Pointer,Array,Struct,Function}Type.prototype.
 // This exists to give said prototypes a class of "CType", and to provide
 // reserved slots for stashing various other prototype objects.
 static JSClass sCTypeProtoClass = {
   "CType",
   JSCLASS_HAS_RESERVED_SLOTS(CTYPEPROTO_SLOTS),
@@ -244,18 +242,17 @@ static JSClass sCTypeProtoClass = {
 };
 
 // Class representing ctypes.CData.prototype and the 'prototype' properties
 // of CTypes. This exists to give said prototypes a class of "CData".
 static JSClass sCDataProtoClass = {
   "CData",
   0,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
 };
 
 static JSClass sCTypeClass = {
   "CType",
   JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(CTYPE_SLOTS),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, CType::Finalize,
   NULL, CType::ConstructData, CType::ConstructData,
@@ -388,42 +385,38 @@ static JSPropertySpec sFunctionProps[] =
   { "isVariadic", 0, CTYPESPROP_FLAGS, FunctionType::IsVariadicGetter, NULL },
   { 0, 0, 0, NULL, NULL }
 };
 
 static JSClass sInt64ProtoClass = {
   "Int64",
   0,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
 };
 
 static JSClass sUInt64ProtoClass = {
   "UInt64",
   0,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
 };
 
 static JSClass sInt64Class = {
   "Int64",
   JSCLASS_HAS_RESERVED_SLOTS(INT64_SLOTS),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Int64Base::Finalize,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Int64Base::Finalize
 };
 
 static JSClass sUInt64Class = {
   "UInt64",
   JSCLASS_HAS_RESERVED_SLOTS(INT64_SLOTS),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Int64Base::Finalize,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Int64Base::Finalize
 };
 
 static JSFunctionSpec sInt64StaticFunctions[] = {
   JS_FN("compare", Int64::Compare, 2, CTYPESFN_FLAGS),
   JS_FN("lo", Int64::Lo, 1, CTYPESFN_FLAGS),
   JS_FN("hi", Int64::Hi, 1, CTYPESFN_FLAGS),
   JS_FN("join", Int64::Join, 2, CTYPESFN_FLAGS),
   JS_FS_END
--- a/js/src/ctypes/Library.cpp
+++ b/js/src/ctypes/Library.cpp
@@ -62,18 +62,17 @@ namespace Library
 /*******************************************************************************
 ** JSObject implementation
 *******************************************************************************/
 
 static JSClass sLibraryClass = {
   "Library",
   JSCLASS_HAS_RESERVED_SLOTS(LIBRARY_SLOTS),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub,JS_ResolveStub, JS_ConvertStub, Library::Finalize,
-  JSCLASS_NO_OPTIONAL_MEMBERS
+  JS_EnumerateStub,JS_ResolveStub, JS_ConvertStub, Library::Finalize
 };
 
 #define CTYPESFN_FLAGS \
   (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)
 
 static JSFunctionSpec sLibraryFunctions[] = {
   JS_FN("close",   Library::Close,   0, CTYPESFN_FLAGS),
   JS_FN("declare", Library::Declare, 0, CTYPESFN_FLAGS),
--- a/js/src/jsapi-tests/testChromeBuffer.cpp
+++ b/js/src/jsapi-tests/testChromeBuffer.cpp
@@ -8,19 +8,17 @@ JSClass global_class = {
     "global",
     JSCLASS_IS_GLOBAL | JSCLASS_GLOBAL_FLAGS,
     JS_PropertyStub,
     JS_PropertyStub,
     JS_PropertyStub,
     JS_StrictPropertyStub,
     JS_EnumerateStub,
     JS_ResolveStub,
-    JS_ConvertStub,
-    JS_FinalizeStub,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_ConvertStub
 };
 
 JS::Anchor<JSObject *> trusted_glob, trusted_fun;
 
 JSBool
 CallTrusted(JSContext *cx, unsigned argc, jsval *vp)
 {
     if (!JS_SaveFrameChain(cx))
--- a/js/src/jsapi-tests/testClassGetter.cpp
+++ b/js/src/jsapi-tests/testClassGetter.cpp
@@ -30,19 +30,17 @@ static JSClass ptestClass = {
     JSCLASS_HAS_PRIVATE,
 
     JS_PropertyStub,       // add
     JS_PropertyStub,       // delete
     test_prop_get,         // get
     JS_StrictPropertyStub, // set
     JS_EnumerateStub,
     JS_ResolveStub,
-    JS_ConvertStub,
-    JS_FinalizeStub,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_ConvertStub
 };
 
 static JSBool test_fn(JSContext *cx, unsigned argc, jsval *vp)
 {
     called_test_fn++;
     return JS_TRUE;
 }
 
--- a/js/src/jsapi-tests/testLookup.cpp
+++ b/js/src/jsapi-tests/testLookup.cpp
@@ -54,18 +54,17 @@ document_resolve(JSContext *cx, JSObject
     }
     *objp = NULL;
     return true;
 }
 
 static JSClass document_class = {
     "document", JSCLASS_NEW_RESOLVE,
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-    JS_EnumerateStub, (JSResolveOp) document_resolve, JS_ConvertStub, JS_FinalizeStub,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_EnumerateStub, (JSResolveOp) document_resolve, JS_ConvertStub
 };
 
 BEGIN_TEST(testLookup_bug570195)
 {
     JSObject *obj = JS_NewObject(cx, &document_class, NULL, NULL);
     CHECK(obj);
     CHECK(JS_DefineProperty(cx, global, "document", OBJECT_TO_JSVAL(obj), NULL, NULL, 0));
     jsvalRoot v(cx);
--- a/js/src/jsapi-tests/testOps.cpp
+++ b/js/src/jsapi-tests/testOps.cpp
@@ -13,18 +13,17 @@ my_convert(JSContext* context, JSObject*
         return JS_NewNumberValue(context, 123, rval);
     return JS_FALSE;
 }
 
 static JSClass myClass = {
     "MyClass",
     0,
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-    JS_EnumerateStub, JS_ResolveStub, my_convert, JS_FinalizeStub,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_EnumerateStub, JS_ResolveStub, my_convert
 };
 
 static JSBool
 createMyObject(JSContext* context, unsigned argc, jsval *vp)
 {
     JS_BeginRequest(context);
 
     //JS_GC(context); //<- if we make GC here, all is ok
--- a/js/src/jsapi-tests/testPropCache.cpp
+++ b/js/src/jsapi-tests/testPropCache.cpp
@@ -12,18 +12,17 @@ CounterAdd(JSContext *cx, JSObject *obj,
     g_counter++;
     return JS_TRUE;
 }
 
 static JSClass CounterClass = {
     "Counter",  /* name */
     0,  /* flags */
     CounterAdd, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
 };
 
 BEGIN_TEST(testPropCache_bug505798)
 {
     g_counter = 0;
     EXEC("var x = {};");
     CHECK(JS_DefineObject(cx, global, "y", &CounterClass, NULL, JSPROP_ENUMERATE));
     EXEC("var arr = [x, y];\n"
--- a/js/src/jsapi-tests/testResolveRecursion.cpp
+++ b/js/src/jsapi-tests/testResolveRecursion.cpp
@@ -16,19 +16,17 @@ BEGIN_TEST(testResolveRecursion)
         JSCLASS_NEW_RESOLVE | JSCLASS_HAS_PRIVATE,
         
         JS_PropertyStub,       // add
         JS_PropertyStub,       // delete
         JS_PropertyStub,         // get
         JS_StrictPropertyStub, // set
         JS_EnumerateStub,
         (JSResolveOp) my_resolve,
-        JS_ConvertStub,
-        JS_FinalizeStub,
-        JSCLASS_NO_OPTIONAL_MEMBERS
+        JS_ConvertStub
     };
     
     obj1 = JS_NewObject(cx, &my_resolve_class, NULL, NULL);
     CHECK(obj1);
     obj2 = JS_NewObject(cx, &my_resolve_class, NULL, NULL);
     CHECK(obj2);
     JS_SetPrivate(obj1, this);
     JS_SetPrivate(obj2, this);
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -300,18 +300,17 @@ class JSAPITest
     }
 
     JSAPITestString messages() const { return msgs; }
 
     static JSClass * basicGlobalClass() {
         static JSClass c = {
             "global", JSCLASS_GLOBAL_FLAGS,
             JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-            JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
-            JSCLASS_NO_OPTIONAL_MEMBERS
+            JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
         };
         return &c;
     }
 
   protected:
     static JSBool
     print(JSContext *cx, unsigned argc, jsval *vp)
     {
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3082,20 +3082,16 @@ JS_ResolveStub(JSContext *cx, JSObject *
 JS_PUBLIC_API(JSBool)
 JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
 {
     JS_ASSERT(type != JSTYPE_OBJECT && type != JSTYPE_FUNCTION);
     JS_ASSERT(obj);
     return DefaultValue(cx, obj, type, vp);
 }
 
-JS_PUBLIC_API(void)
-JS_FinalizeStub(JSContext *cx, JSObject *obj)
-{}
-
 JS_PUBLIC_API(JSObject *)
 JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
              JSClass *clasp, JSNative constructor, unsigned nargs,
              JSPropertySpec *ps, JSFunctionSpec *fs,
              JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
 {
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3604,19 +3604,16 @@ extern JS_PUBLIC_API(JSBool)
 JS_EnumerateStub(JSContext *cx, JSObject *obj);
 
 extern JS_PUBLIC_API(JSBool)
 JS_ResolveStub(JSContext *cx, JSObject *obj, jsid id);
 
 extern JS_PUBLIC_API(JSBool)
 JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
 
-extern JS_PUBLIC_API(void)
-JS_FinalizeStub(JSContext *cx, JSObject *obj);
-
 struct JSConstDoubleSpec {
     double          dval;
     const char      *name;
     uint8_t         flags;
     uint8_t         spare[3];
 };
 
 /*
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -269,17 +269,21 @@ DelegateObject(JSContext *cx, JSObject *
 }
 
 JSObject *
 ArrayBuffer::create(JSContext *cx, int32_t nbytes, uint8_t *contents)
 {
     JSObject *obj = NewBuiltinClassInstance(cx, &ArrayBuffer::slowClass);
     if (!obj)
         return NULL;
+#ifdef JS_THREADSAFE
+    JS_ASSERT(obj->getAllocKind() == gc::FINALIZE_OBJECT16_BACKGROUND);
+#else
     JS_ASSERT(obj->getAllocKind() == gc::FINALIZE_OBJECT16);
+#endif
 
     if (nbytes < 0) {
         /*
          * We're just not going to support arrays that are bigger than what will fit
          * as an integer value; if someone actually ever complains (validly), then we
          * can fix.
          */
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
@@ -1434,17 +1438,21 @@ class TypedArrayTemplate
 
     static JSObject *
     createTypedArray(JSContext *cx, JSObject *bufobj, uint32_t byteOffset, uint32_t len)
     {
         JS_ASSERT(bufobj->isArrayBuffer());
         JSObject *obj = NewBuiltinClassInstance(cx, slowClass());
         if (!obj)
             return NULL;
+#ifdef JS_THREADSAFE
+        JS_ASSERT(obj->getAllocKind() == gc::FINALIZE_OBJECT8_BACKGROUND);
+#else
         JS_ASSERT(obj->getAllocKind() == gc::FINALIZE_OBJECT8);
+#endif
 
         /*
          * Specialize the type of the object on the current scripted location,
          * and mark the type as definitely a typed array.
          */
         JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(slowClass());
         types::TypeObject *type = types::GetTypeCallerInitObject(cx, key);
         if (!type)
@@ -2171,18 +2179,17 @@ Class ArrayBuffer::slowClass = {
     JSCLASS_HAS_RESERVED_SLOTS(ARRAYBUFFER_RESERVED_SLOTS) |
     JSCLASS_HAS_CACHED_PROTO(JSProto_ArrayBuffer),
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
-    JS_ConvertStub,
-    JS_FinalizeStub
+    JS_ConvertStub
 };
 
 Class js::ArrayBufferClass = {
     "ArrayBuffer",
     JSCLASS_HAS_PRIVATE |
     JSCLASS_IMPLEMENTS_BARRIERS |
     Class::NON_NATIVE |
     JSCLASS_HAS_RESERVED_SLOTS(ARRAYBUFFER_RESERVED_SLOTS) |
@@ -2287,18 +2294,17 @@ JSFunctionSpec _typedArray::jsfuncs[] = 
     JSCLASS_HAS_PRIVATE |                                                      \
     JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray),                           \
     JS_PropertyStub,         /* addProperty */                                 \
     JS_PropertyStub,         /* delProperty */                                 \
     JS_PropertyStub,         /* getProperty */                                 \
     JS_StrictPropertyStub,   /* setProperty */                                 \
     JS_EnumerateStub,                                                          \
     JS_ResolveStub,                                                            \
-    JS_ConvertStub,                                                            \
-    JS_FinalizeStub                                                            \
+    JS_ConvertStub                                                             \
 }
 
 #define IMPL_TYPED_ARRAY_FAST_CLASS(_typedArray)                               \
 {                                                                              \
     #_typedArray,                                                              \
     JSCLASS_HAS_RESERVED_SLOTS(TypedArray::FIELD_MAX) |                        \
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |                        \
     JSCLASS_FOR_OF_ITERATION |                                                 \
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -227,22 +227,22 @@ JS_FRIEND_DATA(Class) js::NamespaceClass
     JSCLASS_HAS_CACHED_PROTO(JSProto_Namespace),
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub,
-    JS_FinalizeStub,
+    NULL,                    /* finalize    */
     NULL,                    /* checkAccess */
     NULL,                    /* call        */
     NULL,                    /* construct   */
     NULL,                    /* hasInstance */
-    NULL,                    /* mark        */
+    NULL,                    /* trace       */
     {
         namespace_equality,
         NULL,                /* outerObject    */
         NULL,                /* innerObject    */
         NULL,                /* iteratorObject */
         NULL,                /* wrappedObject  */
     }
 };
@@ -341,22 +341,22 @@ JS_FRIEND_DATA(Class) js::QNameClass = {
     JSCLASS_HAS_CACHED_PROTO(JSProto_QName),
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub,
-    JS_FinalizeStub,
+    NULL,                    /* finalize    */
     NULL,                    /* checkAccess */
     NULL,                    /* call        */
     NULL,                    /* construct   */
     NULL,                    /* hasInstance */
-    NULL,                    /* mark        */
+    NULL,                    /* trace       */
     {
         qname_equality,
         NULL,                /* outerObject    */
         NULL,                /* innerObject    */
         NULL,                /* iteratorObject */
         NULL,                /* wrappedObject  */
     }
 };
@@ -372,32 +372,30 @@ JS_FRIEND_DATA(Class) js::AttributeNameC
     JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_CLASS_RESERVED_SLOTS) |
     JSCLASS_IS_ANONYMOUS,
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
-    JS_ConvertStub,
-    JS_FinalizeStub
+    JS_ConvertStub
 };
 
 JS_FRIEND_DATA(Class) js::AnyNameClass = {
     js_AnyName_str,
     JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_CLASS_RESERVED_SLOTS) |
     JSCLASS_IS_ANONYMOUS,
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
-    JS_ConvertStub,
-    JS_FinalizeStub
+    JS_ConvertStub
 };
 
 #define QNAME_ATTRS (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED)
 
 static JSPropertySpec qname_props[] = {
     {js_uri_str,       0, QNAME_ATTRS, QNameNameURI_getter,   0},
     {js_localName_str, 0, QNAME_ATTRS, QNameLocalName_getter, 0},
     {0,0,0,0,0}
@@ -4716,21 +4714,16 @@ HasProperty(JSContext *cx, JSObject *obj
                 return JS_FALSE;
         } else {
             *found = HasNamedProperty(xml, qn);
         }
     }
     return JS_TRUE;
 }
 
-static void
-xml_finalize(JSContext *cx, JSObject *obj)
-{
-}
-
 /*
  * XML objects are native. Thus xml_lookupGeneric must return a valid
  * Shape pointer parameter via *propp to signify "property found". Since the
  * only call to xml_lookupGeneric is via JSObject::lookupGeneric, and then
  * only from js_FindProperty (in jsobj.c, called from jsinterp.c) or from
  * JSOP_IN case in the interpreter, the only time we add a Shape here is when
  * an unqualified name is being accessed or when "name in xml" is called.
  *
@@ -5371,20 +5364,20 @@ JS_FRIEND_DATA(Class) js::XMLClass = {
     JSCLASS_HAS_CACHED_PROTO(JSProto_XML),
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
     xml_convert,
-    xml_finalize,
-    NULL,                 /* checkAccess */
-    NULL,                 /* call        */
-    NULL,                 /* construct   */
+    NULL,                    /* finalize    */
+    NULL,                    /* checkAccess */
+    NULL,                    /* call        */
+    NULL,                    /* construct   */
     xml_hasInstance,
     xml_trace,
     JS_NULL_CLASS_EXT,
     {
         xml_lookupGeneric,
         xml_lookupProperty,
         xml_lookupElement,
         xml_lookupSpecial,
--- a/js/src/perf/jsperf.cpp
+++ b/js/src/perf/jsperf.cpp
@@ -214,18 +214,17 @@ static const struct pm_const {
     { 0, PerfMeasurement::EventMask(0) }
 };
 
 #undef CONSTANT
 
 static JSClass pm_class = {
     "PerfMeasurement", JSCLASS_HAS_PRIVATE,
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, pm_finalize,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, pm_finalize
 };
 
 // Helpers (declared above)
 
 static PerfMeasurement*
 GetPM(JSContext* cx, JSObject* obj, const char* fname)
 {
     PerfMeasurement* p = (PerfMeasurement*)
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -2589,18 +2589,17 @@ sandbox_resolve(JSContext *cx, JSObject 
 }
 
 static JSClass sandbox_class = {
     "sandbox",
     JSCLASS_NEW_RESOLVE | JSCLASS_GLOBAL_FLAGS,
     JS_PropertyStub,   JS_PropertyStub,
     JS_PropertyStub,   JS_StrictPropertyStub,
     sandbox_enumerate, (JSResolveOp)sandbox_resolve,
-    JS_ConvertStub,    NULL,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_ConvertStub
 };
 
 static JSObject *
 NewSandbox(JSContext *cx, bool lazy)
 {
     JSObject *obj = JS_NewCompartmentAndGlobalObject(cx, &sandbox_class, NULL);
     if (!obj)
         return NULL;
@@ -2850,18 +2849,17 @@ resolver_enumerate(JSContext *cx, JSObje
 }
 
 static JSClass resolver_class = {
     "resolver",
     JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(1),
     JS_PropertyStub,   JS_PropertyStub,
     JS_PropertyStub,   JS_StrictPropertyStub,
     resolver_enumerate, (JSResolveOp)resolver_resolve,
-    JS_ConvertStub,    NULL,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_ConvertStub
 };
 
 
 static JSBool
 Resolver(JSContext *cx, unsigned argc, jsval *vp)
 {
     JSObject *referent, *proto = NULL;
     if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "o/o", &referent, &proto))
@@ -3275,18 +3273,17 @@ Compile(JSContext *cx, unsigned argc, js
     }
 
     static JSClass dummy_class = {
         "jdummy",
         JSCLASS_GLOBAL_FLAGS,
         JS_PropertyStub,  JS_PropertyStub,
         JS_PropertyStub,  JS_StrictPropertyStub,
         JS_EnumerateStub, JS_ResolveStub,
-        JS_ConvertStub,   NULL,
-        JSCLASS_NO_OPTIONAL_MEMBERS
+        JS_ConvertStub
     };
 
     JSObject *fakeGlobal = JS_NewGlobalObject(cx, &dummy_class);
     if (!fakeGlobal)
         return JS_FALSE;
 
     JSString *scriptContents = JSVAL_TO_STRING(arg0);
 
@@ -4107,18 +4104,17 @@ its_finalize(JSContext *cx, JSObject *ob
       delete rootedVal;
     }
 }
 
 static JSClass its_class = {
     "It", JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE | JSCLASS_HAS_PRIVATE,
     its_addProperty,  its_delProperty,  its_getProperty,  its_setProperty,
     (JSEnumerateOp)its_enumerate, (JSResolveOp)its_resolve,
-    its_convert,      its_finalize,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    its_convert,      its_finalize
 };
 
 static JSBool
 its_getter(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 {
     if (JS_GetClass(obj) == &its_class) {
         jsval *val = (jsval *) JS_GetPrivate(obj);
         *vp = val ? *val : JSVAL_VOID;
@@ -4401,18 +4397,17 @@ global_resolve(JSContext *cx, JSObject *
 #endif
 }
 
 JSClass global_class = {
     "global", JSCLASS_NEW_RESOLVE | JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_PRIVATE,
     JS_PropertyStub,  JS_PropertyStub,
     JS_PropertyStub,  JS_StrictPropertyStub,
     global_enumerate, (JSResolveOp) global_resolve,
-    JS_ConvertStub,   its_finalize,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_ConvertStub,   its_finalize
 };
 
 static JSBool
 env_setProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
 {
 /* XXX porting may be easy, but these don't seem to supply setenv by default */
 #if !defined XP_OS2 && !defined SOLARIS
     int rv;
@@ -4515,18 +4510,17 @@ env_resolve(JSContext *cx, JSObject *obj
     return JS_TRUE;
 }
 
 static JSClass env_class = {
     "environment", JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE,
     JS_PropertyStub,  JS_PropertyStub,
     JS_PropertyStub,  env_setProperty,
     env_enumerate, (JSResolveOp) env_resolve,
-    JS_ConvertStub,   NULL,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_ConvertStub
 };
 
 /*
  * Avoid a reentrancy hazard.
  *
  * The non-JS_THREADSAFE shell uses a signal handler to implement timeout().
  * The JS engine is not really reentrant, but JS_TriggerAllOperationCallbacks
  * is mostly safe--the only danger is that we might interrupt JS_NewContext or
--- a/js/xpconnect/src/XPCQuickStubs.cpp
+++ b/js/xpconnect/src/XPCQuickStubs.cpp
@@ -170,18 +170,17 @@ PointerFinalize(JSContext *cx, JSObject 
     JSPropertyOp *popp = static_cast<JSPropertyOp *>(JS_GetPrivate(obj));
     delete popp;
 }
 
 static JSClass
 PointerHolderClass = {
     "Pointer", JSCLASS_HAS_PRIVATE,
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, PointerFinalize,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, PointerFinalize
 };
 
 template<typename Op>
 static JSObject *
 GeneratePropertyOp(JSContext *cx, JSObject *obj, jsid id, unsigned argc, Op pop)
 {
     // The JS engine provides two reserved slots on function objects for
     // XPConnect to use. Use them to stick the necessary info here.
--- a/js/xpconnect/src/dombindingsgen.py
+++ b/js/xpconnect/src/dombindingsgen.py
@@ -447,20 +447,20 @@ listTemplate = (
 "    0,\n"
 "    JS_PropertyStub,        /* addProperty */\n"
 "    JS_PropertyStub,        /* delProperty */\n"
 "    JS_PropertyStub,        /* getProperty */\n"
 "    JS_StrictPropertyStub,  /* setProperty */\n"
 "    JS_EnumerateStub,\n"
 "    JS_ResolveStub,\n"
 "    JS_ConvertStub,\n"
-"    JS_FinalizeStub,\n"
+"    NULL,                   /* finalize    */\n"
 "    NULL,                   /* checkAccess */\n"
-"    NULL,                   /* call */\n"
-"    NULL,                   /* construct */\n"
+"    NULL,                   /* call        */\n"
+"    NULL,                   /* construct   */\n"
 "    interface_hasInstance\n"
 "};\n"
 "\n")
 
 derivedClassTemplate = (
 "template<>\n"
 "bool\n"
 "${name}Wrapper::objIsList(JSObject *obj)\n"
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -104,18 +104,17 @@ static JSBool
 holder_set(JSContext *cx, JSObject *holder, jsid id, JSBool strict, jsval *vp);
 
 namespace XrayUtils {
 
 JSClass HolderClass = {
     "NativePropertyHolder",
     JSCLASS_HAS_RESERVED_SLOTS(3),
     JS_PropertyStub,        JS_PropertyStub, holder_get,      holder_set,
-    JS_EnumerateStub,       JS_ResolveStub,  JS_ConvertStub,  NULL,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_EnumerateStub,       JS_ResolveStub,  JS_ConvertStub
 };
 
 }
 
 using namespace XrayUtils;
 
 static JSObject *
 GetHolder(JSObject *obj)
--- a/startupcache/test/TestStartupCache.cpp
+++ b/startupcache/test/TestStartupCache.cpp
@@ -413,18 +413,17 @@ int main(int argc, char** argv)
     use_js = false;
 
   JSAutoRequest req(cx);
   static JSClass global_class = {
     "global", JSCLASS_NEW_RESOLVE | JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_PRIVATE,
     JS_PropertyStub,  JS_PropertyStub,
     JS_PropertyStub,  JS_StrictPropertyStub,
     JS_EnumerateStub, JS_ResolveStub,
-    JS_ConvertStub,   JS_FinalizeStub,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_ConvertStub
   };
   JSObject *glob = nsnull;
   if (use_js)
     glob = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
   if (!glob)
     use_js = false;
   JSCrossCompartmentCall *compartment = nsnull;
   if (use_js)
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -449,18 +449,17 @@ JSHistogram_Snapshot(JSContext *cx, unsi
 
 nsresult 
 WrapAndReturnHistogram(Histogram *h, JSContext *cx, jsval *ret)
 {
   static JSClass JSHistogram_class = {
     "JSHistogram",  /* name */
     JSCLASS_HAS_PRIVATE, /* flags */
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
   };
 
   JSObject *obj = JS_NewObject(cx, &JSHistogram_class, NULL, NULL);
   if (!obj)
     return NS_ERROR_FAILURE;
   JS::AutoObjectRooter root(cx, obj);
   if (!(JS_DefineFunction (cx, obj, "add", JSHistogram_Add, 1, 0)
         && JS_DefineFunction (cx, obj, "snapshot", JSHistogram_Snapshot, 1, 0))) {