Bug 1533890: Refactor TryAttachCallStub and add disableCacheIRCalls pref r=mgaudet
authorIain Ireland <iireland@mozilla.com>
Tue, 19 Mar 2019 22:57:34 +0000
changeset 465218 93613b622c03c5da9a1343a35aaed6d4e024b63c
parent 465217 0f9e3bff55750b4764e2ddd8c58e10c16e7f6865
child 465219 b04b7f58b4d82205369b1c280739c06d6df8cc1d
push id80965
push useriireland@mozilla.com
push dateWed, 20 Mar 2019 14:22:19 +0000
treeherderautoland@d808eb8f5dd5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmgaudet
bugs1533890
milestone68.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 1533890: Refactor TryAttachCallStub and add disableCacheIRCalls pref r=mgaudet This patch lays the groundwork for CacheIR call ICs. It refactors CallIRGenerator slightly, and adds a preference (on by default) to disable the new ICs. This lets us review and land future patches in a logical order without worrying about the attachment order of the new ICs vs the old ones. (For example, we don't want a CacheIR implementation of CallNative to shadow the old implementation of CallScriptedFunApply.) I also removed the old disableCacheIRBinaryArith pref, after confirming with Matt that it is obsolete. To avoid huge diffs every time the length of the longest CacheIR op changes, I padded the table out to 80 chars with a comment. Thanks, clang-format! Differential Revision: https://phabricator.services.mozilla.com/D22773
js/src/jit/CacheIR.cpp
js/src/jit/CacheIR.h
js/src/jit/IonBuilder.cpp
js/src/jit/JitOptions.cpp
js/src/jit/JitOptions.h
js/src/shell/js.cpp
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -5000,17 +5000,17 @@ bool CallIRGenerator::tryAttachStringSpl
   RootedObjectGroup group(cx_,
                           ObjectGroupRealm::getStringSplitStringGroup(cx_));
   if (!group) {
     return false;
   }
 
   Int32OperandId argcId(writer.setInputOperandId(0));
 
-  // Ensure argc == 1.
+  // Ensure argc == 2.
   writer.guardSpecificInt32Immediate(argcId, 2);
 
   // 2 arguments.  Stack-layout here is (bottom to top):
   //
   //  3: Callee
   //  2: ThisValue
   //  1: Arg0
   //  0: Arg1 <-- Top of stack
@@ -5231,61 +5231,99 @@ bool CallIRGenerator::tryAttachIsSuspend
   // returns Boolean. The stack typeset will be updated when we
   // attach the stub.
   cacheIRStubKind_ = BaselineCacheIRStubKind::Regular;
 
   trackAttached("IsSuspendedGenerator");
   return true;
 }
 
+bool CallIRGenerator::tryAttachSpecialCaseCallNative(HandleFunction callee) {
+  MOZ_ASSERT(callee->isNative());
+
+  if (callee->native() == js::intrinsic_StringSplitString) {
+    if (tryAttachStringSplit()) {
+      return true;
+    }
+  }
+
+  if (callee->native() == js::array_push) {
+    if (tryAttachArrayPush()) {
+      return true;
+    }
+  }
+
+  if (callee->native() == js::array_join) {
+    if (tryAttachArrayJoin()) {
+      return true;
+    }
+  }
+  if (callee->native() == intrinsic_IsSuspendedGenerator) {
+    if (tryAttachIsSuspendedGenerator()) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool CallIRGenerator::tryAttachCallScripted(HandleFunction calleeFunc) {
+  if (JitOptions.disableCacheIRCalls) {
+    return false;
+  }
+
+  return false;
+}
+
+bool CallIRGenerator::tryAttachCallNative(HandleFunction calleeFunc) {
+  MOZ_ASSERT(mode_ == ICState::Mode::Specialized);
+  MOZ_ASSERT(calleeFunc->isNative());
+
+  // Check for specific native-function optimizations.
+  if (tryAttachSpecialCaseCallNative(calleeFunc)) {
+    return true;
+  }
+  if (JitOptions.disableCacheIRCalls) {
+    return false;
+  }
+
+  return false;
+}
+
 bool CallIRGenerator::tryAttachStub() {
   AutoAssertNoPendingException aanpe(cx_);
 
-  // Only optimize on JSOP_CALL or JSOP_CALL_IGNORES_RV.  No fancy business for
-  // now.
-  if ((op_ != JSOP_CALL) && (op_ != JSOP_CALL_IGNORES_RV)) {
-    return false;
+  // Some opcodes are not yet supported.
+  switch (op_) {
+    case JSOP_CALL:
+    case JSOP_CALL_IGNORES_RV:
+      break;
+    default:
+      return false;
   }
 
   // Only optimize when the mode is Specialized.
   if (mode_ != ICState::Mode::Specialized) {
     return false;
   }
 
   // Ensure callee is a function.
   if (!callee_.isObject() || !callee_.toObject().is<JSFunction>()) {
     return false;
   }
 
   RootedFunction calleeFunc(cx_, &callee_.toObject().as<JSFunction>());
 
+  // Check for scripted optimizations.
+  if (calleeFunc->isInterpreted() || calleeFunc->isNativeWithJitEntry()) {
+    return tryAttachCallScripted(calleeFunc);
+  }
+
   // Check for native-function optimizations.
   if (calleeFunc->isNative()) {
-    if (calleeFunc->native() == js::intrinsic_StringSplitString) {
-      if (tryAttachStringSplit()) {
-        return true;
-      }
-    }
-
-    if (calleeFunc->native() == js::array_push) {
-      if (tryAttachArrayPush()) {
-        return true;
-      }
-    }
-
-    if (calleeFunc->native() == js::array_join) {
-      if (tryAttachArrayJoin()) {
-        return true;
-      }
-    }
-    if (calleeFunc->native() == intrinsic_IsSuspendedGenerator) {
-      if (tryAttachIsSuspendedGenerator()) {
-        return true;
-      }
-    }
+    return tryAttachCallNative(calleeFunc);
   }
 
   return false;
 }
 
 void CallIRGenerator::trackAttached(const char* name) {
 #ifdef JS_CACHEIR_SPEW
   if (const CacheIRSpewer::Guard& sp = CacheIRSpewer::Guard(*this, name)) {
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -186,194 +186,194 @@ enum ArgType {
   Int32,
   UInt32,
   Word,
 };
 
 extern const uint32_t OpLengths[];
 }  // namespace CacheIROpFormat
 
-#define CACHE_IR_OPS(_)                                                    \
-  _(GuardIsObject, Id)                                                     \
-  _(GuardIsObjectOrNull, Id)                                               \
-  _(GuardIsNullOrUndefined, Id)                                            \
-  _(GuardIsNotNullOrUndefined, Id)                                         \
-  _(GuardIsNull, Id)                                                       \
-  _(GuardIsUndefined, Id)                                                  \
-  _(GuardIsBoolean, Id, Id)                                                \
-  _(GuardIsString, Id)                                                     \
-  _(GuardIsSymbol, Id)                                                     \
-  _(GuardIsBigInt, Id)                                                     \
-  _(GuardIsNumber, Id)                                                     \
-  _(GuardIsInt32, Id, Id)                                                  \
-  _(GuardIsInt32Index, Id, Id)                                             \
-  _(GuardType, Id, Byte)                                                   \
-  _(GuardShape, Id, Field)                                                 \
-  _(GuardGroup, Id, Field)                                                 \
-  _(GuardProto, Id, Field)                                                 \
-  _(GuardClass, Id, Byte)     /* Guard per GuardClassKind */               \
-  _(GuardAnyClass, Id, Field) /* Guard an arbitrary class */               \
-  _(GuardCompartment, Id, Field, Field)                                    \
-  _(GuardIsExtensible, Id)                                                 \
-  _(GuardIsNativeFunction, Id, Word)                                       \
-  _(GuardIsNativeObject, Id)                                               \
-  _(GuardIsProxy, Id)                                                      \
-  _(GuardHasProxyHandler, Id, Field)                                       \
-  _(GuardNotDOMProxy, Id)                                                  \
-  _(GuardSpecificObject, Id, Field)                                        \
-  _(GuardSpecificAtom, Id, Field)                                          \
-  _(GuardSpecificSymbol, Id, Field)                                        \
-  _(GuardSpecificInt32Immediate, Id, Int32, Byte)                          \
-  _(GuardNoDetachedTypedObjects, None)                                     \
-  _(GuardMagicValue, Id, Byte)                                             \
-  _(GuardFrameHasNoArgumentsObject, None)                                  \
-  _(GuardNoDenseElements, Id)                                              \
-  _(GuardNoUnboxedExpando, Id)                                             \
-  _(GuardAndLoadUnboxedExpando, Id, Id)                                    \
-  _(GuardAndGetIndexFromString, Id, Id)                                    \
-  _(GuardAndGetNumberFromString, Id, Id)                                   \
-  _(GuardAndGetIterator, Id, Id, Field, Field)                             \
-  _(GuardHasGetterSetter, Id, Field)                                       \
-  _(GuardGroupHasUnanalyzedNewScript, Field)                               \
-  _(GuardIndexIsNonNegative, Id)                                           \
-  _(GuardIndexGreaterThanDenseCapacity, Id, Id)                            \
-  _(GuardIndexGreaterThanArrayLength, Id, Id)                              \
-  _(GuardIndexIsValidUpdateOrAdd, Id, Id)                                  \
-  _(GuardIndexGreaterThanDenseInitLength, Id, Id)                          \
-  _(GuardTagNotEqual, Id, Id)                                              \
-  _(GuardXrayExpandoShapeAndDefaultProto, Id, Byte, Field)                 \
-  _(GuardFunctionPrototype, Id, Id, Field)                                 \
-  _(GuardNoAllocationMetadataBuilder, None)                                \
-  _(GuardObjectGroupNotPretenured, Field)                                  \
-  _(LoadStackValue, Id, UInt32)                                            \
-  _(LoadObject, Id, Field)                                                 \
-  _(LoadProto, Id, Id)                                                     \
-  _(LoadEnclosingEnvironment, Id, Id)                                      \
-  _(LoadWrapperTarget, Id, Id)                                             \
-  _(LoadValueTag, Id, Id)                                                  \
-                                                                           \
-  _(TruncateDoubleToUInt32, Id, Id)                                        \
-                                                                           \
-  _(MegamorphicLoadSlotResult, Id, Field, Byte)                            \
-  _(MegamorphicLoadSlotByValueResult, Id, Id, Byte)                        \
-  _(MegamorphicStoreSlot, Id, Field, Id, Byte)                             \
-  _(MegamorphicSetElement, Id, Id, Id, Byte)                               \
-  _(MegamorphicHasPropResult, Id, Id, Byte)                                \
-                                                                           \
-  /* See CacheIR.cpp 'DOM proxies' comment. */                             \
-  _(LoadDOMExpandoValue, Id, Id)                                           \
-  _(LoadDOMExpandoValueGuardGeneration, Id, Field, Field, Id)              \
-  _(LoadDOMExpandoValueIgnoreGeneration, Id, Id)                           \
-  _(GuardDOMExpandoMissingOrGuardShape, Id, Field)                         \
-                                                                           \
-  _(StoreFixedSlot, Id, Field, Id)                                         \
-  _(StoreDynamicSlot, Id, Field, Id)                                       \
-  _(AddAndStoreFixedSlot, Id, Field, Id, Byte, Field, Field)               \
-  _(AddAndStoreDynamicSlot, Id, Field, Id, Byte, Field, Field)             \
-  _(AllocateAndStoreDynamicSlot, Id, Field, Id, Byte, Field, Field, Field) \
-  _(StoreTypedObjectReferenceProperty, Id, Field, Byte, Byte, Id)          \
-  _(StoreTypedObjectScalarProperty, Id, Field, Byte, Byte, Id)             \
-  _(StoreUnboxedProperty, Id, Byte, Field, Id)                             \
-  _(StoreDenseElement, Id, Id, Id)                                         \
-  _(StoreDenseElementHole, Id, Id, Id, Byte)                               \
-  _(ArrayPush, Id, Id)                                                     \
-  _(ArrayJoinResult, Id)                                                   \
-  _(StoreTypedElement, Id, Id, Id, Byte, Byte, Byte)                       \
-  _(CallNativeSetter, Id, Id, Field)                                       \
-  _(CallScriptedSetter, Id, Field, Id, Byte)                               \
-  _(CallSetArrayLength, Id, Byte, Id)                                      \
-  _(CallProxySet, Id, Id, Field, Byte)                                     \
-  _(CallProxySetByValue, Id, Id, Id, Byte)                                 \
-  _(CallAddOrUpdateSparseElementHelper, Id, Id, Id, Byte)                  \
-  _(CallInt32ToString, Id, Id)                                             \
-  _(CallNumberToString, Id, Id)                                            \
-                                                                           \
-  /* The *Result ops load a value into the cache's result register. */     \
-  _(LoadFixedSlotResult, Id, Field)                                        \
-  _(LoadDynamicSlotResult, Id, Field)                                      \
-  _(LoadUnboxedPropertyResult, Id, Byte, Field)                            \
-  _(LoadTypedObjectResult, Id, Byte, Byte, Field)                          \
-  _(LoadDenseElementResult, Id, Id)                                        \
-  _(LoadDenseElementHoleResult, Id, Id)                                    \
-  _(CallGetSparseElementResult, Id, Id)                                    \
-  _(LoadDenseElementExistsResult, Id, Id)                                  \
-  _(LoadTypedElementExistsResult, Id, Id, Byte)                            \
-  _(LoadDenseElementHoleExistsResult, Id, Id)                              \
-  _(LoadTypedElementResult, Id, Id, Byte, Byte)                            \
-  _(LoadInt32ArrayLengthResult, Id)                                        \
-  _(LoadArgumentsObjectArgResult, Id, Id)                                  \
-  _(LoadArgumentsObjectLengthResult, Id)                                   \
-  _(LoadFunctionLengthResult, Id)                                          \
-  _(LoadStringCharResult, Id, Id)                                          \
-  _(LoadStringLengthResult, Id)                                            \
-  _(LoadFrameCalleeResult, None)                                           \
-  _(LoadFrameNumActualArgsResult, None)                                    \
-  _(LoadFrameArgumentResult, Id)                                           \
-  _(LoadEnvironmentFixedSlotResult, Id, Field)                             \
-  _(LoadEnvironmentDynamicSlotResult, Id, Field)                           \
-  _(LoadObjectResult, Id)                                                  \
-  _(CallScriptedGetterResult, Id, Field, Byte)                             \
-  _(CallNativeGetterResult, Id, Field)                                     \
-  _(CallProxyGetResult, Id, Field)                                         \
-  _(CallProxyGetByValueResult, Id, Id)                                     \
-  _(CallProxyHasPropResult, Id, Id, Byte)                                  \
-  _(CallObjectHasSparseElementResult, Id, Id)                              \
-  _(CallNativeGetElementResult, Id, Id)                                    \
-  _(LoadUndefinedResult, None)                                             \
-  _(LoadBooleanResult, Byte)                                               \
-  _(LoadStringResult, Field)                                               \
-  _(LoadInstanceOfObjectResult, Id, Id)                                    \
-  _(LoadTypeOfObjectResult, Id)                                            \
-  _(DoubleAddResult, Id, Id)                                               \
-  _(DoubleSubResult, Id, Id)                                               \
-  _(DoubleMulResult, Id, Id)                                               \
-  _(DoubleDivResult, Id, Id)                                               \
-  _(DoubleModResult, Id, Id)                                               \
-  _(Int32AddResult, Id, Id)                                                \
-  _(Int32SubResult, Id, Id)                                                \
-  _(Int32MulResult, Id, Id)                                                \
-  _(Int32DivResult, Id, Id)                                                \
-  _(Int32ModResult, Id, Id)                                                \
-  _(Int32BitOrResult, Id, Id)                                              \
-  _(Int32BitXorResult, Id, Id)                                             \
-  _(Int32BitAndResult, Id, Id)                                             \
-  _(Int32LeftShiftResult, Id, Id)                                          \
-  _(Int32RightShiftResult, Id, Id)                                         \
-  _(Int32URightShiftResult, Id, Id, Byte)                                  \
-  _(Int32NotResult, Id)                                                    \
-  _(Int32NegationResult, Id)                                               \
-  _(DoubleNegationResult, Id)                                              \
-  _(Int32IncResult, Id)                                                    \
-  _(Int32DecResult, Id)                                                    \
-  _(DoubleIncResult, Id)                                                   \
-  _(DoubleDecResult, Id)                                                   \
-  _(LoadInt32TruthyResult, Id)                                             \
-  _(LoadDoubleTruthyResult, Id)                                            \
-  _(LoadStringTruthyResult, Id)                                            \
-  _(LoadObjectTruthyResult, Id)                                            \
-  _(LoadValueResult, Field)                                                \
-  _(LoadNewObjectFromTemplateResult, Field, UInt32, UInt32)                \
-                                                                           \
-  _(CallStringSplitResult, Id, Id, Field)                                  \
-  _(CallStringConcatResult, Id, Id)                                        \
-  _(CallStringObjectConcatResult, Id, Id)                                  \
-  _(CallIsSuspendedGeneratorResult, Id)                                    \
-                                                                           \
-  _(CompareStringResult, Id, Id, Byte)                                     \
-  _(CompareObjectResult, Id, Id, Byte)                                     \
-  _(CompareSymbolResult, Id, Id, Byte)                                     \
-  _(CompareInt32Result, Id, Id, Byte)                                      \
-  _(CompareDoubleResult, Id, Id, Byte)                                     \
-  _(CompareObjectUndefinedNullResult, Id, Byte)                            \
-                                                                           \
-  _(CallPrintString, Word)                                                 \
-  _(Breakpoint, None)                                                      \
-                                                                           \
-  _(TypeMonitorResult, None)                                               \
-  _(ReturnFromIC, None)                                                    \
+#define CACHE_IR_OPS(_) /****************************************************/ \
+  _(GuardIsObject, Id)                                                         \
+  _(GuardIsObjectOrNull, Id)                                                   \
+  _(GuardIsNullOrUndefined, Id)                                                \
+  _(GuardIsNotNullOrUndefined, Id)                                             \
+  _(GuardIsNull, Id)                                                           \
+  _(GuardIsUndefined, Id)                                                      \
+  _(GuardIsBoolean, Id, Id)                                                    \
+  _(GuardIsString, Id)                                                         \
+  _(GuardIsSymbol, Id)                                                         \
+  _(GuardIsBigInt, Id)                                                         \
+  _(GuardIsNumber, Id)                                                         \
+  _(GuardIsInt32, Id, Id)                                                      \
+  _(GuardIsInt32Index, Id, Id)                                                 \
+  _(GuardType, Id, Byte)                                                       \
+  _(GuardShape, Id, Field)                                                     \
+  _(GuardGroup, Id, Field)                                                     \
+  _(GuardProto, Id, Field)                                                     \
+  _(GuardClass, Id, Byte)     /* Guard per GuardClassKind */                   \
+  _(GuardAnyClass, Id, Field) /* Guard an arbitrary class */                   \
+  _(GuardCompartment, Id, Field, Field)                                        \
+  _(GuardIsExtensible, Id)                                                     \
+  _(GuardIsNativeFunction, Id, Word)                                           \
+  _(GuardIsNativeObject, Id)                                                   \
+  _(GuardIsProxy, Id)                                                          \
+  _(GuardHasProxyHandler, Id, Field)                                           \
+  _(GuardNotDOMProxy, Id)                                                      \
+  _(GuardSpecificObject, Id, Field)                                            \
+  _(GuardSpecificAtom, Id, Field)                                              \
+  _(GuardSpecificSymbol, Id, Field)                                            \
+  _(GuardSpecificInt32Immediate, Id, Int32, Byte)                              \
+  _(GuardNoDetachedTypedObjects, None)                                         \
+  _(GuardMagicValue, Id, Byte)                                                 \
+  _(GuardFrameHasNoArgumentsObject, None)                                      \
+  _(GuardNoDenseElements, Id)                                                  \
+  _(GuardNoUnboxedExpando, Id)                                                 \
+  _(GuardAndLoadUnboxedExpando, Id, Id)                                        \
+  _(GuardAndGetIndexFromString, Id, Id)                                        \
+  _(GuardAndGetNumberFromString, Id, Id)                                       \
+  _(GuardAndGetIterator, Id, Id, Field, Field)                                 \
+  _(GuardHasGetterSetter, Id, Field)                                           \
+  _(GuardGroupHasUnanalyzedNewScript, Field)                                   \
+  _(GuardIndexIsNonNegative, Id)                                               \
+  _(GuardIndexGreaterThanDenseCapacity, Id, Id)                                \
+  _(GuardIndexGreaterThanArrayLength, Id, Id)                                  \
+  _(GuardIndexIsValidUpdateOrAdd, Id, Id)                                      \
+  _(GuardIndexGreaterThanDenseInitLength, Id, Id)                              \
+  _(GuardTagNotEqual, Id, Id)                                                  \
+  _(GuardXrayExpandoShapeAndDefaultProto, Id, Byte, Field)                     \
+  _(GuardFunctionPrototype, Id, Id, Field)                                     \
+  _(GuardNoAllocationMetadataBuilder, None)                                    \
+  _(GuardObjectGroupNotPretenured, Field)                                      \
+  _(LoadStackValue, Id, UInt32)                                                \
+  _(LoadObject, Id, Field)                                                     \
+  _(LoadProto, Id, Id)                                                         \
+  _(LoadEnclosingEnvironment, Id, Id)                                          \
+  _(LoadWrapperTarget, Id, Id)                                                 \
+  _(LoadValueTag, Id, Id)                                                      \
+                                                                               \
+  _(TruncateDoubleToUInt32, Id, Id)                                            \
+                                                                               \
+  _(MegamorphicLoadSlotResult, Id, Field, Byte)                                \
+  _(MegamorphicLoadSlotByValueResult, Id, Id, Byte)                            \
+  _(MegamorphicStoreSlot, Id, Field, Id, Byte)                                 \
+  _(MegamorphicSetElement, Id, Id, Id, Byte)                                   \
+  _(MegamorphicHasPropResult, Id, Id, Byte)                                    \
+                                                                               \
+  /* See CacheIR.cpp 'DOM proxies' comment. */                                 \
+  _(LoadDOMExpandoValue, Id, Id)                                               \
+  _(LoadDOMExpandoValueGuardGeneration, Id, Field, Field, Id)                  \
+  _(LoadDOMExpandoValueIgnoreGeneration, Id, Id)                               \
+  _(GuardDOMExpandoMissingOrGuardShape, Id, Field)                             \
+                                                                               \
+  _(StoreFixedSlot, Id, Field, Id)                                             \
+  _(StoreDynamicSlot, Id, Field, Id)                                           \
+  _(AddAndStoreFixedSlot, Id, Field, Id, Byte, Field, Field)                   \
+  _(AddAndStoreDynamicSlot, Id, Field, Id, Byte, Field, Field)                 \
+  _(AllocateAndStoreDynamicSlot, Id, Field, Id, Byte, Field, Field, Field)     \
+  _(StoreTypedObjectReferenceProperty, Id, Field, Byte, Byte, Id)              \
+  _(StoreTypedObjectScalarProperty, Id, Field, Byte, Byte, Id)                 \
+  _(StoreUnboxedProperty, Id, Byte, Field, Id)                                 \
+  _(StoreDenseElement, Id, Id, Id)                                             \
+  _(StoreDenseElementHole, Id, Id, Id, Byte)                                   \
+  _(ArrayPush, Id, Id)                                                         \
+  _(ArrayJoinResult, Id)                                                       \
+  _(StoreTypedElement, Id, Id, Id, Byte, Byte, Byte)                           \
+  _(CallNativeSetter, Id, Id, Field)                                           \
+  _(CallScriptedSetter, Id, Field, Id, Byte)                                   \
+  _(CallSetArrayLength, Id, Byte, Id)                                          \
+  _(CallProxySet, Id, Id, Field, Byte)                                         \
+  _(CallProxySetByValue, Id, Id, Id, Byte)                                     \
+  _(CallAddOrUpdateSparseElementHelper, Id, Id, Id, Byte)                      \
+  _(CallInt32ToString, Id, Id)                                                 \
+  _(CallNumberToString, Id, Id)                                                \
+                                                                               \
+  /* The *Result ops load a value into the cache's result register. */         \
+  _(LoadFixedSlotResult, Id, Field)                                            \
+  _(LoadDynamicSlotResult, Id, Field)                                          \
+  _(LoadUnboxedPropertyResult, Id, Byte, Field)                                \
+  _(LoadTypedObjectResult, Id, Byte, Byte, Field)                              \
+  _(LoadDenseElementResult, Id, Id)                                            \
+  _(LoadDenseElementHoleResult, Id, Id)                                        \
+  _(CallGetSparseElementResult, Id, Id)                                        \
+  _(LoadDenseElementExistsResult, Id, Id)                                      \
+  _(LoadTypedElementExistsResult, Id, Id, Byte)                                \
+  _(LoadDenseElementHoleExistsResult, Id, Id)                                  \
+  _(LoadTypedElementResult, Id, Id, Byte, Byte)                                \
+  _(LoadInt32ArrayLengthResult, Id)                                            \
+  _(LoadArgumentsObjectArgResult, Id, Id)                                      \
+  _(LoadArgumentsObjectLengthResult, Id)                                       \
+  _(LoadFunctionLengthResult, Id)                                              \
+  _(LoadStringCharResult, Id, Id)                                              \
+  _(LoadStringLengthResult, Id)                                                \
+  _(LoadFrameCalleeResult, None)                                               \
+  _(LoadFrameNumActualArgsResult, None)                                        \
+  _(LoadFrameArgumentResult, Id)                                               \
+  _(LoadEnvironmentFixedSlotResult, Id, Field)                                 \
+  _(LoadEnvironmentDynamicSlotResult, Id, Field)                               \
+  _(LoadObjectResult, Id)                                                      \
+  _(CallScriptedGetterResult, Id, Field, Byte)                                 \
+  _(CallNativeGetterResult, Id, Field)                                         \
+  _(CallProxyGetResult, Id, Field)                                             \
+  _(CallProxyGetByValueResult, Id, Id)                                         \
+  _(CallProxyHasPropResult, Id, Id, Byte)                                      \
+  _(CallObjectHasSparseElementResult, Id, Id)                                  \
+  _(CallNativeGetElementResult, Id, Id)                                        \
+  _(LoadUndefinedResult, None)                                                 \
+  _(LoadBooleanResult, Byte)                                                   \
+  _(LoadStringResult, Field)                                                   \
+  _(LoadInstanceOfObjectResult, Id, Id)                                        \
+  _(LoadTypeOfObjectResult, Id)                                                \
+  _(DoubleAddResult, Id, Id)                                                   \
+  _(DoubleSubResult, Id, Id)                                                   \
+  _(DoubleMulResult, Id, Id)                                                   \
+  _(DoubleDivResult, Id, Id)                                                   \
+  _(DoubleModResult, Id, Id)                                                   \
+  _(Int32AddResult, Id, Id)                                                    \
+  _(Int32SubResult, Id, Id)                                                    \
+  _(Int32MulResult, Id, Id)                                                    \
+  _(Int32DivResult, Id, Id)                                                    \
+  _(Int32ModResult, Id, Id)                                                    \
+  _(Int32BitOrResult, Id, Id)                                                  \
+  _(Int32BitXorResult, Id, Id)                                                 \
+  _(Int32BitAndResult, Id, Id)                                                 \
+  _(Int32LeftShiftResult, Id, Id)                                              \
+  _(Int32RightShiftResult, Id, Id)                                             \
+  _(Int32URightShiftResult, Id, Id, Byte)                                      \
+  _(Int32NotResult, Id)                                                        \
+  _(Int32NegationResult, Id)                                                   \
+  _(DoubleNegationResult, Id)                                                  \
+  _(Int32IncResult, Id)                                                        \
+  _(Int32DecResult, Id)                                                        \
+  _(DoubleIncResult, Id)                                                       \
+  _(DoubleDecResult, Id)                                                       \
+  _(LoadInt32TruthyResult, Id)                                                 \
+  _(LoadDoubleTruthyResult, Id)                                                \
+  _(LoadStringTruthyResult, Id)                                                \
+  _(LoadObjectTruthyResult, Id)                                                \
+  _(LoadValueResult, Field)                                                    \
+  _(LoadNewObjectFromTemplateResult, Field, UInt32, UInt32)                    \
+                                                                               \
+  _(CallStringSplitResult, Id, Id, Field)                                      \
+  _(CallStringConcatResult, Id, Id)                                            \
+  _(CallStringObjectConcatResult, Id, Id)                                      \
+  _(CallIsSuspendedGeneratorResult, Id)                                        \
+                                                                               \
+  _(CompareStringResult, Id, Id, Byte)                                         \
+  _(CompareObjectResult, Id, Id, Byte)                                         \
+  _(CompareSymbolResult, Id, Id, Byte)                                         \
+  _(CompareInt32Result, Id, Id, Byte)                                          \
+  _(CompareDoubleResult, Id, Id, Byte)                                         \
+  _(CompareObjectUndefinedNullResult, Id, Byte)                                \
+                                                                               \
+  _(CallPrintString, Word)                                                     \
+  _(Breakpoint, None)                                                          \
+                                                                               \
+  _(TypeMonitorResult, None)                                                   \
+  _(ReturnFromIC, None)                                                        \
   _(WrapResult, None)
 
 enum class CacheOp {
 #define DEFINE_OP(op, ...) op,
   CACHE_IR_OPS(DEFINE_OP)
 #undef DEFINE_OP
 };
 
@@ -1992,16 +1992,19 @@ class MOZ_RAII CallIRGenerator : public 
   HandleValueArray args_;
   PropertyTypeCheckInfo typeCheckInfo_;
   BaselineCacheIRStubKind cacheIRStubKind_;
 
   bool tryAttachStringSplit();
   bool tryAttachArrayPush();
   bool tryAttachArrayJoin();
   bool tryAttachIsSuspendedGenerator();
+  bool tryAttachCallScripted(HandleFunction calleeFunc);
+  bool tryAttachSpecialCaseCallNative(HandleFunction calleeFunc);
+  bool tryAttachCallNative(HandleFunction calleeFunc);
 
   void trackAttached(const char* name);
 
  public:
   CallIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc, JSOp op,
                   ICState::Mode mode, uint32_t argc, HandleValue callee,
                   HandleValue thisval, HandleValueArray args);
 
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -3656,21 +3656,16 @@ AbortReasonOr<Ok> IonBuilder::binaryArit
 }
 
 AbortReasonOr<Ok> IonBuilder::arithTryBinaryStub(bool* emitted, JSOp op,
                                                  MDefinition* left,
                                                  MDefinition* right) {
   MOZ_ASSERT(*emitted == false);
   JSOp actualOp = JSOp(*pc);
 
-  // Try to emit a binary arith stub cache.
-  if (JitOptions.disableCacheIRBinaryArith) {
-    return Ok();
-  }
-
   // The actual jsop 'jsop_pos' is not supported yet.
   // There's no IC support for JSOP_POW either.
   if (actualOp == JSOP_POS || actualOp == JSOP_POW) {
     return Ok();
   }
 
   MInstruction* stub = nullptr;
   switch (actualOp) {
--- a/js/src/jit/JitOptions.cpp
+++ b/js/src/jit/JitOptions.cpp
@@ -117,18 +117,18 @@ DefaultJitOptions::DefaultJitOptions() {
   SET_DEFAULT(disableRecoverIns, false);
 
   // Toggle whether eager scalar replacement is globally disabled.
   SET_DEFAULT(disableScalarReplacement, false);
 
   // Toggles whether CacheIR stubs are used.
   SET_DEFAULT(disableCacheIR, false);
 
-  // Toggles whether CacheIR stubs for binary arith operations are used
-  SET_DEFAULT(disableCacheIRBinaryArith, false);
+  // Toggles whether CacheIR stubs for calls are used
+  SET_DEFAULT(disableCacheIRCalls, true);
 
 // Toggles whether sincos optimization is globally disabled.
 // See bug984018: The MacOS is the only one that has the sincos fast.
 #if defined(XP_MACOSX)
   SET_DEFAULT(disableSincos, false);
 #else
   SET_DEFAULT(disableSincos, true);
 #endif
--- a/js/src/jit/JitOptions.h
+++ b/js/src/jit/JitOptions.h
@@ -57,17 +57,17 @@ struct DefaultJitOptions {
   bool disableLicm;
   bool disableOptimizationTracking;
   bool disablePgo;
   bool disableInstructionReordering;
   bool disableRangeAnalysis;
   bool disableRecoverIns;
   bool disableScalarReplacement;
   bool disableCacheIR;
-  bool disableCacheIRBinaryArith;
+  bool disableCacheIRCalls;
   bool disableSincos;
   bool disableSink;
   bool eagerCompilation;
   bool forceInlineCaches;
   bool fullDebugChecks;
   bool limitScriptSize;
   bool osr;
   bool wasmFoldOffsets;
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -10210,20 +10210,22 @@ static bool SetContextOptions(JSContext*
 
   if (op.getBoolOption("no-unboxed-objects")) {
     jit::JitOptions.disableUnboxedObjects = true;
   }
 
   if (const char* str = op.getStringOption("cache-ir-stubs")) {
     if (strcmp(str, "on") == 0) {
       jit::JitOptions.disableCacheIR = false;
+      jit::JitOptions.disableCacheIRCalls = true;
     } else if (strcmp(str, "off") == 0) {
       jit::JitOptions.disableCacheIR = true;
-    } else if (strcmp(str, "nobinary") == 0) {
-      jit::JitOptions.disableCacheIRBinaryArith = true;
+    } else if (strcmp(str, "call") == 0) {
+      jit::JitOptions.disableCacheIR = false;
+      jit::JitOptions.disableCacheIRCalls = false;
     } else {
       return OptionFailure("cache-ir-stubs", str);
     }
   }
 
   if (const char* str = op.getStringOption("spectre-mitigations")) {
     if (strcmp(str, "on") == 0) {
       jit::JitOptions.spectreIndexMasking = true;
@@ -10910,20 +10912,19 @@ int main(int argc, char** argv, char** e
                           "(default: on, off to disable)"
 #else
                           "(default: off, on to enable)"
 #endif
                           ) ||
       !op.addStringOption('\0', "spectre-mitigations", "on/off",
                           "Whether Spectre mitigations are enabled (default: "
                           "off, on to enable)") ||
-      !op.addStringOption(
-          '\0', "cache-ir-stubs", "on/off/nobinary",
-          "Use CacheIR stubs (default: on, off to disable, nobinary to"
-          "just disable binary arith)") ||
+      !op.addStringOption('\0', "cache-ir-stubs", "on/off/call",
+                          "Use CacheIR stubs (default: on, off to disable, "
+                          "call to enable work-in-progress call ICs)") ||
       !op.addStringOption('\0', "ion-shared-stubs", "on/off",
                           "Use shared stubs (default: on, off to disable)") ||
       !op.addStringOption('\0', "ion-scalar-replacement", "on/off",
                           "Scalar Replacement (default: on, off to disable)") ||
       !op.addStringOption('\0', "ion-gvn", "[mode]",
                           "Specify Ion global value numbering:\n"
                           "  off: disable GVN\n"
                           "  on:  enable GVN (default)\n") ||