Bug 836274: Disable funapply inlining when typeset of callee is tighter than caller, r=nbp
authorHannes Verschore <hv1989@gmail.com>
Tue, 19 Feb 2013 11:33:42 +0100
changeset 122310 64a2c3fb2052f981a243dc315425ebed719900c8
parent 122309 b35634fa6a4abe215c5b4a649a12b0dda6674264
child 122314 88d66cdbdc81e898d72c580e7d3c411f78dc4eaa
push id23221
push userhv1989@gmail.com
push dateTue, 19 Feb 2013 10:34:37 +0000
treeherdermozilla-inbound@64a2c3fb2052 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs836274
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 836274: Disable funapply inlining when typeset of callee is tighter than caller, r=nbp
js/src/ion/IonBuilder.cpp
js/src/jit-test/tests/ion/bug836274.js
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -3189,21 +3189,56 @@ IonBuilder::makeInliningDecision(AutoObj
     }
 
     RootedScript scriptRoot(cx, script());
     if (!oracle->canInlineCall(scriptRoot, pc)) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to uninlineable call site");
         return false;
     }
 
+    JSOp op = JSOp(*pc);
     for (size_t i = 0; i < targets.length(); i++) {
-        if (!canInlineTarget(targets[i]->toFunction())) {
+        JSFunction *target = targets[i]->toFunction();
+
+        if (!canInlineTarget(target)) {
             IonSpew(IonSpew_Inlining, "Decided not to inline");
             return false;
         }
+
+        // For fun.apply we need to make sure the types of the argument is a subset
+        // of the types used in the callee. Because adding a typeset in the callee,
+        // doesn't update the types in the "apply" function, resulting in missed types.
+        if (op == JSOP_FUNAPPLY) {
+            types::TypeSet *calleeType, *callerType;
+            size_t nargs = Min<size_t>(target->nargs, inlinedArguments_.length());
+            for (size_t i = 0; i < nargs; i++) {
+                calleeType = types::TypeScript::ArgTypes(targetScript, i);
+                // The arguments to this function aren't always available in this script.
+                // We need to get them from the caller at the position where
+                // the function gets called.
+                callerType = oracle->getCallArg(callerBuilder_->script_.get(),
+                                                inlinedArguments_.length(),
+                                                i+1, callerBuilder_->pc);
+
+                if (!callerType->isSubset(calleeType)) {
+                    IonSpew(IonSpew_Inlining, "Funapply inlining failed due to wrong types");
+                    return false;
+                }
+            }
+            // Arguments that weren't provided will be Undefined
+            for (size_t i = nargs; i < target->nargs; i++) {
+                calleeType = types::TypeScript::ArgTypes(targetScript, i);
+                if (calleeType->unknown() ||
+                    !calleeType->hasType(types::Type::UndefinedType()))
+                {
+                    IonSpew(IonSpew_Inlining, "Funapply inlining failed due to wrong types");
+                    return false;
+                }
+            }
+        }
     }
 
     return true;
 }
 
 static bool
 CanInlineGetPropertyCache(MGetPropertyCache *cache, MDefinition *thisDef)
 {
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug836274.js
@@ -0,0 +1,13 @@
+function dumpArgs6(i) {
+  if (i == 90)
+    return funapply6.arguments.length;
+  return [i];
+}
+function funapply6() {
+  return dumpArgs6.apply({}, arguments);
+}
+function test6(i) {
+  return funapply6(i,1,2,3);
+}
+test6(89)[0]
+test6(0.2)