Bug 1506968 - Fix an invalid assert in IonBuilder::improveThisTypesForCall. r=nbp
authorJan de Mooij <jdemooij@mozilla.com>
Mon, 26 Nov 2018 11:03:41 +0000
changeset 504400 3c2cc6c7a72e8c9ab0adf9da2c265f815b3d659f
parent 504399 e35e048ef39639d5c5038ade352a12e2957bdf2e
child 504401 703630d3fc2757d5aaa94ab706a5faf826b0b1c3
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1506968
milestone65.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 1506968 - Fix an invalid assert in IonBuilder::improveThisTypesForCall. r=nbp Differential Revision: https://phabricator.services.mozilla.com/D12638
js/src/jit-test/tests/ion/bug1506968.js
js/src/jit/IonBuilder.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1506968.js
@@ -0,0 +1,14 @@
+// |jit-test| skip-if: typeof Intl === 'undefined'
+function f(a, b) {
+    a.formatToParts();
+    a.format();
+}
+var a = new Intl.NumberFormat();
+f(a, []);
+try {
+    f();
+} catch (e) {}
+f(a, []);
+try {
+    f();
+} catch (e) {}
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -10923,22 +10923,26 @@ IonBuilder::improveThisTypesForCall()
     // ... [this: obj], [callee: obj.prop]
     //
     // If obj is null or undefined, obj.prop would have thrown an exception so
     // at this point we can remove null and undefined from obj's TypeSet, to
     // improve type information for the call that will follow.
 
     MOZ_ASSERT(*pc == JSOP_CALLPROP || *pc == JSOP_CALLELEM);
 
-    // Ensure |this| has types {object, null/undefined}.
+    // Ensure |this| has types {object, null/undefined}. For simplicity don't
+    // optimize if the callee is a Phi (this can happen in rare cases after
+    // inlining a scripted getter).
     MDefinition* thisDef = current->peek(-2);
+    MDefinition* calleeDef = current->peek(-1);
     if (thisDef->type() != MIRType::Value ||
         !thisDef->mightBeType(MIRType::Object) ||
         !thisDef->resultTypeSet() ||
-        !thisDef->resultTypeSet()->objectOrSentinel())
+        !thisDef->resultTypeSet()->objectOrSentinel() ||
+        calleeDef->isPhi())
     {
         return Ok();
     }
 
     // Remove null/undefined from the TypeSet.
     TemporaryTypeSet* types = thisDef->resultTypeSet()->cloneObjectsOnly(alloc_->lifoAlloc());
     if (!types) {
         return abort(AbortReason::Alloc);
@@ -10946,17 +10950,17 @@ IonBuilder::improveThisTypesForCall()
 
     MFilterTypeSet* filter = MFilterTypeSet::New(alloc(), thisDef, types);
     current->add(filter);
     current->rewriteAtDepth(-2, filter);
 
     // FilterTypeSetPolicy::adjustInputs will insert an infallible Unbox(Object)
     // for the input. Don't hoist this unbox above the getprop or getelem
     // operation.
-    filter->setDependency(current->peek(-1)->toInstruction());
+    filter->setDependency(calleeDef);
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::checkIsDefinitelyOptimizedArguments(MDefinition* obj, bool* isOptimizedArgs)
 {
     if (obj->type() != MIRType::MagicOptimizedArguments) {
         if (script()->argumentsHasVarBinding() &&