static Intrinsics GetIntrinsic()

in compiler/optimizing/intrinsics.cc [124:517]


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:
      // The inliner can handle these two cases - and this is the preferred approach
      // since after inlining the call is no longer visible (as opposed to waiting
      // until codegen to handle intrinsic).
      return Intrinsics::kNone;
    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;
}