Bug 1259877 - Rename FastInvokeGuard to FastCallGuard and make it not depend on CallArgs::set{Callee,This}, and remove js::Invoke. r=shu
authorJeff Walden <jwalden@mit.edu>
Tue, 22 Mar 2016 13:40:21 -0700
changeset 293152 f5ca1d46b22ace7d9f1b3fe1f25a3ad0fcf5838f
parent 293151 4099b331a79a3466a939016f0715a75e3bf6a698
child 293153 69d4569f7601c7c4e700f29a31d9d252deed7b44
push id30175
push usercbook@mozilla.com
push dateThu, 14 Apr 2016 09:38:40 +0000
treeherdermozilla-central@91115264629d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu
bugs1259877
milestone48.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 1259877 - Rename FastInvokeGuard to FastCallGuard and make it not depend on CallArgs::set{Callee,This}, and remove js::Invoke. r=shu
js/src/builtin/MapObject.cpp
js/src/builtin/Reflect.cpp
js/src/builtin/WeakMapObject.cpp
js/src/builtin/WeakSetObject.cpp
js/src/vm/Interpreter-inl.h
js/src/vm/Interpreter.cpp
js/src/vm/Interpreter.h
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -505,24 +505,26 @@ MapObject::construct(JSContext* cx, unsi
         if (!GetProperty(cx, obj, obj, cx->names().set, &adderVal))
             return false;
 
         if (!IsCallable(adderVal))
             return ReportIsNotFunction(cx, adderVal);
 
         bool isOriginalAdder = IsNativeFunction(adderVal, MapObject::set);
         RootedValue mapVal(cx, ObjectValue(*obj));
-        FastInvokeGuard fig(cx, adderVal);
+        FastCallGuard fig(cx, adderVal);
         InvokeArgs& args2 = fig.args();
 
         ForOfIterator iter(cx);
         if (!iter.init(args[0]))
             return false;
+
         RootedValue pairVal(cx);
         RootedObject pairObj(cx);
+        RootedValue dummy(cx);
         Rooted<HashableValue> hkey(cx);
         ValueMap* map = obj->getData();
         while (true) {
             bool done;
             if (!iter.next(&pairVal, &done))
                 return false;
             if (done)
                 break;
@@ -553,22 +555,20 @@ MapObject::construct(JSContext* cx, unsi
                     ReportOutOfMemory(cx);
                     return false;
                 }
                 WriteBarrierPost(cx->runtime(), map, key);
             } else {
                 if (!args2.init(2))
                     return false;
 
-                args2.setCallee(adderVal);
-                args2.setThis(mapVal);
                 args2[0].set(key);
                 args2[1].set(val);
 
-                if (!fig.invoke(cx))
+                if (!fig.call(cx, adderVal, mapVal, &dummy))
                     return false;
             }
         }
     }
 
     args.rval().setObject(*obj);
     return true;
 }
@@ -1177,24 +1177,25 @@ SetObject::construct(JSContext* cx, unsi
         if (!GetProperty(cx, obj, obj, cx->names().add, &adderVal))
             return false;
 
         if (!IsCallable(adderVal))
             return ReportIsNotFunction(cx, adderVal);
 
         bool isOriginalAdder = IsNativeFunction(adderVal, SetObject::add);
         RootedValue setVal(cx, ObjectValue(*obj));
-        FastInvokeGuard fig(cx, adderVal);
+        FastCallGuard fig(cx, adderVal);
         InvokeArgs& args2 = fig.args();
 
         RootedValue keyVal(cx);
         ForOfIterator iter(cx);
         if (!iter.init(args[0]))
             return false;
         Rooted<HashableValue> key(cx);
+        RootedValue dummy(cx);
         ValueSet* set = obj->getData();
         while (true) {
             bool done;
             if (!iter.next(&keyVal, &done))
                 return false;
             if (done)
                 break;
 
@@ -1205,21 +1206,19 @@ SetObject::construct(JSContext* cx, unsi
                     ReportOutOfMemory(cx);
                     return false;
                 }
                 WriteBarrierPost(cx->runtime(), set, keyVal);
             } else {
                 if (!args2.init(1))
                     return false;
 
-                args2.setCallee(adderVal);
-                args2.setThis(setVal);
                 args2[0].set(keyVal);
 
-                if (!fig.invoke(cx))
+                if (!fig.call(cx, adderVal, setVal, &dummy))
                     return false;
             }
         }
     }
 
     args.rval().setObject(*obj);
     return true;
 }
--- a/js/src/builtin/Reflect.cpp
+++ b/js/src/builtin/Reflect.cpp
@@ -65,28 +65,23 @@ Reflect_apply(JSContext* cx, unsigned ar
     // Step 1.
     if (!IsCallable(args.get(0))) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NOT_FUNCTION,
                              "Reflect.apply argument");
         return false;
     }
 
     // Steps 2-3.
-    FastInvokeGuard fig(cx, args.get(0));
+    FastCallGuard fig(cx, args.get(0));
     InvokeArgs& invokeArgs = fig.args();
     if (!InitArgsFromArrayLike(cx, args.get(2), &invokeArgs))
         return false;
-    invokeArgs.setCallee(args.get(0));
-    invokeArgs.setThis(args.get(1));
 
     // Steps 4-5. This is specified to be a tail call, but isn't.
-    if (!fig.invoke(cx))
-        return false;
-    args.rval().set(invokeArgs.rval());
-    return true;
+    return fig.call(cx, args.get(0), args.get(1), args.rval());
 }
 
 /* ES6 26.1.2 Reflect.construct(target, argumentsList [, newTarget]) */
 static bool
 Reflect_construct(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
--- a/js/src/builtin/WeakMapObject.cpp
+++ b/js/src/builtin/WeakMapObject.cpp
@@ -305,29 +305,30 @@ WeakMap_construct(JSContext* cx, unsigne
             return false;
 
         // Step 7c.
         if (!IsCallable(adderVal))
             return ReportIsNotFunction(cx, adderVal);
 
         bool isOriginalAdder = IsNativeFunction(adderVal, WeakMap_set);
         RootedValue mapVal(cx, ObjectValue(*obj));
-        FastInvokeGuard fig(cx, adderVal);
+        FastCallGuard fig(cx, adderVal);
         InvokeArgs& args2 = fig.args();
 
         // Steps 7d-e.
         JS::ForOfIterator iter(cx);
         if (!iter.init(args[0]))
             return false;
 
         RootedValue pairVal(cx);
         RootedObject pairObject(cx);
         RootedValue keyVal(cx);
         RootedObject keyObject(cx);
         RootedValue val(cx);
+        RootedValue dummy(cx);
         while (true) {
             // Steps 12a-e.
             bool done;
             if (!iter.next(&pairVal, &done))
                 return false;
             if (done)
                 break;
 
@@ -363,22 +364,20 @@ WeakMap_construct(JSContext* cx, unsigne
 
                 keyObject = &keyVal.toObject();
                 if (!SetWeakMapEntry(cx, obj, keyObject, val))
                     return false;
             } else {
                 if (!args2.init(2))
                     return false;
 
-                args2.setCallee(adderVal);
-                args2.setThis(mapVal);
                 args2[0].set(keyVal);
                 args2[1].set(val);
 
-                if (!fig.invoke(cx))
+                if (!fig.call(cx, adderVal, mapVal, &dummy))
                     return false;
             }
         }
     }
 
     args.rval().setObject(*obj);
     return true;
 }
--- a/js/src/builtin/WeakSetObject.cpp
+++ b/js/src/builtin/WeakSetObject.cpp
@@ -100,25 +100,26 @@ WeakSetObject::construct(JSContext* cx, 
 
         if (!IsCallable(adderVal))
             return ReportIsNotFunction(cx, adderVal);
 
         JSFunction* adder;
         bool isOriginalAdder = IsFunctionObject(adderVal, &adder) &&
                                IsSelfHostedFunctionWithName(adder, cx->names().WeakSet_add);
         RootedValue setVal(cx, ObjectValue(*obj));
-        FastInvokeGuard fig(cx, adderVal);
+        FastCallGuard fig(cx, adderVal);
         InvokeArgs& args2 = fig.args();
 
         JS::ForOfIterator iter(cx);
         if (!iter.init(args[0]))
             return false;
 
         RootedValue keyVal(cx);
         RootedObject keyObject(cx);
+        RootedValue dummy(cx);
         RootedValue placeholder(cx, BooleanValue(true));
         while (true) {
             bool done;
             if (!iter.next(&keyVal, &done))
                 return false;
             if (done)
                 break;
 
@@ -134,21 +135,19 @@ WeakSetObject::construct(JSContext* cx, 
 
                 keyObject = &keyVal.toObject();
                 if (!SetWeakMapEntry(cx, map, keyObject, placeholder))
                     return false;
             } else {
                 if (!args2.init(1))
                     return false;
 
-                args2.setCallee(adderVal);
-                args2.setThis(setVal);
                 args2[0].set(keyVal);
 
-                if (!fig.invoke(cx))
+                if (!fig.call(cx, adderVal, setVal, &dummy))
                     return false;
             }
         }
     }
 
     args.rval().setObject(*obj);
     return true;
 }
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -771,33 +771,33 @@ ReportIfNotFunction(JSContext* cx, Handl
     if (v.isObject() && v.toObject().is<JSFunction>())
         return &v.toObject().as<JSFunction>();
 
     ReportIsNotFunction(cx, v, -1, construct);
     return nullptr;
 }
 
 /*
- * FastInvokeGuard is used to optimize calls to JS functions from natives written
- * in C++, for instance Array.map. If the callee is not Ion-compiled, this will
- * just call Invoke. If the callee has a valid IonScript, however, it will enter
- * Ion directly.
+ * FastCallGuard is used to optimize calls to JS functions from natives written
+ * in C++, e.g. Array.prototype.map.  If the callee is not Ion-compiled, this
+ * will just call js::Call.  If the callee has a valid IonScript, however, it
+ * will enter Ion directly.
  */
-class FastInvokeGuard
+class FastCallGuard
 {
     InvokeArgs args_;
     RootedFunction fun_;
     RootedScript script_;
 
     // Constructing a JitContext is pretty expensive due to the TLS access,
     // so only do this if we have to.
     bool useIon_;
 
   public:
-    FastInvokeGuard(JSContext* cx, const Value& fval)
+    FastCallGuard(JSContext* cx, const Value& fval)
       : args_(cx)
       , fun_(cx)
       , script_(cx)
       , useIon_(jit::IsIonEnabled(cx))
     {
         initFunction(fval);
     }
 
@@ -808,17 +808,20 @@ class FastInvokeGuard
                 fun_ = fun;
         }
     }
 
     InvokeArgs& args() {
         return args_;
     }
 
-    bool invoke(JSContext* cx) {
+    bool call(JSContext* cx, HandleValue callee, HandleValue thisv, MutableHandleValue rval) {
+        args_.CallArgs::setCallee(callee);
+        args_.CallArgs::setThis(thisv);
+
         if (useIon_ && fun_) {
             if (!script_) {
                 script_ = fun_->getOrCreateScript(cx);
                 if (!script_)
                     return false;
             }
             MOZ_ASSERT(fun_->nonLazyScript() == script_);
 
@@ -826,31 +829,36 @@ class FastInvokeGuard
             if (status == jit::Method_Error)
                 return false;
             if (status == jit::Method_Compiled) {
                 jit::JitExecStatus result = jit::FastInvoke(cx, fun_, args_);
                 if (IsErrorStatus(result))
                     return false;
 
                 MOZ_ASSERT(result == jit::JitExec_Ok);
+                rval.set(args_.CallArgs::rval());
                 return true;
             }
 
             MOZ_ASSERT(status == jit::Method_Skipped);
 
             if (script_->canIonCompile()) {
                 // This script is not yet hot. Since calling into Ion is much
                 // faster here, bump the warm-up counter a bit to account for this.
                 script_->incWarmUpCounter(5);
             }
         }
 
-        return InternalCallOrConstruct(cx, args_, NO_CONSTRUCT);
+        if (!InternalCallOrConstruct(cx, args_, NO_CONSTRUCT))
+            return false;
+
+        rval.set(args_.CallArgs::rval());
+        return true;
     }
 
   private:
-    FastInvokeGuard(const FastInvokeGuard& other) = delete;
-    const FastInvokeGuard& operator=(const FastInvokeGuard& other) = delete;
+    FastCallGuard(const FastCallGuard& other) = delete;
+    void operator=(const FastCallGuard& other) = delete;
 };
 
 }  /* namespace js */
 
 #endif /* vm_Interpreter_inl_h */
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -543,34 +543,16 @@ js::Call(JSContext* cx, HandleValue fval
 
     if (!InternalCall(cx, args))
         return false;
 
     rval.set(args.rval());
     return true;
 }
 
-// DEPRECATED.  TO BE REMOVED.  DO NOT ADD NEW USES.
-bool
-js::Invoke(JSContext* cx, const Value& thisv, const Value& fval, unsigned argc, const Value* argv,
-           MutableHandleValue rval)
-{
-    RootedValue fv(cx, fval);
-    RootedValue tv(cx, thisv);
-
-    InvokeArgs args(cx);
-    if (!args.init(argc))
-        return false;
-
-    for (unsigned i = 0; i < argc; i++)
-        args[i].set(argv[i]);
-
-    return Call(cx, fv, tv, args, rval);
-}
-
 static bool
 InternalConstruct(JSContext* cx, const AnyConstructArgs& args)
 {
     MOZ_ASSERT(args.array() + args.length() + 1 == args.end(),
                "must pass constructing arguments to a construction attempt");
     MOZ_ASSERT(!JSFunction::class_.getConstruct());
 
     // Callers are responsible for enforcing these preconditions.
--- a/js/src/vm/Interpreter.h
+++ b/js/src/vm/Interpreter.h
@@ -67,21 +67,16 @@ InternalCallOrConstruct(JSContext* cx, c
 
 /* A call operation that'll be rewritten later in this patch stack. */
 inline bool
 Invoke(JSContext* cx, const AnyInvokeArgs& args)
 {
     return InternalCallOrConstruct(cx, args, NO_CONSTRUCT);
 }
 
-// DEPRECATED.  TO BE REMOVED.  DO NOT ADD NEW USES.
-extern bool
-Invoke(JSContext* cx, const Value& thisv, const Value& fval, unsigned argc, const Value* argv,
-       MutableHandleValue rval);
-
 /*
  * These helpers take care of the infinite-recursion check necessary for
  * getter/setter calls.
  */
 extern bool
 CallGetter(JSContext* cx, HandleValue thisv, HandleValue getter, MutableHandleValue rval);
 
 extern bool