171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe/* 271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * Copyright (C) 2015 The Android Open Source Project 371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * 471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * Licensed under the Apache License, Version 2.0 (the "License"); 571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * you may not use this file except in compliance with the License. 671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * You may obtain a copy of the License at 771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * 871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * http://www.apache.org/licenses/LICENSE-2.0 971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * 1071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * Unless required by applicable law or agreed to in writing, software 1171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * distributed under the License is distributed on an "AS IS" BASIS, 1271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * See the License for the specific language governing permissions and 1471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * limitations under the License. 1571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe */ 1671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 1771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "intrinsics.h" 1871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 1971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "dex/quick/dex_file_method_inliner.h" 2071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "dex/quick/dex_file_to_method_inliner_map.h" 2171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "driver/compiler_driver.h" 2271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "invoke_type.h" 2371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "nodes.h" 2471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "quick/inline_method_analyser.h" 2541b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko#include "utils.h" 2671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 2771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampenamespace art { 2871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 2971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe// Function that returns whether an intrinsic is static/direct or virtual. 3071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampestatic inline InvokeType GetIntrinsicInvokeType(Intrinsics i) { 3171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (i) { 3271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case Intrinsics::kNone: 3371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return kInterface; // Non-sensical for intrinsic. 3471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#define OPTIMIZING_INTRINSICS(Name, IsStatic) \ 3571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case Intrinsics::k ## Name: \ 3671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return IsStatic; 3771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "intrinsics_list.h" 3871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas GampeINTRINSICS_LIST(OPTIMIZING_INTRINSICS) 3971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef INTRINSICS_LIST 4071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef OPTIMIZING_INTRINSICS 4171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 4271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return kInterface; 4371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe} 4471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 4571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 4671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 4771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampestatic Primitive::Type GetType(uint64_t data, bool is_op_size) { 4871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe if (is_op_size) { 4971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (static_cast<OpSize>(data)) { 5071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kSignedByte: 51878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe return Primitive::kPrimByte; 5271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kSignedHalf: 53878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe return Primitive::kPrimShort; 5471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case k32: 55878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe return Primitive::kPrimInt; 5671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case k64: 57878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe return Primitive::kPrimLong; 5871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe default: 5971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe LOG(FATAL) << "Unknown/unsupported op size " << data; 6071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe UNREACHABLE(); 6171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 6271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } else { 6371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe if ((data & kIntrinsicFlagIsLong) != 0) { 64878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe return Primitive::kPrimLong; 6571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 6671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe if ((data & kIntrinsicFlagIsObject) != 0) { 67878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe return Primitive::kPrimNot; 6871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 69878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe return Primitive::kPrimInt; 7071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 7171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe} 7271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 7371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampestatic Intrinsics GetIntrinsic(InlineMethod method) { 7471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (method.opcode) { 7571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Floating-point conversions. 7671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicDoubleCvt: 7771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return ((method.d.data & kIntrinsicFlagToFloatingPoint) == 0) ? 7871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe Intrinsics::kDoubleDoubleToRawLongBits : Intrinsics::kDoubleLongBitsToDouble; 7971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicFloatCvt: 8071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return ((method.d.data & kIntrinsicFlagToFloatingPoint) == 0) ? 8171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe Intrinsics::kFloatFloatToRawIntBits : Intrinsics::kFloatIntBitsToFloat; 8271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 8371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Bit manipulations. 8471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicReverseBits: 8571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (GetType(method.d.data, true)) { 86878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimInt: 8771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kIntegerReverse; 88878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimLong: 8971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kLongReverse; 9071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe default: 9171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe LOG(FATAL) << "Unknown/unsupported op size " << method.d.data; 9271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe UNREACHABLE(); 9371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 9471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicReverseBytes: 9571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (GetType(method.d.data, true)) { 96878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimShort: 9771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kShortReverseBytes; 98878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimInt: 9971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kIntegerReverseBytes; 100878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimLong: 10171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kLongReverseBytes; 10271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe default: 10371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe LOG(FATAL) << "Unknown/unsupported op size " << method.d.data; 10471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe UNREACHABLE(); 10571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 10671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 10771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Abs. 10871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicAbsDouble: 10971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMathAbsDouble; 11071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicAbsFloat: 11171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMathAbsFloat; 11271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicAbsInt: 11371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMathAbsInt; 11471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicAbsLong: 11571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMathAbsLong; 11671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 11771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Min/max. 11871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicMinMaxDouble: 11971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return ((method.d.data & kIntrinsicFlagMin) == 0) ? 12071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe Intrinsics::kMathMaxDoubleDouble : Intrinsics::kMathMinDoubleDouble; 12171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicMinMaxFloat: 12271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return ((method.d.data & kIntrinsicFlagMin) == 0) ? 12371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe Intrinsics::kMathMaxFloatFloat : Intrinsics::kMathMinFloatFloat; 12471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicMinMaxInt: 12571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return ((method.d.data & kIntrinsicFlagMin) == 0) ? 12671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe Intrinsics::kMathMaxIntInt : Intrinsics::kMathMinIntInt; 12771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicMinMaxLong: 12871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return ((method.d.data & kIntrinsicFlagMin) == 0) ? 12971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe Intrinsics::kMathMaxLongLong : Intrinsics::kMathMinLongLong; 13071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 13171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Misc math. 13271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicSqrt: 13371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMathSqrt; 13471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicCeil: 13571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMathCeil; 13671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicFloor: 13771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMathFloor; 13871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicRint: 13971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMathRint; 14071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicRoundDouble: 14171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMathRoundDouble; 14271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicRoundFloat: 14371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMathRoundFloat; 14471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 14571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // System.arraycopy. 14671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicSystemArrayCopyCharArray: 14771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kSystemArrayCopyChar; 14871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 14971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Thread.currentThread. 15071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicCurrentThread: 15171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kThreadCurrentThread; 15271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 15371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Memory.peek. 15471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicPeek: 15571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (GetType(method.d.data, true)) { 156878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimByte: 15771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMemoryPeekByte; 158878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimShort: 15971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMemoryPeekShortNative; 160878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimInt: 16171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMemoryPeekIntNative; 162878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimLong: 16371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMemoryPeekLongNative; 16471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe default: 16571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe LOG(FATAL) << "Unknown/unsupported op size " << method.d.data; 16671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe UNREACHABLE(); 16771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 16871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 16971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Memory.poke. 17071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicPoke: 17171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (GetType(method.d.data, true)) { 172878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimByte: 17371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMemoryPokeByte; 174878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimShort: 17571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMemoryPokeShortNative; 176878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimInt: 17771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMemoryPokeIntNative; 178878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimLong: 17971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kMemoryPokeLongNative; 18071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe default: 18171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe LOG(FATAL) << "Unknown/unsupported op size " << method.d.data; 18271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe UNREACHABLE(); 18371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 18471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 18571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // String. 18671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicCharAt: 18771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kStringCharAt; 18871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicCompareTo: 18971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kStringCompareTo; 190848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao case kIntrinsicGetCharsNoCheck: 191848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao return Intrinsics::kStringGetCharsNoCheck; 19271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicIsEmptyOrLength: 1933e90a96f403cbc353731e6687fe12a088f996ceeRazvan A Lupusoru // The inliner can handle these two cases - and this is the preferred approach 1943e90a96f403cbc353731e6687fe12a088f996ceeRazvan A Lupusoru // since after inlining the call is no longer visible (as opposed to waiting 1953e90a96f403cbc353731e6687fe12a088f996ceeRazvan A Lupusoru // until codegen to handle intrinsic). 1963e90a96f403cbc353731e6687fe12a088f996ceeRazvan A Lupusoru return Intrinsics::kNone; 19771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicIndexOf: 19871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return ((method.d.data & kIntrinsicFlagBase0) == 0) ? 19971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe Intrinsics::kStringIndexOfAfter : Intrinsics::kStringIndexOf; 200848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao case kIntrinsicNewStringFromBytes: 201848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao return Intrinsics::kStringNewStringFromBytes; 202848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao case kIntrinsicNewStringFromChars: 203848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao return Intrinsics::kStringNewStringFromChars; 204848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao case kIntrinsicNewStringFromString: 205848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao return Intrinsics::kStringNewStringFromString; 20671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 20771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicCas: 20871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (GetType(method.d.data, false)) { 209878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimNot: 21071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kUnsafeCASObject; 211878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimInt: 21271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kUnsafeCASInt; 213878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimLong: 21471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kUnsafeCASLong; 21571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe default: 21671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe LOG(FATAL) << "Unknown/unsupported op size " << method.d.data; 21771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe UNREACHABLE(); 21871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 21971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicUnsafeGet: { 22071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe const bool is_volatile = (method.d.data & kIntrinsicFlagIsVolatile); 22171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (GetType(method.d.data, false)) { 222878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimInt: 22371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return is_volatile ? Intrinsics::kUnsafeGetVolatile : Intrinsics::kUnsafeGet; 224878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimLong: 22571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return is_volatile ? Intrinsics::kUnsafeGetLongVolatile : Intrinsics::kUnsafeGetLong; 226878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimNot: 227878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe return is_volatile ? Intrinsics::kUnsafeGetObjectVolatile : Intrinsics::kUnsafeGetObject; 22871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe default: 22971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe LOG(FATAL) << "Unknown/unsupported op size " << method.d.data; 23071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe UNREACHABLE(); 23171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 23271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 23371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicUnsafePut: { 23471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe enum Sync { kNoSync, kVolatile, kOrdered }; 23571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe const Sync sync = 23671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe ((method.d.data & kIntrinsicFlagIsVolatile) != 0) ? kVolatile : 23771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe ((method.d.data & kIntrinsicFlagIsOrdered) != 0) ? kOrdered : 23871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe kNoSync; 23971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (GetType(method.d.data, false)) { 240878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimInt: 24171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (sync) { 24271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kNoSync: 24371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kUnsafePut; 24471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kVolatile: 24571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kUnsafePutVolatile; 24671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kOrdered: 24771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kUnsafePutOrdered; 24871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 24971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe break; 250878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimLong: 25171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (sync) { 25271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kNoSync: 25371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kUnsafePutLong; 25471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kVolatile: 25571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kUnsafePutLongVolatile; 25671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kOrdered: 25771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kUnsafePutLongOrdered; 25871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 25971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe break; 260878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe case Primitive::kPrimNot: 26171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (sync) { 26271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kNoSync: 26371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kUnsafePutObject; 26471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kVolatile: 26571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kUnsafePutObjectVolatile; 26671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kOrdered: 26771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kUnsafePutObjectOrdered; 26871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 26971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe break; 27071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe default: 27171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe LOG(FATAL) << "Unknown/unsupported op size " << method.d.data; 27271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe UNREACHABLE(); 27371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 27471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe break; 27571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 27671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 27771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Virtual cases. 27871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 27971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kIntrinsicReferenceGetReferent: 28071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kReferenceGetReferent; 28171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 28271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Quick inliner cases. Remove after refactoring. They are here so that we can use the 28371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // compiler to warn on missing cases. 28471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 28571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kInlineOpNop: 28671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kInlineOpReturnArg: 28771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kInlineOpNonWideConst: 28871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kInlineOpIGet: 28971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kInlineOpIPut: 29071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kNone; 29171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 292848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao // String init cases, not intrinsics. 293848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao 294848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao case kInlineStringInit: 295848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao return Intrinsics::kNone; 296848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao 29771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // No default case to make the compiler warn on missing cases. 29871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 29971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return Intrinsics::kNone; 30071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe} 30171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 30271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampestatic bool CheckInvokeType(Intrinsics intrinsic, HInvoke* invoke) { 30371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // The DexFileMethodInliner should have checked whether the methods are agreeing with 30471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // what we expect, i.e., static methods are called as such. Add another check here for 30571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // our expectations: 30671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Whenever the intrinsic is marked as static-or-direct, report an error if we find an 30771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // InvokeVirtual. The other direction is not possible: we have intrinsics for virtual 30871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // functions that will perform a check inline. If the precise type is known, however, 30971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // the instruction will be sharpened to an InvokeStaticOrDirect. 31071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe InvokeType intrinsic_type = GetIntrinsicInvokeType(intrinsic); 31171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe InvokeType invoke_type = invoke->IsInvokeStaticOrDirect() ? 31271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe invoke->AsInvokeStaticOrDirect()->GetInvokeType() : 31371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe invoke->IsInvokeVirtual() ? kVirtual : kSuper; 31471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (intrinsic_type) { 31571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kStatic: 31671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return (invoke_type == kStatic); 31771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kDirect: 31871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return (invoke_type == kDirect); 31971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case kVirtual: 32071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Call might be devirtualized. 32171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return (invoke_type == kVirtual || invoke_type == kDirect); 32271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 32371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe default: 32471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return false; 32571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 32671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe} 32771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 32871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe// TODO: Refactor DexFileMethodInliner and have something nicer than InlineMethod. 32971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampevoid IntrinsicsRecognizer::Run() { 33071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe DexFileMethodInliner* inliner = driver_->GetMethodInlinerMap()->GetMethodInliner(dex_file_); 33171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe DCHECK(inliner != nullptr); 33271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 33371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) { 33471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe HBasicBlock* block = it.Current(); 33571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe for (HInstructionIterator inst_it(block->GetInstructions()); !inst_it.Done(); 33671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe inst_it.Advance()) { 33771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe HInstruction* inst = inst_it.Current(); 33871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe if (inst->IsInvoke()) { 33971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe HInvoke* invoke = inst->AsInvoke(); 34071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe InlineMethod method; 34171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe if (inliner->IsIntrinsic(invoke->GetDexMethodIndex(), &method)) { 34271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe Intrinsics intrinsic = GetIntrinsic(method); 34371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 34471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe if (intrinsic != Intrinsics::kNone) { 34571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe if (!CheckInvokeType(intrinsic, invoke)) { 34671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe LOG(WARNING) << "Found an intrinsic with unexpected invoke type: " 34771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe << intrinsic << " for " 34871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe << PrettyMethod(invoke->GetDexMethodIndex(), *dex_file_); 34971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } else { 35071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe invoke->SetIntrinsic(intrinsic); 35171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 35271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 35371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 35471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 35571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 35671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 35771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe} 35871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 35971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampestd::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic) { 36071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (intrinsic) { 36171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case Intrinsics::kNone: 36271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe os << "No intrinsic."; 36371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe break; 36471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#define OPTIMIZING_INTRINSICS(Name, IsStatic) \ 36571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case Intrinsics::k ## Name: \ 36671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe os << # Name; \ 36771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe break; 36871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "intrinsics_list.h" 36971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas GampeINTRINSICS_LIST(OPTIMIZING_INTRINSICS) 37071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef STATIC_INTRINSICS_LIST 37171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef VIRTUAL_INTRINSICS_LIST 37271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef OPTIMIZING_INTRINSICS 37371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 37471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return os; 37571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe} 37671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 37771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe} // namespace art 378