Simplify our intrinsic recognizer.

- Use the modifiers for storing the intrinsic kind.
- Delete dex_file_method_inliner and its associated map.

This work was also motivated by the fact that the inline
method analyzer leaks intrinsic tables, and even worse, might re-use
a table from one dex file to another unrelated dex file in the presence
of class unloading and the unlikely event of the dex files getting
the same address.

test: m test-art-host m test-art-target

Change-Id: Ia653d2c72df13889dc85dd8c84997582c034ea4b
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index 2131279..412ccfc 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -18,13 +18,10 @@
 
 #include "art_method.h"
 #include "class_linker.h"
-#include "dex/quick/dex_file_method_inliner.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
 #include "driver/compiler_driver.h"
 #include "invoke_type.h"
 #include "mirror/dex_cache-inl.h"
 #include "nodes.h"
-#include "quick/inline_method_analyser.h"
 #include "scoped_thread_state_change-inl.h"
 #include "thread-inl.h"
 #include "utils.h"
@@ -36,7 +33,7 @@
   switch (i) {
     case Intrinsics::kNone:
       return kInterface;  // Non-sensical for intrinsic.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
     case Intrinsics::k ## Name: \
       return IsStatic;
 #include "intrinsics_list.h"
@@ -52,7 +49,7 @@
   switch (i) {
     case Intrinsics::kNone:
       return kNeedsEnvironmentOrCache;  // Non-sensical for intrinsic.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
     case Intrinsics::k ## Name: \
       return NeedsEnvironmentOrCache;
 #include "intrinsics_list.h"
@@ -68,7 +65,7 @@
   switch (i) {
     case Intrinsics::kNone:
       return kAllSideEffects;
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
     case Intrinsics::k ## Name: \
       return SideEffects;
 #include "intrinsics_list.h"
@@ -84,7 +81,7 @@
   switch (i) {
     case Intrinsics::kNone:
       return kCanThrow;
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
     case Intrinsics::k ## Name: \
       return Exceptions;
 #include "intrinsics_list.h"
@@ -95,430 +92,7 @@
   return kCanThrow;
 }
 
-static Primitive::Type GetType(uint64_t data, bool is_op_size) {
-  if (is_op_size) {
-    switch (static_cast<OpSize>(data)) {
-      case kSignedByte:
-        return Primitive::kPrimByte;
-      case kSignedHalf:
-        return Primitive::kPrimShort;
-      case k32:
-        return Primitive::kPrimInt;
-      case k64:
-        return Primitive::kPrimLong;
-      default:
-        LOG(FATAL) << "Unknown/unsupported op size " << data;
-        UNREACHABLE();
-    }
-  } else {
-    if ((data & kIntrinsicFlagIsLong) != 0) {
-      return Primitive::kPrimLong;
-    }
-    if ((data & kIntrinsicFlagIsObject) != 0) {
-      return Primitive::kPrimNot;
-    }
-    return Primitive::kPrimInt;
-  }
-}
-
-static Intrinsics GetIntrinsic(InlineMethod method) {
-  switch (method.opcode) {
-    // Floating-point conversions.
-    case kIntrinsicDoubleCvt:
-      return ((method.d.data & kIntrinsicFlagToFloatingPoint) == 0) ?
-          Intrinsics::kDoubleDoubleToRawLongBits : Intrinsics::kDoubleLongBitsToDouble;
-    case kIntrinsicFloatCvt:
-      return ((method.d.data & kIntrinsicFlagToFloatingPoint) == 0) ?
-          Intrinsics::kFloatFloatToRawIntBits : Intrinsics::kFloatIntBitsToFloat;
-    case kIntrinsicFloat2Int:
-      return Intrinsics::kFloatFloatToIntBits;
-    case kIntrinsicDouble2Long:
-      return Intrinsics::kDoubleDoubleToLongBits;
-
-    // Floating-point tests.
-    case kIntrinsicFloatIsInfinite:
-      return Intrinsics::kFloatIsInfinite;
-    case kIntrinsicDoubleIsInfinite:
-      return Intrinsics::kDoubleIsInfinite;
-    case kIntrinsicFloatIsNaN:
-      return Intrinsics::kFloatIsNaN;
-    case kIntrinsicDoubleIsNaN:
-      return Intrinsics::kDoubleIsNaN;
-
-    // Bit manipulations.
-    case kIntrinsicReverseBits:
-      switch (GetType(method.d.data, true)) {
-        case Primitive::kPrimInt:
-          return Intrinsics::kIntegerReverse;
-        case Primitive::kPrimLong:
-          return Intrinsics::kLongReverse;
-        default:
-          LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
-          UNREACHABLE();
-      }
-    case kIntrinsicReverseBytes:
-      switch (GetType(method.d.data, true)) {
-        case Primitive::kPrimShort:
-          return Intrinsics::kShortReverseBytes;
-        case Primitive::kPrimInt:
-          return Intrinsics::kIntegerReverseBytes;
-        case Primitive::kPrimLong:
-          return Intrinsics::kLongReverseBytes;
-        default:
-          LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
-          UNREACHABLE();
-      }
-    case kIntrinsicRotateRight:
-      switch (GetType(method.d.data, true)) {
-        case Primitive::kPrimInt:
-          return Intrinsics::kIntegerRotateRight;
-        case Primitive::kPrimLong:
-          return Intrinsics::kLongRotateRight;
-        default:
-          LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
-          UNREACHABLE();
-      }
-    case kIntrinsicRotateLeft:
-      switch (GetType(method.d.data, true)) {
-        case Primitive::kPrimInt:
-          return Intrinsics::kIntegerRotateLeft;
-        case Primitive::kPrimLong:
-          return Intrinsics::kLongRotateLeft;
-        default:
-          LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
-          UNREACHABLE();
-      }
-
-    // Misc data processing.
-    case kIntrinsicBitCount:
-      switch (GetType(method.d.data, true)) {
-        case Primitive::kPrimInt:
-          return Intrinsics::kIntegerBitCount;
-        case Primitive::kPrimLong:
-          return Intrinsics::kLongBitCount;
-        default:
-          LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
-          UNREACHABLE();
-      }
-    case kIntrinsicCompare:
-      switch (GetType(method.d.data, true)) {
-        case Primitive::kPrimInt:
-          return Intrinsics::kIntegerCompare;
-        case Primitive::kPrimLong:
-          return Intrinsics::kLongCompare;
-        default:
-          LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
-          UNREACHABLE();
-      }
-    case kIntrinsicHighestOneBit:
-      switch (GetType(method.d.data, true)) {
-        case Primitive::kPrimInt:
-          return Intrinsics::kIntegerHighestOneBit;
-        case Primitive::kPrimLong:
-          return Intrinsics::kLongHighestOneBit;
-        default:
-          LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
-          UNREACHABLE();
-      }
-    case kIntrinsicLowestOneBit:
-      switch (GetType(method.d.data, true)) {
-        case Primitive::kPrimInt:
-          return Intrinsics::kIntegerLowestOneBit;
-        case Primitive::kPrimLong:
-          return Intrinsics::kLongLowestOneBit;
-        default:
-          LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
-          UNREACHABLE();
-      }
-    case kIntrinsicNumberOfLeadingZeros:
-      switch (GetType(method.d.data, true)) {
-        case Primitive::kPrimInt:
-          return Intrinsics::kIntegerNumberOfLeadingZeros;
-        case Primitive::kPrimLong:
-          return Intrinsics::kLongNumberOfLeadingZeros;
-        default:
-          LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
-          UNREACHABLE();
-      }
-    case kIntrinsicNumberOfTrailingZeros:
-      switch (GetType(method.d.data, true)) {
-        case Primitive::kPrimInt:
-          return Intrinsics::kIntegerNumberOfTrailingZeros;
-        case Primitive::kPrimLong:
-          return Intrinsics::kLongNumberOfTrailingZeros;
-        default:
-          LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
-          UNREACHABLE();
-      }
-    case kIntrinsicSignum:
-      switch (GetType(method.d.data, true)) {
-        case Primitive::kPrimInt:
-          return Intrinsics::kIntegerSignum;
-        case Primitive::kPrimLong:
-          return Intrinsics::kLongSignum;
-        default:
-          LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
-          UNREACHABLE();
-      }
-
-    // Abs.
-    case kIntrinsicAbsDouble:
-      return Intrinsics::kMathAbsDouble;
-    case kIntrinsicAbsFloat:
-      return Intrinsics::kMathAbsFloat;
-    case kIntrinsicAbsInt:
-      return Intrinsics::kMathAbsInt;
-    case kIntrinsicAbsLong:
-      return Intrinsics::kMathAbsLong;
-
-    // Min/max.
-    case kIntrinsicMinMaxDouble:
-      return ((method.d.data & kIntrinsicFlagMin) == 0) ?
-          Intrinsics::kMathMaxDoubleDouble : Intrinsics::kMathMinDoubleDouble;
-    case kIntrinsicMinMaxFloat:
-      return ((method.d.data & kIntrinsicFlagMin) == 0) ?
-          Intrinsics::kMathMaxFloatFloat : Intrinsics::kMathMinFloatFloat;
-    case kIntrinsicMinMaxInt:
-      return ((method.d.data & kIntrinsicFlagMin) == 0) ?
-          Intrinsics::kMathMaxIntInt : Intrinsics::kMathMinIntInt;
-    case kIntrinsicMinMaxLong:
-      return ((method.d.data & kIntrinsicFlagMin) == 0) ?
-          Intrinsics::kMathMaxLongLong : Intrinsics::kMathMinLongLong;
-
-    // More math builtins.
-    case kIntrinsicCos:
-      return Intrinsics::kMathCos;
-    case kIntrinsicSin:
-      return Intrinsics::kMathSin;
-    case kIntrinsicAcos:
-      return Intrinsics::kMathAcos;
-    case kIntrinsicAsin:
-      return Intrinsics::kMathAsin;
-    case kIntrinsicAtan:
-      return Intrinsics::kMathAtan;
-    case kIntrinsicAtan2:
-      return Intrinsics::kMathAtan2;
-    case kIntrinsicCbrt:
-      return Intrinsics::kMathCbrt;
-    case kIntrinsicCosh:
-      return Intrinsics::kMathCosh;
-    case kIntrinsicExp:
-      return Intrinsics::kMathExp;
-    case kIntrinsicExpm1:
-      return Intrinsics::kMathExpm1;
-    case kIntrinsicHypot:
-      return Intrinsics::kMathHypot;
-    case kIntrinsicLog:
-      return Intrinsics::kMathLog;
-    case kIntrinsicLog10:
-      return Intrinsics::kMathLog10;
-    case kIntrinsicNextAfter:
-      return Intrinsics::kMathNextAfter;
-    case kIntrinsicSinh:
-      return Intrinsics::kMathSinh;
-    case kIntrinsicTan:
-      return Intrinsics::kMathTan;
-    case kIntrinsicTanh:
-      return Intrinsics::kMathTanh;
-
-    // Misc math.
-    case kIntrinsicSqrt:
-      return Intrinsics::kMathSqrt;
-    case kIntrinsicCeil:
-      return Intrinsics::kMathCeil;
-    case kIntrinsicFloor:
-      return Intrinsics::kMathFloor;
-    case kIntrinsicRint:
-      return Intrinsics::kMathRint;
-    case kIntrinsicRoundDouble:
-      return Intrinsics::kMathRoundDouble;
-    case kIntrinsicRoundFloat:
-      return Intrinsics::kMathRoundFloat;
-
-    // System.arraycopy.
-    case kIntrinsicSystemArrayCopyCharArray:
-      return Intrinsics::kSystemArrayCopyChar;
-
-    case kIntrinsicSystemArrayCopy:
-      return Intrinsics::kSystemArrayCopy;
-
-    // Thread.currentThread.
-    case kIntrinsicCurrentThread:
-      return Intrinsics::kThreadCurrentThread;
-
-    // Memory.peek.
-    case kIntrinsicPeek:
-      switch (GetType(method.d.data, true)) {
-        case Primitive::kPrimByte:
-          return Intrinsics::kMemoryPeekByte;
-        case Primitive::kPrimShort:
-          return Intrinsics::kMemoryPeekShortNative;
-        case Primitive::kPrimInt:
-          return Intrinsics::kMemoryPeekIntNative;
-        case Primitive::kPrimLong:
-          return Intrinsics::kMemoryPeekLongNative;
-        default:
-          LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
-          UNREACHABLE();
-      }
-
-    // Memory.poke.
-    case kIntrinsicPoke:
-      switch (GetType(method.d.data, true)) {
-        case Primitive::kPrimByte:
-          return Intrinsics::kMemoryPokeByte;
-        case Primitive::kPrimShort:
-          return Intrinsics::kMemoryPokeShortNative;
-        case Primitive::kPrimInt:
-          return Intrinsics::kMemoryPokeIntNative;
-        case Primitive::kPrimLong:
-          return Intrinsics::kMemoryPokeLongNative;
-        default:
-          LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
-          UNREACHABLE();
-      }
-
-    // String.
-    case kIntrinsicCharAt:
-      return Intrinsics::kStringCharAt;
-    case kIntrinsicCompareTo:
-      return Intrinsics::kStringCompareTo;
-    case kIntrinsicEquals:
-      return Intrinsics::kStringEquals;
-    case kIntrinsicGetCharsNoCheck:
-      return Intrinsics::kStringGetCharsNoCheck;
-    case kIntrinsicIsEmptyOrLength:
-      return ((method.d.data & kIntrinsicFlagIsEmpty) == 0) ?
-          Intrinsics::kStringLength : Intrinsics::kStringIsEmpty;
-    case kIntrinsicIndexOf:
-      return ((method.d.data & kIntrinsicFlagBase0) == 0) ?
-          Intrinsics::kStringIndexOfAfter : Intrinsics::kStringIndexOf;
-    case kIntrinsicNewStringFromBytes:
-      return Intrinsics::kStringNewStringFromBytes;
-    case kIntrinsicNewStringFromChars:
-      return Intrinsics::kStringNewStringFromChars;
-    case kIntrinsicNewStringFromString:
-      return Intrinsics::kStringNewStringFromString;
-
-    case kIntrinsicCas:
-      switch (GetType(method.d.data, false)) {
-        case Primitive::kPrimNot:
-          return Intrinsics::kUnsafeCASObject;
-        case Primitive::kPrimInt:
-          return Intrinsics::kUnsafeCASInt;
-        case Primitive::kPrimLong:
-          return Intrinsics::kUnsafeCASLong;
-        default:
-          LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
-          UNREACHABLE();
-      }
-    case kIntrinsicUnsafeGet: {
-      const bool is_volatile = (method.d.data & kIntrinsicFlagIsVolatile);
-      switch (GetType(method.d.data, false)) {
-        case Primitive::kPrimInt:
-          return is_volatile ? Intrinsics::kUnsafeGetVolatile : Intrinsics::kUnsafeGet;
-        case Primitive::kPrimLong:
-          return is_volatile ? Intrinsics::kUnsafeGetLongVolatile : Intrinsics::kUnsafeGetLong;
-        case Primitive::kPrimNot:
-          return is_volatile ? Intrinsics::kUnsafeGetObjectVolatile : Intrinsics::kUnsafeGetObject;
-        default:
-          LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
-          UNREACHABLE();
-      }
-    }
-    case kIntrinsicUnsafePut: {
-      enum Sync { kNoSync, kVolatile, kOrdered };
-      const Sync sync =
-          ((method.d.data & kIntrinsicFlagIsVolatile) != 0) ? kVolatile :
-          ((method.d.data & kIntrinsicFlagIsOrdered) != 0)  ? kOrdered :
-                                                              kNoSync;
-      switch (GetType(method.d.data, false)) {
-        case Primitive::kPrimInt:
-          switch (sync) {
-            case kNoSync:
-              return Intrinsics::kUnsafePut;
-            case kVolatile:
-              return Intrinsics::kUnsafePutVolatile;
-            case kOrdered:
-              return Intrinsics::kUnsafePutOrdered;
-          }
-          break;
-        case Primitive::kPrimLong:
-          switch (sync) {
-            case kNoSync:
-              return Intrinsics::kUnsafePutLong;
-            case kVolatile:
-              return Intrinsics::kUnsafePutLongVolatile;
-            case kOrdered:
-              return Intrinsics::kUnsafePutLongOrdered;
-          }
-          break;
-        case Primitive::kPrimNot:
-          switch (sync) {
-            case kNoSync:
-              return Intrinsics::kUnsafePutObject;
-            case kVolatile:
-              return Intrinsics::kUnsafePutObjectVolatile;
-            case kOrdered:
-              return Intrinsics::kUnsafePutObjectOrdered;
-          }
-          break;
-        default:
-          LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
-          UNREACHABLE();
-      }
-      break;
-    }
-
-    // 1.8.
-    case kIntrinsicUnsafeGetAndAddInt:
-      return Intrinsics::kUnsafeGetAndAddInt;
-    case kIntrinsicUnsafeGetAndAddLong:
-      return Intrinsics::kUnsafeGetAndAddLong;
-    case kIntrinsicUnsafeGetAndSetInt:
-      return Intrinsics::kUnsafeGetAndSetInt;
-    case kIntrinsicUnsafeGetAndSetLong:
-      return Intrinsics::kUnsafeGetAndSetLong;
-    case kIntrinsicUnsafeGetAndSetObject:
-      return Intrinsics::kUnsafeGetAndSetObject;
-    case kIntrinsicUnsafeLoadFence:
-      return Intrinsics::kUnsafeLoadFence;
-    case kIntrinsicUnsafeStoreFence:
-      return Intrinsics::kUnsafeStoreFence;
-    case kIntrinsicUnsafeFullFence:
-      return Intrinsics::kUnsafeFullFence;
-
-    // Virtual cases.
-
-    case kIntrinsicReferenceGetReferent:
-      return Intrinsics::kReferenceGetReferent;
-
-    // Quick inliner cases. Remove after refactoring. They are here so that we can use the
-    // compiler to warn on missing cases.
-
-    case kInlineOpNop:
-    case kInlineOpReturnArg:
-    case kInlineOpNonWideConst:
-    case kInlineOpIGet:
-    case kInlineOpIPut:
-    case kInlineOpConstructor:
-      return Intrinsics::kNone;
-
-    // String init cases, not intrinsics.
-
-    case kInlineStringInit:
-      return Intrinsics::kNone;
-
-    // No default case to make the compiler warn on missing cases.
-  }
-  return Intrinsics::kNone;
-}
-
-static bool CheckInvokeType(Intrinsics intrinsic, HInvoke* invoke, const DexFile& dex_file) {
-  // The DexFileMethodInliner should have checked whether the methods are agreeing with
-  // what we expect, i.e., static methods are called as such. Add another check here for
-  // our expectations:
-  //
+static bool CheckInvokeType(Intrinsics intrinsic, HInvoke* invoke) {
   // Whenever the intrinsic is marked as static, report an error if we find an InvokeVirtual.
   //
   // Whenever the intrinsic is marked as direct and we find an InvokeVirtual, a devirtualization
@@ -542,13 +116,9 @@
         return true;
       }
       if (invoke_type == kVirtual) {
-        ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+        ArtMethod* art_method = invoke->GetResolvedMethod();
         ScopedObjectAccess soa(Thread::Current());
-        ArtMethod* art_method =
-            class_linker->FindDexCache(soa.Self(), dex_file)->GetResolvedMethod(
-                invoke->GetDexMethodIndex(), class_linker->GetImagePointerSize());
-        return art_method != nullptr &&
-            (art_method->IsFinal() || art_method->GetDeclaringClass()->IsFinal());
+        return (art_method->IsFinal() || art_method->GetDeclaringClass()->IsFinal());
       }
       return false;
 
@@ -561,8 +131,8 @@
   }
 }
 
-// TODO: Refactor DexFileMethodInliner and have something nicer than InlineMethod.
 void IntrinsicsRecognizer::Run() {
+  ScopedObjectAccess soa(Thread::Current());
   for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
     HBasicBlock* block = it.Current();
     for (HInstructionIterator inst_it(block->GetInstructions()); !inst_it.Done();
@@ -570,26 +140,20 @@
       HInstruction* inst = inst_it.Current();
       if (inst->IsInvoke()) {
         HInvoke* invoke = inst->AsInvoke();
-        InlineMethod method;
-        const DexFile& dex_file = invoke->GetDexFile();
-        DexFileMethodInliner* inliner = driver_->GetMethodInlinerMap()->GetMethodInliner(&dex_file);
-        DCHECK(inliner != nullptr);
-        if (inliner->IsIntrinsic(invoke->GetDexMethodIndex(), &method)) {
-          Intrinsics intrinsic = GetIntrinsic(method);
-
-          if (intrinsic != Intrinsics::kNone) {
-            if (!CheckInvokeType(intrinsic, invoke, dex_file)) {
-              LOG(WARNING) << "Found an intrinsic with unexpected invoke type: "
-                  << intrinsic << " for "
-                  << PrettyMethod(invoke->GetDexMethodIndex(), invoke->GetDexFile())
-                  << invoke->DebugName();
-            } else {
-              invoke->SetIntrinsic(intrinsic,
-                                   NeedsEnvironmentOrCache(intrinsic),
-                                   GetSideEffects(intrinsic),
-                                   GetExceptions(intrinsic));
-              MaybeRecordStat(MethodCompilationStat::kIntrinsicRecognized);
-            }
+        ArtMethod* art_method = invoke->GetResolvedMethod();
+        if (art_method != nullptr && art_method->IsIntrinsic()) {
+          Intrinsics intrinsic = static_cast<Intrinsics>(art_method->GetIntrinsic());
+          if (!CheckInvokeType(intrinsic, invoke)) {
+            LOG(WARNING) << "Found an intrinsic with unexpected invoke type: "
+                << intrinsic << " for "
+                << PrettyMethod(invoke->GetDexMethodIndex(), invoke->GetDexFile())
+                << invoke->DebugName();
+          } else {
+            invoke->SetIntrinsic(intrinsic,
+                                 NeedsEnvironmentOrCache(intrinsic),
+                                 GetSideEffects(intrinsic),
+                                 GetExceptions(intrinsic));
+            MaybeRecordStat(MethodCompilationStat::kIntrinsicRecognized);
           }
         }
       }
@@ -602,7 +166,7 @@
     case Intrinsics::kNone:
       os << "None";
       break;
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
     case Intrinsics::k ## Name: \
       os << # Name; \
       break;