Bug 836255 part 1 - Refactor some arguments-related functions to use AbstractFramePtr. r=dvander
authorJan de Mooij <jdemooij@mozilla.com>
Thu, 31 Jan 2013 11:50:07 +0100
changeset 120461 7ee87ad80dd109075c28c1d97dd757bc42365e64
parent 120460 585183fb7a13a9fbba479c03f4515156d546a8c7
child 120462 14c3c3913e3c07bbc947aac54bf07f4abac165c7
child 127211 9c9caa2723203634145914f46491ae01a37575bd
push id24251
push userryanvm@gmail.com
push dateThu, 31 Jan 2013 20:56:22 +0000
treeherdermozilla-central@683b08dc1afd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs836255
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 836255 part 1 - Refactor some arguments-related functions to use AbstractFramePtr. r=dvander
js/src/jsinterpinlines.h
js/src/vm/Stack-inl.h
js/src/vm/Stack.h
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -115,44 +115,53 @@ ComputeThis(JSContext *cx, AbstractFrame
  * one is received, act as if the value were the function's ArgumentsObject.
  * Additionally, it is possible that, after 'arguments' was copied into a
  * temporary, the arguments object has been created a some other failed guard
  * that called JSScript::argumentsOptimizationFailed. In this case, it is
  * always valid (and necessary) to replace JS_OPTIMIZED_ARGUMENTS with the real
  * arguments object.
  */
 static inline bool
-IsOptimizedArguments(StackFrame *fp, Value *vp)
+IsOptimizedArguments(AbstractFramePtr frame, Value *vp)
 {
     AutoAssertNoGC nogc;
-    if (vp->isMagic(JS_OPTIMIZED_ARGUMENTS) && fp->script()->needsArgsObj())
-        *vp = ObjectValue(fp->argsObj());
+    if (vp->isMagic(JS_OPTIMIZED_ARGUMENTS) && frame.script()->needsArgsObj())
+        *vp = ObjectValue(frame.argsObj());
     return vp->isMagic(JS_OPTIMIZED_ARGUMENTS);
 }
 
 /*
  * One optimized consumer of MagicValue(JS_OPTIMIZED_ARGUMENTS) is f.apply.
  * However, this speculation must be guarded before calling 'apply' in case it
  * is not the builtin Function.prototype.apply.
  */
+static bool
+GuardFunApplyArgumentsOptimization(JSContext *cx, AbstractFramePtr frame, HandleValue callee,
+                                   Value *args, uint32_t argc)
+{
+    if (argc == 2 && IsOptimizedArguments(frame, &args[1])) {
+        if (!IsNativeFunction(callee, js_fun_apply)) {
+            RootedScript script(cx, frame.script());
+            if (!JSScript::argumentsOptimizationFailed(cx, script))
+                return false;
+            args[1] = ObjectValue(frame.argsObj());
+        }
+    }
+
+    return true;
+}
+
 static inline bool
 GuardFunApplyArgumentsOptimization(JSContext *cx)
 {
     AssertCanGC();
     FrameRegs &regs = cx->regs();
-    if (IsOptimizedArguments(regs.fp(), &regs.sp[-1])) {
-        CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
-        if (!IsNativeFunction(args.calleev(), js_fun_apply)) {
-            RootedScript script(cx, regs.fp()->script());
-            if (!JSScript::argumentsOptimizationFailed(cx, script))
-                return false;
-            regs.sp[-1] = ObjectValue(regs.fp()->argsObj());
-        }
-    }
-    return true;
+    CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
+    return GuardFunApplyArgumentsOptimization(cx, cx->fp(), args.calleev(), args.array(),
+                                              args.length());
 }
 
 /*
  * Return an object on which we should look for the properties of |value|.
  * This helps us implement the custom [[Get]] method that ES5's GetValue
  * algorithm uses for primitive values, without actually constructing the
  * temporary object that the specification does.
  *
@@ -858,16 +867,42 @@ GetObjectElementOperation(JSContext *cx,
     }
 #endif
 
     assertSameCompartmentDebugOnly(cx, res);
     return true;
 }
 
 static JS_ALWAYS_INLINE bool
+GetElemOptimizedArguments(JSContext *cx, AbstractFramePtr frame, MutableHandleValue lref,
+                          HandleValue rref, MutableHandleValue res, bool *done)
+{
+    JS_ASSERT(!*done);
+
+    if (IsOptimizedArguments(frame, lref.address())) {
+        if (rref.isInt32()) {
+            int32_t i = rref.toInt32();
+            if (i >= 0 && uint32_t(i) < frame.numActualArgs()) {
+                res.set(frame.unaliasedActual(i));
+                *done = true;
+                return true;
+            }
+        }
+
+        RootedScript script(cx, frame.script());
+        if (!JSScript::argumentsOptimizationFailed(cx, script))
+            return false;
+
+        lref.set(ObjectValue(frame.argsObj()));
+    }
+
+    return true;
+}
+
+static JS_ALWAYS_INLINE bool
 GetElementOperation(JSContext *cx, JSOp op, MutableHandleValue lref, HandleValue rref,
                     MutableHandleValue res)
 {
     AssertCanGC();
     JS_ASSERT(op == JSOP_GETELEM || op == JSOP_CALLELEM);
 
     uint32_t index;
     if (lref.isString() && IsDefinitelyIndex(rref, &index)) {
@@ -876,32 +911,21 @@ GetElementOperation(JSContext *cx, JSOp 
             str = cx->runtime->staticStrings.getUnitStringForElement(cx, str, index);
             if (!str)
                 return false;
             res.setString(str);
             return true;
         }
     }
 
-    StackFrame *fp = cx->fp();
-    if (IsOptimizedArguments(fp, lref.address())) {
-        if (rref.isInt32()) {
-            int32_t i = rref.toInt32();
-            if (i >= 0 && uint32_t(i) < fp->numActualArgs()) {
-                res.set(fp->unaliasedActual(i));
-                return true;
-            }
-        }
-
-        RootedScript script(cx, fp->script());
-        if (!JSScript::argumentsOptimizationFailed(cx, script))
-            return false;
-
-        lref.set(ObjectValue(fp->argsObj()));
-    }
+    bool done = false;
+    if (!GetElemOptimizedArguments(cx, cx->fp(), lref, rref, res, &done))
+        return false;
+    if (done)
+        return true;
 
     bool isObject = lref.isObject();
     JSObject *obj = ToObjectFromStack(cx, lref);
     if (!obj)
         return false;
     return GetObjectElementOperation(cx, op, obj, isObject, rref, res);
 }
 
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -700,16 +700,25 @@ inline Value &
 AbstractFramePtr::unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing)
 {
     if (isStackFrame())
         return asStackFrame()->unaliasedFormal(i, checkAliasing);
     JS_NOT_REACHED("Invalid frame");
     return asStackFrame()->unaliasedFormal(i);
 }
 
+inline Value &
+AbstractFramePtr::unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing)
+{
+    if (isStackFrame())
+        return asStackFrame()->unaliasedActual(i, checkAliasing);
+    JS_NOT_REACHED("Invalid frame");
+    return asStackFrame()->unaliasedActual(i);
+}
+
 inline JSGenerator *
 AbstractFramePtr::maybeSuspendedGenerator(JSRuntime *rt) const
 {
     if (isStackFrame())
         return asStackFrame()->maybeSuspendedGenerator(rt);
     return NULL;
 }
 
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -298,16 +298,17 @@ class AbstractFramePtr
     inline ArgumentsObject &argsObj() const;
     inline void initArgsObj(ArgumentsObject &argsobj) const;
 
     inline bool copyRawFrameSlots(AutoValueVector *vec) const;
 
     inline Value &unaliasedVar(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
     inline Value &unaliasedLocal(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
     inline Value &unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
+    inline Value &unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
 
     inline bool prevUpToDate() const;
     inline void setPrevUpToDate() const;
     inline AbstractFramePtr evalPrev() const;
 
     inline void *maybeHookData() const;
     inline void setHookData(void *data) const;
     inline void setReturnValue(const Value &rval) const;