Bug 514568 - Add JSObject::callIsForEval rather than using JSObject::getCallObjCallee() == NULL. r=igor
authorJeff Walden <jwalden@mit.edu>
Wed, 05 Jan 2011 14:54:04 -0600
changeset 60243 27a0e3715095ff2ac264f8283e0d1a76b103d288
parent 60242 1417c3808f048da0a0817922d449b6b7f2928f63
child 60244 97401505439586c55ee8beb84f463a1248c4da97
push id17896
push usercleary@mozilla.com
push dateSat, 08 Jan 2011 08:51:06 +0000
treeherdermozilla-central@df3c1150dd7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersigor
bugs514568
milestone2.0b9pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 514568 - Add JSObject::callIsForEval rather than using JSObject::getCallObjCallee() == NULL. r=igor
js/src/jsfun.cpp
js/src/jsinterpinlines.h
js/src/jsobj.h
js/src/jsobjinlines.h
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1072,46 +1072,56 @@ CopyValuesToCallObject(JSObject &callobj
     memcpy(base + nargs, slots, nvars * sizeof(Value));
 }
 
 void
 js_PutCallObject(JSContext *cx, JSStackFrame *fp)
 {
     JSObject &callobj = fp->callObj();
 
+    /*
+     * Strict mode eval frames have Call objects to put.  Normal eval frames
+     * never put a Call object.
+     */
+    JS_ASSERT(fp->isEvalFrame() == callobj.callIsForEval());
+
     /* Get the arguments object to snapshot fp's actual argument values. */
     if (fp->hasArgsObj()) {
-        JS_ASSERT(!fp->isEvalFrame());
         if (!fp->hasOverriddenArgs())
             callobj.setCallObjArguments(ObjectValue(fp->argsObj()));
         js_PutArgsObject(cx, fp);
     }
 
     JSScript *script = fp->script();
     Bindings &bindings = script->bindings;
 
-    JSObject *callee = callobj.getCallObjCallee();
-    if (callee) {
+    if (callobj.callIsForEval()) {
+        JS_ASSERT(script->strictModeCode);
+        JS_ASSERT(bindings.countArgs() == 0);
+
+        /* This could be optimized as below, but keep it simple for now. */
+        CopyValuesToCallObject(callobj, 0, NULL, bindings.countVars(), fp->slots());
+    } else {
         JSFunction *fun = fp->fun();
-        JS_ASSERT(fun == callee->getFunctionPrivate());
+        JS_ASSERT(fun == callobj.getCallObjCalleeFunction());
         JS_ASSERT(script == fun->script());
 
         if (uintN n = bindings.countArgsAndVars()) {
             JS_ASSERT(JSObject::CALL_RESERVED_SLOTS + n <= callobj.numSlots());
 
             uint32 nvars = bindings.countVars();
             uint32 nargs = bindings.countArgs();
             JS_ASSERT(fun->nargs == nargs);
             JS_ASSERT(nvars + nargs == n);
 
             JSScript *script = fun->script();
             if (script->usesEval
-    #ifdef JS_METHODJIT
+#ifdef JS_METHODJIT
                 || script->debugMode
-    #endif
+#endif
                 ) {
                 CopyValuesToCallObject(callobj, nargs, fp->formalArgs(), nvars, fp->slots());
             } else {
                 /*
                  * For each arg & var that is closed over, copy it from the stack
                  * into the call object.
                  */
                 uint32 nclosed = script->nClosedArgs;
@@ -1131,23 +1141,16 @@ js_PutCallObject(JSContext *cx, JSStackF
         /* Clear private pointers to fp, which is about to go away (js_Invoke). */
         if (js_IsNamedLambda(fun)) {
             JSObject *env = callobj.getParent();
 
             JS_ASSERT(env->getClass() == &js_DeclEnvClass);
             JS_ASSERT(env->getPrivate() == fp);
             env->setPrivate(NULL);
         }
-    } else {
-        JS_ASSERT(fp->isEvalFrame());
-        JS_ASSERT(script->strictModeCode);
-        JS_ASSERT(bindings.countArgs() == 0);
-
-        /* This could be optimized as above.  But for now, keep it simple. */
-        CopyValuesToCallObject(callobj, 0, NULL, bindings.countVars(), fp->slots());
     }
 
     callobj.setPrivate(NULL);
     fp->clearCallObj();
 }
 
 JSBool JS_FASTCALL
 js_PutCallObjectOnTrace(JSContext *cx, JSObject *callobj, uint32 nargs, Value *argv,
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -726,28 +726,31 @@ ScriptEpilogue(JSContext *cx, JSStackFra
         /*
          * The parent (ancestor for nested eval) of a non-strict eval frame
          * owns its activation objects. Strict mode eval frames own their own
          * Call objects but never have an arguments object (the first non-eval
          * parent frame has it).
          */
         if (fp->script()->strictModeCode) {
             JS_ASSERT(!fp->isYielding());
+            JS_ASSERT(!fp->hasArgsObj());
             JS_ASSERT(fp->hasCallObj());
-            JS_ASSERT(!fp->hasArgsObj());
+            JS_ASSERT(fp->callObj().callIsForEval());
             js_PutCallObject(cx, fp);
         }
     } else {
         /*
          * Otherwise only function frames have activation objects. A yielding
          * frame's activation objects are transferred to the floating frame,
          * stored in the generator, and thus need not be synced.
          */
-        if (fp->isFunctionFrame() && !fp->isYielding())
+        if (fp->isFunctionFrame() && !fp->isYielding()) {
+            JS_ASSERT_IF(fp->hasCallObj(), !fp->callObj().callIsForEval());
             PutActivationObjects(cx, fp);
+        }
     }
 
     /*
      * If inline-constructing, replace primitive rval with the new object
      * passed in via |this|, and instrument this constructor invocation.
      */
     if (fp->isConstructing() && ok) {
         if (fp->returnValue().isPrimitive())
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -892,16 +892,19 @@ struct JSObject : js::gc::Cell {
      */
     static const uint32 JSSLOT_CALL_CALLEE = 0;
     static const uint32 JSSLOT_CALL_ARGUMENTS = 1;
 
   public:
     /* Number of reserved slots. */
     static const uint32 CALL_RESERVED_SLOTS = 2;
 
+    /* True if this is for a strict mode eval frame or for a function call. */
+    inline bool callIsForEval() const;
+
     /* The stack frame for this Call object, if the frame is still active. */
     inline JSStackFrame *maybeCallObjStackFrame() const;
 
     /*
      * The callee function if this Call object was created for a function
      * invocation, or null if it was created for a strict mode eval frame.
      */
     inline JSObject *getCallObjCallee() const;
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -427,16 +427,26 @@ JSObject::addressOfArgsElement(uint32 i)
 inline void
 JSObject::setArgsElement(uint32 i, const js::Value &v)
 {
     JS_ASSERT(isArguments());
     JS_ASSERT(i < getArgsInitialLength());
     getArgsData()->slots[i] = v;
 }
 
+inline bool
+JSObject::callIsForEval() const
+{
+    JS_ASSERT(isCall());
+    JS_ASSERT(getSlot(JSSLOT_CALL_CALLEE).isObjectOrNull());
+    JS_ASSERT_IF(getSlot(JSSLOT_CALL_CALLEE).isObject(),
+                 getSlot(JSSLOT_CALL_CALLEE).toObject().isFunction());
+    return getSlot(JSSLOT_CALL_CALLEE).isNull();
+}
+
 inline JSStackFrame *
 JSObject::maybeCallObjStackFrame() const
 {
     JS_ASSERT(isCall());
     return reinterpret_cast<JSStackFrame *>(getPrivate());
 }
 
 inline void
@@ -460,25 +470,25 @@ JSObject::getCallObjCalleeFunction() con
     JS_ASSERT(isCall());
     return getSlot(JSSLOT_CALL_CALLEE).toObject().getFunctionPrivate();
 }
 
 inline const js::Value &
 JSObject::getCallObjArguments() const
 {
     JS_ASSERT(isCall());
-    JS_ASSERT(getCallObjCallee() != NULL);
+    JS_ASSERT(!callIsForEval());
     return getSlot(JSSLOT_CALL_ARGUMENTS);
 }
 
 inline void
 JSObject::setCallObjArguments(const js::Value &v)
 {
     JS_ASSERT(isCall());
-    JS_ASSERT(getCallObjCallee() != NULL);
+    JS_ASSERT(!callIsForEval());
     setSlot(JSSLOT_CALL_ARGUMENTS, v);
 }
 
 inline const js::Value &
 JSObject::callObjArg(uintN i) const
 {
     JS_ASSERT(isCall());
     JS_ASSERT(i < getCallObjCalleeFunction()->nargs);