Bug 784400 - Enable cloning of object literals within functions. r=luke
authorTill Schneidereit <tschneidereit@gmail.com>
Thu, 11 Oct 2012 11:53:02 +0200
changeset 110283 a821bac3baa965771fd631e2a0f4d0315cb357e5
parent 110282 c9e4a0971222b391c811e36816333b9155ccc989
child 110284 f305661c121702176a565fdde36133511c87bccf
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersluke
bugs784400
milestone19.0a1
Bug 784400 - Enable cloning of object literals within functions. r=luke
js/src/jsinterpinlines.h
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsscript.cpp
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -395,18 +395,17 @@ FetchName(JSContext *cx, HandleObject ob
     }
     return true;
 }
 
 inline bool
 IntrinsicNameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, MutableHandleValue vp)
 {
     JSOp op = JSOp(*pc);
-    RootedPropertyName name(cx);
-    name = GetNameFromBytecode(cx, script, pc, op);
+    RootedPropertyName name(cx,  GetNameFromBytecode(cx, script, pc, op));
     cx->global()->getIntrinsicValue(cx, name, vp);
     return true;
 }
 
 inline bool
 NameOperation(JSContext *cx, jsbytecode *pc, MutableHandleValue vp)
 {
     RootedObject obj(cx, cx->stack.currentScriptedScopeChain());
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2647,16 +2647,24 @@ js::CloneObject(JSContext *cx, HandleObj
         JS_ASSERT(obj->isProxy());
         if (!CopySlots(cx, obj, clone))
             return NULL;
     }
 
     return clone;
 }
 
+JSObject *
+js::CloneObjectLiteral(JSContext *cx, HandleObject parent, HandleObject srcObj)
+{
+    Rooted<TypeObject*> typeObj(cx, cx->global()->getOrCreateObjectPrototype(cx)->getNewType(cx));
+    RootedShape shape(cx, srcObj->lastProperty());
+    return NewReshapedObject(cx, typeObj, parent, srcObj->getAllocKind(), shape);
+}
+
 struct JSObject::TradeGutsReserved {
     Vector<Value> avals;
     Vector<Value> bvals;
     int newafixed;
     int newbfixed;
     Shape *newashape;
     Shape *newbshape;
     HeapSlot *newaslots;
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1385,16 +1385,19 @@ ToObject(JSContext *cx, HandleValue vp)
 JS_ALWAYS_INLINE JSObject *
 ToObjectFromStack(JSContext *cx, HandleValue vp)
 {
     if (vp.isObject())
         return &vp.toObject();
     return ToObjectSlow(cx, vp, true);
 }
 
+extern JSObject *
+CloneObjectLiteral(JSContext *cx, HandleObject parent, HandleObject srcObj);
+
 } /* namespace js */
 
 extern void
 js_GetObjectSlotName(JSTracer *trc, char *buf, size_t bufsize);
 
 extern JSBool
 js_ReportGetterOnlyAssignment(JSContext *cx);
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -2123,27 +2123,35 @@ js::CloneScript(JSContext *cx, HandleObj
 
                 RootedObject enclosingScope(cx);
                 if (StaticBlockObject *enclosingBlock = innerBlock->enclosingBlock())
                     enclosingScope = objects[FindBlockIndex(src, *enclosingBlock)];
                 else
                     enclosingScope = fun;
 
                 clone = CloneStaticBlockObject(cx, enclosingScope, innerBlock);
-            } else {
+            } else if (obj->isFunction()) {
                 RootedFunction innerFun(cx, obj->toFunction());
 
                 StaticScopeIter ssi(innerFun->script()->enclosingStaticScope());
                 RootedObject enclosingScope(cx);
                 if (!ssi.done() && ssi.type() == StaticScopeIter::BLOCK)
                     enclosingScope = objects[FindBlockIndex(src, ssi.block())];
                 else
                     enclosingScope = fun;
 
                 clone = CloneInterpretedFunction(cx, enclosingScope, innerFun);
+            } else {
+                /*
+                 * Clone object literals emitted for the JSOP_NEWOBJECT opcode. We only emit that
+                 * instead of the less-optimized JSOP_NEWINIT for self-hosted code or code compiled
+                 * with JSOPTION_COMPILE_N_GO set. As we don't clone the latter type of code, this
+                 * case should only ever be hit when cloning objects from self-hosted code.
+                 */
+                clone = CloneObjectLiteral(cx, cx->global(), obj);
             }
             if (!clone || !objects.append(clone))
                 return NULL;
         }
     }
 
     /* RegExps */