Bug 1395927 - Part 1: Replace argument count tests with assertions in MCallOptimize for intrinsic functions. r=jandem
authorAndré Bargull <andre.bargull@gmail.com>
Fri, 08 Sep 2017 16:40:55 +0200
changeset 429416 5e429fee90bf68de37ed43aaa446bdf9d84a7f85
parent 429415 9ddbac4df595b2b6d524b9eecf1bd417f35f973f
child 429417 6665f8db3a80067abdcc9625ff40c606f570d9c6
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1395927
milestone57.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 1395927 - Part 1: Replace argument count tests with assertions in MCallOptimize for intrinsic functions. r=jandem
js/src/jit/MCallOptimize.cpp
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -1054,20 +1054,18 @@ IonBuilder::inlineBoolean(CallInfo& call
         pushConstant(BooleanValue(false));
     }
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineNewIterator(CallInfo& callInfo, MNewIterator::Type type)
 {
-    if (callInfo.argc() != 0 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 0);
 
     JSObject* templateObject = nullptr;
     switch (type) {
       case MNewIterator::ArrayIterator:
         templateObject = inspector->getTemplateObjectForNative(pc, js::intrinsic_NewArrayIterator);
         MOZ_ASSERT_IF(templateObject, templateObject->is<ArrayIteratorObject>());
         break;
       case MNewIterator::StringIterator:
@@ -1693,20 +1691,18 @@ IonBuilder::inlineConstantStringSplitStr
     MInstruction* setLength = setInitializedLength(array, unboxedType, initLength);
     MOZ_TRY(resumeAfter(setLength));
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineStringSplitString(CallInfo& callInfo)
 {
-    if (callInfo.argc() != 2 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 2);
 
     MDefinition* strArg = callInfo.getArg(0);
     MDefinition* sepArg = callInfo.getArg(1);
 
     if (strArg->type() != MIRType::String)
         return InliningStatus_NotInlined;
 
     if (sepArg->type() != MIRType::String)
@@ -1743,20 +1739,18 @@ IonBuilder::inlineStringSplitString(Call
     current->push(ins);
 
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineObjectHasPrototype(CallInfo& callInfo)
 {
-    if (callInfo.argc() != 2 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 2);
 
     MDefinition* objArg = callInfo.getArg(0);
     MDefinition* protoArg = callInfo.getArg(1);
 
     if (objArg->type() != MIRType::Object)
         return InliningStatus_NotInlined;
     if (protoArg->type() != MIRType::Object)
         return InliningStatus_NotInlined;
@@ -2065,20 +2059,18 @@ IonBuilder::inlineStringConvertCase(Call
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineRegExpMatcher(CallInfo& callInfo)
 {
     // This is called from Self-hosted JS, after testing each argument,
     // most of following tests should be passed.
 
-    if (callInfo.argc() != 3 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 3);
 
     MDefinition* rxArg = callInfo.getArg(0);
     MDefinition* strArg = callInfo.getArg(1);
     MDefinition* lastIndexArg = callInfo.getArg(2);
 
     if (rxArg->type() != MIRType::Object && rxArg->type() != MIRType::Value)
         return InliningStatus_NotInlined;
 
@@ -2111,20 +2103,18 @@ IonBuilder::inlineRegExpMatcher(CallInfo
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineRegExpSearcher(CallInfo& callInfo)
 {
     // This is called from Self-hosted JS, after testing each argument,
     // most of following tests should be passed.
 
-    if (callInfo.argc() != 3 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 3);
 
     MDefinition* rxArg = callInfo.getArg(0);
     MDefinition* strArg = callInfo.getArg(1);
     MDefinition* lastIndexArg = callInfo.getArg(2);
 
     if (rxArg->type() != MIRType::Object && rxArg->type() != MIRType::Value)
         return InliningStatus_NotInlined;
 
@@ -2157,20 +2147,18 @@ IonBuilder::inlineRegExpSearcher(CallInf
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineRegExpTester(CallInfo& callInfo)
 {
     // This is called from Self-hosted JS, after testing each argument,
     // most of following tests should be passed.
 
-    if (callInfo.argc() != 3 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 3);
 
     MDefinition* rxArg = callInfo.getArg(0);
     MDefinition* strArg = callInfo.getArg(1);
     MDefinition* lastIndexArg = callInfo.getArg(2);
 
     if (rxArg->type() != MIRType::Object && rxArg->type() != MIRType::Value)
         return InliningStatus_NotInlined;
 
@@ -2199,20 +2187,18 @@ IonBuilder::inlineRegExpTester(CallInfo&
 
     MOZ_TRY(resumeAfter(tester));
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineIsRegExpObject(CallInfo& callInfo)
 {
-    if (callInfo.constructing() || callInfo.argc() != 1) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 1);
 
     if (getInlineReturnType() != MIRType::Boolean)
         return InliningStatus_NotInlined;
 
     MDefinition* arg = callInfo.getArg(0);
 
     bool isRegExpObject;
     if (!arg->mightBeType(MIRType::Object)) {
@@ -2233,20 +2219,18 @@ IonBuilder::inlineIsRegExpObject(CallInf
 
     callInfo.setImplicitlyUsedUnchecked();
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineRegExpPrototypeOptimizable(CallInfo& callInfo)
 {
-    if (callInfo.argc() != 1 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 1);
 
     MDefinition* protoArg = callInfo.getArg(0);
 
     if (protoArg->type() != MIRType::Object)
         return InliningStatus_NotInlined;
 
     if (getInlineReturnType() != MIRType::Boolean)
         return InliningStatus_NotInlined;
@@ -2258,20 +2242,18 @@ IonBuilder::inlineRegExpPrototypeOptimiz
     current->push(opt);
 
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineRegExpInstanceOptimizable(CallInfo& callInfo)
 {
-    if (callInfo.argc() != 2 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 2);
 
     MDefinition* rxArg = callInfo.getArg(0);
     MDefinition* protoArg = callInfo.getArg(1);
 
     if (rxArg->type() != MIRType::Object)
         return InliningStatus_NotInlined;
 
     if (protoArg->type() != MIRType::Object)
@@ -2287,20 +2269,18 @@ IonBuilder::inlineRegExpInstanceOptimiza
     current->push(opt);
 
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineGetFirstDollarIndex(CallInfo& callInfo)
 {
-    if (callInfo.argc() != 1 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 1);
 
     MDefinition* strArg = callInfo.getArg(0);
 
     if (strArg->type() != MIRType::String)
         return InliningStatus_NotInlined;
 
     if (getInlineReturnType() != MIRType::Int32)
         return InliningStatus_NotInlined;
@@ -2312,20 +2292,18 @@ IonBuilder::inlineGetFirstDollarIndex(Ca
     current->push(ins);
 
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineStringReplaceString(CallInfo& callInfo)
 {
-    if (callInfo.argc() != 3 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 3);
 
     if (getInlineReturnType() != MIRType::String)
         return InliningStatus_NotInlined;
 
     MDefinition* strArg = callInfo.getArg(0);
     MDefinition* patArg = callInfo.getArg(1);
     MDefinition* replArg = callInfo.getArg(2);
 
@@ -2346,18 +2324,18 @@ IonBuilder::inlineStringReplaceString(Ca
     if (cte->isEffectful())
         MOZ_TRY(resumeAfter(cte));
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineSubstringKernel(CallInfo& callInfo)
 {
+    MOZ_ASSERT(!callInfo.constructing());
     MOZ_ASSERT(callInfo.argc() == 3);
-    MOZ_ASSERT(!callInfo.constructing());
 
     // Return: String.
     if (getInlineReturnType() != MIRType::String)
         return InliningStatus_NotInlined;
 
     // Arg 0: String.
     if (callInfo.getArg(0)->type() != MIRType::String)
         return InliningStatus_NotInlined;
@@ -2494,20 +2472,18 @@ IonBuilder::inlineObjectToString(CallInf
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineHasClass(CallInfo& callInfo,
                            const Class* clasp1, const Class* clasp2,
                            const Class* clasp3, const Class* clasp4)
 {
-    if (callInfo.constructing() || callInfo.argc() != 1) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 1);
 
     if (callInfo.getArg(0)->type() != MIRType::Object)
         return InliningStatus_NotInlined;
     if (getInlineReturnType() != MIRType::Boolean)
         return InliningStatus_NotInlined;
 
     TemporaryTypeSet* types = callInfo.getArg(0)->resultTypeSet();
     const Class* knownClass = types ? types->getKnownClass(constraints()) : nullptr;
@@ -2541,20 +2517,18 @@ IonBuilder::inlineHasClass(CallInfo& cal
 
     callInfo.setImplicitlyUsedUnchecked();
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineGetNextEntryForIterator(CallInfo& callInfo, MGetNextEntryForIterator::Mode mode)
 {
-    if (callInfo.argc() != 2 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 2);
 
     MDefinition* iterArg = callInfo.getArg(0);
     MDefinition* resultArg = callInfo.getArg(1);
 
     if (iterArg->type() != MIRType::Object)
         return InliningStatus_NotInlined;
 
     TemporaryTypeSet* iterTypes = iterArg->resultTypeSet();
@@ -2870,20 +2844,18 @@ IonBuilder::inlineSetDisjointTypedElemen
     MOZ_TRY(resumeAfter(sets));
     callInfo.setImplicitlyUsedUnchecked();
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineObjectIsTypeDescr(CallInfo& callInfo)
 {
-    if (callInfo.constructing() || callInfo.argc() != 1) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 1);
 
     if (callInfo.getArg(0)->type() != MIRType::Object)
         return InliningStatus_NotInlined;
     if (getInlineReturnType() != MIRType::Boolean)
         return InliningStatus_NotInlined;
 
     // The test is elaborate: in-line only if there is exact
     // information.
@@ -2909,20 +2881,18 @@ IonBuilder::inlineObjectIsTypeDescr(Call
 
     callInfo.setImplicitlyUsedUnchecked();
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineSetTypedObjectOffset(CallInfo& callInfo)
 {
-    if (callInfo.argc() != 2 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 2);
 
     MDefinition* typedObj = callInfo.getArg(0);
     MDefinition* offset = callInfo.getArg(1);
 
     // Return type should be undefined or something wacky is going on.
     if (getInlineReturnType() != MIRType::Undefined)
         return InliningStatus_NotInlined;
 
@@ -2953,20 +2923,19 @@ IonBuilder::inlineSetTypedObjectOffset(C
     current->add(ins);
     current->push(ins);
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineUnsafeSetReservedSlot(CallInfo& callInfo)
 {
-    if (callInfo.argc() != 3 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 3);
+
     if (getInlineReturnType() != MIRType::Undefined)
         return InliningStatus_NotInlined;
 
     MDefinition* obj = callInfo.getArg(0);
     if (obj->type() != MIRType::Object && obj->type() != MIRType::Value)
         return InliningStatus_NotInlined;
 
     MDefinition* arg = callInfo.getArg(1);
@@ -2993,20 +2962,18 @@ IonBuilder::inlineUnsafeSetReservedSlot(
         current->add(MPostWriteBarrier::New(alloc(), obj, callInfo.getArg(2)));
 
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineUnsafeGetReservedSlot(CallInfo& callInfo, MIRType knownValueType)
 {
-    if (callInfo.argc() != 2 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 2);
 
     MDefinition* obj = callInfo.getArg(0);
     if (obj->type() != MIRType::Object && obj->type() != MIRType::Value)
         return InliningStatus_NotInlined;
 
     MDefinition* arg = callInfo.getArg(1);
     if (arg->type() != MIRType::Int32)
         return InliningStatus_NotInlined;
@@ -3040,20 +3007,18 @@ IonBuilder::inlineUnsafeGetReservedSlot(
     // We don't track reserved slot types, so always emit a barrier.
     MOZ_TRY(pushTypeBarrier(load, getInlineReturnTypeSet(), BarrierKind::TypeSet));
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineIsCallable(CallInfo& callInfo)
 {
-    if (callInfo.argc() != 1 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 1);
 
     if (getInlineReturnType() != MIRType::Boolean)
         return InliningStatus_NotInlined;
 
     MDefinition* arg = callInfo.getArg(0);
 
     // Try inlining with constant true/false: only objects may be callable at
     // all, and if we know the class check if it is callable.
@@ -3108,20 +3073,19 @@ IonBuilder::inlineIsConstructor(CallInfo
     current->push(ins);
 
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineIsObject(CallInfo& callInfo)
 {
-    if (callInfo.argc() != 1 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 1);
+
     if (getInlineReturnType() != MIRType::Boolean)
         return InliningStatus_NotInlined;
 
     callInfo.setImplicitlyUsedUnchecked();
     if (callInfo.getArg(0)->type() == MIRType::Object) {
         pushConstant(BooleanValue(true));
     } else {
         MIsObject* isObject = MIsObject::New(alloc(), callInfo.getArg(0));
@@ -3129,20 +3093,18 @@ IonBuilder::inlineIsObject(CallInfo& cal
         current->push(isObject);
     }
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineToObject(CallInfo& callInfo)
 {
-    if (callInfo.argc() != 1 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 1);
 
     if (getInlineReturnType() != MIRType::Object)
         return InliningStatus_NotInlined;
 
     MDefinition* object = callInfo.getArg(0);
     if (object->type() != MIRType::Object && object->type() != MIRType::Value)
         return InliningStatus_NotInlined;
 
@@ -3160,20 +3122,18 @@ IonBuilder::inlineToObject(CallInfo& cal
     }
 
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineIsWrappedArrayConstructor(CallInfo& callInfo)
 {
-    if (callInfo.constructing() || callInfo.argc() != 1) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 1);
 
     if (getInlineReturnType() != MIRType::Boolean)
         return InliningStatus_NotInlined;
     MDefinition* arg = callInfo.getArg(0);
     if (arg->type() != MIRType::Object)
         return InliningStatus_NotInlined;
 
     TemporaryTypeSet* types = arg->resultTypeSet();
@@ -3191,20 +3151,18 @@ IonBuilder::inlineIsWrappedArrayConstruc
     // Inline only if argument is absolutely *not* a Proxy.
     pushConstant(BooleanValue(false));
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineToInteger(CallInfo& callInfo)
 {
-    if (callInfo.argc() != 1 || callInfo.constructing()) {
-        trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
-        return InliningStatus_NotInlined;
-    }
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 1);
 
     MDefinition* input = callInfo.getArg(0);
 
     // Only optimize cases where input contains only number, null or boolean
     if (input->mightBeType(MIRType::Object) ||
         input->mightBeType(MIRType::String) ||
         input->mightBeType(MIRType::Symbol) ||
         input->mightBeType(MIRType::Undefined) ||
@@ -3226,18 +3184,18 @@ IonBuilder::inlineToInteger(CallInfo& ca
     current->add(toInt32);
     current->push(toInt32);
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult
 IonBuilder::inlineToString(CallInfo& callInfo)
 {
-    if (callInfo.argc() != 1 || callInfo.constructing())
-        return InliningStatus_NotInlined;
+    MOZ_ASSERT(!callInfo.constructing());
+    MOZ_ASSERT(callInfo.argc() == 1);
 
     if (getInlineReturnType() != MIRType::String)
         return InliningStatus_NotInlined;
 
     callInfo.setImplicitlyUsedUnchecked();
     MToString* toString = MToString::New(alloc(), callInfo.getArg(0));
     current->add(toString);
     current->push(toString);