Remove JSObject::isNewborn, refactor object creation code, bug 684507.
authorBrian Hackett <bhackett1024@gmail.com>
Wed, 02 Nov 2011 13:34:19 -0700
changeset 81288 3e9445901e8bc78e663e539f42683b08bbd6a8a6
parent 81287 ef1f81733ed8764409930afeacd268323fdd1e6c
child 81289 daa488a2e663671f96bbe4238f9be024e1b6e4e8
push id21565
push userbhackett@mozilla.com
push dateSat, 03 Dec 2011 20:25:52 +0000
treeherdermozilla-central@13afcd4c097c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs684507
milestone10.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
Remove JSObject::isNewborn, refactor object creation code, bug 684507.
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jsclass.h
js/src/jscompartment.cpp
js/src/jsexn.cpp
js/src/jsfun.cpp
js/src/jsgcinlines.h
js/src/jsgcmark.cpp
js/src/jsinterp.cpp
js/src/jsiter.cpp
js/src/jsmath.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/json.cpp
js/src/jsproxy.cpp
js/src/jsreflect.cpp
js/src/jstypedarray.cpp
js/src/jsxml.cpp
js/src/vm/BooleanObject-inl.h
js/src/vm/CallObject.cpp
js/src/vm/Debugger.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/NumberObject-inl.h
js/src/vm/RegExpObject.cpp
js/src/vm/RegExpStatics.cpp
js/src/vm/StringObject-inl.h
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3050,42 +3050,34 @@ JS_GetInstancePrivate(JSContext *cx, JSO
     if (!JS_InstanceOf(cx, obj, clasp, argv))
         return NULL;
     return obj->getPrivate();
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetPrototype(JSContext *cx, JSObject *obj)
 {
-    JSObject *proto;
-
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
-    proto = obj->getProto();
-
-    /* Beware ref to dead object (we may be called from obj's finalizer). */
-    return proto && !proto->isNewborn() ? proto : NULL;
+    return obj->getProto();
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, proto);
     return SetProto(cx, obj, proto, JS_FALSE);
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetParent(JSContext *cx, JSObject *obj)
 {
     assertSameCompartment(cx, obj);
-    JSObject *parent = obj->getParent();
-
-    /* Beware ref to dead object (we may be called from obj's finalizer). */
-    return parent && !parent->isNewborn() ? parent : NULL;
+    return obj->getParent();
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
 {
     CHECK_REQUEST(cx);
     JS_ASSERT(!obj->isScope());
     JS_ASSERT(parent || !obj->getParent());
@@ -3178,17 +3170,17 @@ JS_NewObject(JSContext *cx, JSClass *jsc
         clasp = &ObjectClass;    /* default class is Object */
 
     JS_ASSERT(clasp != &FunctionClass);
     JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
 
     if (proto)
         proto->getNewType(cx, NULL, /* markUnknown = */ true);
 
-    JSObject *obj = NewNonFunction<WithProto::Class>(cx, clasp, proto, parent);
+    JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, parent);
     if (obj) {
         if (clasp->ext.equality)
             MarkTypeObjectFlags(cx, obj, OBJECT_FLAG_SPECIAL_EQUALITY);
         MarkTypeObjectUnknownProperties(cx, obj->type());
     }
 
     JS_ASSERT_IF(obj, obj->getParent());
     return obj;
@@ -3203,17 +3195,17 @@ JS_NewObjectWithGivenProto(JSContext *cx
 
     Class *clasp = Valueify(jsclasp);
     if (!clasp)
         clasp = &ObjectClass;    /* default class is Object */
 
     JS_ASSERT(clasp != &FunctionClass);
     JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
 
-    JSObject *obj = NewNonFunction<WithProto::Given>(cx, clasp, proto, parent);
+    JSObject *obj = NewObjectWithGivenProto(cx, clasp, proto, parent);
     if (obj)
         MarkTypeObjectUnknownProperties(cx, obj->type());
     return obj;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_NewObjectForConstructor(JSContext *cx, const jsval *vp)
 {
@@ -3620,17 +3612,17 @@ JS_DefineObject(JSContext *cx, JSObject 
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, proto);
 
     Class *clasp = Valueify(jsclasp);
     if (!clasp)
         clasp = &ObjectClass;    /* default class is Object */
 
-    JSObject *nobj = NewObject<WithProto::Class>(cx, clasp, proto, obj);
+    JSObject *nobj = NewObjectWithClassProto(cx, clasp, proto, obj);
     if (!nobj)
         return NULL;
 
     if (!DefineProperty(cx, obj, name, ObjectValue(*nobj), NULL, NULL, attrs, 0, 0))
         return NULL;
 
     return nobj;
 }
@@ -4079,17 +4071,17 @@ JS_NewPropertyIterator(JSContext *cx, JS
 {
     JSObject *iterobj;
     const void *pdata;
     jsint index;
     JSIdArray *ida;
 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
-    iterobj = NewNonFunction<WithProto::Class>(cx, &prop_iter_class, NULL, obj);
+    iterobj = NewObjectWithClassProto(cx, &prop_iter_class, NULL, obj);
     if (!iterobj)
         return NULL;
 
     if (obj->isNative()) {
         /* Native case: start with the last property in obj. */
         pdata = obj->lastProperty();
         index = -1;
     } else {
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1310,17 +1310,17 @@ Class js::SlowArrayClass = {
 };
 
 bool
 JSObject::allocateSlowArrayElements(JSContext *cx)
 {
     JS_ASSERT(hasClass(&js::SlowArrayClass));
     JS_ASSERT(elements == emptyObjectElements);
 
-    ObjectElements *header = cx->new_<ObjectElements>(0);
+    ObjectElements *header = cx->new_<ObjectElements>(0, 0);
     if (!header)
         return false;
 
     elements = header->elements();
     return true;
 }
 
 static bool
@@ -1369,25 +1369,25 @@ JSObject::makeDenseArraySlow(JSContext *
     }
 
     /*
      * Save old map now, before calling InitScopeForObject. We'll have to undo
      * on error. This is gross, but a better way is not obvious. Note: the
      * exact contents of the array are not preserved on error.
      */
     js::Shape *oldShape = lastProperty();
-    shape_ = NULL;
 
     /* Create a native scope. */
     gc::AllocKind kind = getAllocKind();
-    if (!InitScopeForObject(cx, this, &SlowArrayClass, oldShape->getObjectParent(),
-                            getProto()->getNewType(cx), kind)) {
-        setLastPropertyInfallible(oldShape);
+    Shape *shape = GetInitialShapeForObject(cx, &SlowArrayClass,
+                                            oldShape->getObjectParent(),
+                                            getProto()->getNewType(cx), kind);
+    if (!shape)
         return false;
-    }
+    setLastPropertyInfallible(shape);
 
     /* Take ownership of the dense elements, reset to an empty dense array. */
     Value *elems = elements;
     elements = emptyObjectElements;
 
     /* Root all values in the array during conversion. */
     AutoValueArray autoArray(cx, elems, arrayInitialized);
 
@@ -3683,39 +3683,54 @@ js_InitArrayClass(JSContext *cx, JSObjec
  * Array allocation functions.
  */
 namespace js {
 
 template<bool allocateCapacity>
 static JS_ALWAYS_INLINE JSObject *
 NewArray(JSContext *cx, jsuint length, JSObject *proto)
 {
-    JS_ASSERT_IF(proto, proto->isArray());
+    if (!proto && !FindProto(cx, &ArrayClass, NULL, &proto))
+        return NULL;
 
     gc::AllocKind kind = GuessArrayGCKind(length);
-    JSObject *obj = NewObject<WithProto::Class>(cx, &ArrayClass, proto, NULL, kind);
+
+#ifdef JS_THREADSAFE
+    JS_ASSERT(CanBeFinalizedInBackground(kind, &ArrayClass));
+    kind = GetBackgroundAllocKind(kind);
+#endif
+
+    types::TypeObject *type = proto->getNewType(cx);
+    if (!type)
+        return NULL;
+
+    Shape *shape = GetInitialShapeForObject(cx, &ArrayClass, proto->getParent(), type, kind);
+    if (!shape)
+        return NULL;
+
+    JSObject* obj = js_NewGCObject(cx, kind);
     if (!obj)
         return NULL;
 
-    obj->initDenseArray();
-    obj->setArrayLength(cx, length);
+    obj->initializeDenseArray(shape, type, length);
 
     if (allocateCapacity) {
         /*
          * If ensureElements creates dynamically allocated slots, then having
          * fixedSlots is a waste.
          */
         DebugOnly<uint32> cap = obj->getDenseArrayCapacity();
 
         if (!obj->ensureElements(cx, length))
             return NULL;
 
         JS_ASSERT_IF(cap, !obj->hasDynamicElements());
     }
 
+    Probes::createObject(cx, obj);
     return obj;
 }
 
 JSObject * JS_FASTCALL
 NewDenseEmptyArray(JSContext *cx, JSObject *proto)
 {
     return NewArray<false>(cx, 0, proto);
 }
@@ -3780,17 +3795,17 @@ JS_DEFINE_CALLINFO_3(extern, OBJECT, New
                      nanojit::ACCSET_STORE_ANY)
 #endif
 
 
 
 JSObject *
 NewSlowEmptyArray(JSContext *cx)
 {
-    JSObject *obj = NewNonFunction<WithProto::Class>(cx, &SlowArrayClass, NULL, NULL);
+    JSObject *obj = NewBuiltinClassInstance(cx, &SlowArrayClass);
     if (!obj || !AddLengthProperty(cx, obj))
         return NULL;
 
     obj->setArrayLength(cx, 0);
     return obj;
 }
 
 }
--- a/js/src/jsclass.h
+++ b/js/src/jsclass.h
@@ -352,16 +352,20 @@ struct Class
                             sizeof(ClassExtension) - sizeof(ObjectOps)];
 
     /* Class is not native and its map is not a scope. */
     static const uint32 NON_NATIVE = JSCLASS_INTERNAL_FLAG2;
 
     bool isNative() const {
         return !(flags & NON_NATIVE);
     }
+
+    bool hasPrivate() const {
+        return !!(flags & JSCLASS_HAS_PRIVATE);
+    }
 };
 
 JS_STATIC_ASSERT(offsetof(JSClass, name) == offsetof(Class, name));
 JS_STATIC_ASSERT(offsetof(JSClass, flags) == offsetof(Class, flags));
 JS_STATIC_ASSERT(offsetof(JSClass, addProperty) == offsetof(Class, addProperty));
 JS_STATIC_ASSERT(offsetof(JSClass, delProperty) == offsetof(Class, delProperty));
 JS_STATIC_ASSERT(offsetof(JSClass, getProperty) == offsetof(Class, getProperty));
 JS_STATIC_ASSERT(offsetof(JSClass, setProperty) == offsetof(Class, setProperty));
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -436,17 +436,17 @@ JSCompartment::markTypes(JSTracer *trc)
         MarkScript(trc, script, "mark_types_script");
     }
 
     for (size_t thingKind = FINALIZE_OBJECT0;
          thingKind <= FINALIZE_OBJECT_LAST;
          thingKind++) {
         for (CellIterUnderGC i(this, AllocKind(thingKind)); !i.done(); i.next()) {
             JSObject *object = i.get<JSObject>();
-            if (!object->isNewborn() && object->hasSingletonType())
+            if (object->hasSingletonType())
                 MarkObject(trc, *object, "mark_types_singleton");
         }
     }
 
     for (CellIterUnderGC i(this, FINALIZE_TYPE_OBJECT); !i.done(); i.next())
         MarkTypeObject(trc, i.get<types::TypeObject>(), "mark_types_scan");
 }
 
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -713,17 +713,17 @@ Exception(JSContext *cx, uintN argc, Val
         return false;
 
     if (!protov.isObject()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROTOTYPE, "Error");
         return false;
     }
 
     JSObject *errProto = &protov.toObject();
-    JSObject *obj = NewNativeClassInstance(cx, &ErrorClass, errProto);
+    JSObject *obj = NewObjectWithGivenProto(cx, &ErrorClass, errProto, NULL);
     if (!obj)
         return false;
 
     /* Set the 'message' property. */
     JSString *message;
     if (args.length() != 0 && !args[0].isUndefined()) {
         message = js_ValueToString(cx, args[0]);
         if (!message)
@@ -1162,17 +1162,17 @@ js_ErrorToException(JSContext *cx, const
      * exception constructor name in the scope chain of the current context's
      * top stack frame, or in the global object if no frame is active.
      */
     ok = js_GetClassPrototype(cx, NULL, GetExceptionProtoKey(exn), &errProto);
     if (!ok)
         goto out;
     tv[0] = OBJECT_TO_JSVAL(errProto);
 
-    errObject = NewNativeClassInstance(cx, &ErrorClass, errProto);
+    errObject = NewObjectWithGivenProto(cx, &ErrorClass, errProto, NULL);
     if (!errObject) {
         ok = JS_FALSE;
         goto out;
     }
     tv[1] = OBJECT_TO_JSVAL(errObject);
 
     messageStr = JS_NewStringCopyZ(cx, message);
     if (!messageStr) {
@@ -1350,13 +1350,13 @@ js_CopyErrorObject(JSContext *cx, JSObje
     copy->lineno = priv->lineno;
     copy->stackDepth = 0;
     copy->exnType = priv->exnType;
 
     // Create the Error object.
     JSObject *proto;
     if (!js_GetClassPrototype(cx, scope->getGlobal(), GetExceptionProtoKey(copy->exnType), &proto))
         return NULL;
-    JSObject *copyobj = NewNativeClassInstance(cx, &ErrorClass, proto);
+    JSObject *copyobj = NewObjectWithGivenProto(cx, &ErrorClass, proto, NULL);
     copyobj->setPrivate(copy);
     autoFree.p = NULL;
     return copyobj;
 }
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -132,38 +132,36 @@ ArgumentsObject::create(JSContext *cx, u
     JSObject *proto = callee.getGlobal()->getOrCreateObjectPrototype(cx);
     if (!proto)
         return NULL;
 
     TypeObject *type = proto->getNewType(cx);
     if (!type)
         return NULL;
 
-    JS_STATIC_ASSERT(NormalArgumentsObject::RESERVED_SLOTS == 2);
-    JS_STATIC_ASSERT(StrictArgumentsObject::RESERVED_SLOTS == 2);
-    JSObject *obj = js_NewGCObject(cx, FINALIZE_OBJECT4);
-    if (!obj)
-        return NULL;
-
     bool strict = callee.toFunction()->inStrictMode();
     Class *clasp = strict ? &StrictArgumentsObjectClass : &NormalArgumentsObjectClass;
     Shape *emptyArgumentsShape = BaseShape::lookupInitialShape(cx, clasp, proto->getParent(),
                                                                FINALIZE_OBJECT4);
     if (!emptyArgumentsShape)
         return NULL;
 
     ArgumentsData *data = (ArgumentsData *)
         cx->malloc_(offsetof(ArgumentsData, slots) + argc * sizeof(Value));
     if (!data)
         return NULL;
     SetValueRangeToUndefined(data->slots, argc);
 
-    /* Can't fail from here on, so initialize everything in argsobj. */
-    obj->init(cx, type);
-    obj->setInitialPropertyInfallible(emptyArgumentsShape);
+    /* We have everything needed to fill in the object, so make the object. */
+    JS_STATIC_ASSERT(NormalArgumentsObject::RESERVED_SLOTS == 2);
+    JS_STATIC_ASSERT(StrictArgumentsObject::RESERVED_SLOTS == 2);
+    JSObject *obj = js_NewGCObject(cx, FINALIZE_OBJECT4);
+    if (!obj)
+        return NULL;
+    obj->initialize(emptyArgumentsShape, type, NULL);
 
     ArgumentsObject *argsobj = obj->asArguments();
 
     JS_ASSERT(UINT32_MAX > (uint64(argc) << PACKED_BITS_COUNT));
     argsobj->setInitialLength(argc);
 
     argsobj->setCalleeAndData(callee, data);
 
@@ -699,31 +697,30 @@ Class js::DeclEnvClass = {
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub
 };
 
 static inline JSObject *
 NewDeclEnvObject(JSContext *cx, StackFrame *fp)
 {
-    JSObject *envobj = js_NewGCObject(cx, FINALIZE_OBJECT2);
-    if (!envobj)
-        return NULL;
-
     types::TypeObject *type = cx->compartment->getEmptyType(cx);
     if (!type)
         return NULL;
 
     JSObject *parent = fp->scopeChain().getGlobal();
     Shape *emptyDeclEnvShape = BaseShape::lookupInitialShape(cx, &DeclEnvClass, parent,
                                                              FINALIZE_OBJECT2);
     if (!emptyDeclEnvShape)
         return NULL;
-    envobj->init(cx, type);
-    envobj->setInitialPropertyInfallible(emptyDeclEnvShape);
+
+    JSObject *envobj = js_NewGCObject(cx, FINALIZE_OBJECT2);
+    if (!envobj)
+        return NULL;
+    envobj->initialize(emptyDeclEnvShape, type, NULL);
     envobj->setPrivate(fp);
 
     envobj->setScopeChain(&fp->scopeChain());
 
     return envobj;
 }
 
 namespace js {
@@ -1377,17 +1374,17 @@ ResolveInterpretedFunctionPrototype(JSCo
 
     /*
      * Make the prototype object an instance of Object with the same parent
      * as the function object itself.
      */
     JSObject *objProto;
     if (!js_GetClassPrototype(cx, obj->getParent(), JSProto_Object, &objProto))
         return NULL;
-    JSObject *proto = NewNativeClassInstance(cx, &ObjectClass, objProto);
+    JSObject *proto = NewObjectWithGivenProto(cx, &ObjectClass, objProto, NULL);
     if (!proto || !proto->setSingletonType(cx))
         return NULL;
 
     /*
      * Per ES5 15.3.5.2 a user-defined function's .prototype property is
      * initially non-configurable, non-enumerable, and writable.  Per ES5 13.2
      * the prototype's .constructor property is configurable, non-enumerable,
      * and writable.
@@ -2279,17 +2276,17 @@ js_NewFunction(JSContext *cx, JSObject *
                uintN flags, JSObject *parent, JSAtom *atom, js::gc::AllocKind kind)
 {
     JSFunction *fun;
 
     if (funobj) {
         JS_ASSERT(funobj->isFunction());
         JS_ASSERT(funobj->getParent() == parent);
     } else {
-        funobj = NewFunction(cx, SkipScopeParent(parent), kind);
+        funobj = NewObjectWithClassProto(cx, &FunctionClass, NULL, SkipScopeParent(parent), kind);
         if (!funobj)
             return NULL;
     }
     fun = static_cast<JSFunction *>(funobj);
 
     /* Initialize all function members. */
     fun->nargs = uint16(nargs);
     fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_KINDMASK);
@@ -2324,19 +2321,20 @@ js_NewFunction(JSContext *cx, JSObject *
 
 JSFunction * JS_FASTCALL
 js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
                        JSObject *proto, gc::AllocKind kind)
 {
     JS_ASSERT(parent);
     JS_ASSERT(proto);
 
-    JSFunction *clone = NewFunction(cx, SkipScopeParent(parent), kind);
-    if (!clone)
+    JSObject *cloneobj = NewObjectWithClassProto(cx, &FunctionClass, NULL, SkipScopeParent(parent), kind);
+    if (!cloneobj)
         return NULL;
+    JSFunction *clone = static_cast<JSFunction *>(cloneobj);
 
     clone->nargs = fun->nargs;
     clone->flags = fun->flags & ~JSFUN_EXTENDED;
     clone->u = fun->toFunction()->u;
     clone->atom = fun->atom;
 
     if (kind == JSFunction::ExtendedFinalizeKind) {
         clone->flags |= JSFUN_EXTENDED;
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -397,20 +397,17 @@ NewGCThing(JSContext *cx, js::gc::AllocK
     void *t = cx->compartment->arenas.allocateFromFreeList(kind, thingSize);
     return static_cast<T *>(t ? t : js::gc::ArenaLists::refillFreeList(cx, kind));
 }
 
 inline JSObject *
 js_NewGCObject(JSContext *cx, js::gc::AllocKind kind)
 {
     JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST);
-    JSObject *obj = NewGCThing<JSObject>(cx, kind, js::gc::Arena::thingSize(kind));
-    if (obj)
-        obj->earlyInit();
-    return obj;
+    return NewGCThing<JSObject>(cx, kind, js::gc::Arena::thingSize(kind));
 }
 
 inline JSString *
 js_NewGCString(JSContext *cx)
 {
     return NewGCThing<JSString>(cx, js::gc::FINALIZE_STRING, sizeof(JSString));
 }
 
--- a/js/src/jsgcmark.cpp
+++ b/js/src/jsgcmark.cpp
@@ -686,19 +686,16 @@ PushMarkStack(GCMarker *gcmarker, JSStri
     }
 }
 
 static const uintN LARGE_OBJECT_CHUNK_SIZE = 2048;
 
 static void
 ScanObject(GCMarker *gcmarker, JSObject *obj)
 {
-    if (obj->isNewborn())
-        return;
-
     types::TypeObject *type = obj->typeFromGC();
     PushMarkStack(gcmarker, type);
 
     if (JSObject *parent = obj->getParentMaybeScope())
         PushMarkStack(gcmarker, parent);
 
     /*
      * Call the trace hook if necessary, and check for a newType on objects
@@ -758,20 +755,16 @@ ScanLargeObject(GCMarker *gcmarker, Larg
 
     item.markpos += LARGE_OBJECT_CHUNK_SIZE;
     return false;
 }
 
 void
 MarkChildren(JSTracer *trc, JSObject *obj)
 {
-    /* If obj has no map, it must be a newborn. */
-    if (obj->isNewborn())
-        return;
-
     MarkTypeObject(trc, obj->typeFromGC(), "type");
 
     /* Trace universal (ops-independent) members. */
     if (JSObject *parent = obj->getParentMaybeScope())
         MarkObject(trc, *parent, "parent");
 
     Class *clasp = obj->getClass();
     if (clasp->trace)
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -509,17 +509,17 @@ js::OnUnknownMethod(JSContext *cx, Value
         /* Extract the function name from function::name qname. */
         if (vp[0].isObject()) {
             obj = &vp[0].toObject();
             if (js_GetLocalNameFromFunctionQName(obj, &id, cx))
                 vp[0] = IdToValue(id);
         }
 #endif
 
-        obj = NewNonFunction<WithProto::Given>(cx, &js_NoSuchMethodClass, NULL, NULL);
+        obj = NewObjectWithClassProto(cx, &js_NoSuchMethodClass, NULL, NULL);
         if (!obj)
             return false;
 
         obj->setSlot(JSSLOT_FOUND_FUNCTION, tvr.value());
         obj->setSlot(JSSLOT_SAVED_ID, vp[0]);
         vp[0].setObject(*obj);
     }
     return true;
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -404,39 +404,30 @@ Compare(T *a, T *b, size_t c)
     }
     return true;
 }
 
 static inline JSObject *
 NewIteratorObject(JSContext *cx, uintN flags)
 {
     if (flags & JSITER_ENUMERATE) {
-        /*
-         * Non-escaping native enumerator objects do not need map, proto, or
-         * parent. However, code in jstracer.cpp and elsewhere may find such a
-         * native enumerator object via the stack and (as for all objects that
-         * are not stillborn, with the exception of "NoSuchMethod" internal
-         * helper objects) expect it to have a non-null map pointer, so we
-         * share an empty Enumerator scope in the runtime.
-         */
-        JSObject *obj = js_NewGCObject(cx, FINALIZE_OBJECT2);
-        if (!obj)
-            return NULL;
-
         types::TypeObject *type = cx->compartment->getEmptyType(cx);
         if (!type)
             return NULL;
 
         Shape *emptyEnumeratorShape = BaseShape::lookupInitialShape(cx, &IteratorClass, NULL,
                                                                     FINALIZE_OBJECT2);
         if (!emptyEnumeratorShape)
             return NULL;
 
-        obj->init(cx, type);
-        obj->setInitialPropertyInfallible(emptyEnumeratorShape);
+        JSObject *obj = js_NewGCObject(cx, FINALIZE_OBJECT2);
+        if (!obj)
+            return NULL;
+
+        obj->initialize(emptyEnumeratorShape, type, NULL);
 
         JS_ASSERT(obj->numFixedSlots() == JSObject::ITER_CLASS_NFIXED_SLOTS);
         return obj;
     }
 
     return NewBuiltinClassInstance(cx, &IteratorClass);
 }
 
@@ -1189,17 +1180,17 @@ js_NewGenerator(JSContext *cx)
     StackFrame *stackfp = stackRegs.fp();
     JS_ASSERT(stackfp->base() == cx->regs().sp);
     JS_ASSERT(stackfp->actualArgs() <= stackfp->formalArgs());
 
     GlobalObject *global = stackfp->scopeChain().getGlobal();
     JSObject *proto = global->getOrCreateGeneratorPrototype(cx);
     if (!proto)
         return NULL;
-    JSObject *obj = NewNonFunction<WithProto::Given>(cx, &GeneratorClass, proto, global);
+    JSObject *obj = NewObjectWithGivenProto(cx, &GeneratorClass, proto, global);
     if (!obj)
         return NULL;
 
     /* Load and compute stack slot counts. */
     Value *stackvp = stackfp->actualArgs() - 2;
     uintN vplen = stackfp->formalArgsEnd() - stackvp;
 
     /* Compute JSGenerator size. */
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -860,17 +860,17 @@ js_IsMathFunction(Native native)
             return true;
     }
     return false;
 }
 
 JSObject *
 js_InitMathClass(JSContext *cx, JSObject *obj)
 {
-    JSObject *Math = NewNonFunction<WithProto::Class>(cx, &MathClass, NULL, obj);
+    JSObject *Math = NewObjectWithClassProto(cx, &MathClass, NULL, obj);
     if (!Math || !Math->setSingletonType(cx))
         return NULL;
 
     if (!JS_DefineProperty(cx, obj, js_Math_str, OBJECT_TO_JSVAL(Math),
                            JS_PropertyStub, JS_StrictPropertyStub, 0)) {
         return NULL;
     }
 
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2609,18 +2609,17 @@ obj_create(JSContext *cx, uintN argc, Va
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_XML_PROTO_FORBIDDEN);
         return false;
     }
 
     /*
      * Use the callee's global as the parent of the new object to avoid dynamic
      * scoping (i.e., using the caller's global).
      */
-    JSObject *obj = NewNonFunction<WithProto::Given>(cx, &ObjectClass, proto,
-                                                     vp->toObject().getGlobal());
+    JSObject *obj = NewObjectWithGivenProto(cx, &ObjectClass, proto, vp->toObject().getGlobal());
     if (!obj)
         return JS_FALSE;
     vp->setObject(*obj); /* Root and prepare for eventual return. */
 
     /* Don't track types or array-ness for objects created here. */
     MarkTypeObjectUnknownProperties(cx, obj->type());
 
     /* 15.2.3.5 step 4. */
@@ -2906,16 +2905,84 @@ js_Object(JSContext *cx, uintN argc, Val
             return JS_FALSE;
         obj->setType(type);
     }
     vp->setObject(*obj);
     return JS_TRUE;
 }
 
 JSObject *
+js::NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
+                            gc::AllocKind kind)
+{
+    types::TypeObject *type = proto ? proto->getNewType(cx) : cx->compartment->getEmptyType(cx);
+    if (!type)
+        return NULL;
+
+    JS_ASSERT_IF(clasp == &FunctionClass,
+                 kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
+
+    if (CanBeFinalizedInBackground(kind, clasp))
+        kind = GetBackgroundAllocKind(kind);
+
+    /*
+     * Default parent to the parent of the prototype, which was set from
+     * the parent of the prototype's constructor.
+     */
+    if (!parent && proto)
+        parent = proto->getParent();
+
+    Shape *shape = GetInitialShapeForObject(cx, clasp, parent, type, kind);
+    if (!shape)
+        return NULL;
+
+    Value *slots;
+    if (!ReserveObjectDynamicSlots(cx, shape, &slots))
+        return NULL;
+
+    JSObject* obj = js_NewGCObject(cx, kind);
+    if (!obj)
+        return NULL;
+
+    obj->initialize(shape, type, slots);
+
+    Probes::createObject(cx, obj);
+    return obj;
+}
+
+JSObject *
+js::NewObjectWithType(JSContext *cx, types::TypeObject *type, JSObject *parent, gc::AllocKind kind)
+{
+    JS_ASSERT(type->proto->hasNewType(type));
+
+    if (CanBeFinalizedInBackground(kind, &ObjectClass))
+        kind = GetBackgroundAllocKind(kind);
+
+    /*
+     * Default parent to the parent of the prototype, which was set from
+     * the parent of the prototype's constructor.
+     */
+    if (!parent && type->proto)
+        parent = type->proto->getParent();
+
+    Shape *shape = GetInitialShapeForObject(cx, &ObjectClass, parent, type, kind);
+    if (!shape)
+        return NULL;
+
+    JSObject* obj = js_NewGCObject(cx, kind);
+    if (!obj)
+        return NULL;
+
+    obj->initialize(shape, type, NULL);
+
+    Probes::createObject(cx, obj);
+    return obj;
+}
+
+JSObject *
 js::NewReshapedObject(JSContext *cx, TypeObject *type, JSObject *parent,
                       gc::AllocKind kind, const Shape *shape)
 {
     JSObject *res = NewObjectWithType(cx, type, parent, kind);
     if (!res)
         return NULL;
 
     if (shape->isEmptyShape())
@@ -2959,17 +3026,17 @@ js_CreateThis(JSContext *cx, JSObject *c
 
     Value protov;
     if (!callee->getProperty(cx, cx->runtime->atomState.classPrototypeAtom, &protov))
         return NULL;
 
     JSObject *proto = protov.isObjectOrNull() ? protov.toObjectOrNull() : NULL;
     JSObject *parent = callee->getParent();
     gc::AllocKind kind = NewObjectGCKind(cx, newclasp);
-    return NewObject<WithProto::Class>(cx, newclasp, proto, parent, kind);
+    return NewObjectWithClassProto(cx, newclasp, proto, parent, kind);
 }
 
 static inline JSObject *
 CreateThisForFunctionWithType(JSContext *cx, types::TypeObject *type, JSObject *parent)
 {
     if (type->newScript) {
         /*
          * Make an object with the type's associated finalize kind and shape,
@@ -2994,17 +3061,17 @@ js_CreateThisForFunctionWithProto(JSCont
 
     if (proto) {
         types::TypeObject *type = proto->getNewType(cx, callee->toFunction());
         if (!type)
             return NULL;
         res = CreateThisForFunctionWithType(cx, type, callee->getParent());
     } else {
         gc::AllocKind kind = NewObjectGCKind(cx, &ObjectClass);
-        res = NewNonFunction<WithProto::Class>(cx, &ObjectClass, proto, callee->getParent(), kind);
+        res = NewObjectWithClassProto(cx, &ObjectClass, proto, callee->getParent(), kind);
     }
 
     if (res && cx->typeInferenceEnabled())
         TypeScript::SetThis(cx, callee->toFunction()->script(), types::Type::ObjectType(res));
 
     return res;
 }
 
@@ -3038,29 +3105,29 @@ js_CreateThisForFunction(JSContext *cx, 
 }
 
 #ifdef JS_TRACER
 
 JSObject* FASTCALL
 js_Object_tn(JSContext* cx, JSObject* proto)
 {
     JS_ASSERT(!(ObjectClass.flags & JSCLASS_HAS_PRIVATE));
-    return NewObjectWithClassProto(cx, &ObjectClass, proto, FINALIZE_OBJECT8);
+    return NewObjectWithClassProto(cx, &ObjectClass, proto, NULL, FINALIZE_OBJECT8);
 }
 
 JS_DEFINE_TRCINFO_1(js_Object,
     (2, (extern, CONSTRUCTOR_RETRY, js_Object_tn, CONTEXT, CALLEE_PROTOTYPE, 0,
          nanojit::ACCSET_STORE_ANY)))
 
 JSObject* FASTCALL
 js_InitializerObject(JSContext* cx, JSObject *proto, JSObject *baseobj)
 {
     if (!baseobj) {
         gc::AllocKind kind = GuessObjectGCKind(0);
-        return NewObjectWithClassProto(cx, &ObjectClass, proto, kind);
+        return NewObjectWithClassProto(cx, &ObjectClass, proto, NULL, kind);
     }
 
     /* :FIXME: bug 637856 new Objects do not have the right type when created on trace. */
     TypeObject *type = proto->getNewType(cx);
     if (!type)
         return NULL;
 
     return CopyInitializerObject(cx, baseobj, type);
@@ -3465,31 +3532,28 @@ JS_REQUIRES_STACK JSObject *
 js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
 {
     JSObject *obj;
 
     TypeObject *type = proto->getNewType(cx);
     if (!type)
         return NULL;
 
-    obj = js_NewGCObject(cx, FINALIZE_OBJECT4);
-    if (!obj)
-        return NULL;
-
     StackFrame *priv = js_FloatingFrameIfGenerator(cx, cx->fp());
 
-    obj->init(cx, type);
-
     Shape *emptyWithShape = BaseShape::lookupInitialShape(cx, &WithClass,
                                                           parent->getGlobal(),
                                                           FINALIZE_OBJECT4);
     if (!emptyWithShape)
         return NULL;
 
-    obj->setInitialPropertyInfallible(emptyWithShape);
+    obj = js_NewGCObject(cx, FINALIZE_OBJECT4);
+    if (!obj)
+        return NULL;
+    obj->initialize(emptyWithShape, type, NULL);
     OBJ_SET_BLOCK_DEPTH(cx, obj, depth);
 
     obj->setScopeChain(parent);
     obj->setPrivate(priv);
 
     AutoObjectRooter tvr(cx, obj);
     JSObject *thisp = proto->thisObject(cx);
     if (!thisp)
@@ -3499,65 +3563,74 @@ js_NewWithObject(JSContext *cx, JSObject
 
     obj->setWithThis(thisp);
     return obj;
 }
 
 JSObject *
 js_NewBlockObject(JSContext *cx)
 {
-    /*
-     * Null obj's proto slot so that Object.prototype.* does not pollute block
-     * scopes and to give the block object its own scope.
-     */
-    JSObject *blockObj = js_NewGCObject(cx, FINALIZE_OBJECT4);
-    if (!blockObj)
-        return NULL;
-
     types::TypeObject *type = cx->compartment->getEmptyType(cx);
     if (!type)
         return NULL;
 
     Shape *emptyBlockShape = BaseShape::lookupInitialShape(cx, &BlockClass, NULL,
                                                            FINALIZE_OBJECT4);
     if (!emptyBlockShape)
         return NULL;
 
-    blockObj->init(cx, type);
-    blockObj->setInitialPropertyInfallible(emptyBlockShape);
+    JSObject *blockObj = js_NewGCObject(cx, FINALIZE_OBJECT4);
+    if (!blockObj)
+        return NULL;
+    blockObj->initialize(emptyBlockShape, type, NULL);
 
     return blockObj;
 }
 
 static const uint32 BLOCK_RESERVED_SLOTS = 2;
 
 JSObject *
 js_CloneBlockObject(JSContext *cx, JSObject *proto, StackFrame *fp)
 {
     JS_ASSERT(proto->isStaticBlock());
 
     TypeObject *type = proto->getNewType(cx);
     if (!type)
         return NULL;
 
+    Value *slots;
+    if (!ReserveObjectDynamicSlots(cx, proto->lastProperty(), &slots))
+        return NULL;
+
     JSObject *clone = js_NewGCObject(cx, FINALIZE_OBJECT4);
     if (!clone)
         return NULL;
 
+    clone->initialize(proto->lastProperty(), type, slots);
+
     StackFrame *priv = js_FloatingFrameIfGenerator(cx, fp);
 
-    /* The caller sets parent on its own. */
-    if (!clone->initClonedBlock(cx, type, priv))
+    /* Set the parent if necessary, as for call objects. */
+    JSObject *global = priv->scopeChain().getGlobal();
+    if (global != clone->getParentMaybeScope()) {
+        JS_ASSERT(clone->getParentMaybeScope() == NULL);
+        if (!clone->setParent(cx, global))
+            return NULL;
+    }
+
+    JS_ASSERT(!clone->inDictionaryMode());
+    JS_ASSERT(clone->isClonedBlock());
+    JS_ASSERT(clone->slotSpan() >= OBJ_BLOCK_COUNT(cx, proto) + BLOCK_RESERVED_SLOTS);
+
+    clone->setPrivate(priv);
+    clone->setSlot(JSSLOT_BLOCK_DEPTH, proto->getSlot(JSSLOT_BLOCK_DEPTH));
+
+    if (clone->lastProperty()->extensibleParents() && !clone->generateOwnShape(cx))
         return NULL;
 
-    JS_ASSERT(clone->slotSpan() >= OBJ_BLOCK_COUNT(cx, proto) + BLOCK_RESERVED_SLOTS);
-
-    clone->setSlot(JSSLOT_BLOCK_DEPTH, proto->getSlot(JSSLOT_BLOCK_DEPTH));
-
-    JS_ASSERT(clone->isClonedBlock());
     return clone;
 }
 
 JS_REQUIRES_STACK JSBool
 js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
 {
     StackFrame *const fp = cx->fp();
     JSObject *obj = &fp->scopeChain();
@@ -3753,17 +3826,17 @@ JS_CloneObject(JSContext *cx, JSObject *
             if (!obj->makeDenseArraySlow(cx))
                 return NULL;
         } else if (!obj->isProxy()) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                  JSMSG_CANT_CLONE_OBJECT);
             return NULL;
         }
     }
-    JSObject *clone = NewObject<WithProto::Given>(cx, obj->getClass(), proto, parent, obj->getAllocKind());
+    JSObject *clone = NewObjectWithGivenProto(cx, obj->getClass(), proto, parent, obj->getAllocKind());
     if (!clone)
         return NULL;
     if (obj->isNative()) {
         if (clone->isFunction() && (obj->compartment() != clone->compartment())) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                  JSMSG_CANT_CLONE_OBJECT);
             return NULL;
         }
@@ -4277,17 +4350,17 @@ DefineConstructorAndPrototype(JSContext 
 
     /*
      * Create the prototype object.  (GlobalObject::createBlankPrototype isn't
      * used because it parents the prototype object to the global and because
      * it uses WithProto::Given.  FIXME: Undo dependencies on this parentage
      * [which already needs to happen for bug 638316], figure out nicer
      * semantics for null-protoProto, and use createBlankPrototype.)
      */
-    JSObject *proto = NewObject<WithProto::Class>(cx, clasp, protoProto, obj);
+    JSObject *proto = NewObjectWithClassProto(cx, clasp, protoProto, obj);
     if (!proto)
         return NULL;
 
     if (!proto->setSingletonType(cx))
         return NULL;
 
     if (clasp == &ArrayClass && !proto->makeDenseArraySlow(cx))
         return NULL;
@@ -4484,35 +4557,16 @@ JSObject::copySlotRange(size_t start, co
             memcpy(slots, vector + localCopy, (length - localCopy) * sizeof(Value));
         }
     } else {
         memcpy(slots + start - fixed, vector, length * sizeof(Value));
     }
 }
 
 inline void
-JSObject::clearSlotRange(size_t start, size_t length)
-{
-    JS_ASSERT(!isDenseArray());
-    JS_ASSERT(slotInRange(start + length, /* sentinelAllowed = */ true));
-    size_t fixed = numFixedSlots();
-    if (start < fixed) {
-        if (start + length < fixed) {
-            ClearValueRange(fixedSlots() + start, length);
-        } else {
-            size_t localClear = fixed - start;
-            ClearValueRange(fixedSlots() + start, localClear);
-            ClearValueRange(slots, length - localClear);
-        }
-    } else {
-        ClearValueRange(slots + start - fixed, length);
-    }
-}
-
-inline void
 JSObject::invalidateSlotRange(size_t start, size_t length)
 {
 #ifdef DEBUG
     JS_ASSERT(!isDenseArray());
 
     size_t fixed = numFixedSlots();
     size_t numSlots = fixed + numDynamicSlots();
 
@@ -4548,66 +4602,18 @@ JSObject::updateSlotsForSpan(size_t oldS
 
     if (oldSpan < newSpan)
         clearSlotRange(oldSpan, newSpan - oldSpan);
     else
         invalidateSlotRange(newSpan, oldSpan - newSpan);
 }
 
 bool
-JSObject::setInitialProperty(JSContext *cx, const js::Shape *shape)
-{
-    JS_ASSERT(isNewborn());
-    JS_ASSERT(shape->compartment() == compartment());
-    JS_ASSERT(!shape->inDictionary());
-    JS_ASSERT(gc::GetGCKindSlots(getAllocKind(), shape->getObjectClass()) == shape->numFixedSlots());
-
-    size_t span = shape->slotSpan();
-
-    if (span) {
-        size_t count = dynamicSlotsCount(shape->numFixedSlots(), span);
-        if (count && !growSlots(cx, 0, count))
-            return false;
-    }
-
-    shape_ = const_cast<js::Shape *>(shape);
-    if (hasPrivate())
-        setPrivate(NULL);
-
-    if (span)
-        updateSlotsForSpan(0, span);
-
-    return true;
-}
-
-void
-JSObject::setInitialPropertyInfallible(const js::Shape *shape)
-{
-    JS_ASSERT(isNewborn());
-    JS_ASSERT(shape->compartment() == compartment());
-    JS_ASSERT(!shape->inDictionary());
-    JS_ASSERT(gc::GetGCKindSlots(getAllocKind(), shape->getObjectClass()) == shape->numFixedSlots());
-    JS_ASSERT_IF(shape->getObjectClass()->ext.equality && !hasSingletonType(),
-                 type()->hasAnyFlags(js::types::OBJECT_FLAG_SPECIAL_EQUALITY));
-
-    JS_ASSERT(dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan()) == 0);
-
-    shape_ = const_cast<js::Shape *>(shape);
-    if (hasPrivate())
-        setPrivate(NULL);
-
-    size_t span = shape->slotSpan();
-    if (span)
-        updateSlotsForSpan(0, span);
-}
-
-bool
 JSObject::setLastProperty(JSContext *cx, const js::Shape *shape)
 {
-    JS_ASSERT(!isNewborn());
     JS_ASSERT(!inDictionaryMode());
     JS_ASSERT(!shape->inDictionary());
     JS_ASSERT(shape->compartment() == compartment());
     JS_ASSERT(shape->numFixedSlots() == numFixedSlots());
 
     size_t oldSpan = lastProperty()->slotSpan();
     size_t newSpan = shape->slotSpan();
 
@@ -4649,25 +4655,25 @@ JSObject::setSlotSpan(JSContext *cx, uin
     return true;
 }
 
 bool
 JSObject::growSlots(JSContext *cx, uint32 oldCount, uint32 newCount)
 {
     JS_ASSERT(newCount > oldCount);
     JS_ASSERT(newCount >= SLOT_CAPACITY_MIN);
-    JS_ASSERT_IF(!isNewborn(), !isDenseArray());
+    JS_ASSERT(!isDenseArray());
 
     /*
      * Slots are only allocated for call objects when new properties are
      * added to them, which can only happen while the call is still on the
      * stack (and an eval, DEFFUN, etc. happens). We thus do not need to
      * worry about updating any active outer function args/vars.
      */
-    JS_ASSERT_IF(!isNewborn() && isCall(), asCall().maybeStackFrame() != NULL);
+    JS_ASSERT_IF(isCall(), asCall().maybeStackFrame() != NULL);
 
     /*
      * Slot capacities are determined by the span of allocated objects. Due to
      * the limited number of bits to store shape slots, object growth is
      * throttled well before the slot capacity can overflow.
      */
     JS_ASSERT(newCount < NELEMENTS_LIMIT);
 
@@ -5090,17 +5096,17 @@ js_ConstructObject(JSContext *cx, Class 
     if (!proto) {
         Value rval;
         if (!ctor->getProperty(cx, cx->runtime->atomState.classPrototypeAtom, &rval))
             return NULL;
         if (rval.isObjectOrNull())
             proto = rval.toObjectOrNull();
     }
 
-    JSObject *obj = NewObject<WithProto::Class>(cx, clasp, proto, parent);
+    JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, parent);
     if (!obj)
         return NULL;
 
     MarkTypeObjectUnknownProperties(cx, obj->type());
 
     Value rval;
     if (!InvokeConstructorWithGivenThis(cx, obj, cval, argc, argv, &rval))
         return NULL;
@@ -7129,17 +7135,17 @@ GlobalObject *
 JSObject::getGlobal() const
 {
     JSObject *obj = const_cast<JSObject *>(this);
     while (JSObject *parent = obj->getParentMaybeScope())
         obj = parent;
     return obj->asGlobal();
 }
 
-static ObjectElements emptyObjectHeader(0);
+static ObjectElements emptyObjectHeader(0, 0);
 Value *js::emptyObjectElements = (Value *) (jsuword(&emptyObjectHeader) + sizeof(ObjectElements));
 
 JSBool
 js_ReportGetterOnlyAssignment(JSContext *cx)
 {
     return JS_ReportErrorFlagsAndNumber(cx,
                                         JSREPORT_WARNING | JSREPORT_STRICT |
                                         JSREPORT_STRICT_MODE_ERROR,
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -371,18 +371,18 @@ struct ObjectElements
     uint32 initializedLength;
 
     /* 'length' property of array objects, unused for other objects. */
     uint32 length;
 
     /* :XXX: bug 586842 store state about sparse slots. */
     uint32 unused;
 
-    ObjectElements(uint32 capacity)
-        : capacity(capacity), initializedLength(0), length(0)
+    ObjectElements(uint32 capacity, uint32 length)
+        : capacity(capacity), initializedLength(0), length(length)
     {}
 
     Value * elements() { return (Value *)(jsuword(this) + sizeof(ObjectElements)); }
     static ObjectElements * fromElements(Value *elems) {
         return (ObjectElements *)(jsuword(elems) - sizeof(ObjectElements));
     }
 
     static int offsetOfCapacity() {
@@ -487,21 +487,21 @@ struct JSObject : js::gc::Cell
      * Update the last property, keeping the number of allocated slots in sync
      * with the object's new slot span.
      */
     bool setLastProperty(JSContext *cx, const js::Shape *shape);
 
     /* As above, but does not change the slot span. */
     inline void setLastPropertyInfallible(const js::Shape *shape);
 
-    /* Set the initial property for a newborn object. */
-    bool setInitialProperty(JSContext *cx, const js::Shape *shape);
+    /* Set the initial state of a newborn object. */
+    inline void initialize(js::Shape *shape, js::types::TypeObject *type, JS::Value *slots);
 
-    /* As above, but the slot span is guaranteed to fit in the fixed slots. */
-    void setInitialPropertyInfallible(const js::Shape *shape);
+    /* Set the initial state of a newborn dense array. */
+    inline void initializeDenseArray(js::Shape *shape, js::types::TypeObject *type, uint32 length);
 
     /*
      * Remove the last property of an object, provided that it is safe to do so
      * (the shape and previous shape do not carry conflicting information about
      * the object itself).
      */
     inline void removeLastProperty(JSContext *cx);
     inline bool canRemoveLastProperty();
@@ -526,17 +526,16 @@ struct JSObject : js::gc::Cell
 
   private:
     js::Value   *slots;                     /* Slots for object properties. */
     js::Value   *elements;                  /* Slots for object elements. */
 
   public:
 
     inline bool isNative() const;
-    inline bool isNewborn() const { return !shape_; }
 
     inline js::Class *getClass() const;
     inline JSClass *getJSClass() const;
     inline bool hasClass(const js::Class *c) const;
     inline const js::ObjectOps *getOps() const;
 
     inline void trace(JSTracer *trc);
     inline void scanSlots(js::GCMarker *gcmarker);
@@ -567,35 +566,30 @@ struct JSObject : js::gc::Cell
 
     inline bool watched() const;
     inline bool setWatched(JSContext *cx);
 
     /* See StackFrame::varObj. */
     inline bool isVarObj() const;
     inline bool setVarObj(JSContext *cx);
 
-  private:
     bool generateOwnShape(JSContext *cx, js::Shape *newShape = NULL);
 
+  private:
     enum GenerateShape {
         GENERATE_NONE,
         GENERATE_SHAPE
     };
 
     bool setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32 flag,
                  GenerateShape generateShape = GENERATE_NONE);
 
   public:
     inline bool nativeEmpty() const;
 
-    /* Functions for setting up scope chain object maps and shapes. */
-    bool initCall(JSContext *cx, const js::Bindings &bindings, JSObject *parent);
-    bool initClonedBlock(JSContext *cx, js::types::TypeObject *type, js::StackFrame *priv);
-    void setBlockOwnShape(JSContext *cx);
-
     const js::Shape *methodShapeChange(JSContext *cx, const js::Shape &shape);
     bool protoShapeChange(JSContext *cx);
     bool shadowingShapeChange(JSContext *cx, const js::Shape &shape);
 
     /*
      * Read barrier to clone a joined function object stored as a method.
      * Defined in jsobjinlines.h, but not declared inline per standard style in
      * order to avoid gcc warnings.
@@ -1111,45 +1105,19 @@ struct JSObject : js::gc::Cell
     inline JSObject *getWithThis() const;
     inline void setWithThis(JSObject *thisp);
 
     /*
      * Back to generic stuff.
      */
     inline bool isCallable();
 
-    /* Do initialization required immediately after allocation. */
-    void earlyInit()
-    {
-        /* Stops obj from being scanned until initializated. */
-        shape_ = NULL;
-    }
-
-    /* The last property is not initialized here and should be set separately. */
-    void init(JSContext *cx, js::types::TypeObject *type);
-
-    /*
-     * Finish initializing the elements in a dense array, after its initial
-     * property has been set.
-     */
-    void initDenseArray();
-
     inline void finish(JSContext *cx);
     JS_ALWAYS_INLINE void finalize(JSContext *cx, bool background);
 
-    /*
-     * Like init, but also initializes map.  proto must have an empty shape
-     * created for it via proto->getEmptyShape.
-     */
-    inline bool initSharingEmptyShape(JSContext *cx,
-                                      js::Class *clasp,
-                                      js::types::TypeObject *type,
-                                      void *priv,
-                                      js::gc::AllocKind kind);
-
     inline bool hasProperty(JSContext *cx, jsid id, bool *foundp, uintN flags = 0);
 
     /*
      * Allocate and free an object slot.
      *
      * FIXME: bug 593129 -- slot allocation should be done by object methods
      * after calling object-parameter-free shape methods, avoiding coupling
      * logic across the object vs. shape module wall.
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -70,29 +70,29 @@
 #include "jsatominlines.h"
 #include "jsfuninlines.h"
 #include "jsgcinlines.h"
 #include "jsscopeinlines.h"
 
 inline bool
 JSObject::hasPrivate() const
 {
-    return getClass()->flags & JSCLASS_HAS_PRIVATE;
+    return getClass()->hasPrivate();
 }
 
 inline void *&
 JSObject::privateAddress(uint32 nfixed) const
 {
     /*
      * The private pointer of an object can hold any word sized value.
      * Private pointers are stored immediately after the last fixed slot of
      * the object.
      */
     JS_ASSERT(nfixed == numFixedSlots());
-    JS_ASSERT_IF(!isNewborn(), hasPrivate());
+    JS_ASSERT(hasPrivate());
     js::Value *end = &fixedSlots()[nfixed];
     return *reinterpret_cast<void**>(end);
 }
 
 inline void *
 JSObject::getPrivate() const { return privateAddress(numFixedSlots()); }
 
 inline void *
@@ -250,20 +250,16 @@ inline JSBool
 JSObject::deleteSpecial(JSContext *cx, js::SpecialId sid, js::Value *rval, JSBool strict)
 {
     return deleteGeneric(cx, SPECIALID_TO_JSID(sid), rval, strict);
 }
 
 inline void
 JSObject::finalize(JSContext *cx, bool background)
 {
-    /* Cope with stillborn objects that have no map. */
-    if (isNewborn())
-        return;
-
     js::Probes::finalizeObject(this);
 
     if (!background) {
         /*
          * Finalize obj first, in case it needs map and slots. Objects with
          * finalize hooks are not finalized in the background, as the class is
          * stored in the object's shape, which may have already been destroyed.
          */
@@ -326,87 +322,16 @@ JSObject::setScopeChain(JSObject *obj)
 }
 
 /*static*/ inline size_t
 JSObject::offsetOfScopeChain()
 {
     return getFixedSlotOffset(0);
 }
 
-/* 
- * Initializer for Call objects for functions and eval frames. Set class,
- * parent, map, and shape, and allocate slots.
- */
-inline bool
-JSObject::initCall(JSContext *cx, const js::Bindings &bindings, JSObject *parent)
-{
-    js::types::TypeObject *type = cx->compartment->getEmptyType(cx);
-    if (!type)
-        return false;
-
-    init(cx, type);
-    if (!setInitialProperty(cx, bindings.lastShape()))
-        return false;
-
-    /*
-     * Update the parent for bindings associated with non-compileAndGo scripts,
-     * whose call objects do not have a consistent global variable and need
-     * to be updated dynamically.
-     */
-    JSObject *global = parent->getGlobal();
-    if (global != getParentMaybeScope()) {
-        JS_ASSERT(getParentMaybeScope() == NULL);
-        if (!setParent(cx, global))
-            return false;
-    }
-
-    JS_ASSERT(isCall());
-    JS_ASSERT(!inDictionaryMode());
-
-    setScopeChain(parent);
-
-    /*
-     * If |bindings| is for a function that has extensible parents, that means
-     * its Call should have its own shape; see js::BaseShape::extensibleParents.
-     */
-    if (lastProperty()->extensibleParents())
-        return generateOwnShape(cx);
-    return true;
-}
-
-/*
- * Initializer for cloned block objects. Set class, prototype, frame, map, and
- * shape.
- */
-inline bool
-JSObject::initClonedBlock(JSContext *cx, js::types::TypeObject *type, js::StackFrame *frame)
-{
-    init(cx, type);
-
-    if (!setInitialProperty(cx, getProto()->lastProperty()))
-        return false;
-
-    /* Set the parent if necessary, as for call objects. */
-    JSObject *global = frame->scopeChain().getGlobal();
-    if (global != getParentMaybeScope()) {
-        JS_ASSERT(getParentMaybeScope() == NULL);
-        if (!setParent(cx, global))
-            return false;
-    }
-
-    setPrivate(frame);
-
-    JS_ASSERT(!inDictionaryMode());
-    JS_ASSERT(isClonedBlock());
-
-    if (lastProperty()->extensibleParents())
-        return generateOwnShape(cx);
-    return true;
-}
-
 /*
  * Property read barrier for deferred cloning of compiler-created function
  * objects optimized as typically non-escaping, ad-hoc methods in obj.
  */
 inline const js::Shape *
 JSObject::methodReadBarrier(JSContext *cx, const js::Shape &shape, js::Value *vp)
 {
     JS_ASSERT(nativeContains(cx, shape));
@@ -862,19 +787,19 @@ JSObject::clearType(JSContext *cx)
 inline void
 JSObject::setType(js::types::TypeObject *newType)
 {
 #ifdef DEBUG
     JS_ASSERT(newType);
     for (JSObject *obj = newType->proto; obj; obj = obj->getProto())
         JS_ASSERT(obj != this);
 #endif
-    JS_ASSERT_IF(!isNewborn() && hasSpecialEquality(),
+    JS_ASSERT_IF(hasSpecialEquality(),
                  newType->hasAnyFlags(js::types::OBJECT_FLAG_SPECIAL_EQUALITY));
-    JS_ASSERT_IF(!isNewborn(), !hasSingletonType());
+    JS_ASSERT(!hasSingletonType());
     type_ = newType;
 }
 
 inline bool JSObject::setIteratedSingleton(JSContext *cx) {
     return setFlag(cx, js::BaseShape::ITERATED_SINGLETON);
 }
 
 inline bool JSObject::setSystem(JSContext *cx) {
@@ -968,70 +893,86 @@ inline bool
 JSObject::isQName() const
 {
     return hasClass(&js::QNameClass)
         || hasClass(&js::AttributeNameClass)
         || hasClass(&js::AnyNameClass);
 }
 
 inline void
-JSObject::init(JSContext *cx, js::types::TypeObject *type)
+JSObject::clearSlotRange(size_t start, size_t length)
 {
-    slots = NULL;
-    elements = js::emptyObjectElements;
-
-    setType(type);
+    JS_ASSERT(!isDenseArray());
+    JS_ASSERT(slotInRange(start + length, /* sentinelAllowed = */ true));
+    size_t fixed = numFixedSlots();
+    if (start < fixed) {
+        if (start + length < fixed) {
+            js::ClearValueRange(fixedSlots() + start, length);
+        } else {
+            size_t localClear = fixed - start;
+            js::ClearValueRange(fixedSlots() + start, localClear);
+            js::ClearValueRange(slots, length - localClear);
+        }
+    } else {
+        js::ClearValueRange(slots + start - fixed, length);
+    }
 }
 
 inline void
-JSObject::initDenseArray()
+JSObject::initialize(js::Shape *shape, js::types::TypeObject *type, JS::Value *slots)
 {
-    JS_ASSERT(hasClass(&js::ArrayClass));
+    /*
+     * Callers must use dynamicSlotsCount to size the initial slot array of the
+     * object. We can't check the allocated capacity of the dynamic slots, but
+     * make sure their presence is consistent with the shape.
+     */
+    JS_ASSERT(shape && type);
+    JS_ASSERT(!!dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan()) == !!slots);
+    JS_ASSERT(js::gc::GetGCKindSlots(getAllocKind(), shape->getObjectClass()) == shape->numFixedSlots());
+
+    this->shape_ = shape;
+    this->type_ = type;
+    this->slots = slots;
+    this->elements = js::emptyObjectElements;
+
+    if (shape->getObjectClass()->hasPrivate())
+        setPrivate(NULL);
+
+    size_t span = shape->slotSpan();
+    if (span)
+        clearSlotRange(0, span);
+}
+
+inline void
+JSObject::initializeDenseArray(js::Shape *shape, js::types::TypeObject *type, uint32 length)
+{
+    JS_ASSERT(shape && type);
+    JS_ASSERT(shape->getObjectClass() == &js::ArrayClass);
+    JS_ASSERT(js::gc::GetGCKindSlots(getAllocKind(), shape->getObjectClass()) == shape->numFixedSlots());
 
     JS_STATIC_ASSERT(sizeof(js::ObjectElements) == 2 * sizeof(js::Value));
-    JS_ASSERT(numFixedSlots() >= 2);
+    JS_ASSERT(shape->numFixedSlots() >= 2);
 
-    /* Fill in the object's inline elements header. */
-    elements = fixedElements();
-    new (getElementsHeader()) js::ObjectElements(numFixedSlots() - 2);
+    this->shape_ = shape;
+    this->type_ = type;
+    this->slots = NULL;
+    this->elements = fixedElements();
+    new (getElementsHeader()) js::ObjectElements(shape->numFixedSlots() - 2, length);
 }
 
 inline void
 JSObject::finish(JSContext *cx)
 {
     if (hasDynamicSlots())
         cx->free_(slots);
     if (hasDynamicElements())
         cx->free_(getElementsHeader());
 }
 
 inline bool
-JSObject::initSharingEmptyShape(JSContext *cx,
-                                js::Class *aclasp,
-                                js::types::TypeObject *type,
-                                void *privateValue,
-                                js::gc::AllocKind kind)
-{
-    init(cx, type);
-
-    js::EmptyShape *empty = type->getEmptyShape(cx, aclasp, kind);
-    if (!empty)
-        return false;
-
-    if (!setInitialProperty(cx, empty))
-        return false;
-
-    if (privateValue)
-        setPrivate(privateValue);
-
-    JS_ASSERT(!isDenseArray());
-    return true;
-}
-
-inline bool
 JSObject::hasProperty(JSContext *cx, jsid id, bool *foundp, uintN flags)
 {
     JSObject *pobj;
     JSProperty *prop;
     JSAutoResolveFlags rf(cx, flags);
     if (!lookupGeneric(cx, id, &pobj, &prop))
         return false;
     *foundp = !!prop;
@@ -1051,17 +992,16 @@ JSObject::principals(JSContext *cx)
     if (JSObjectPrincipalsFinder finder = cb ? cb->findObjectPrincipals : NULL)
         return finder(cx, this);
     return cx->compartment ? cx->compartment->principals : NULL;
 }
 
 inline uint32
 JSObject::slotSpan() const
 {
-    JS_ASSERT(!isNewborn());
     if (inDictionaryMode())
         return lastProperty()->base()->slotSpan();
     return lastProperty()->slotSpan();
 }
 
 inline bool
 JSObject::containsSlot(uint32 slot) const
 {
@@ -1444,52 +1384,16 @@ class AutoPropertyDescriptorRooter : pri
         setter = desc->setter;
         value = desc->value;
     }
 
     friend void AutoGCRooter::trace(JSTracer *trc);
 };
 
 static inline bool
-InitScopeForObject(JSContext* cx, JSObject* obj, js::Class *clasp, JSObject *parent,
-                   js::types::TypeObject *type, gc::AllocKind kind)
-{
-    JS_ASSERT(clasp->isNative());
-
-    /* Share proto's emptyShape only if obj is similar to proto. */
-    js::EmptyShape *empty = NULL;
-
-    if (type->canProvideEmptyShape(clasp) && parent == type->proto->getParent())
-        empty = type->getEmptyShape(cx, clasp, kind);
-    else
-        empty = js::EmptyShape::create(cx, clasp, parent, gc::GetGCKindSlots(kind, clasp));
-    if (!empty) {
-        JS_ASSERT(obj->isNewborn());
-        return false;
-    }
-
-    return obj->setInitialProperty(cx, empty);
-}
-
-static inline bool
-InitScopeForNonNativeObject(JSContext *cx, JSObject *obj, js::Class *clasp, JSObject *parent,
-                            gc::AllocKind kind)
-{
-    JS_ASSERT(!clasp->isNative());
-
-    const js::Shape *empty = js::BaseShape::lookupInitialShape(cx, clasp, parent, kind);
-    if (!empty)
-        return false;
-    JS_ASSERT(empty->isEmptyShape());
-
-    obj->setInitialPropertyInfallible(empty);
-    return true;
-}
-
-static inline bool
 CanBeFinalizedInBackground(gc::AllocKind kind, Class *clasp)
 {
 #ifdef JS_THREADSAFE
     JS_ASSERT(kind <= gc::FINALIZE_OBJECT_LAST);
     /* If the class has no finalizer or a finalizer that is safe to call on
      * a different thread, we change the finalize kind. For example,
      * FINALIZE_OBJECT0 calls the finalizer on the main thread,
      * FINALIZE_OBJECT0_BACKGROUND calls the finalizer on the gcHelperThread.
@@ -1498,299 +1402,169 @@ CanBeFinalizedInBackground(gc::AllocKind
      */
     if (!gc::IsBackgroundAllocKind(kind) && !clasp->finalize)
         return true;
 #endif
     return false;
 }
 
 /*
- * Helper optimized for creating a native instance of the given class (not the
- * class's prototype object). Use this in preference to NewObject, but use
- * NewBuiltinClassInstance if you need the default class prototype as proto.
+ * Make an object with the specified prototype. If parent is null, it will
+ * default to the prototype's global if the prototype is non-null.
  */
-static inline JSObject *
-NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto, gc::AllocKind kind)
+JSObject *
+NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
+                        gc::AllocKind kind);
+
+inline JSObject *
+NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent)
 {
-    JS_ASSERT(proto);
-    JS_ASSERT(kind <= gc::FINALIZE_OBJECT_LAST);
-
-    types::TypeObject *type = proto->getNewType(cx);
-    if (!type)
-        return NULL;
-
-    /*
-     * Allocate an object from the GC heap and initialize all its fields before
-     * doing any operation that can potentially trigger GC.
-     */
+    gc::AllocKind kind = gc::GetGCObjectKind(clasp);
+    return NewObjectWithGivenProto(cx, clasp, proto, parent, kind);
+}
 
-    if (CanBeFinalizedInBackground(kind, clasp))
-        kind = GetBackgroundAllocKind(kind);
-
-    JSObject* obj = js_NewGCObject(cx, kind);
-    if (!obj)
-        return NULL;
+inline JSProtoKey
+GetClassProtoKey(js::Class *clasp)
+{
+    JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
+    if (key != JSProto_Null)
+        return key;
+    if (clasp->flags & JSCLASS_IS_ANONYMOUS)
+        return JSProto_Object;
+    return JSProto_Null;
+}
 
-    /*
-     * Default parent to the parent of the prototype, which was set from
-     * the parent of the prototype's constructor.
-     */
-    obj->init(cx, type);
-
-    JS_ASSERT(type->canProvideEmptyShape(clasp));
-
-    js::EmptyShape *empty = type->getEmptyShape(cx, clasp, kind);
-    if (!empty || !obj->setInitialProperty(cx, empty))
-        return NULL;
-
-    return obj;
+inline bool
+FindProto(JSContext *cx, js::Class *clasp, JSObject *parent, JSObject ** proto)
+{
+    JSProtoKey protoKey = GetClassProtoKey(clasp);
+    if (!js_GetClassPrototype(cx, parent, protoKey, proto, clasp))
+        return false;
+    if (!(*proto) && !js_GetClassPrototype(cx, parent, JSProto_Object, proto))
+        return false;
+    return true;
 }
 
-static inline JSObject *
-NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto)
+/*
+ * Make an object with the prototype set according to the specified prototype or class:
+ *
+ * if proto is non-null:
+ *   use the specified proto
+ * for a built-in class:
+ *   use the memoized original value of the class constructor .prototype
+ *   property object
+ * else if available
+ *   the current value of .prototype
+ * else
+ *   Object.prototype.
+ *
+ * The class prototype will be fetched from the parent's global. If global is
+ * null, the context's active global will be used, and the resulting object's
+ * parent will be that global.
+ */
+inline JSObject *
+NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
+                        gc::AllocKind kind)
+{
+    if (!proto && !FindProto(cx, clasp, parent, &proto))
+        return NULL;
+    return NewObjectWithGivenProto(cx, clasp, proto, parent, kind);
+}
+
+inline JSObject *
+NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent)
 {
     gc::AllocKind kind = gc::GetGCObjectKind(clasp);
-    return NewNativeClassInstance(cx, clasp, proto, kind);
+    return NewObjectWithClassProto(cx, clasp, proto, parent, kind);
+}
+
+/*
+ * Create a native instance of the given class with parent and proto set
+ * according to the context's active global.
+ */
+inline JSObject *
+NewBuiltinClassInstance(JSContext *cx, Class *clasp, gc::AllocKind kind)
+{
+    return NewObjectWithClassProto(cx, clasp, NULL, NULL, kind);
+}
+
+inline JSObject *
+NewBuiltinClassInstance(JSContext *cx, Class *clasp)
+{
+    gc::AllocKind kind = gc::GetGCObjectKind(clasp);
+    return NewBuiltinClassInstance(cx, clasp, kind);
 }
 
 inline GlobalObject *
 GetCurrentGlobal(JSContext *cx)
 {
     JSObject *scopeChain = (cx->hasfp()) ? &cx->fp()->scopeChain() : cx->globalObject;
     return scopeChain ? scopeChain->getGlobal() : NULL;
 }
 
 bool
 FindClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey, JSObject **protop,
                    Class *clasp);
 
 /*
- * Helper used to create Boolean, Date, RegExp, etc. instances of built-in
- * classes with class prototypes of the same Class. See, e.g., jsdate.cpp,
- * jsregexp.cpp, and js_PrimitiveToObject in jsobj.cpp. Use this to get the
- * right default proto and parent for clasp in cx.
+ * Create a plain object with the specified type. This bypasses getNewType to
+ * avoid losing creation site information for objects made by scripted 'new'.
  */
-static inline JSObject *
-NewBuiltinClassInstance(JSContext *cx, Class *clasp, gc::AllocKind kind)
-{
-    VOUCH_DOES_NOT_REQUIRE_STACK();
-
-    JSProtoKey protoKey = JSCLASS_CACHED_PROTO_KEY(clasp);
-    JS_ASSERT(protoKey != JSProto_Null);
-
-    /* NB: inline-expanded and specialized version of js_GetClassPrototype. */
-    JSObject *global;
-    if (!cx->hasfp()) {
-        global = JS_ObjectToInnerObject(cx, cx->globalObject);
-        if (!global)
-            return NULL;
-    } else {
-        global = cx->fp()->scopeChain().getGlobal();
-    }
-    JS_ASSERT(global->isGlobal());
-
-    const Value &v = global->getReservedSlot(JSProto_LIMIT + protoKey);
-    JSObject *proto;
-    if (v.isObject()) {
-        proto = &v.toObject();
-    } else {
-        if (!FindClassPrototype(cx, global, protoKey, &proto, clasp))
-            return NULL;
-    }
-    JS_ASSERT(proto->getParent() == global);
-
-    return NewNativeClassInstance(cx, clasp, proto, kind);
-}
-
-static inline JSObject *
-NewBuiltinClassInstance(JSContext *cx, Class *clasp)
-{
-    gc::AllocKind kind = gc::GetGCObjectKind(clasp);
-    return NewBuiltinClassInstance(cx, clasp, kind);
-}
-
-static inline JSProtoKey
-GetClassProtoKey(js::Class *clasp)
-{
-    JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
-    if (key != JSProto_Null)
-        return key;
-    if (clasp->flags & JSCLASS_IS_ANONYMOUS)
-        return JSProto_Object;
-    return JSProto_Null;
-}
+JSObject *
+NewObjectWithType(JSContext *cx, types::TypeObject *type, JSObject *parent, gc::AllocKind kind);
 
-namespace WithProto {
-    enum e {
-        Class = 0,
-        Given = 1
-    };
-}
+/* Make an object with pregenerated shape from a NEWOBJECT bytecode. */
+static inline JSObject *
+CopyInitializerObject(JSContext *cx, JSObject *baseobj, types::TypeObject *type)
+{
+    JS_ASSERT(baseobj->getClass() == &ObjectClass);
+    JS_ASSERT(!baseobj->inDictionaryMode());
 
-/*
- * Create an instance of any class, native or not, JSFunction-sized or not.
- *
- * If withProto is 'Class':
- *    If proto is null:
- *      for a built-in class:
- *        use the memoized original value of the class constructor .prototype
- *        property object
- *      else if available
- *        the current value of .prototype
- *      else
- *        Object.prototype.
- *
- *    If parent is null, default it to proto->getParent() if proto is non
- *    null, else to null.
- *
- * If withProto is 'Given':
- *    We allocate an object with exactly the given proto.  A null parent
- *    defaults to proto->getParent() if proto is non-null (else to null).
- *
- * If isFunction is true, return a JSFunction-sized object. If isFunction is
- * false, return a normal object.
- *
- * Note that as a template, there will be lots of instantiations, which means
- * the internals will be specialized based on the template parameters.
- */
-static JS_ALWAYS_INLINE bool
-FindProto(JSContext *cx, js::Class *clasp, JSObject *parent, JSObject ** proto)
-{
-    JSProtoKey protoKey = GetClassProtoKey(clasp);
-    if (!js_GetClassPrototype(cx, parent, protoKey, proto, clasp))
-        return false;
-    if (!(*proto) && !js_GetClassPrototype(cx, parent, JSProto_Object, proto))
-        return false;
+    gc::AllocKind kind = gc::GetGCObjectFixedSlotsKind(baseobj->numFixedSlots());
+#ifdef JS_THREADSAFE
+    kind = gc::GetBackgroundAllocKind(kind);
+#endif
+    JS_ASSERT(kind == baseobj->getAllocKind());
+    JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
 
-    return true;
-}
-
-template <bool withProto>
-static JS_ALWAYS_INLINE JSObject *
-NewObject(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
-          gc::AllocKind kind)
-{
-    /* Bootstrap the ur-object, and make it the default prototype object. */
-    if (withProto == WithProto::Class && !proto) {
-        if (!FindProto(cx, clasp, parent, &proto))
-          return NULL;
-    }
-
-    types::TypeObject *type = proto ? proto->getNewType(cx) : cx->compartment->getEmptyType(cx);
-    if (!type)
+    if (!obj)
         return NULL;
 
-    /*
-     * Allocate an object from the GC heap and initialize all its fields before
-     * doing any operation that can potentially trigger GC. Functions have a
-     * larger non-standard allocation size.
-     *
-     * The should be specialized by the template.
-     */
-
-    JS_ASSERT_IF(clasp == &FunctionClass,
-                 kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
-
-    if (CanBeFinalizedInBackground(kind, clasp))
-        kind = GetBackgroundAllocKind(kind);
-
-    JSObject* obj = js_NewGCObject(cx, kind);
-    if (!obj)
-        goto out;
+    obj->setType(type);
 
-    obj->init(cx, type);
-
-    /*
-     * Default parent to the parent of the prototype, which was set from
-     * the parent of the prototype's constructor.
-     */
-    if (!parent && proto)
-        parent = proto->getParent();
+    if (!obj->setLastProperty(cx, baseobj->lastProperty()))
+        return NULL;
 
-    if (clasp->isNative()
-        ? !InitScopeForObject(cx, obj, clasp, parent, type, kind)
-        : !InitScopeForNonNativeObject(cx, obj, clasp, parent, kind)) {
-        obj = NULL;
-    }
-
-out:
-    Probes::createObject(cx, obj);
     return obj;
 }
 
-template <WithProto::e withProto>
-static JS_ALWAYS_INLINE JSObject *
-NewObject(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent)
-{
-    gc::AllocKind kind = gc::GetGCObjectKind(clasp);
-    return NewObject<withProto>(cx, clasp, proto, parent, kind);
-}
+JSObject *
+NewReshapedObject(JSContext *cx, js::types::TypeObject *type, JSObject *parent,
+                  gc::AllocKind kind, const Shape *shape);
 
-static JS_ALWAYS_INLINE JSFunction *
-NewFunction(JSContext *cx, JSObject *parent, gc::AllocKind kind)
-{
-    JSObject *obj = NewObject<WithProto::Class>(cx, &FunctionClass, NULL, parent, kind);
-    return static_cast<JSFunction *>(obj);
-}
-
-template <WithProto::e withProto>
-static JS_ALWAYS_INLINE JSObject *
-NewNonFunction(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
-               gc::AllocKind kind)
-{
-    return NewObject<withProto>(cx, clasp, proto, parent, kind);
-}
-
-template <WithProto::e withProto>
-static JS_ALWAYS_INLINE JSObject *
-NewNonFunction(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent)
+inline Shape *
+GetInitialShapeForObject(JSContext* cx, Class *clasp, JSObject *parent,
+                         types::TypeObject *type, gc::AllocKind kind)
 {
-    gc::AllocKind kind = gc::GetGCObjectKind(clasp);
-    return NewObject<withProto>(cx, clasp, proto, parent, kind);
-}
-
-/*
- * Create a plain object with the specified type. This bypasses getNewType to
- * avoid losing creation site information for objects made by scripted 'new'.
- */
-static JS_ALWAYS_INLINE JSObject *
-NewObjectWithType(JSContext *cx, types::TypeObject *type, JSObject *parent, gc::AllocKind kind)
-{
-    JS_ASSERT(type->proto->hasNewType(type));
-
-    if (CanBeFinalizedInBackground(kind, &ObjectClass))
-        kind = GetBackgroundAllocKind(kind);
+    if (clasp->isNative()) {
+        /* Share empty shapes on the type only if the object is similar to the proto. */
+        if (type->canProvideEmptyShape(clasp) && parent == type->proto->getParent())
+            return type->getEmptyShape(cx, clasp, kind);
 
-    JSObject* obj = js_NewGCObject(cx, kind);
-    if (!obj)
-        goto out;
-
-    obj->init(cx, type);
-
-    /*
-     * Default parent to the parent of the prototype, which was set from
-     * the parent of the prototype's constructor.
-     */
-    if (!parent && type->proto)
-        parent = type->proto->getParent();
-
-    if (!InitScopeForObject(cx, obj, &ObjectClass, parent, type, kind)) {
-        obj = NULL;
-        goto out;
+        return EmptyShape::create(cx, clasp, parent, gc::GetGCKindSlots(kind, clasp));
     }
 
-out:
-    Probes::createObject(cx, obj);
-    return obj;
+    Shape *empty = BaseShape::lookupInitialShape(cx, clasp, parent, kind);
+    if (!empty)
+        return NULL;
+    JS_ASSERT(empty->isEmptyShape());
+
+    return empty;
 }
 
-extern JSObject *
-NewReshapedObject(JSContext *cx, js::types::TypeObject *type, JSObject *parent,
-                  gc::AllocKind kind, const Shape *shape);
-
 /*
  * As for gc::GetGCObjectKind, where numSlots is a guess at the final size of
  * the object, zero if the final size is unknown. This should only be used for
  * objects that do not require any fixed slots.
  */
 static inline gc::AllocKind
 GuessObjectGCKind(size_t numSlots)
 {
@@ -1816,61 +1590,33 @@ NewObjectGCKind(JSContext *cx, js::Class
 {
     if (clasp == &ArrayClass || clasp == &SlowArrayClass)
         return gc::FINALIZE_OBJECT8;
     if (clasp == &FunctionClass)
         return gc::FINALIZE_OBJECT2;
     return gc::FINALIZE_OBJECT4;
 }
 
-static JS_ALWAYS_INLINE JSObject*
-NewObjectWithClassProto(JSContext *cx, Class *clasp, JSObject *proto,
-                        gc::AllocKind kind)
+/*
+ * Fill slots with the initial slot array to use for a newborn object which
+ * may need dynamic slots.
+ */
+inline bool
+ReserveObjectDynamicSlots(JSContext *cx, Shape *shape, Value **slots)
 {
-    JS_ASSERT(clasp->isNative());
-
-    types::TypeObject *type = proto->getNewType(cx);
-    if (!type)
-        return NULL;
-
-    if (CanBeFinalizedInBackground(kind, clasp))
-        kind = GetBackgroundAllocKind(kind);
-
-    JSObject* obj = js_NewGCObject(cx, kind);
-    if (!obj)
-        return NULL;
-
-    if (!obj->initSharingEmptyShape(cx, clasp, type, NULL, kind))
-        return NULL;
-    return obj;
-}
-
-/* Make an object with pregenerated shape from a NEWOBJECT bytecode. */
-static inline JSObject *
-CopyInitializerObject(JSContext *cx, JSObject *baseobj, types::TypeObject *type)
-{
-    JS_ASSERT(baseobj->getClass() == &ObjectClass);
-    JS_ASSERT(!baseobj->inDictionaryMode());
-
-    gc::AllocKind kind = gc::GetGCObjectFixedSlotsKind(baseobj->numFixedSlots());
-#ifdef JS_THREADSAFE
-    kind = gc::GetBackgroundAllocKind(kind);
-#endif
-    JS_ASSERT(kind == baseobj->getAllocKind());
-    JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
-
-    if (!obj)
-        return NULL;
-
-    obj->setType(type);
-
-    if (!obj->setLastProperty(cx, baseobj->lastProperty()))
-        return NULL;
-
-    return obj;
+    size_t count = JSObject::dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan());
+    if (count) {
+        *slots = (Value *) cx->malloc_(count * sizeof(Value));
+        if (!*slots)
+            return false;
+        Debug_SetValueRangeToCrashOnTouch(*slots, count);
+        return true;
+    }
+    *slots = NULL;
+    return true;
 }
 
 inline bool
 DefineConstructorAndPrototype(JSContext *cx, GlobalObject *global,
                               JSProtoKey key, JSObject *ctor, JSObject *proto)
 {
     JS_ASSERT(!global->nativeEmpty()); /* reserved slots already allocated */
     JS_ASSERT(ctor);
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -927,17 +927,17 @@ static JSFunctionSpec json_static_method
     JS_FN("parse",          js_json_parse,      2, 0),
     JS_FN("stringify",      js_json_stringify,  3, 0),
     JS_FS_END
 };
 
 JSObject *
 js_InitJSONClass(JSContext *cx, JSObject *obj)
 {
-    JSObject *JSON = NewNonFunction<WithProto::Class>(cx, &JSONClass, NULL, obj);
+    JSObject *JSON = NewObjectWithClassProto(cx, &JSONClass, NULL, obj);
     if (!JSON || !JSON->setSingletonType(cx))
         return NULL;
 
     if (!JS_DefineProperty(cx, obj, js_JSON_str, OBJECT_TO_JSVAL(JSON),
                            JS_PropertyStub, JS_StrictPropertyStub, 0))
         return NULL;
 
     if (!JS_DefineFunctions(cx, JSON, json_static_methods))
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -1426,17 +1426,17 @@ js::NewProxyObject(JSContext *cx, ProxyH
     /*
      * Eagerly mark properties unknown for proxies, so we don't try to track
      * their properties and so that we don't need to walk the compartment if
      * their prototype changes later.
      */
     if (proto)
         proto->getNewType(cx, NULL, /* markUnknown = */ true);
 
-    JSObject *obj = NewNonFunction<WithProto::Given>(cx, clasp, proto, parent);
+    JSObject *obj = NewObjectWithGivenProto(cx, clasp, proto, parent);
     if (!obj)
         return NULL;
     obj->setSlot(JSSLOT_PROXY_HANDLER, PrivateValue(handler));
     obj->setSlot(JSSLOT_PROXY_PRIVATE, priv);
     if (fun) {
         obj->setSlot(JSSLOT_PROXY_CALL, call ? ObjectValue(*call) : UndefinedValue());
         if (construct) {
             obj->setSlot(JSSLOT_PROXY_CONSTRUCT, ObjectValue(*construct));
@@ -1606,17 +1606,17 @@ callable_Construct(JSContext *cx, uintN 
         if (protov.isObject()) {
             proto = &protov.toObject();
         } else {
             proto = callable->getGlobal()->getOrCreateObjectPrototype(cx);
             if (!proto)
                 return false;
         }
 
-        JSObject *newobj = NewNativeClassInstance(cx, &ObjectClass, proto);
+        JSObject *newobj = NewObjectWithGivenProto(cx, &ObjectClass, proto, NULL);
         if (!newobj)
             return false;
 
         /* If the call returns an object, return that, otherwise the original newobj. */
         Value rval;
         if (!Invoke(cx, ObjectValue(*newobj), callable->getSlot(JSSLOT_CALLABLE_CALL),
                     argc, vp + 2, &rval)) {
             return false;
@@ -1673,17 +1673,17 @@ js::FixProxy(JSContext *cx, JSObject *pr
     JSObject *parent = proxy->getParent();
     Class *clasp = IsFunctionProxy(proxy) ? &CallableObjectClass : &ObjectClass;
 
     /*
      * Make a blank object from the recipe fix provided to us.  This must have
      * number of fixed slots as the proxy so that we can swap their contents.
      */
     gc::AllocKind kind = proxy->getAllocKind();
-    JSObject *newborn = NewNonFunction<WithProto::Given>(cx, clasp, proto, parent, kind);
+    JSObject *newborn = NewObjectWithGivenProto(cx, clasp, proto, parent, kind);
     if (!newborn)
         return false;
     AutoObjectRooter tvr2(cx, newborn);
 
     if (clasp == &CallableObjectClass) {
         newborn->setSlot(JSSLOT_CALLABLE_CALL, GetCall(proxy));
         newborn->setSlot(JSSLOT_CALLABLE_CONSTRUCT, GetConstruct(proxy));
     }
@@ -1714,17 +1714,17 @@ Class js::ProxyClass = {
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub
 };
 
 JS_FRIEND_API(JSObject *)
 js_InitProxyClass(JSContext *cx, JSObject *obj)
 {
-    JSObject *module = NewNonFunction<WithProto::Class>(cx, &ProxyClass, NULL, obj);
+    JSObject *module = NewObjectWithClassProto(cx, &ProxyClass, NULL, obj);
     if (!module || !module->setSingletonType(cx))
         return NULL;
 
     if (!JS_DefineProperty(cx, obj, "Proxy", OBJECT_TO_JSVAL(module),
                            JS_PropertyStub, JS_StrictPropertyStub, 0)) {
         return NULL;
     }
     if (!JS_DefineFunctions(cx, module, static_methods))
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -316,17 +316,17 @@ class NodeBuilder
         if (!atom)
             return false;
 
         dst->setString(atom);
         return true;
     }
 
     bool newObject(JSObject **dst) {
-        JSObject *nobj = NewNonFunction<WithProto::Class>(cx, &ObjectClass, NULL, NULL);
+        JSObject *nobj = NewBuiltinClassInstance(cx, &ObjectClass);
         if (!nobj)
             return false;
 
         *dst = nobj;
         return true;
     }
 
     bool newArray(NodeVector &elts, Value *dst);
@@ -626,17 +626,17 @@ class NodeBuilder
 
 bool
 NodeBuilder::newNode(ASTType type, TokenPos *pos, JSObject **dst)
 {
     JS_ASSERT(type > AST_ERROR && type < AST_LIMIT);
 
     Value tv;
 
-    JSObject *node = NewNonFunction<WithProto::Class>(cx, &ObjectClass, NULL, NULL);
+    JSObject *node = NewBuiltinClassInstance(cx, &ObjectClass);
     if (!node ||
         !setNodeLoc(node, pos) ||
         !atomValue(nodeTypeNames[type], &tv) ||
         !setProperty(node, "type", tv)) {
         return false;
     }
 
     *dst = node;
@@ -3241,17 +3241,17 @@ static JSFunctionSpec static_methods[] =
 };
 
 
 JS_BEGIN_EXTERN_C
 
 JS_PUBLIC_API(JSObject *)
 JS_InitReflect(JSContext *cx, JSObject *obj)
 {
-    JSObject *Reflect = NewNonFunction<WithProto::Class>(cx, &ObjectClass, NULL, obj);
+    JSObject *Reflect = NewObjectWithClassProto(cx, &ObjectClass, NULL, obj);
     if (!Reflect || !Reflect->setSingletonType(cx))
         return NULL;
 
     if (!JS_DefineProperty(cx, obj, "Reflect", OBJECT_TO_JSVAL(Reflect),
                            JS_PropertyStub, JS_StrictPropertyStub, 0)) {
         return NULL;
     }
 
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -190,17 +190,17 @@ JSObject::allocateArrayBufferSlots(JSCon
 
     return true;
 }
 
 static JSObject *
 DelegateObject(JSContext *cx, JSObject *obj)
 {
     if (!obj->getPrivate()) {
-        JSObject *delegate = NewNonFunction<WithProto::Given>(cx, &ObjectClass, obj->getProto(), NULL);
+        JSObject *delegate = NewObjectWithGivenProto(cx, &ObjectClass, obj->getProto(), NULL);
         obj->setPrivate(delegate);
         return delegate;
     }
     return static_cast<JSObject*>(obj->getPrivate());
 }
 
 JSObject *
 ArrayBuffer::create(JSContext *cx, int32 nbytes)
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -502,17 +502,17 @@ static JSObject *
 NewXMLAttributeName(JSContext *cx, JSLinearString *uri, JSLinearString *prefix,
                     JSAtom *localName)
 {
     /*
      * AttributeName is an internal anonymous class which instances are not
      * exposed to scripts.
      */
     JSObject *parent = GetGlobalForScopeChain(cx);
-    JSObject *obj = NewNonFunction<WithProto::Given>(cx, &AttributeNameClass, NULL, parent);
+    JSObject *obj = NewObjectWithGivenProto(cx, &AttributeNameClass, NULL, parent);
     if (!obj)
         return NULL;
     JS_ASSERT(obj->isQName());
     if (!InitXMLQName(cx, obj, uri, prefix, localName))
         return NULL;
     return obj;
 }
 
@@ -7322,17 +7322,17 @@ js_NewXMLObject(JSContext *cx, JSXMLClas
 }
 
 static JSObject *
 NewXMLObject(JSContext *cx, JSXML *xml)
 {
     JSObject *obj;
 
     JSObject *parent = GetGlobalForScopeChain(cx);
-    obj = NewNonFunction<WithProto::Class>(cx, &XMLClass, NULL, parent);
+    obj = NewObjectWithClassProto(cx, &XMLClass, NULL, parent);
     if (!obj)
         return NULL;
     obj->setPrivate(xml);
     return obj;
 }
 
 JSObject *
 js_GetXMLObject(JSContext *cx, JSXML *xml)
@@ -7659,17 +7659,17 @@ js_ValueToXMLString(JSContext *cx, const
 }
 
 JSBool
 js_GetAnyName(JSContext *cx, jsid *idp)
 {
     JSObject *global = cx->hasfp() ? cx->fp()->scopeChain().getGlobal() : cx->globalObject;
     Value v = global->getReservedSlot(JSProto_AnyName);
     if (v.isUndefined()) {
-        JSObject *obj = NewNonFunction<WithProto::Given>(cx, &AnyNameClass, NULL, global);
+        JSObject *obj = NewObjectWithGivenProto(cx, &AnyNameClass, NULL, global);
         if (!obj)
             return false;
 
         JS_ASSERT(!obj->getProto());
 
         JSRuntime *rt = cx->runtime;
         if (!InitXMLQName(cx, obj, rt->emptyString, rt->emptyString, rt->atomState.starAtom))
             return false;
@@ -7928,17 +7928,17 @@ js_StepXMLListFilter(JSContext *cx, JSBo
              */
             sp[-1] = OBJECT_TO_JSVAL(obj);
             list = (JSXML *) obj->getPrivate();
             if (!Append(cx, list, xml))
                 return JS_FALSE;
         }
 
         JSObject *parent = GetGlobalForScopeChain(cx);
-        filterobj = NewNonFunction<WithProto::Given>(cx, &js_XMLFilterClass, NULL, parent);
+        filterobj = NewObjectWithGivenProto(cx, &js_XMLFilterClass, NULL, parent);
         if (!filterobj)
             return JS_FALSE;
 
         /*
          * Init all filter fields before setPrivate exposes it to
          * xmlfilter_trace or xmlfilter_finalize.
          */
         filter = cx->new_<JSXMLFilter>(list, &list->xml_kids);
--- a/js/src/vm/BooleanObject-inl.h
+++ b/js/src/vm/BooleanObject-inl.h
@@ -63,17 +63,17 @@ BooleanObject::create(JSContext *cx, boo
     BooleanObject *boolobj = obj->asBoolean();
     boolobj->setPrimitiveValue(b);
     return boolobj;
 }
 
 inline BooleanObject *
 BooleanObject::createWithProto(JSContext *cx, bool b, JSObject &proto)
 {
-    JSObject *obj = NewObjectWithClassProto(cx, &BooleanClass, &proto,
+    JSObject *obj = NewObjectWithClassProto(cx, &BooleanClass, &proto, NULL,
                                             gc::GetGCObjectKind(RESERVED_SLOTS));
     if (!obj)
         return NULL;
     BooleanObject *boolobj = obj->asBoolean();
     boolobj->setPrimitiveValue(b);
     return boolobj;
 }
 
--- a/js/src/vm/CallObject.cpp
+++ b/js/src/vm/CallObject.cpp
@@ -52,32 +52,62 @@ namespace js {
  * must be null.
  */
 CallObject *
 CallObject::create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObject *callee)
 {
     Bindings &bindings = script->bindings;
     gc::AllocKind kind = gc::GetGCObjectKind(bindings.lastShape()->numFixedSlots() + 1);
 
+    js::types::TypeObject *type = cx->compartment->getEmptyType(cx);
+    if (!type)
+        return NULL;
+
+    Value *slots;
+    if (!ReserveObjectDynamicSlots(cx, bindings.lastShape(), &slots))
+        return NULL;
+
     JSObject *obj = js_NewGCObject(cx, kind);
     if (!obj)
         return NULL;
 
-    /* Init immediately to avoid GC seeing a half-init'ed object. */
-    if (!obj->initCall(cx, bindings, &scopeChain))
-        return NULL;
+    obj->initialize(bindings.lastShape(), type, slots);
+
+    /*
+     * Update the parent for bindings associated with non-compileAndGo scripts,
+     * whose call objects do not have a consistent global variable and need
+     * to be updated dynamically.
+     */
+    JSObject *global = scopeChain.getGlobal();
+    if (global != obj->getParentMaybeScope()) {
+        JS_ASSERT(obj->getParentMaybeScope() == NULL);
+        if (!obj->setParent(cx, global))
+            return NULL;
+    }
 
 #ifdef DEBUG
     for (Shape::Range r = obj->lastProperty(); !r.empty(); r.popFront()) {
         const Shape &s = r.front();
         if (s.hasSlot()) {
             JS_ASSERT(s.slot() + 1 == obj->slotSpan());
             break;
         }
     }
 #endif
 
+    JS_ASSERT(obj->isCall());
+    JS_ASSERT(!obj->inDictionaryMode());
+
+    obj->setScopeChain(&scopeChain);
+
+    /*
+     * If |bindings| is for a function that has extensible parents, that means
+     * its Call should have its own shape; see js::BaseShape::extensibleParents.
+     */
+    if (obj->lastProperty()->extensibleParents() && !obj->generateOwnShape(cx))
+        return NULL;
+
     CallObject &callobj = obj->asCall();
     callobj.setCallee(callee);
     return &callobj;
 }
 
 }
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -361,17 +361,17 @@ bool
 Debugger::getScriptFrame(JSContext *cx, StackFrame *fp, Value *vp)
 {
     JS_ASSERT(fp->isScriptFrame());
     FrameMap::AddPtr p = frames.lookupForAdd(fp);
     if (!p) {
         /* Create and populate the Debugger.Frame object. */
         JSObject *proto = &object->getReservedSlot(JSSLOT_DEBUG_FRAME_PROTO).toObject();
         JSObject *frameobj =
-            NewNonFunction<WithProto::Given>(cx, &DebuggerFrame_class, proto, NULL);
+            NewObjectWithGivenProto(cx, &DebuggerFrame_class, proto, NULL);
         if (!frameobj)
             return false;
         frameobj->setPrivate(fp);
         frameobj->setReservedSlot(JSSLOT_DEBUGFRAME_OWNER, ObjectValue(*object));
 
         if (!frames.add(p, fp, frameobj)) {
             js_ReportOutOfMemory(cx);
             return false;
@@ -490,17 +490,17 @@ Debugger::wrapDebuggeeValue(JSContext *c
 
         CellWeakMap::AddPtr p = objects.lookupForAdd(obj);
         if (p) {
             vp->setObject(*p->value);
         } else {
             /* Create a new Debugger.Object for obj. */
             JSObject *proto = &object->getReservedSlot(JSSLOT_DEBUG_OBJECT_PROTO).toObject();
             JSObject *dobj =
-                NewNonFunction<WithProto::Given>(cx, &DebuggerObject_class, proto, NULL);
+                NewObjectWithGivenProto(cx, &DebuggerObject_class, proto, NULL);
             if (!dobj)
                 return false;
             dobj->setPrivate(obj);
             dobj->setReservedSlot(JSSLOT_DEBUGOBJECT_OWNER, ObjectValue(*object));
             if (!objects.relookupOrAdd(p, obj, dobj)) {
                 js_ReportOutOfMemory(cx);
                 return false;
             }
@@ -1593,17 +1593,17 @@ Debugger::construct(JSContext *cx, uintN
     JSObject *proto = &v.toObject();
     JS_ASSERT(proto->getClass() == &Debugger::jsclass);
 
     /*
      * Make the new Debugger object. Each one has a reference to
      * Debugger.{Frame,Object,Script}.prototype in reserved slots. The rest of
      * the reserved slots are for hooks; they default to undefined.
      */
-    JSObject *obj = NewNonFunction<WithProto::Given>(cx, &Debugger::jsclass, proto, NULL);
+    JSObject *obj = NewObjectWithGivenProto(cx, &Debugger::jsclass, proto, NULL);
     if (!obj)
         return false;
     for (uintN slot = JSSLOT_DEBUG_PROTO_START; slot < JSSLOT_DEBUG_PROTO_STOP; slot++)
         obj->setReservedSlot(slot, proto->getReservedSlot(slot));
 
     Debugger *dbg = cx->new_<Debugger>(cx, obj);
     if (!dbg)
         return false;
@@ -1807,17 +1807,17 @@ Class DebuggerScript_class = {
 
 JSObject *
 Debugger::newDebuggerScript(JSContext *cx, JSScript *script)
 {
     assertSameCompartment(cx, object);
 
     JSObject *proto = &object->getReservedSlot(JSSLOT_DEBUG_SCRIPT_PROTO).toObject();
     JS_ASSERT(proto);
-    JSObject *scriptobj = NewNonFunction<WithProto::Given>(cx, &DebuggerScript_class, proto, NULL);
+    JSObject *scriptobj = NewObjectWithGivenProto(cx, &DebuggerScript_class, proto, NULL);
     if (!scriptobj)
         return NULL;
     scriptobj->setPrivate(script);
     scriptobj->setReservedSlot(JSSLOT_DEBUGSCRIPT_OWNER, ObjectValue(*object));
 
     return scriptobj;
 }
 
@@ -2553,17 +2553,17 @@ DebuggerFrame_getArguments(JSContext *cx
 
     JSObject *argsobj;
     if (fp->hasArgs()) {
         /* Create an arguments object. */
         GlobalObject *global = args.callee().getGlobal();
         JSObject *proto;
         if (!js_GetClassPrototype(cx, global, JSProto_Array, &proto))
             return false;
-        argsobj = NewNonFunction<WithProto::Given>(cx, &DebuggerArguments_class, proto, global);
+        argsobj = NewObjectWithGivenProto(cx, &DebuggerArguments_class, proto, global);
         if (!argsobj ||
             !js_SetReservedSlot(cx, argsobj, JSSLOT_DEBUGARGUMENTS_FRAME, ObjectValue(*thisobj)))
         {
             return false;
         }
 
         JS_ASSERT(fp->numActualArgs() <= 0x7fffffff);
         int32 fargc = int32(fp->numActualArgs());
@@ -2787,17 +2787,17 @@ DebuggerFrameEval(JSContext *cx, uintN a
 
     JSObject *scobj = JS_GetFrameScopeChain(cx, Jsvalify(fp));
     if (!scobj)
         return false;
 
     /* If evalWithBindings, create the inner scope object. */
     if (mode == WithBindings) {
         /* TODO - Should probably create a With object here. */
-        scobj = NewNonFunction<WithProto::Given>(cx, &ObjectClass, NULL, scobj);
+        scobj = NewObjectWithGivenProto(cx, &ObjectClass, NULL, scobj);
         if (!scobj)
             return false;
         for (size_t i = 0; i < keys.length(); i++) {
             if (!cx->compartment->wrap(cx, &values[i]) ||
                 !DefineNativeProperty(cx, scobj, keys[i], values[i], NULL, NULL, 0, 0, 0))
             {
                 return false;
             }
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -95,27 +95,27 @@ GlobalObject::initFunctionAndObjectClass
     /* If cx has no global object, make this the global object. */
     if (!cx->globalObject)
         JS_SetGlobalObject(cx, this);
 
     /*
      * Create |Object.prototype| first, mirroring CreateBlankProto but for the
      * prototype of the created object.
      */
-    JSObject *objectProto = NewNonFunction<WithProto::Given>(cx, &ObjectClass, NULL, this);
+    JSObject *objectProto = NewObjectWithGivenProto(cx, &ObjectClass, NULL, this);
     if (!objectProto || !objectProto->setSingletonType(cx))
         return NULL;
     types::TypeObject *objectType = objectProto->getNewType(cx, NULL, /* markUnknown = */ true);
     if (!objectType || !objectType->getEmptyShape(cx, &ObjectClass, gc::FINALIZE_OBJECT0))
         return NULL;
 
     /* Create |Function.prototype| next so we can create other functions. */
     JSFunction *functionProto;
     {
-        JSObject *proto = NewObject<WithProto::Given>(cx, &FunctionClass, objectProto, this);
+        JSObject *proto = NewObjectWithGivenProto(cx, &FunctionClass, objectProto, this);
         if (!proto)
             return NULL;
 
         /*
          * Bizarrely, |Function.prototype| must be an interpreted function, so
          * give it the guts to be one.
          */
         functionProto = js_NewFunction(cx, proto, NULL, 0, JSFUN_INTERPRETED, this, NULL);
@@ -142,17 +142,17 @@ GlobalObject::initFunctionAndObjectClass
         if (!functionType || !functionType->getEmptyShape(cx, &FunctionClass, gc::FINALIZE_OBJECT0))
             return NULL;
     }
 
     /* Create the Object function now that we have a [[Prototype]] for it. */
     jsid objectId = ATOM_TO_JSID(CLASS_ATOM(cx, Object));
     JSFunction *objectCtor;
     {
-        JSObject *ctor = NewObject<WithProto::Given>(cx, &FunctionClass, functionProto, this);
+        JSObject *ctor = NewObjectWithGivenProto(cx, &FunctionClass, functionProto, this);
         if (!ctor)
             return NULL;
         objectCtor = js_NewFunction(cx, ctor, js_Object, 1, JSFUN_CONSTRUCTOR, this,
                                     JSID_TO_ATOM(objectId));
         if (!objectCtor)
             return NULL;
         JS_ASSERT(ctor == objectCtor);
 
@@ -165,17 +165,17 @@ GlobalObject::initFunctionAndObjectClass
      */
     setObjectClassDetails(objectCtor, objectProto);
 
     /* Create |Function| so it and |Function.prototype| can be installed. */
     jsid functionId = ATOM_TO_JSID(CLASS_ATOM(cx, Function));
     JSFunction *functionCtor;
     {
         JSObject *ctor =
-            NewObject<WithProto::Given>(cx, &FunctionClass, functionProto, this);
+            NewObjectWithGivenProto(cx, &FunctionClass, functionProto, this);
         if (!ctor)
             return NULL;
         functionCtor = js_NewFunction(cx, ctor, Function, 1, JSFUN_CONSTRUCTOR, this,
                                       JSID_TO_ATOM(functionId));
         if (!functionCtor)
             return NULL;
         JS_ASSERT(ctor == functionCtor);
 
@@ -245,17 +245,17 @@ GlobalObject::initFunctionAndObjectClass
     return functionProto;
 }
 
 GlobalObject *
 GlobalObject::create(JSContext *cx, Class *clasp)
 {
     JS_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
 
-    JSObject *obj = NewNonFunction<WithProto::Given>(cx, clasp, NULL, NULL);
+    JSObject *obj = NewObjectWithGivenProto(cx, clasp, NULL, NULL);
     if (!obj || !obj->setSingletonType(cx))
         return NULL;
 
     GlobalObject *globalObj = obj->asGlobal();
     if (!globalObj->setVarObj(cx))
         return NULL;
 
     /* Construct a regexp statics object for this global object. */
@@ -366,17 +366,17 @@ GlobalObject::createConstructor(JSContex
 }
 
 static JSObject *
 CreateBlankProto(JSContext *cx, Class *clasp, JSObject &proto, GlobalObject &global)
 {
     JS_ASSERT(clasp != &ObjectClass);
     JS_ASSERT(clasp != &FunctionClass);
 
-    JSObject *blankProto = NewNonFunction<WithProto::Given>(cx, clasp, &proto, &global);
+    JSObject *blankProto = NewObjectWithGivenProto(cx, clasp, &proto, &global);
     if (!blankProto || !blankProto->setSingletonType(cx))
         return NULL;
 
     /*
      * Supply the created prototype object with an empty shape for the benefit
      * of callers of JSObject::initSharingEmptyShape.
      */
     types::TypeObject *type = blankProto->getNewType(cx);
@@ -446,17 +446,17 @@ GlobalObject::getDebuggers()
 GlobalObject::DebuggerVector *
 GlobalObject::getOrCreateDebuggers(JSContext *cx)
 {
     assertSameCompartment(cx, this);
     DebuggerVector *debuggers = getDebuggers();
     if (debuggers)
         return debuggers;
 
-    JSObject *obj = NewNonFunction<WithProto::Given>(cx, &GlobalDebuggees_class, NULL, this);
+    JSObject *obj = NewObjectWithGivenProto(cx, &GlobalDebuggees_class, NULL, this);
     if (!obj)
         return NULL;
     debuggers = cx->new_<DebuggerVector>();
     if (!debuggers)
         return NULL;
     obj->setPrivate(debuggers);
     setReservedSlot(DEBUGGERS, ObjectValue(*obj));
     return debuggers;
--- a/js/src/vm/NumberObject-inl.h
+++ b/js/src/vm/NumberObject-inl.h
@@ -61,17 +61,17 @@ NumberObject::create(JSContext *cx, jsdo
     NumberObject *numobj = obj->asNumber();
     numobj->setPrimitiveValue(d);
     return numobj;
 }
 
 inline NumberObject *
 NumberObject::createWithProto(JSContext *cx, jsdouble d, JSObject &proto)
 {
-    JSObject *obj = NewObjectWithClassProto(cx, &NumberClass, &proto,
+    JSObject *obj = NewObjectWithClassProto(cx, &NumberClass, &proto, NULL,
                                             gc::GetGCObjectKind(RESERVED_SLOTS));
     if (!obj)
         return NULL;
     NumberObject *numobj = obj->asNumber();
     numobj->setPrimitiveValue(d);
     return numobj;
 }
 
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -377,17 +377,17 @@ RegExpPrivate::create(JSContext *cx, JSL
         return AlreadyIncRefed<RegExpPrivate>(NULL);
 
     return create(cx, str, flags, ts);
 }
 
 RegExpObject *
 RegExpObject::clone(JSContext *cx, RegExpObject *reobj, RegExpObject *proto)
 {
-    JSObject *clone = NewNativeClassInstance(cx, &RegExpClass, proto);
+    JSObject *clone = NewObjectWithGivenProto(cx, &RegExpClass, proto, NULL);
     if (!clone)
         return NULL;
 
     /*
      * This clone functionality does not duplicate the JIT'd code blob,
      * which is necessary for cross-compartment cloning functionality.
      */
     assertSameCompartment(cx, reobj, clone);
--- a/js/src/vm/RegExpStatics.cpp
+++ b/js/src/vm/RegExpStatics.cpp
@@ -85,17 +85,17 @@ static Class regexp_statics_class = {
     NULL,                    /* xdrObject   */
     NULL,                    /* hasInstance */
     resc_trace
 };
 
 JSObject *
 RegExpStatics::create(JSContext *cx, GlobalObject *parent)
 {
-    JSObject *obj = NewObject<WithProto::Given>(cx, &regexp_statics_class, NULL, parent);
+    JSObject *obj = NewObjectWithGivenProto(cx, &regexp_statics_class, NULL, parent);
     if (!obj)
         return NULL;
     RegExpStatics *res = cx->new_<RegExpStatics>();
     if (!res)
         return NULL;
     obj->setPrivate(static_cast<void *>(res));
     return obj;
 }
--- a/js/src/vm/StringObject-inl.h
+++ b/js/src/vm/StringObject-inl.h
@@ -63,17 +63,17 @@ StringObject::create(JSContext *cx, JSSt
         return NULL;
     return strobj;
 }
 
 inline StringObject *
 StringObject::createWithProto(JSContext *cx, JSString *str, JSObject &proto)
 {
     JS_ASSERT(gc::FINALIZE_OBJECT2 == gc::GetGCObjectKind(JSCLASS_RESERVED_SLOTS(&StringClass)));
-    JSObject *obj = NewObjectWithClassProto(cx, &StringClass, &proto, gc::FINALIZE_OBJECT2);
+    JSObject *obj = NewObjectWithClassProto(cx, &StringClass, &proto, NULL, gc::FINALIZE_OBJECT2);
     if (!obj)
         return NULL;
     StringObject *strobj = obj->asString();
     if (!strobj->init(cx, str))
         return NULL;
     return strobj;
 }