- 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
"dex/verified_method.cc",
"dex/verification_results.cc",
"dex/quick_compiler_callbacks.cc",
- "dex/quick/dex_file_method_inliner.cc",
- "dex/quick/dex_file_to_method_inliner_map.cc",
"driver/compiled_method_storage.cc",
"driver/compiler_driver.cc",
"driver/compiler_options.cc",
#include "class_linker.h"
#include "compiled_method.h"
#include "dex/quick_compiler_callbacks.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "dex/verification_results.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
size_t number_of_threads) {
compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
verification_results_.get(),
- method_inliner_map_.get(),
kind,
isa,
instruction_set_features_.get(),
compiler_options_.reset(new CompilerOptions);
verification_results_.reset(new VerificationResults(compiler_options_.get()));
- method_inliner_map_.reset(new DexFileToMethodInlinerMap);
callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
- method_inliner_map_.get(),
CompilerCallbacks::CallbackMode::kCompileApp));
}
timer_.reset();
compiler_driver_.reset();
callbacks_.reset();
- method_inliner_map_.reset();
verification_results_.reset();
compiler_options_.reset();
image_reservation_.reset();
class CompilerDriver;
class CompilerOptions;
class CumulativeLogger;
-class DexFileToMethodInlinerMap;
class VerificationResults;
template<class T> class Handle;
Compiler::Kind compiler_kind_ = Compiler::kOptimizing;
std::unique_ptr<CompilerOptions> compiler_options_;
std::unique_ptr<VerificationResults> verification_results_;
- std::unique_ptr<DexFileToMethodInlinerMap> method_inliner_map_;
std::unique_ptr<CompilerDriver> compiler_driver_;
std::unique_ptr<CumulativeLogger> timer_;
std::unique_ptr<const InstructionSetFeatures> instruction_set_features_;
+++ /dev/null
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "dex_file_method_inliner.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/mutex-inl.h"
-#include "driver/compiler_driver.h"
-#include "thread-inl.h"
-#include "dex_instruction-inl.h"
-#include "driver/dex_compilation_unit.h"
-#include "verifier/method_verifier-inl.h"
-
-namespace art {
-
-namespace { // anonymous namespace
-
-static constexpr bool kIntrinsicIsStatic[] = {
- true, // kIntrinsicDoubleCvt
- true, // kIntrinsicFloatCvt
- true, // kIntrinsicFloat2Int
- true, // kIntrinsicDouble2Long
- true, // kIntrinsicFloatIsInfinite
- true, // kIntrinsicDoubleIsInfinite
- true, // kIntrinsicFloatIsNaN
- true, // kIntrinsicDoubleIsNaN
- true, // kIntrinsicReverseBits
- true, // kIntrinsicReverseBytes
- true, // kIntrinsicBitCount
- true, // kIntrinsicCompare,
- true, // kIntrinsicHighestOneBit
- true, // kIntrinsicLowestOneBit
- true, // kIntrinsicNumberOfLeadingZeros
- true, // kIntrinsicNumberOfTrailingZeros
- true, // kIntrinsicRotateRight
- true, // kIntrinsicRotateLeft
- true, // kIntrinsicSignum
- true, // kIntrinsicAbsInt
- true, // kIntrinsicAbsLong
- true, // kIntrinsicAbsFloat
- true, // kIntrinsicAbsDouble
- true, // kIntrinsicMinMaxInt
- true, // kIntrinsicMinMaxLong
- true, // kIntrinsicMinMaxFloat
- true, // kIntrinsicMinMaxDouble
- true, // kIntrinsicCos
- true, // kIntrinsicSin
- true, // kIntrinsicAcos
- true, // kIntrinsicAsin
- true, // kIntrinsicAtan
- true, // kIntrinsicAtan2
- true, // kIntrinsicCbrt
- true, // kIntrinsicCosh
- true, // kIntrinsicExp
- true, // kIntrinsicExpm1
- true, // kIntrinsicHypot
- true, // kIntrinsicLog
- true, // kIntrinsicLog10
- true, // kIntrinsicNextAfter
- true, // kIntrinsicSinh
- true, // kIntrinsicTan
- true, // kIntrinsicTanh
- true, // kIntrinsicSqrt
- true, // kIntrinsicCeil
- true, // kIntrinsicFloor
- true, // kIntrinsicRint
- true, // kIntrinsicRoundFloat
- true, // kIntrinsicRoundDouble
- false, // kIntrinsicReferenceGetReferent
- false, // kIntrinsicCharAt
- false, // kIntrinsicCompareTo
- false, // kIntrinsicEquals
- false, // kIntrinsicGetCharsNoCheck
- false, // kIntrinsicIsEmptyOrLength
- false, // kIntrinsicIndexOf
- true, // kIntrinsicNewStringFromBytes
- true, // kIntrinsicNewStringFromChars
- true, // kIntrinsicNewStringFromString
- true, // kIntrinsicCurrentThread
- true, // kIntrinsicPeek
- true, // kIntrinsicPoke
- false, // kIntrinsicCas
- false, // kIntrinsicUnsafeGet
- false, // kIntrinsicUnsafePut
- false, // kIntrinsicUnsafeGetAndAddInt,
- false, // kIntrinsicUnsafeGetAndAddLong,
- false, // kIntrinsicUnsafeGetAndSetInt,
- false, // kIntrinsicUnsafeGetAndSetLong,
- false, // kIntrinsicUnsafeGetAndSetObject,
- false, // kIntrinsicUnsafeLoadFence,
- false, // kIntrinsicUnsafeStoreFence,
- false, // kIntrinsicUnsafeFullFence,
- true, // kIntrinsicSystemArrayCopyCharArray
- true, // kIntrinsicSystemArrayCopy
-};
-static_assert(arraysize(kIntrinsicIsStatic) == kInlineOpNop,
- "arraysize of kIntrinsicIsStatic unexpected");
-static_assert(kIntrinsicIsStatic[kIntrinsicDoubleCvt], "DoubleCvt must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicFloatCvt], "FloatCvt must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicFloat2Int], "Float2Int must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicDouble2Long], "Double2Long must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicFloatIsInfinite], "FloatIsInfinite must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicDoubleIsInfinite], "DoubleIsInfinite must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicFloatIsNaN], "FloatIsNaN must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicDoubleIsNaN], "DoubleIsNaN must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicReverseBits], "ReverseBits must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicReverseBytes], "ReverseBytes must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicBitCount], "BitCount must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicCompare], "Compare must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicHighestOneBit], "HighestOneBit must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicLowestOneBit], "LowestOneBit must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicNumberOfLeadingZeros],
- "NumberOfLeadingZeros must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicNumberOfTrailingZeros],
- "NumberOfTrailingZeros must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicRotateRight], "RotateRight must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicRotateLeft], "RotateLeft must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicSignum], "Signum must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicAbsInt], "AbsInt must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicAbsLong], "AbsLong must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicAbsFloat], "AbsFloat must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicAbsDouble], "AbsDouble must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicMinMaxInt], "MinMaxInt must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicMinMaxLong], "MinMaxLong must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicMinMaxFloat], "MinMaxFloat must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicMinMaxDouble], "MinMaxDouble must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicCos], "Cos must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicSin], "Sin must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicAcos], "Acos must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicAsin], "Asin must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicAtan], "Atan must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicAtan2], "Atan2 must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicCbrt], "Cbrt must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicCosh], "Cosh must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicExp], "Exp must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicExpm1], "Expm1 must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicHypot], "Hypot must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicLog], "Log must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicLog10], "Log10 must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicNextAfter], "NextAfter must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicSinh], "Sinh must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicTan], "Tan must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicTanh], "Tanh must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicSqrt], "Sqrt must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicCeil], "Ceil must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicFloor], "Floor must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicRint], "Rint must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicRoundFloat], "RoundFloat must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicRoundDouble], "RoundDouble must be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicReferenceGetReferent], "Get must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicCharAt], "CharAt must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicCompareTo], "CompareTo must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicEquals], "String equals must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicGetCharsNoCheck], "GetCharsNoCheck must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicIsEmptyOrLength], "IsEmptyOrLength must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicIndexOf], "IndexOf must not be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicNewStringFromBytes],
- "NewStringFromBytes must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicNewStringFromChars],
- "NewStringFromChars must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicNewStringFromString],
- "NewStringFromString must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicCurrentThread], "CurrentThread must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicPeek], "Peek must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicPoke], "Poke must be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicCas], "Cas must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGet], "UnsafeGet must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafePut], "UnsafePut must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndAddInt], "UnsafeGetAndAddInt must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndAddLong], "UnsafeGetAndAddLong must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndSetInt], "UnsafeGetAndSetInt must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndSetLong], "UnsafeGetAndSetLong must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndSetObject], "UnsafeGetAndSetObject must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeLoadFence], "UnsafeLoadFence must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeStoreFence], "UnsafeStoreFence must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeFullFence], "UnsafeFullFence must not be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicSystemArrayCopyCharArray],
- "SystemArrayCopyCharArray must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicSystemArrayCopy],
- "SystemArrayCopy must be static");
-
-} // anonymous namespace
-
-const uint32_t DexFileMethodInliner::kIndexUnresolved;
-const char* const DexFileMethodInliner::kClassCacheNames[] = {
- "Z", // kClassCacheBoolean
- "B", // kClassCacheByte
- "C", // kClassCacheChar
- "S", // kClassCacheShort
- "I", // kClassCacheInt
- "J", // kClassCacheLong
- "F", // kClassCacheFloat
- "D", // kClassCacheDouble
- "V", // kClassCacheVoid
- "[B", // kClassCacheJavaLangByteArray
- "[C", // kClassCacheJavaLangCharArray
- "[I", // kClassCacheJavaLangIntArray
- "Ljava/lang/Object;", // kClassCacheJavaLangObject
- "Ljava/lang/ref/Reference;", // kClassCacheJavaLangRefReference
- "Ljava/lang/String;", // kClassCacheJavaLangString
- "Ljava/lang/StringBuffer;", // kClassCacheJavaLangStringBuffer
- "Ljava/lang/StringBuilder;", // kClassCacheJavaLangStringBuilder
- "Ljava/lang/StringFactory;", // kClassCacheJavaLangStringFactory
- "Ljava/lang/Double;", // kClassCacheJavaLangDouble
- "Ljava/lang/Float;", // kClassCacheJavaLangFloat
- "Ljava/lang/Integer;", // kClassCacheJavaLangInteger
- "Ljava/lang/Long;", // kClassCacheJavaLangLong
- "Ljava/lang/Short;", // kClassCacheJavaLangShort
- "Ljava/lang/Math;", // kClassCacheJavaLangMath
- "Ljava/lang/StrictMath;", // kClassCacheJavaLangStrictMath
- "Ljava/lang/Thread;", // kClassCacheJavaLangThread
- "Ljava/nio/charset/Charset;", // kClassCacheJavaNioCharsetCharset
- "Llibcore/io/Memory;", // kClassCacheLibcoreIoMemory
- "Lsun/misc/Unsafe;", // kClassCacheSunMiscUnsafe
- "Ljava/lang/System;", // kClassCacheJavaLangSystem
-};
-
-const char* const DexFileMethodInliner::kNameCacheNames[] = {
- "reverse", // kNameCacheReverse
- "reverseBytes", // kNameCacheReverseBytes
- "doubleToRawLongBits", // kNameCacheDoubleToRawLongBits
- "longBitsToDouble", // kNameCacheLongBitsToDouble
- "floatToRawIntBits", // kNameCacheFloatToRawIntBits
- "intBitsToFloat", // kNameCacheIntBitsToFloat
- "abs", // kNameCacheAbs
- "max", // kNameCacheMax
- "min", // kNameCacheMin
- "cos", // kNameCacheCos
- "sin", // kNameCacheSin
- "acos", // kNameCacheAcos
- "asin", // kNameCacheAsin
- "atan", // kNameCacheAtan
- "atan2", // kNameCacheAtan2
- "cbrt", // kNameCacheCbrt
- "cosh", // kNameCacheCosh
- "exp", // kNameCacheExp
- "expm1", // kNameCacheExpm1
- "hypot", // kNameCacheHypot
- "log", // kNameCacheLog
- "log10", // kNameCacheLog10
- "nextAfter", // kNameCacheNextAfter
- "sinh", // kNameCacheSinh
- "tan", // kNameCacheTan
- "tanh", // kNameCacheTanh
- "sqrt", // kNameCacheSqrt
- "ceil", // kNameCacheCeil
- "floor", // kNameCacheFloor
- "rint", // kNameCacheRint
- "round", // kNameCacheRound
- "getReferent", // kNameCacheReferenceGet
- "charAt", // kNameCacheCharAt
- "compareTo", // kNameCacheCompareTo
- "equals", // kNameCacheEquals
- "getCharsNoCheck", // kNameCacheGetCharsNoCheck
- "isEmpty", // kNameCacheIsEmpty
- "floatToIntBits", // kNameCacheFloatToIntBits
- "doubleToLongBits", // kNameCacheDoubleToLongBits
- "isInfinite", // kNameCacheIsInfinite
- "isNaN", // kNameCacheIsNaN
- "indexOf", // kNameCacheIndexOf
- "length", // kNameCacheLength
- "<init>", // kNameCacheInit
- "newStringFromBytes", // kNameCacheNewStringFromBytes
- "newStringFromChars", // kNameCacheNewStringFromChars
- "newStringFromString", // kNameCacheNewStringFromString
- "currentThread", // kNameCacheCurrentThread
- "peekByte", // kNameCachePeekByte
- "peekIntNative", // kNameCachePeekIntNative
- "peekLongNative", // kNameCachePeekLongNative
- "peekShortNative", // kNameCachePeekShortNative
- "pokeByte", // kNameCachePokeByte
- "pokeIntNative", // kNameCachePokeIntNative
- "pokeLongNative", // kNameCachePokeLongNative
- "pokeShortNative", // kNameCachePokeShortNative
- "compareAndSwapInt", // kNameCacheCompareAndSwapInt
- "compareAndSwapLong", // kNameCacheCompareAndSwapLong
- "compareAndSwapObject", // kNameCacheCompareAndSwapObject
- "getInt", // kNameCacheGetInt
- "getIntVolatile", // kNameCacheGetIntVolatile
- "putInt", // kNameCachePutInt
- "putIntVolatile", // kNameCachePutIntVolatile
- "putOrderedInt", // kNameCachePutOrderedInt
- "getLong", // kNameCacheGetLong
- "getLongVolatile", // kNameCacheGetLongVolatile
- "putLong", // kNameCachePutLong
- "putLongVolatile", // kNameCachePutLongVolatile
- "putOrderedLong", // kNameCachePutOrderedLong
- "getObject", // kNameCacheGetObject
- "getObjectVolatile", // kNameCacheGetObjectVolatile
- "putObject", // kNameCachePutObject
- "putObjectVolatile", // kNameCachePutObjectVolatile
- "putOrderedObject", // kNameCachePutOrderedObject
- "getAndAddInt", // kNameCacheGetAndAddInt,
- "getAndAddLong", // kNameCacheGetAndAddLong,
- "getAndSetInt", // kNameCacheGetAndSetInt,
- "getAndSetLong", // kNameCacheGetAndSetLong,
- "getAndSetObject", // kNameCacheGetAndSetObject,
- "loadFence", // kNameCacheLoadFence,
- "storeFence", // kNameCacheStoreFence,
- "fullFence", // kNameCacheFullFence,
- "arraycopy", // kNameCacheArrayCopy
- "bitCount", // kNameCacheBitCount
- "compare", // kNameCacheCompare
- "highestOneBit", // kNameCacheHighestOneBit
- "lowestOneBit", // kNameCacheLowestOneBit
- "numberOfLeadingZeros", // kNameCacheNumberOfLeadingZeros
- "numberOfTrailingZeros", // kNameCacheNumberOfTrailingZeros
- "rotateRight", // kNameCacheRotateRight
- "rotateLeft", // kNameCacheRotateLeft
- "signum", // kNameCacheSignum
-};
-
-const DexFileMethodInliner::ProtoDef DexFileMethodInliner::kProtoCacheDefs[] = {
- // kProtoCacheI_I
- { kClassCacheInt, 1, { kClassCacheInt } },
- // kProtoCacheJ_J
- { kClassCacheLong, 1, { kClassCacheLong } },
- // kProtoCacheS_S
- { kClassCacheShort, 1, { kClassCacheShort } },
- // kProtoCacheD_D
- { kClassCacheDouble, 1, { kClassCacheDouble } },
- // kProtoCacheDD_D
- { kClassCacheDouble, 2, { kClassCacheDouble, kClassCacheDouble } },
- // kProtoCacheF_F
- { kClassCacheFloat, 1, { kClassCacheFloat } },
- // kProtoCacheFF_F
- { kClassCacheFloat, 2, { kClassCacheFloat, kClassCacheFloat } },
- // kProtoCacheD_J
- { kClassCacheLong, 1, { kClassCacheDouble } },
- // kProtoCacheD_Z
- { kClassCacheBoolean, 1, { kClassCacheDouble } },
- // kProtoCacheJ_D
- { kClassCacheDouble, 1, { kClassCacheLong } },
- // kProtoCacheF_I
- { kClassCacheInt, 1, { kClassCacheFloat } },
- // kProtoCacheF_Z
- { kClassCacheBoolean, 1, { kClassCacheFloat } },
- // kProtoCacheI_F
- { kClassCacheFloat, 1, { kClassCacheInt } },
- // kProtoCacheII_I
- { kClassCacheInt, 2, { kClassCacheInt, kClassCacheInt } },
- // kProtoCacheI_C
- { kClassCacheChar, 1, { kClassCacheInt } },
- // kProtoCacheString_I
- { kClassCacheInt, 1, { kClassCacheJavaLangString } },
- // kProtoCache_Z
- { kClassCacheBoolean, 0, { } },
- // kProtoCache_I
- { kClassCacheInt, 0, { } },
- // kProtoCache_Object
- { kClassCacheJavaLangObject, 0, { } },
- // kProtoCache_Thread
- { kClassCacheJavaLangThread, 0, { } },
- // kProtoCacheJ_B
- { kClassCacheByte, 1, { kClassCacheLong } },
- // kProtoCacheJ_I
- { kClassCacheInt, 1, { kClassCacheLong } },
- // kProtoCacheJ_S
- { kClassCacheShort, 1, { kClassCacheLong } },
- // kProtoCacheJB_V
- { kClassCacheVoid, 2, { kClassCacheLong, kClassCacheByte } },
- // kProtoCacheJI_V
- { kClassCacheVoid, 2, { kClassCacheLong, kClassCacheInt } },
- // kProtoCacheJJ_J
- { kClassCacheLong, 2, { kClassCacheLong, kClassCacheLong } },
- // kProtoCacheJJ_I
- { kClassCacheInt, 2, { kClassCacheLong, kClassCacheLong } },
- // kProtoCacheJJ_V
- { kClassCacheVoid, 2, { kClassCacheLong, kClassCacheLong } },
- // kProtoCacheJS_V
- { kClassCacheVoid, 2, { kClassCacheLong, kClassCacheShort } },
- // kProtoCacheObject_Z
- { kClassCacheBoolean, 1, { kClassCacheJavaLangObject } },
- // kProtoCacheJI_J
- { kClassCacheLong, 2, { kClassCacheLong, kClassCacheInt } },
- // kProtoCacheObjectJII_Z
- { kClassCacheBoolean, 4, { kClassCacheJavaLangObject, kClassCacheLong,
- kClassCacheInt, kClassCacheInt } },
- // kProtoCacheObjectJJJ_Z
- { kClassCacheBoolean, 4, { kClassCacheJavaLangObject, kClassCacheLong,
- kClassCacheLong, kClassCacheLong } },
- // kProtoCacheObjectJObjectObject_Z
- { kClassCacheBoolean, 4, { kClassCacheJavaLangObject, kClassCacheLong,
- kClassCacheJavaLangObject, kClassCacheJavaLangObject } },
- // kProtoCacheObjectJ_I
- { kClassCacheInt, 2, { kClassCacheJavaLangObject, kClassCacheLong } },
- // kProtoCacheObjectJI_I
- { kClassCacheInt, 3, { kClassCacheJavaLangObject, kClassCacheLong, kClassCacheInt } },
- // kProtoCacheObjectJI_V
- { kClassCacheVoid, 3, { kClassCacheJavaLangObject, kClassCacheLong, kClassCacheInt } },
- // kProtoCacheObjectJ_J
- { kClassCacheLong, 2, { kClassCacheJavaLangObject, kClassCacheLong } },
- // kProtoCacheObjectJJ_J
- { kClassCacheLong, 3, { kClassCacheJavaLangObject, kClassCacheLong, kClassCacheLong } },
- // kProtoCacheObjectJJ_V
- { kClassCacheVoid, 3, { kClassCacheJavaLangObject, kClassCacheLong, kClassCacheLong } },
- // kProtoCacheObjectJ_Object
- { kClassCacheJavaLangObject, 2, { kClassCacheJavaLangObject, kClassCacheLong } },
- // kProtoCacheObjectJObject_V
- { kClassCacheVoid, 3, { kClassCacheJavaLangObject, kClassCacheLong,
- kClassCacheJavaLangObject } },
- // kProtoCacheObjectJObject_Object
- { kClassCacheJavaLangObject, 3, { kClassCacheJavaLangObject, kClassCacheLong,
- kClassCacheJavaLangObject } },
- // kProtoCacheCharArrayICharArrayII_V
- { kClassCacheVoid, 5, {kClassCacheJavaLangCharArray, kClassCacheInt,
- kClassCacheJavaLangCharArray, kClassCacheInt, kClassCacheInt} },
- // kProtoCacheObjectIObjectII_V
- { kClassCacheVoid, 5, {kClassCacheJavaLangObject, kClassCacheInt,
- kClassCacheJavaLangObject, kClassCacheInt, kClassCacheInt} },
- // kProtoCacheIICharArrayI_V
- { kClassCacheVoid, 4, { kClassCacheInt, kClassCacheInt, kClassCacheJavaLangCharArray,
- kClassCacheInt } },
- // kProtoCacheByteArrayIII_String
- { kClassCacheJavaLangString, 4, { kClassCacheJavaLangByteArray, kClassCacheInt, kClassCacheInt,
- kClassCacheInt } },
- // kProtoCacheIICharArray_String
- { kClassCacheJavaLangString, 3, { kClassCacheInt, kClassCacheInt,
- kClassCacheJavaLangCharArray } },
- // kProtoCacheString_String
- { kClassCacheJavaLangString, 1, { kClassCacheJavaLangString } },
- // kProtoCache_V
- { kClassCacheVoid, 0, { } },
- // kProtoCacheByteArray_V
- { kClassCacheVoid, 1, { kClassCacheJavaLangByteArray } },
- // kProtoCacheByteArrayI_V
- { kClassCacheVoid, 2, { kClassCacheJavaLangByteArray, kClassCacheInt } },
- // kProtoCacheByteArrayII_V
- { kClassCacheVoid, 3, { kClassCacheJavaLangByteArray, kClassCacheInt, kClassCacheInt } },
- // kProtoCacheByteArrayIII_V
- { kClassCacheVoid, 4, { kClassCacheJavaLangByteArray, kClassCacheInt, kClassCacheInt,
- kClassCacheInt } },
- // kProtoCacheByteArrayIIString_V
- { kClassCacheVoid, 4, { kClassCacheJavaLangByteArray, kClassCacheInt, kClassCacheInt,
- kClassCacheJavaLangString } },
- // kProtoCacheByteArrayString_V
- { kClassCacheVoid, 2, { kClassCacheJavaLangByteArray, kClassCacheJavaLangString } },
- // kProtoCacheByteArrayIICharset_V
- { kClassCacheVoid, 4, { kClassCacheJavaLangByteArray, kClassCacheInt, kClassCacheInt,
- kClassCacheJavaNioCharsetCharset } },
- // kProtoCacheByteArrayCharset_V
- { kClassCacheVoid, 2, { kClassCacheJavaLangByteArray, kClassCacheJavaNioCharsetCharset } },
- // kProtoCacheCharArray_V
- { kClassCacheVoid, 1, { kClassCacheJavaLangCharArray } },
- // kProtoCacheCharArrayII_V
- { kClassCacheVoid, 3, { kClassCacheJavaLangCharArray, kClassCacheInt, kClassCacheInt } },
- // kProtoCacheIICharArray_V
- { kClassCacheVoid, 3, { kClassCacheInt, kClassCacheInt, kClassCacheJavaLangCharArray } },
- // kProtoCacheIntArrayII_V
- { kClassCacheVoid, 3, { kClassCacheJavaLangIntArray, kClassCacheInt, kClassCacheInt } },
- // kProtoCacheString_V
- { kClassCacheVoid, 1, { kClassCacheJavaLangString } },
- // kProtoCacheStringBuffer_V
- { kClassCacheVoid, 1, { kClassCacheJavaLangStringBuffer } },
- // kProtoCacheStringBuilder_V
- { kClassCacheVoid, 1, { kClassCacheJavaLangStringBuilder } },
-};
-
-const DexFileMethodInliner::IntrinsicDef DexFileMethodInliner::kIntrinsicMethods[] = {
-#define INTRINSIC(c, n, p, o, d) \
- { { kClassCache ## c, kNameCache ## n, kProtoCache ## p }, { o, kInlineIntrinsic, { d } } }
-
- INTRINSIC(JavaLangDouble, DoubleToRawLongBits, D_J, kIntrinsicDoubleCvt, 0),
- INTRINSIC(JavaLangDouble, LongBitsToDouble, J_D, kIntrinsicDoubleCvt, kIntrinsicFlagToFloatingPoint),
- INTRINSIC(JavaLangFloat, FloatToRawIntBits, F_I, kIntrinsicFloatCvt, 0),
- INTRINSIC(JavaLangFloat, IntBitsToFloat, I_F, kIntrinsicFloatCvt, kIntrinsicFlagToFloatingPoint),
-
- INTRINSIC(JavaLangFloat, FloatToIntBits, F_I, kIntrinsicFloat2Int, 0),
- INTRINSIC(JavaLangDouble, DoubleToLongBits, D_J, kIntrinsicDouble2Long, 0),
-
- INTRINSIC(JavaLangFloat, IsInfinite, F_Z, kIntrinsicFloatIsInfinite, 0),
- INTRINSIC(JavaLangDouble, IsInfinite, D_Z, kIntrinsicDoubleIsInfinite, 0),
- INTRINSIC(JavaLangFloat, IsNaN, F_Z, kIntrinsicFloatIsNaN, 0),
- INTRINSIC(JavaLangDouble, IsNaN, D_Z, kIntrinsicDoubleIsNaN, 0),
-
- INTRINSIC(JavaLangInteger, ReverseBytes, I_I, kIntrinsicReverseBytes, k32),
- INTRINSIC(JavaLangLong, ReverseBytes, J_J, kIntrinsicReverseBytes, k64),
- INTRINSIC(JavaLangShort, ReverseBytes, S_S, kIntrinsicReverseBytes, kSignedHalf),
- INTRINSIC(JavaLangInteger, Reverse, I_I, kIntrinsicReverseBits, k32),
- INTRINSIC(JavaLangLong, Reverse, J_J, kIntrinsicReverseBits, k64),
-
- INTRINSIC(JavaLangInteger, BitCount, I_I, kIntrinsicBitCount, k32),
- INTRINSIC(JavaLangLong, BitCount, J_I, kIntrinsicBitCount, k64),
- INTRINSIC(JavaLangInteger, Compare, II_I, kIntrinsicCompare, k32),
- INTRINSIC(JavaLangLong, Compare, JJ_I, kIntrinsicCompare, k64),
- INTRINSIC(JavaLangInteger, HighestOneBit, I_I, kIntrinsicHighestOneBit, k32),
- INTRINSIC(JavaLangLong, HighestOneBit, J_J, kIntrinsicHighestOneBit, k64),
- INTRINSIC(JavaLangInteger, LowestOneBit, I_I, kIntrinsicLowestOneBit, k32),
- INTRINSIC(JavaLangLong, LowestOneBit, J_J, kIntrinsicLowestOneBit, k64),
- INTRINSIC(JavaLangInteger, NumberOfLeadingZeros, I_I, kIntrinsicNumberOfLeadingZeros, k32),
- INTRINSIC(JavaLangLong, NumberOfLeadingZeros, J_I, kIntrinsicNumberOfLeadingZeros, k64),
- INTRINSIC(JavaLangInteger, NumberOfTrailingZeros, I_I, kIntrinsicNumberOfTrailingZeros, k32),
- INTRINSIC(JavaLangLong, NumberOfTrailingZeros, J_I, kIntrinsicNumberOfTrailingZeros, k64),
- INTRINSIC(JavaLangInteger, Signum, I_I, kIntrinsicSignum, k32),
- INTRINSIC(JavaLangLong, Signum, J_I, kIntrinsicSignum, k64),
-
- INTRINSIC(JavaLangMath, Abs, I_I, kIntrinsicAbsInt, 0),
- INTRINSIC(JavaLangStrictMath, Abs, I_I, kIntrinsicAbsInt, 0),
- INTRINSIC(JavaLangMath, Abs, J_J, kIntrinsicAbsLong, 0),
- INTRINSIC(JavaLangStrictMath, Abs, J_J, kIntrinsicAbsLong, 0),
- INTRINSIC(JavaLangMath, Abs, F_F, kIntrinsicAbsFloat, 0),
- INTRINSIC(JavaLangStrictMath, Abs, F_F, kIntrinsicAbsFloat, 0),
- INTRINSIC(JavaLangMath, Abs, D_D, kIntrinsicAbsDouble, 0),
- INTRINSIC(JavaLangStrictMath, Abs, D_D, kIntrinsicAbsDouble, 0),
- INTRINSIC(JavaLangMath, Min, II_I, kIntrinsicMinMaxInt, kIntrinsicFlagMin),
- INTRINSIC(JavaLangStrictMath, Min, II_I, kIntrinsicMinMaxInt, kIntrinsicFlagMin),
- INTRINSIC(JavaLangMath, Max, II_I, kIntrinsicMinMaxInt, kIntrinsicFlagMax),
- INTRINSIC(JavaLangStrictMath, Max, II_I, kIntrinsicMinMaxInt, kIntrinsicFlagMax),
- INTRINSIC(JavaLangMath, Min, JJ_J, kIntrinsicMinMaxLong, kIntrinsicFlagMin),
- INTRINSIC(JavaLangStrictMath, Min, JJ_J, kIntrinsicMinMaxLong, kIntrinsicFlagMin),
- INTRINSIC(JavaLangMath, Max, JJ_J, kIntrinsicMinMaxLong, kIntrinsicFlagMax),
- INTRINSIC(JavaLangStrictMath, Max, JJ_J, kIntrinsicMinMaxLong, kIntrinsicFlagMax),
- INTRINSIC(JavaLangMath, Min, FF_F, kIntrinsicMinMaxFloat, kIntrinsicFlagMin),
- INTRINSIC(JavaLangStrictMath, Min, FF_F, kIntrinsicMinMaxFloat, kIntrinsicFlagMin),
- INTRINSIC(JavaLangMath, Max, FF_F, kIntrinsicMinMaxFloat, kIntrinsicFlagMax),
- INTRINSIC(JavaLangStrictMath, Max, FF_F, kIntrinsicMinMaxFloat, kIntrinsicFlagMax),
- INTRINSIC(JavaLangMath, Min, DD_D, kIntrinsicMinMaxDouble, kIntrinsicFlagMin),
- INTRINSIC(JavaLangStrictMath, Min, DD_D, kIntrinsicMinMaxDouble, kIntrinsicFlagMin),
- INTRINSIC(JavaLangMath, Max, DD_D, kIntrinsicMinMaxDouble, kIntrinsicFlagMax),
- INTRINSIC(JavaLangStrictMath, Max, DD_D, kIntrinsicMinMaxDouble, kIntrinsicFlagMax),
-
- INTRINSIC(JavaLangMath, Cos, D_D, kIntrinsicCos, 0),
- INTRINSIC(JavaLangMath, Sin, D_D, kIntrinsicSin, 0),
- INTRINSIC(JavaLangMath, Acos, D_D, kIntrinsicAcos, 0),
- INTRINSIC(JavaLangMath, Asin, D_D, kIntrinsicAsin, 0),
- INTRINSIC(JavaLangMath, Atan, D_D, kIntrinsicAtan, 0),
- INTRINSIC(JavaLangMath, Atan2, DD_D, kIntrinsicAtan2, 0),
- INTRINSIC(JavaLangMath, Cbrt, D_D, kIntrinsicCbrt, 0),
- INTRINSIC(JavaLangMath, Cosh, D_D, kIntrinsicCosh, 0),
- INTRINSIC(JavaLangMath, Exp, D_D, kIntrinsicExp, 0),
- INTRINSIC(JavaLangMath, Expm1, D_D, kIntrinsicExpm1, 0),
- INTRINSIC(JavaLangMath, Hypot, DD_D, kIntrinsicHypot, 0),
- INTRINSIC(JavaLangMath, Log, D_D, kIntrinsicLog, 0),
- INTRINSIC(JavaLangMath, Log10, D_D, kIntrinsicLog10, 0),
- INTRINSIC(JavaLangMath, NextAfter, DD_D, kIntrinsicNextAfter, 0),
- INTRINSIC(JavaLangMath, Sinh, D_D, kIntrinsicSinh, 0),
- INTRINSIC(JavaLangMath, Tan, D_D, kIntrinsicTan, 0),
- INTRINSIC(JavaLangMath, Tanh, D_D, kIntrinsicTanh, 0),
- INTRINSIC(JavaLangMath, Sqrt, D_D, kIntrinsicSqrt, 0),
- INTRINSIC(JavaLangStrictMath, Sqrt, D_D, kIntrinsicSqrt, 0),
-
- INTRINSIC(JavaLangMath, Ceil, D_D, kIntrinsicCeil, 0),
- INTRINSIC(JavaLangStrictMath, Ceil, D_D, kIntrinsicCeil, 0),
- INTRINSIC(JavaLangMath, Floor, D_D, kIntrinsicFloor, 0),
- INTRINSIC(JavaLangStrictMath, Floor, D_D, kIntrinsicFloor, 0),
- INTRINSIC(JavaLangMath, Rint, D_D, kIntrinsicRint, 0),
- INTRINSIC(JavaLangStrictMath, Rint, D_D, kIntrinsicRint, 0),
- INTRINSIC(JavaLangMath, Round, F_I, kIntrinsicRoundFloat, 0),
- INTRINSIC(JavaLangStrictMath, Round, F_I, kIntrinsicRoundFloat, 0),
- INTRINSIC(JavaLangMath, Round, D_J, kIntrinsicRoundDouble, 0),
- INTRINSIC(JavaLangStrictMath, Round, D_J, kIntrinsicRoundDouble, 0),
-
- INTRINSIC(JavaLangRefReference, ReferenceGetReferent, _Object, kIntrinsicReferenceGetReferent, 0),
-
- INTRINSIC(JavaLangString, CharAt, I_C, kIntrinsicCharAt, 0),
- INTRINSIC(JavaLangString, CompareTo, String_I, kIntrinsicCompareTo, 0),
- INTRINSIC(JavaLangString, Equals, Object_Z, kIntrinsicEquals, 0),
- INTRINSIC(JavaLangString, GetCharsNoCheck, IICharArrayI_V, kIntrinsicGetCharsNoCheck, 0),
- INTRINSIC(JavaLangString, IsEmpty, _Z, kIntrinsicIsEmptyOrLength, kIntrinsicFlagIsEmpty),
- INTRINSIC(JavaLangString, IndexOf, II_I, kIntrinsicIndexOf, kIntrinsicFlagNone),
- INTRINSIC(JavaLangString, IndexOf, I_I, kIntrinsicIndexOf, kIntrinsicFlagBase0),
- INTRINSIC(JavaLangString, Length, _I, kIntrinsicIsEmptyOrLength, kIntrinsicFlagLength),
-
- INTRINSIC(JavaLangStringFactory, NewStringFromBytes, ByteArrayIII_String,
- kIntrinsicNewStringFromBytes, kIntrinsicFlagNone),
- INTRINSIC(JavaLangStringFactory, NewStringFromChars, IICharArray_String,
- kIntrinsicNewStringFromChars, kIntrinsicFlagNone),
- INTRINSIC(JavaLangStringFactory, NewStringFromString, String_String,
- kIntrinsicNewStringFromString, kIntrinsicFlagNone),
-
- INTRINSIC(JavaLangThread, CurrentThread, _Thread, kIntrinsicCurrentThread, 0),
-
- INTRINSIC(LibcoreIoMemory, PeekByte, J_B, kIntrinsicPeek, kSignedByte),
- INTRINSIC(LibcoreIoMemory, PeekIntNative, J_I, kIntrinsicPeek, k32),
- INTRINSIC(LibcoreIoMemory, PeekLongNative, J_J, kIntrinsicPeek, k64),
- INTRINSIC(LibcoreIoMemory, PeekShortNative, J_S, kIntrinsicPeek, kSignedHalf),
- INTRINSIC(LibcoreIoMemory, PokeByte, JB_V, kIntrinsicPoke, kSignedByte),
- INTRINSIC(LibcoreIoMemory, PokeIntNative, JI_V, kIntrinsicPoke, k32),
- INTRINSIC(LibcoreIoMemory, PokeLongNative, JJ_V, kIntrinsicPoke, k64),
- INTRINSIC(LibcoreIoMemory, PokeShortNative, JS_V, kIntrinsicPoke, kSignedHalf),
-
- INTRINSIC(SunMiscUnsafe, CompareAndSwapInt, ObjectJII_Z, kIntrinsicCas,
- kIntrinsicFlagNone),
- INTRINSIC(SunMiscUnsafe, CompareAndSwapLong, ObjectJJJ_Z, kIntrinsicCas,
- kIntrinsicFlagIsLong),
- INTRINSIC(SunMiscUnsafe, CompareAndSwapObject, ObjectJObjectObject_Z, kIntrinsicCas,
- kIntrinsicFlagIsObject),
-
-#define UNSAFE_GET_PUT(type, code, type_flags) \
- INTRINSIC(SunMiscUnsafe, Get ## type, ObjectJ_ ## code, kIntrinsicUnsafeGet, \
- type_flags), \
- INTRINSIC(SunMiscUnsafe, Get ## type ## Volatile, ObjectJ_ ## code, kIntrinsicUnsafeGet, \
- (type_flags) | kIntrinsicFlagIsVolatile), \
- INTRINSIC(SunMiscUnsafe, Put ## type, ObjectJ ## code ## _V, kIntrinsicUnsafePut, \
- type_flags), \
- INTRINSIC(SunMiscUnsafe, Put ## type ## Volatile, ObjectJ ## code ## _V, kIntrinsicUnsafePut, \
- (type_flags) | kIntrinsicFlagIsVolatile), \
- INTRINSIC(SunMiscUnsafe, PutOrdered ## type, ObjectJ ## code ## _V, kIntrinsicUnsafePut, \
- (type_flags) | kIntrinsicFlagIsOrdered)
-
- UNSAFE_GET_PUT(Int, I, kIntrinsicFlagNone),
- UNSAFE_GET_PUT(Long, J, kIntrinsicFlagIsLong),
- UNSAFE_GET_PUT(Object, Object, kIntrinsicFlagIsObject),
-#undef UNSAFE_GET_PUT
-
- // 1.8
- INTRINSIC(SunMiscUnsafe, GetAndAddInt, ObjectJI_I, kIntrinsicUnsafeGetAndAddInt, 0),
- INTRINSIC(SunMiscUnsafe, GetAndAddLong, ObjectJJ_J, kIntrinsicUnsafeGetAndAddLong, 0),
- INTRINSIC(SunMiscUnsafe, GetAndSetInt, ObjectJI_I, kIntrinsicUnsafeGetAndSetInt, 0),
- INTRINSIC(SunMiscUnsafe, GetAndSetLong, ObjectJJ_J, kIntrinsicUnsafeGetAndSetLong, 0),
- INTRINSIC(SunMiscUnsafe, GetAndSetObject, ObjectJObject_Object, kIntrinsicUnsafeGetAndSetObject, 0),
- INTRINSIC(SunMiscUnsafe, LoadFence, _V, kIntrinsicUnsafeLoadFence, 0),
- INTRINSIC(SunMiscUnsafe, StoreFence, _V, kIntrinsicUnsafeStoreFence, 0),
- INTRINSIC(SunMiscUnsafe, FullFence, _V, kIntrinsicUnsafeFullFence, 0),
-
- INTRINSIC(JavaLangSystem, ArrayCopy, CharArrayICharArrayII_V , kIntrinsicSystemArrayCopyCharArray,
- 0),
- INTRINSIC(JavaLangSystem, ArrayCopy, ObjectIObjectII_V , kIntrinsicSystemArrayCopy,
- 0),
-
- INTRINSIC(JavaLangInteger, RotateRight, II_I, kIntrinsicRotateRight, k32),
- INTRINSIC(JavaLangLong, RotateRight, JI_J, kIntrinsicRotateRight, k64),
- INTRINSIC(JavaLangInteger, RotateLeft, II_I, kIntrinsicRotateLeft, k32),
- INTRINSIC(JavaLangLong, RotateLeft, JI_J, kIntrinsicRotateLeft, k64),
-
-#undef INTRINSIC
-};
-
-DexFileMethodInliner::DexFileMethodInliner()
- : lock_("DexFileMethodInliner lock", kDexFileMethodInlinerLock),
- dex_file_(nullptr) {
- static_assert(kClassCacheFirst == 0, "kClassCacheFirst not 0");
- static_assert(arraysize(kClassCacheNames) == kClassCacheLast,
- "bad arraysize for kClassCacheNames");
- static_assert(kNameCacheFirst == 0, "kNameCacheFirst not 0");
- static_assert(arraysize(kNameCacheNames) == kNameCacheLast,
- "bad arraysize for kNameCacheNames");
- static_assert(kProtoCacheFirst == 0, "kProtoCacheFirst not 0");
- static_assert(arraysize(kProtoCacheDefs) == kProtoCacheLast,
- "bad arraysize kProtoCacheNames");
-}
-
-DexFileMethodInliner::~DexFileMethodInliner() {
-}
-
-bool DexFileMethodInliner::AnalyseMethodCode(verifier::MethodVerifier* verifier) {
- InlineMethod method;
- bool success = InlineMethodAnalyser::AnalyseMethodCode(verifier, &method);
- return success && AddInlineMethod(verifier->GetMethodReference().dex_method_index, method);
-}
-
-InlineMethodFlags DexFileMethodInliner::IsIntrinsicOrSpecial(uint32_t method_index) {
- ReaderMutexLock mu(Thread::Current(), lock_);
- auto it = inline_methods_.find(method_index);
- if (it != inline_methods_.end()) {
- DCHECK_NE(it->second.flags & (kInlineIntrinsic | kInlineSpecial), 0);
- return it->second.flags;
- } else {
- return kNoInlineMethodFlags;
- }
-}
-
-bool DexFileMethodInliner::IsIntrinsic(uint32_t method_index, InlineMethod* intrinsic) {
- ReaderMutexLock mu(Thread::Current(), lock_);
- auto it = inline_methods_.find(method_index);
- bool res = (it != inline_methods_.end() && (it->second.flags & kInlineIntrinsic) != 0);
- if (res && intrinsic != nullptr) {
- *intrinsic = it->second;
- }
- return res;
-}
-
-bool DexFileMethodInliner::IsSpecial(uint32_t method_index) {
- ReaderMutexLock mu(Thread::Current(), lock_);
- auto it = inline_methods_.find(method_index);
- return it != inline_methods_.end() && (it->second.flags & kInlineSpecial) != 0;
-}
-
-uint32_t DexFileMethodInliner::FindClassIndex(const DexFile* dex_file, IndexCache* cache,
- ClassCacheIndex index) {
- uint32_t* class_index = &cache->class_indexes[index];
- if (*class_index != kIndexUnresolved) {
- return *class_index;
- }
-
- const DexFile::TypeId* type_id = dex_file->FindTypeId(kClassCacheNames[index]);
- if (type_id == nullptr) {
- *class_index = kIndexNotFound;
- return *class_index;
- }
- *class_index = dex_file->GetIndexForTypeId(*type_id);
- return *class_index;
-}
-
-uint32_t DexFileMethodInliner::FindNameIndex(const DexFile* dex_file, IndexCache* cache,
- NameCacheIndex index) {
- uint32_t* name_index = &cache->name_indexes[index];
- if (*name_index != kIndexUnresolved) {
- return *name_index;
- }
-
- const DexFile::StringId* string_id = dex_file->FindStringId(kNameCacheNames[index]);
- if (string_id == nullptr) {
- *name_index = kIndexNotFound;
- return *name_index;
- }
- *name_index = dex_file->GetIndexForStringId(*string_id);
- return *name_index;
-}
-
-uint32_t DexFileMethodInliner::FindProtoIndex(const DexFile* dex_file, IndexCache* cache,
- ProtoCacheIndex index) {
- uint32_t* proto_index = &cache->proto_indexes[index];
- if (*proto_index != kIndexUnresolved) {
- return *proto_index;
- }
-
- const ProtoDef& proto_def = kProtoCacheDefs[index];
- uint32_t return_index = FindClassIndex(dex_file, cache, proto_def.return_type);
- if (return_index == kIndexNotFound) {
- *proto_index = kIndexNotFound;
- return *proto_index;
- }
- uint16_t return_type = static_cast<uint16_t>(return_index);
- DCHECK_EQ(static_cast<uint32_t>(return_type), return_index);
-
- uint32_t signature_length = proto_def.param_count;
- uint16_t signature_type_idxs[kProtoMaxParams];
- for (uint32_t i = 0; i != signature_length; ++i) {
- uint32_t param_index = FindClassIndex(dex_file, cache, proto_def.params[i]);
- if (param_index == kIndexNotFound) {
- *proto_index = kIndexNotFound;
- return *proto_index;
- }
- signature_type_idxs[i] = static_cast<uint16_t>(param_index);
- DCHECK_EQ(static_cast<uint32_t>(signature_type_idxs[i]), param_index);
- }
-
- const DexFile::ProtoId* proto_id = dex_file->FindProtoId(return_type, signature_type_idxs,
- signature_length);
- if (proto_id == nullptr) {
- *proto_index = kIndexNotFound;
- return *proto_index;
- }
- *proto_index = dex_file->GetIndexForProtoId(*proto_id);
- return *proto_index;
-}
-
-uint32_t DexFileMethodInliner::FindMethodIndex(const DexFile* dex_file, IndexCache* cache,
- const MethodDef& method_def) {
- uint32_t declaring_class_index = FindClassIndex(dex_file, cache, method_def.declaring_class);
- if (declaring_class_index == kIndexNotFound) {
- return kIndexNotFound;
- }
- uint32_t name_index = FindNameIndex(dex_file, cache, method_def.name);
- if (name_index == kIndexNotFound) {
- return kIndexNotFound;
- }
- uint32_t proto_index = FindProtoIndex(dex_file, cache, method_def.proto);
- if (proto_index == kIndexNotFound) {
- return kIndexNotFound;
- }
- const DexFile::MethodId* method_id =
- dex_file->FindMethodId(dex_file->GetTypeId(declaring_class_index),
- dex_file->GetStringId(name_index),
- dex_file->GetProtoId(proto_index));
- if (method_id == nullptr) {
- return kIndexNotFound;
- }
- return dex_file->GetIndexForMethodId(*method_id);
-}
-
-DexFileMethodInliner::IndexCache::IndexCache() {
- std::fill_n(class_indexes, arraysize(class_indexes), kIndexUnresolved);
- std::fill_n(name_indexes, arraysize(name_indexes), kIndexUnresolved);
- std::fill_n(proto_indexes, arraysize(proto_indexes), kIndexUnresolved);
-}
-
-void DexFileMethodInliner::FindIntrinsics(const DexFile* dex_file) {
- DCHECK(dex_file != nullptr);
- DCHECK(dex_file_ == nullptr);
- IndexCache cache;
- for (const IntrinsicDef& def : kIntrinsicMethods) {
- uint32_t method_idx = FindMethodIndex(dex_file, &cache, def.method_def);
- if (method_idx != kIndexNotFound) {
- DCHECK(inline_methods_.find(method_idx) == inline_methods_.end());
- inline_methods_.Put(method_idx, def.intrinsic);
- }
- }
- dex_file_ = dex_file;
-}
-
-bool DexFileMethodInliner::AddInlineMethod(int32_t method_idx, const InlineMethod& method) {
- WriterMutexLock mu(Thread::Current(), lock_);
- if (LIKELY(inline_methods_.find(method_idx) == inline_methods_.end())) {
- inline_methods_.Put(method_idx, method);
- return true;
- } else {
- if (PrettyMethod(method_idx, *dex_file_) == "int java.lang.String.length()") {
- // TODO: String.length is both kIntrinsicIsEmptyOrLength and kInlineOpIGet.
- } else {
- LOG(WARNING) << "Inliner: " << PrettyMethod(method_idx, *dex_file_) << " already inline";
- }
- return false;
- }
-}
-
-} // namespace art
+++ /dev/null
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_
-#define ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_
-
-#include <stdint.h>
-
-#include "base/enums.h"
-#include "base/mutex.h"
-#include "base/macros.h"
-#include "safe_map.h"
-#include "dex_file.h"
-#include "quick/inline_method_analyser.h"
-
-namespace art {
-
-namespace verifier {
-class MethodVerifier;
-} // namespace verifier
-
-enum OpSize {
- k32,
- k64,
- kSignedHalf,
- kSignedByte,
-};
-
-/**
- * Handles inlining of methods from a particular DexFile.
- *
- * Intrinsics are a special case of inline methods. The DexFile indices for
- * all the supported intrinsic methods are looked up once by the FindIntrinsics
- * function and cached by this class for quick lookup by the method index.
- *
- * TODO: Detect short methods (at least getters, setters and empty functions)
- * from the verifier and mark them for inlining. Inline these methods early
- * during compilation to allow further optimizations. Similarly, provide
- * additional information about intrinsics to the early phases of compilation.
- */
-class DexFileMethodInliner {
- public:
- DexFileMethodInliner();
- ~DexFileMethodInliner();
-
- /**
- * Analyse method code to determine if the method is a candidate for inlining.
- * If it is, record its data for later.
- *
- * @param verifier the method verifier holding data about the method to analyse.
- * @return true if the method is a candidate for inlining, false otherwise.
- */
- bool AnalyseMethodCode(verifier::MethodVerifier* verifier)
- REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!lock_);
-
- /**
- * Check whether a particular method index corresponds to an intrinsic or special function.
- */
- InlineMethodFlags IsIntrinsicOrSpecial(uint32_t method_index) REQUIRES(!lock_);
-
- /**
- * Check whether a particular method index corresponds to an intrinsic function.
- */
- bool IsIntrinsic(uint32_t method_index, InlineMethod* intrinsic) REQUIRES(!lock_);
-
- /**
- * Check whether a particular method index corresponds to a special function.
- */
- bool IsSpecial(uint32_t method_index) REQUIRES(!lock_);
-
- /**
- * To avoid multiple lookups of a class by its descriptor, we cache its
- * type index in the IndexCache. These are the indexes into the IndexCache
- * class_indexes array.
- */
- enum ClassCacheIndex : uint8_t { // unit8_t to save space, make larger if needed
- kClassCacheFirst = 0,
- kClassCacheBoolean = kClassCacheFirst,
- kClassCacheByte,
- kClassCacheChar,
- kClassCacheShort,
- kClassCacheInt,
- kClassCacheLong,
- kClassCacheFloat,
- kClassCacheDouble,
- kClassCacheVoid,
- kClassCacheJavaLangByteArray,
- kClassCacheJavaLangCharArray,
- kClassCacheJavaLangIntArray,
- kClassCacheJavaLangObject,
- kClassCacheJavaLangRefReference,
- kClassCacheJavaLangString,
- kClassCacheJavaLangStringBuffer,
- kClassCacheJavaLangStringBuilder,
- kClassCacheJavaLangStringFactory,
- kClassCacheJavaLangDouble,
- kClassCacheJavaLangFloat,
- kClassCacheJavaLangInteger,
- kClassCacheJavaLangLong,
- kClassCacheJavaLangShort,
- kClassCacheJavaLangMath,
- kClassCacheJavaLangStrictMath,
- kClassCacheJavaLangThread,
- kClassCacheJavaNioCharsetCharset,
- kClassCacheLibcoreIoMemory,
- kClassCacheSunMiscUnsafe,
- kClassCacheJavaLangSystem,
- kClassCacheLast
- };
-
- /**
- * To avoid multiple lookups of a method name string, we cache its string
- * index in the IndexCache. These are the indexes into the IndexCache
- * name_indexes array.
- */
- enum NameCacheIndex : uint8_t { // unit8_t to save space, make larger if needed
- kNameCacheFirst = 0,
- kNameCacheReverse = kNameCacheFirst,
- kNameCacheReverseBytes,
- kNameCacheDoubleToRawLongBits,
- kNameCacheLongBitsToDouble,
- kNameCacheFloatToRawIntBits,
- kNameCacheIntBitsToFloat,
- kNameCacheAbs,
- kNameCacheMax,
- kNameCacheMin,
- kNameCacheCos,
- kNameCacheSin,
- kNameCacheAcos,
- kNameCacheAsin,
- kNameCacheAtan,
- kNameCacheAtan2,
- kNameCacheCbrt,
- kNameCacheCosh,
- kNameCacheExp,
- kNameCacheExpm1,
- kNameCacheHypot,
- kNameCacheLog,
- kNameCacheLog10,
- kNameCacheNextAfter,
- kNameCacheSinh,
- kNameCacheTan,
- kNameCacheTanh,
- kNameCacheSqrt,
- kNameCacheCeil,
- kNameCacheFloor,
- kNameCacheRint,
- kNameCacheRound,
- kNameCacheReferenceGetReferent,
- kNameCacheCharAt,
- kNameCacheCompareTo,
- kNameCacheEquals,
- kNameCacheGetCharsNoCheck,
- kNameCacheIsEmpty,
- kNameCacheFloatToIntBits,
- kNameCacheDoubleToLongBits,
- kNameCacheIsInfinite,
- kNameCacheIsNaN,
- kNameCacheIndexOf,
- kNameCacheLength,
- kNameCacheInit,
- kNameCacheNewStringFromBytes,
- kNameCacheNewStringFromChars,
- kNameCacheNewStringFromString,
- kNameCacheCurrentThread,
- kNameCachePeekByte,
- kNameCachePeekIntNative,
- kNameCachePeekLongNative,
- kNameCachePeekShortNative,
- kNameCachePokeByte,
- kNameCachePokeIntNative,
- kNameCachePokeLongNative,
- kNameCachePokeShortNative,
- kNameCacheCompareAndSwapInt,
- kNameCacheCompareAndSwapLong,
- kNameCacheCompareAndSwapObject,
- kNameCacheGetInt,
- kNameCacheGetIntVolatile,
- kNameCachePutInt,
- kNameCachePutIntVolatile,
- kNameCachePutOrderedInt,
- kNameCacheGetLong,
- kNameCacheGetLongVolatile,
- kNameCachePutLong,
- kNameCachePutLongVolatile,
- kNameCachePutOrderedLong,
- kNameCacheGetObject,
- kNameCacheGetObjectVolatile,
- kNameCachePutObject,
- kNameCachePutObjectVolatile,
- kNameCachePutOrderedObject,
- kNameCacheGetAndAddInt,
- kNameCacheGetAndAddLong,
- kNameCacheGetAndSetInt,
- kNameCacheGetAndSetLong,
- kNameCacheGetAndSetObject,
- kNameCacheLoadFence,
- kNameCacheStoreFence,
- kNameCacheFullFence,
- kNameCacheArrayCopy,
- kNameCacheBitCount,
- kNameCacheCompare,
- kNameCacheHighestOneBit,
- kNameCacheLowestOneBit,
- kNameCacheNumberOfLeadingZeros,
- kNameCacheNumberOfTrailingZeros,
- kNameCacheRotateRight,
- kNameCacheRotateLeft,
- kNameCacheSignum,
- kNameCacheLast
- };
-
- /**
- * To avoid multiple lookups of a method signature, we cache its proto
- * index in the IndexCache. These are the indexes into the IndexCache
- * proto_indexes array.
- */
- enum ProtoCacheIndex : uint8_t { // unit8_t to save space, make larger if needed
- kProtoCacheFirst = 0,
- kProtoCacheI_I = kProtoCacheFirst,
- kProtoCacheJ_J,
- kProtoCacheS_S,
- kProtoCacheD_D,
- kProtoCacheDD_D,
- kProtoCacheF_F,
- kProtoCacheFF_F,
- kProtoCacheD_J,
- kProtoCacheD_Z,
- kProtoCacheJ_D,
- kProtoCacheF_I,
- kProtoCacheF_Z,
- kProtoCacheI_F,
- kProtoCacheII_I,
- kProtoCacheI_C,
- kProtoCacheString_I,
- kProtoCache_Z,
- kProtoCache_I,
- kProtoCache_Object,
- kProtoCache_Thread,
- kProtoCacheJ_B,
- kProtoCacheJ_I,
- kProtoCacheJ_S,
- kProtoCacheJB_V,
- kProtoCacheJI_V,
- kProtoCacheJJ_J,
- kProtoCacheJJ_I,
- kProtoCacheJJ_V,
- kProtoCacheJS_V,
- kProtoCacheObject_Z,
- kProtoCacheJI_J,
- kProtoCacheObjectJII_Z,
- kProtoCacheObjectJJJ_Z,
- kProtoCacheObjectJObjectObject_Z,
- kProtoCacheObjectJ_I,
- kProtoCacheObjectJI_I,
- kProtoCacheObjectJI_V,
- kProtoCacheObjectJ_J,
- kProtoCacheObjectJJ_J,
- kProtoCacheObjectJJ_V,
- kProtoCacheObjectJ_Object,
- kProtoCacheObjectJObject_V,
- kProtoCacheObjectJObject_Object,
- kProtoCacheCharArrayICharArrayII_V,
- kProtoCacheObjectIObjectII_V,
- kProtoCacheIICharArrayI_V,
- kProtoCacheByteArrayIII_String,
- kProtoCacheIICharArray_String,
- kProtoCacheString_String,
- kProtoCache_V,
- kProtoCacheByteArray_V,
- kProtoCacheByteArrayI_V,
- kProtoCacheByteArrayII_V,
- kProtoCacheByteArrayIII_V,
- kProtoCacheByteArrayIIString_V,
- kProtoCacheByteArrayString_V,
- kProtoCacheByteArrayIICharset_V,
- kProtoCacheByteArrayCharset_V,
- kProtoCacheCharArray_V,
- kProtoCacheCharArrayII_V,
- kProtoCacheIICharArray_V,
- kProtoCacheIntArrayII_V,
- kProtoCacheString_V,
- kProtoCacheStringBuffer_V,
- kProtoCacheStringBuilder_V,
- kProtoCacheLast
- };
-
- private:
- /**
- * The maximum number of method parameters we support in the ProtoDef.
- */
- static constexpr uint32_t kProtoMaxParams = 6;
-
- /**
- * The method signature (proto) definition using cached class indexes.
- * The return_type and params are used with the IndexCache to look up
- * appropriate class indexes to be passed to DexFile::FindProtoId().
- */
- struct ProtoDef {
- ClassCacheIndex return_type;
- uint8_t param_count;
- ClassCacheIndex params[kProtoMaxParams];
- };
-
- /**
- * The method definition using cached class, name and proto indexes.
- * The class index, method name index and proto index are used with
- * IndexCache to look up appropriate parameters for DexFile::FindMethodId().
- */
- struct MethodDef {
- ClassCacheIndex declaring_class;
- NameCacheIndex name;
- ProtoCacheIndex proto;
- };
-
- /**
- * The definition of an intrinsic function binds the method definition
- * to an Intrinsic.
- */
- struct IntrinsicDef {
- MethodDef method_def;
- InlineMethod intrinsic;
- };
-
- /**
- * Cache for class, method name and method signature indexes used during
- * intrinsic function lookup to avoid multiple lookups of the same items.
- *
- * Many classes have multiple intrinsics and/or they are used in multiple
- * method signatures and we want to avoid repeated lookups since they are
- * not exactly cheap. The method names and method signatures are sometimes
- * reused and therefore cached as well.
- */
- struct IndexCache {
- IndexCache();
-
- uint32_t class_indexes[kClassCacheLast - kClassCacheFirst];
- uint32_t name_indexes[kNameCacheLast - kNameCacheFirst];
- uint32_t proto_indexes[kProtoCacheLast - kProtoCacheFirst];
- };
-
- static const char* const kClassCacheNames[];
- static const char* const kNameCacheNames[];
- static const ProtoDef kProtoCacheDefs[];
- static const IntrinsicDef kIntrinsicMethods[];
-
- static const uint32_t kIndexNotFound = static_cast<uint32_t>(-1);
- static const uint32_t kIndexUnresolved = static_cast<uint32_t>(-2);
-
- static uint32_t FindClassIndex(const DexFile* dex_file, IndexCache* cache,
- ClassCacheIndex index);
- static uint32_t FindNameIndex(const DexFile* dex_file, IndexCache* cache,
- NameCacheIndex index);
- static uint32_t FindProtoIndex(const DexFile* dex_file, IndexCache* cache,
- ProtoCacheIndex index);
- static uint32_t FindMethodIndex(const DexFile* dex_file, IndexCache* cache,
- const MethodDef& method_def);
-
- /**
- * Find all known intrinsic methods in the dex_file and cache their indices.
- *
- * Only DexFileToMethodInlinerMap may call this function to initialize the inliner.
- */
- void FindIntrinsics(const DexFile* dex_file) REQUIRES(lock_);
-
- friend class DexFileToMethodInlinerMap;
-
- bool AddInlineMethod(int32_t method_idx, const InlineMethod& method) REQUIRES(!lock_);
-
- ReaderWriterMutex lock_;
- /*
- * Maps method indexes (for the particular DexFile) to Intrinsic defintions.
- */
- SafeMap<uint32_t, InlineMethod> inline_methods_ GUARDED_BY(lock_);
- const DexFile* dex_file_;
-
- DISALLOW_COPY_AND_ASSIGN(DexFileMethodInliner);
-};
-
-} // namespace art
-
-#endif // ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_
+++ /dev/null
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <algorithm>
-#include <utility>
-#include "thread.h"
-#include "thread-inl.h"
-#include "base/mutex.h"
-#include "base/mutex-inl.h"
-#include "base/logging.h"
-#include "driver/compiler_driver.h"
-
-#include "dex_file_to_method_inliner_map.h"
-
-namespace art {
-
-DexFileToMethodInlinerMap::DexFileToMethodInlinerMap()
- : lock_("DexFileToMethodInlinerMap lock", kDexFileToMethodInlinerMapLock) {
-}
-
-DexFileToMethodInlinerMap::~DexFileToMethodInlinerMap() {
- for (auto& entry : inliners_) {
- delete entry.second;
- }
-}
-
-DexFileMethodInliner* DexFileToMethodInlinerMap::GetMethodInliner(const DexFile* dex_file) {
- Thread* self = Thread::Current();
- {
- ReaderMutexLock mu(self, lock_);
- auto it = inliners_.find(dex_file);
- if (it != inliners_.end()) {
- return it->second;
- }
- }
-
- // We need to acquire our lock_ to modify inliners_ but we want to release it
- // before we initialize the new inliner. However, we need to acquire the
- // new inliner's lock_ before we release our lock_ to prevent another thread
- // from using the uninitialized inliner. This requires explicit calls to
- // ExclusiveLock()/ExclusiveUnlock() on one of the locks, the other one
- // can use WriterMutexLock.
- DexFileMethodInliner* locked_inliner;
- {
- WriterMutexLock mu(self, lock_);
- DexFileMethodInliner** inliner = &inliners_[dex_file]; // inserts new entry if not found
- if (*inliner) {
- return *inliner;
- }
- *inliner = new DexFileMethodInliner;
- DCHECK(*inliner != nullptr);
- locked_inliner = *inliner;
- locked_inliner->lock_.ExclusiveLock(self); // Acquire inliner's lock_ before releasing lock_.
- }
- locked_inliner->FindIntrinsics(dex_file);
- locked_inliner->lock_.ExclusiveUnlock(self);
- return locked_inliner;
-}
-
-} // namespace art
+++ /dev/null
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_COMPILER_DEX_QUICK_DEX_FILE_TO_METHOD_INLINER_MAP_H_
-#define ART_COMPILER_DEX_QUICK_DEX_FILE_TO_METHOD_INLINER_MAP_H_
-
-#include <map>
-#include <vector>
-#include "base/macros.h"
-#include "base/mutex.h"
-
-#include "dex/quick/dex_file_method_inliner.h"
-
-namespace art {
-
-class CompilerDriver;
-class DexFile;
-
-/**
- * Map each DexFile to its DexFileMethodInliner.
- *
- * The method inliner is created and initialized the first time it's requested
- * for a particular DexFile.
- */
-class DexFileToMethodInlinerMap {
- public:
- DexFileToMethodInlinerMap();
- ~DexFileToMethodInlinerMap();
-
- DexFileMethodInliner* GetMethodInliner(const DexFile* dex_file) NO_THREAD_SAFETY_ANALYSIS;
- // TODO: There is an irregular non-scoped use of locks that defeats annotalysis with -O0.
- // Fix the NO_THREAD_SAFETY_ANALYSIS when this works and add the appropriate LOCKS_EXCLUDED.
-
- private:
- ReaderWriterMutex lock_;
- std::map<const DexFile*, DexFileMethodInliner*> inliners_ GUARDED_BY(lock_);
-
- DISALLOW_COPY_AND_ASSIGN(DexFileToMethodInlinerMap);
-};
-
-} // namespace art
-
-#endif // ART_COMPILER_DEX_QUICK_DEX_FILE_TO_METHOD_INLINER_MAP_H_
#include "quick_compiler_callbacks.h"
-#include "quick/dex_file_to_method_inliner_map.h"
#include "verifier/method_verifier-inl.h"
#include "verification_results.h"
void QuickCompilerCallbacks::MethodVerified(verifier::MethodVerifier* verifier) {
verification_results_->ProcessVerifiedMethod(verifier);
- MethodReference ref = verifier->GetMethodReference();
- method_inliner_map_->GetMethodInliner(ref.dex_file)->AnalyseMethodCode(verifier);
}
void QuickCompilerCallbacks::ClassRejected(ClassReference ref) {
namespace art {
class VerificationResults;
-class DexFileToMethodInlinerMap;
class QuickCompilerCallbacks FINAL : public CompilerCallbacks {
public:
QuickCompilerCallbacks(VerificationResults* verification_results,
- DexFileToMethodInlinerMap* method_inliner_map,
CompilerCallbacks::CallbackMode mode)
: CompilerCallbacks(mode),
verification_results_(verification_results),
- method_inliner_map_(method_inliner_map),
verifier_deps_(nullptr) {
CHECK(verification_results != nullptr);
- CHECK(method_inliner_map != nullptr);
}
~QuickCompilerCallbacks() { }
private:
VerificationResults* const verification_results_;
- DexFileToMethodInlinerMap* const method_inliner_map_;
verifier::VerifierDeps* verifier_deps_;
};
#include "compiler_driver.h"
#include "compiler_options.h"
#include "dex/verification_results.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
namespace art {
TEST(CompiledMethodStorage, Deduplicate) {
CompilerOptions compiler_options;
VerificationResults verification_results(&compiler_options);
- DexFileToMethodInlinerMap method_inliner_map;
CompilerDriver driver(&compiler_options,
&verification_results,
- &method_inliner_map,
Compiler::kOptimizing,
/* instruction_set_ */ kNone,
/* instruction_set_features */ nullptr,
#include "dex/dex_to_dex_compiler.h"
#include "dex/verification_results.h"
#include "dex/verified_method.h"
-#include "dex/quick/dex_file_method_inliner.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "driver/compiler_options.h"
+#include "intrinsics_enum.h"
#include "jni_internal.h"
#include "object_lock.h"
#include "runtime.h"
CompilerDriver::CompilerDriver(
const CompilerOptions* compiler_options,
VerificationResults* verification_results,
- DexFileToMethodInlinerMap* method_inliner_map,
Compiler::Kind compiler_kind,
InstructionSet instruction_set,
const InstructionSetFeatures* instruction_set_features,
const ProfileCompilationInfo* profile_compilation_info)
: compiler_options_(compiler_options),
verification_results_(verification_results),
- method_inliner_map_(method_inliner_map),
compiler_(Compiler::Create(this, compiler_kind)),
compiler_kind_(compiler_kind),
instruction_set_(instruction_set == kArm ? kThumb2: instruction_set),
dex_to_dex_references_(),
current_dex_to_dex_methods_(nullptr) {
DCHECK(compiler_options_ != nullptr);
- DCHECK(method_inliner_map_ != nullptr);
compiler_->Init();
}
#undef CREATE_TRAMPOLINE
+static void SetupIntrinsic(Thread* self,
+ Intrinsics intrinsic,
+ InvokeType invoke_type,
+ const char* class_name,
+ const char* method_name,
+ const char* signature)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ PointerSize image_size = class_linker->GetImagePointerSize();
+ mirror::Class* cls = class_linker->FindSystemClass(self, class_name);
+ if (cls == nullptr) {
+ LOG(FATAL) << "Could not find class of intrinsic " << class_name;
+ }
+ ArtMethod* method = (invoke_type == kStatic || invoke_type == kDirect)
+ ? cls->FindDeclaredDirectMethod(method_name, signature, image_size)
+ : cls->FindDeclaredVirtualMethod(method_name, signature, image_size);
+ if (method == nullptr) {
+ LOG(FATAL) << "Could not find method of intrinsic " << class_name << method_name << signature;
+ }
+ DCHECK_EQ(method->GetInvokeType(), invoke_type);
+ method->SetIntrinsic(static_cast<uint32_t>(intrinsic));
+}
+
void CompilerDriver::CompileAll(jobject class_loader,
const std::vector<const DexFile*>& dex_files,
TimingLogger* timings) {
// 3) Attempt to verify all classes
// 4) Attempt to initialize image classes, and trivially initialized classes
PreCompile(class_loader, dex_files, timings);
+ if (IsBootImage()) {
+ // We don't need to setup the intrinsics for non boot image compilation, as
+ // those compilations will pick up a boot image that have the ArtMethod already
+ // set with the intrinsics flag.
+ ScopedObjectAccess soa(Thread::Current());
+#define OPTIMIZING_INTRINSICS(Name, InvokeType, NeedsEnvironmentOrCache, SideEffects, Exceptions, ClassName, MethodName, Signature) \
+ SetupIntrinsic(soa.Self(), Intrinsics::k##Name, InvokeType, ClassName, MethodName, Signature);
+#include "intrinsics_list.h"
+INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+#undef INTRINSICS_LIST
+ }
// Compile:
// 1) Compile all classes and methods enabled for compilation. May fall back to dex-to-dex
// compilation.
class CompiledMethod;
class CompilerOptions;
class DexCompilationUnit;
-class DexFileToMethodInlinerMap;
struct InlineIGetIPutData;
class InstructionSetFeatures;
class ParallelCompilationManager;
// classes.
CompilerDriver(const CompilerOptions* compiler_options,
VerificationResults* verification_results,
- DexFileToMethodInlinerMap* method_inliner_map,
Compiler::Kind compiler_kind,
InstructionSet instruction_set,
const InstructionSetFeatures* instruction_set_features,
return verification_results_;
}
- DexFileToMethodInlinerMap* GetMethodInlinerMap() const {
- return method_inliner_map_;
- }
-
InstructionSet GetInstructionSet() const {
return instruction_set_;
}
const CompilerOptions* const compiler_options_;
VerificationResults* const verification_results_;
- DexFileToMethodInlinerMap* const method_inliner_map_;
std::unique_ptr<Compiler> compiler_;
Compiler::Kind compiler_kind_;
--- /dev/null
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_INTRINSICS_ENUM_H_
+#define ART_COMPILER_INTRINSICS_ENUM_H_
+
+namespace art {
+
+enum class Intrinsics {
+#define OPTIMIZING_INTRINSICS(Name, ...) \
+ k ## Name,
+#include "intrinsics_list.h"
+ kNone,
+ INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+#undef INTRINSICS_LIST
+#undef OPTIMIZING_INTRINSICS
+};
+std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic);
+
+} // namespace art
+
+#endif // ART_COMPILER_INTRINSICS_ENUM_H_
--- /dev/null
+/*
+ * Copyright (C, "", "", "") 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License", "", "", "");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_INTRINSICS_LIST_H_
+#define ART_COMPILER_INTRINSICS_LIST_H_
+
+// All intrinsics supported by ART. Format is name, then whether it is expected
+// to be a HInvokeStaticOrDirect node (compared to HInvokeVirtual), then whether it requires an
+// environment, may have side effects, or may throw exceptions.
+
+// Note: adding a new intrinsic requires an art image version change,
+// as the modifiers flag for some ArtMethods will need to be changed.
+
+#define INTRINSICS_LIST(V) \
+ V(DoubleDoubleToRawLongBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "doubleToRawLongBits", "(D)J") \
+ V(DoubleDoubleToLongBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "doubleToLongBits", "(D)J") \
+ V(DoubleIsInfinite, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "isInfinite", "(D)Z") \
+ V(DoubleIsNaN, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "isNaN", "(D)Z") \
+ V(DoubleLongBitsToDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "longBitsToDouble", "(J)D") \
+ V(FloatFloatToRawIntBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "floatToRawIntBits", "(F)I") \
+ V(FloatFloatToIntBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "floatToIntBits", "(F)I") \
+ V(FloatIsInfinite, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "isInfinite", "(F)Z") \
+ V(FloatIsNaN, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "isNaN", "(F)Z") \
+ V(FloatIntBitsToFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "intBitsToFloat", "(I)F") \
+ V(IntegerReverse, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "reverse", "(I)I") \
+ V(IntegerReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "reverseBytes", "(I)I") \
+ V(IntegerBitCount, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "bitCount", "(I)I") \
+ V(IntegerCompare, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "compare", "(II)I") \
+ V(IntegerHighestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "highestOneBit", "(I)I") \
+ V(IntegerLowestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "lowestOneBit", "(I)I") \
+ V(IntegerNumberOfLeadingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "numberOfLeadingZeros", "(I)I") \
+ V(IntegerNumberOfTrailingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "numberOfTrailingZeros", "(I)I") \
+ V(IntegerRotateRight, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "rotateRight", "(II)I") \
+ V(IntegerRotateLeft, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "rotateLeft", "(II)I") \
+ V(IntegerSignum, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "signum", "(I)I") \
+ V(LongReverse, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "reverse", "(J)J") \
+ V(LongReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "reverseBytes", "(J)J") \
+ V(LongBitCount, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "bitCount", "(J)I") \
+ V(LongCompare, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "compare", "(JJ)I") \
+ V(LongHighestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "highestOneBit", "(J)J") \
+ V(LongLowestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "lowestOneBit", "(J)J") \
+ V(LongNumberOfLeadingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "numberOfLeadingZeros", "(J)I") \
+ V(LongNumberOfTrailingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "numberOfTrailingZeros", "(J)I") \
+ V(LongRotateRight, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "rotateRight", "(JI)J") \
+ V(LongRotateLeft, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "rotateLeft", "(JI)J") \
+ V(LongSignum, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "signum", "(J)I") \
+ V(ShortReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Short;", "reverseBytes", "(S)S") \
+ V(MathAbsDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(D)D") \
+ V(MathAbsFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(F)F") \
+ V(MathAbsLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(J)J") \
+ V(MathAbsInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(I)I") \
+ V(MathMinDoubleDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(DD)D") \
+ V(MathMinFloatFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(FF)F") \
+ V(MathMinLongLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(JJ)J") \
+ V(MathMinIntInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(II)I") \
+ V(MathMaxDoubleDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(DD)D") \
+ V(MathMaxFloatFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(FF)F") \
+ V(MathMaxLongLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(JJ)J") \
+ V(MathMaxIntInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(II)I") \
+ V(MathCos, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "cos", "(D)D") \
+ V(MathSin, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "sin", "(D)D") \
+ V(MathAcos, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "acos", "(D)D") \
+ V(MathAsin, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "asin", "(D)D") \
+ V(MathAtan, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "atan", "(D)D") \
+ V(MathAtan2, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "atan2", "(DD)D") \
+ V(MathCbrt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "cbrt", "(D)D") \
+ V(MathCosh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "cosh", "(D)D") \
+ V(MathExp, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "exp", "(D)D") \
+ V(MathExpm1, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "expm1", "(D)D") \
+ V(MathHypot, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "hypot", "(DD)D") \
+ V(MathLog, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "log", "(D)D") \
+ V(MathLog10, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "log10", "(D)D") \
+ V(MathNextAfter, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "nextAfter", "(DD)D") \
+ V(MathSinh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "sinh", "(D)D") \
+ V(MathTan, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "tan", "(D)D") \
+ V(MathTanh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "tanh", "(D)D") \
+ V(MathSqrt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "sqrt", "(D)D") \
+ V(MathCeil, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "ceil", "(D)D") \
+ V(MathFloor, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "floor", "(D)D") \
+ V(MathRint, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "rint", "(D)D") \
+ V(MathRoundDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "round", "(D)J") \
+ V(MathRoundFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "round", "(F)I") \
+ V(SystemArrayCopyChar, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/System;", "arraycopy", "([CI[CII)V") \
+ V(SystemArrayCopy, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/System;", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V") \
+ V(ThreadCurrentThread, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Thread;", "currentThread", "()Ljava/lang/Thread;") \
+ V(MemoryPeekByte, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Llibcore/io/Memory;", "peekByte", "(J)B") \
+ V(MemoryPeekIntNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Llibcore/io/Memory;", "peekIntNative", "(J)I") \
+ V(MemoryPeekLongNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Llibcore/io/Memory;", "peekLongNative", "(J)J") \
+ V(MemoryPeekShortNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Llibcore/io/Memory;", "peekShortNative", "(J)S") \
+ V(MemoryPokeByte, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow, "Llibcore/io/Memory;", "pokeByte", "(JB)V") \
+ V(MemoryPokeIntNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow, "Llibcore/io/Memory;", "pokeIntNative", "(JI)V") \
+ V(MemoryPokeLongNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow, "Llibcore/io/Memory;", "pokeLongNative", "(JJ)V") \
+ V(MemoryPokeShortNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow, "Llibcore/io/Memory;", "pokeShortNative", "(JS)V") \
+ V(StringCharAt, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "charAt", "(I)C") \
+ V(StringCompareTo, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "compareTo", "(Ljava/lang/String;)I") \
+ V(StringEquals, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "equals", "(Ljava/lang/Object;)Z") \
+ V(StringGetCharsNoCheck, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "getCharsNoCheck", "(II[CI)V") \
+ V(StringIndexOf, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "indexOf", "(I)I") \
+ V(StringIndexOfAfter, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "indexOf", "(II)I") \
+ V(StringIsEmpty, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "isEmpty", "()Z") \
+ V(StringLength, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "length", "()I") \
+ V(StringNewStringFromBytes, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromBytes", "([BIII)Ljava/lang/String;") \
+ V(StringNewStringFromChars, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromChars", "(II[C)Ljava/lang/String;") \
+ V(StringNewStringFromString, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromString", "(Ljava/lang/String;)Ljava/lang/String;") \
+ V(UnsafeCASInt, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "compareAndSwapInt", "(Ljava/lang/Object;JII)Z") \
+ V(UnsafeCASLong, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z") \
+ V(UnsafeCASObject, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "compareAndSwapObject", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \
+ V(UnsafeGet, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getInt", "(Ljava/lang/Object;J)I") \
+ V(UnsafeGetVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getIntVolatile", "(Ljava/lang/Object;J)I") \
+ V(UnsafeGetObject, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;") \
+ V(UnsafeGetObjectVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;") \
+ V(UnsafeGetLong, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getLong", "(Ljava/lang/Object;J)J") \
+ V(UnsafeGetLongVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getLongVolatile", "(Ljava/lang/Object;J)J") \
+ V(UnsafePut, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putInt", "(Ljava/lang/Object;JI)V") \
+ V(UnsafePutOrdered, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putOrderedInt", "(Ljava/lang/Object;JI)V") \
+ V(UnsafePutVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putIntVolatile", "(Ljava/lang/Object;JI)V") \
+ V(UnsafePutObject, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
+ V(UnsafePutObjectOrdered, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putOrderedObject", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
+ V(UnsafePutObjectVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
+ V(UnsafePutLong, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putLong", "(Ljava/lang/Object;JJ)V") \
+ V(UnsafePutLongOrdered, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putOrderedLong", "(Ljava/lang/Object;JJ)V") \
+ V(UnsafePutLongVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putLongVolatile", "(Ljava/lang/Object;JJ)V") \
+ V(UnsafeGetAndAddInt, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndAddInt", "(Ljava/lang/Object;JI)I") \
+ V(UnsafeGetAndAddLong, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndAddLong", "(Ljava/lang/Object;JJ)J") \
+ V(UnsafeGetAndSetInt, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetInt", "(Ljava/lang/Object;JI)I") \
+ V(UnsafeGetAndSetLong, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetLong", "(Ljava/lang/Object;JJ)J") \
+ V(UnsafeGetAndSetObject, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetObject", "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;") \
+ V(UnsafeLoadFence, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "loadFence", "()V") \
+ V(UnsafeStoreFence, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "storeFence", "()V") \
+ V(UnsafeFullFence, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "fullFence", "()V") \
+ V(ReferenceGetReferent, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/ref/Reference;", "getReferent", "()Ljava/lang/Object;")
+
+#endif // ART_COMPILER_INTRINSICS_LIST_H_
+#undef ART_COMPILER_INTRINSICS_LIST_H_ // #define is only for lint.
instruction_set_features_.reset(InstructionSetFeatures::FromCppDefines());
}
cumulative_logger_.reset(new CumulativeLogger("jit times"));
- method_inliner_map_.reset(new DexFileToMethodInlinerMap);
compiler_driver_.reset(new CompilerDriver(
compiler_options_.get(),
/* verification_results */ nullptr,
- method_inliner_map_.get(),
Compiler::kOptimizing,
instruction_set,
instruction_set_features_.get(),
#include "base/mutex.h"
#include "compiled_method.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
private:
std::unique_ptr<CompilerOptions> compiler_options_;
std::unique_ptr<CumulativeLogger> cumulative_logger_;
- std::unique_ptr<DexFileToMethodInlinerMap> method_inliner_map_;
std::unique_ptr<CompilerDriver> compiler_driver_;
std::unique_ptr<const InstructionSetFeatures> instruction_set_features_;
std::unique_ptr<File> perf_file_;
#include "base/array_ref.h"
#include "base/macros.h"
#include "compiled_method.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "dex/verification_results.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
RelativePatcherTest(InstructionSet instruction_set, const std::string& variant)
: compiler_options_(),
verification_results_(&compiler_options_),
- inliner_map_(),
driver_(&compiler_options_,
&verification_results_,
- &inliner_map_,
Compiler::kQuick,
instruction_set,
/* instruction_set_features*/ nullptr,
CompilerOptions compiler_options_;
VerificationResults verification_results_;
- DexFileToMethodInlinerMap inliner_map_;
CompilerDriver driver_; // Needed for constructing CompiledMethod.
std::string error_msg_;
InstructionSet instruction_set_;
#include "compiled_method.h"
#include "compiler.h"
#include "debug/method_debug_info.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "dex/quick_compiler_callbacks.h"
#include "dex/verification_results.h"
#include "driver/compiler_driver.h"
compiler_options_->ParseCompilerOption(option, Usage);
}
verification_results_.reset(new VerificationResults(compiler_options_.get()));
- method_inliner_map_.reset(new DexFileToMethodInlinerMap);
callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
- method_inliner_map_.get(),
CompilerCallbacks::CallbackMode::kCompileApp));
Runtime::Current()->SetCompilerCallbacks(callbacks_.get());
timer_.reset(new CumulativeLogger("Compilation times"));
compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
verification_results_.get(),
- method_inliner_map_.get(),
compiler_kind,
insn_set,
insn_features_.get(),
HConstantFolding fold(callee_graph);
HSharpening sharpening(callee_graph, codegen_, dex_compilation_unit, compiler_driver_);
InstructionSimplifier simplify(callee_graph, stats_);
- IntrinsicsRecognizer intrinsics(callee_graph, compiler_driver_, stats_);
+ IntrinsicsRecognizer intrinsics(callee_graph, stats_);
HOptimization* optimizations[] = {
&intrinsics,
#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"
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"
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"
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"
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"
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
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;
}
}
-// 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();
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);
}
}
}
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;
// Recognize intrinsics from HInvoke nodes.
class IntrinsicsRecognizer : public HOptimization {
public:
- IntrinsicsRecognizer(HGraph* graph, CompilerDriver* driver, OptimizingCompilerStats* stats)
- : HOptimization(graph, kIntrinsicsRecognizerPassName, stats),
- driver_(driver) {}
+ IntrinsicsRecognizer(HGraph* graph, OptimizingCompilerStats* stats)
+ : HOptimization(graph, kIntrinsicsRecognizerPassName, stats) {}
void Run() OVERRIDE;
static constexpr const char* kIntrinsicsRecognizerPassName = "intrinsics_recognition";
private:
- CompilerDriver* driver_;
-
DISALLOW_COPY_AND_ASSIGN(IntrinsicsRecognizer);
};
switch (invoke->GetIntrinsic()) {
case Intrinsics::kNone:
return;
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, ...) \
case Intrinsics::k ## Name: \
Visit ## Name(invoke); \
return;
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, ...) \
virtual void Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
}
#include "intrinsics_list.h"
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+++ /dev/null
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_COMPILER_OPTIMIZING_INTRINSICS_LIST_H_
-#define ART_COMPILER_OPTIMIZING_INTRINSICS_LIST_H_
-
-// All intrinsics supported by the optimizing compiler. Format is name, then whether it is expected
-// to be a HInvokeStaticOrDirect node (compared to HInvokeVirtual), then whether it requires an
-// environment, may have side effects, or may throw exceptions.
-
-#define INTRINSICS_LIST(V) \
- V(DoubleDoubleToRawLongBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(DoubleDoubleToLongBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(DoubleIsInfinite, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(DoubleIsNaN, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(DoubleLongBitsToDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(FloatFloatToRawIntBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(FloatFloatToIntBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(FloatIsInfinite, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(FloatIsNaN, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(FloatIntBitsToFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerReverse, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerBitCount, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerCompare, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerHighestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerLowestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerNumberOfLeadingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerNumberOfTrailingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerRotateRight, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerRotateLeft, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerSignum, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongReverse, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongBitCount, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongCompare, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongHighestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongLowestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongNumberOfLeadingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongNumberOfTrailingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongRotateRight, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongRotateLeft, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongSignum, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(ShortReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathAbsDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathAbsFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathAbsLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathAbsInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathMinDoubleDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathMinFloatFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathMinLongLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathMinIntInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathMaxDoubleDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathMaxFloatFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathMaxLongLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathMaxIntInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathCos, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathSin, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathAcos, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathAsin, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathAtan, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathAtan2, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathCbrt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathCosh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathExp, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathExpm1, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathHypot, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathLog, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathLog10, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathNextAfter, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathSinh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathTan, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathTanh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathSqrt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathCeil, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathFloor, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathRint, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathRoundDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathRoundFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(SystemArrayCopyChar, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(SystemArrayCopy, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(ThreadCurrentThread, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MemoryPeekByte, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(MemoryPeekIntNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(MemoryPeekLongNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(MemoryPeekShortNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(MemoryPokeByte, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow) \
- V(MemoryPokeIntNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow) \
- V(MemoryPokeLongNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow) \
- V(MemoryPokeShortNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow) \
- V(StringCharAt, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(StringCompareTo, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(StringEquals, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(StringGetCharsNoCheck, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(StringIndexOf, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(StringIndexOfAfter, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(StringIsEmpty, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow) \
- V(StringLength, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow) \
- V(StringNewStringFromBytes, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(StringNewStringFromChars, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(StringNewStringFromString, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeCASInt, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeCASLong, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeCASObject, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGet, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetObject, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetObjectVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetLong, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetLongVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePut, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePutOrdered, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePutVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePutObject, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePutObjectOrdered, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePutObjectVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePutLong, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePutLongOrdered, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePutLongVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetAndAddInt, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetAndAddLong, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetAndSetInt, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetAndSetLong, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetAndSetObject, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeLoadFence, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeStoreFence, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeFullFence, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(ReferenceGetReferent, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow)
-
-#endif // ART_COMPILER_OPTIMIZING_INTRINSICS_LIST_H_
-#undef ART_COMPILER_OPTIMIZING_INTRINSICS_LIST_H_ // #define is only for lint.
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
#include "handle.h"
#include "handle_scope.h"
#include "invoke_type.h"
+#include "intrinsics_enum.h"
#include "locations.h"
#include "method_reference.h"
#include "mirror/class.h"
DISALLOW_COPY_AND_ASSIGN(HNewInstance);
};
-enum class Intrinsics {
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
- k ## Name,
-#include "intrinsics_list.h"
- kNone,
- INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
-#undef INTRINSICS_LIST
-#undef OPTIMIZING_INTRINSICS
-};
-std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic);
-
enum IntrinsicNeedsEnvironmentOrCache {
kNoEnvironmentOrCache, // Intrinsic does not require an environment or dex cache.
kNeedsEnvironmentOrCache // Intrinsic requires an environment or requires a dex cache.
#include "dead_code_elimination.h"
#include "debug/elf_debug_writer.h"
#include "debug/method_debug_info.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "dex/verification_results.h"
#include "dex/verified_method.h"
#include "driver/compiler_driver-inl.h"
} else if (opt_name == InstructionSimplifier::kInstructionSimplifierPassName) {
return new (arena) InstructionSimplifier(graph, stats, pass_name.c_str());
} else if (opt_name == IntrinsicsRecognizer::kIntrinsicsRecognizerPassName) {
- return new (arena) IntrinsicsRecognizer(graph, driver, stats);
+ return new (arena) IntrinsicsRecognizer(graph, stats);
} else if (opt_name == LICM::kLoopInvariantCodeMotionPassName) {
CHECK(most_recent_side_effects != nullptr);
return new (arena) LICM(graph, *most_recent_side_effects, stats);
graph, stats, "instruction_simplifier$after_bce");
InstructionSimplifier* simplify3 = new (arena) InstructionSimplifier(
graph, stats, "instruction_simplifier$before_codegen");
- IntrinsicsRecognizer* intrinsics = new (arena) IntrinsicsRecognizer(graph, driver, stats);
+ IntrinsicsRecognizer* intrinsics = new (arena) IntrinsicsRecognizer(graph, stats);
HOptimization* optimizations1[] = {
intrinsics,
#include "compiler_callbacks.h"
#include "debug/elf_debug_writer.h"
#include "debug/method_debug_info.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "dex/quick_compiler_callbacks.h"
#include "dex/verification_results.h"
#include "dex_file-inl.h"
image_patch_delta_(0),
key_value_store_(nullptr),
verification_results_(nullptr),
- method_inliner_map_(),
runtime_(nullptr),
thread_count_(sysconf(_SC_NPROCESSORS_CONF)),
start_ns_(NanoTime()),
verification_results_.reset(new VerificationResults(compiler_options_.get()));
callbacks_.reset(new QuickCompilerCallbacks(
verification_results_.get(),
- &method_inliner_map_,
IsBootImage() ?
CompilerCallbacks::CallbackMode::kCompileBootImage :
CompilerCallbacks::CallbackMode::kCompileApp));
driver_.reset(new CompilerDriver(compiler_options_.get(),
verification_results_.get(),
- &method_inliner_map_,
compiler_kind_,
instruction_set_,
instruction_set_features_.get(),
std::unique_ptr<VerificationResults> verification_results_;
- DexFileToMethodInlinerMap method_inliner_map_;
std::unique_ptr<QuickCompilerCallbacks> callbacks_;
std::unique_ptr<Runtime> runtime_;
return (GetAccessFlags() & kAccFinal) != 0;
}
+ bool IsIntrinsic() {
+ return (GetAccessFlags() & kAccIntrinsic) != 0;
+ }
+
+ void SetIntrinsic(uint32_t intrinsic) {
+ DCHECK(IsUint<8>(intrinsic));
+ uint32_t new_value = (GetAccessFlags() & kAccFlagsNotUsedByIntrinsic) |
+ kAccIntrinsic |
+ (intrinsic << POPCOUNT(kAccFlagsNotUsedByIntrinsic));
+ if (kIsDebugBuild) {
+ uint32_t java_flags = (GetAccessFlags() & kAccJavaFlagsMask);
+ bool is_constructor = IsConstructor();
+ bool is_synchronized = IsSynchronized();
+ bool skip_access_checks = SkipAccessChecks();
+ bool is_fast_native = IsFastNative();
+ bool is_copied = IsCopied();
+ bool is_miranda = IsMiranda();
+ bool is_default = IsDefault();
+ bool is_default_conflict = IsDefaultConflicting();
+ bool is_compilable = IsCompilable();
+ bool must_count_locks = MustCountLocks();
+ SetAccessFlags(new_value);
+ DCHECK_EQ(java_flags, (GetAccessFlags() & kAccJavaFlagsMask));
+ DCHECK_EQ(is_constructor, IsConstructor());
+ DCHECK_EQ(is_synchronized, IsSynchronized());
+ DCHECK_EQ(skip_access_checks, SkipAccessChecks());
+ DCHECK_EQ(is_fast_native, IsFastNative());
+ DCHECK_EQ(is_copied, IsCopied());
+ DCHECK_EQ(is_miranda, IsMiranda());
+ DCHECK_EQ(is_default, IsDefault());
+ DCHECK_EQ(is_default_conflict, IsDefaultConflicting());
+ DCHECK_EQ(is_compilable, IsCompilable());
+ DCHECK_EQ(must_count_locks, MustCountLocks());
+ } else {
+ SetAccessFlags(new_value);
+ }
+ }
+
+ uint32_t GetIntrinsic() {
+ DCHECK(IsIntrinsic());
+ return (GetAccessFlags() >> POPCOUNT(kAccFlagsNotUsedByIntrinsic)) & kAccMaxIntrinsic;
+ }
+
bool IsCopied() {
+ static_assert((kAccCopied & kAccFlagsNotUsedByIntrinsic) == kAccCopied,
+ "kAccCopied conflicts with intrinsic modifier");
const bool copied = (GetAccessFlags() & kAccCopied) != 0;
// (IsMiranda() || IsDefaultConflicting()) implies copied
DCHECK(!(IsMiranda() || IsDefaultConflicting()) || copied)
}
bool IsMiranda() {
+ static_assert((kAccMiranda & kAccFlagsNotUsedByIntrinsic) == kAccMiranda,
+ "kAccMiranda conflicts with intrinsic modifier");
return (GetAccessFlags() & kAccMiranda) != 0;
}
}
bool IsCompilable() {
+ if (IsIntrinsic()) {
+ return true;
+ }
return (GetAccessFlags() & kAccCompileDontBother) == 0;
}
// multiple default methods. It cannot be invoked, throwing an IncompatibleClassChangeError if one
// attempts to do so.
bool IsDefaultConflicting() {
+ if (IsIntrinsic()) {
+ return false;
+ }
return (GetAccessFlags() & kAccDefaultConflict) != 0u;
}
// This is set by the class linker.
bool IsDefault() {
+ static_assert((kAccDefault & kAccFlagsNotUsedByIntrinsic) == kAccDefault,
+ "kAccDefault conflicts with intrinsic modifier");
return (GetAccessFlags() & kAccDefault) != 0;
}
// Should this method be run in the interpreter and count locks (e.g., failed structured-
// locking verification)?
bool MustCountLocks() {
+ if (IsIntrinsic()) {
+ return false;
+ }
return (GetAccessFlags() & kAccMustCountLocks) != 0;
}
kAllocSpaceLock,
kBumpPointerSpaceBlockLock,
kArenaPoolLock,
- kDexFileMethodInlinerLock,
kDexFileToMethodInlinerMapLock,
kInternTableLock,
kOatFileSecondaryLookupLock,
namespace art {
const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '3', '0', '\0' };
+const uint8_t ImageHeader::kImageVersion[] = { '0', '3', '1', '\0' };
ImageHeader::ImageHeader(uint32_t image_begin,
uint32_t image_size,
// Set by the verifier for a method that could not be verified to follow structured locking.
static constexpr uint32_t kAccMustCountLocks = 0x02000000; // method (runtime)
+static constexpr uint32_t kAccIntrinsic = 0x80000000; // method (runtime)
// Special runtime-only flags.
// Interface and all its super-interfaces with default methods have been recursively initialized.
// class/ancestor overrides finalize()
static constexpr uint32_t kAccClassIsFinalizable = 0x80000000;
+static constexpr uint32_t kAccFlagsNotUsedByIntrinsic = 0x007FFFFF;
+static constexpr uint32_t kAccMaxIntrinsic = 0xFF;
+
// Valid (meaningful) bits for a field.
static constexpr uint32_t kAccValidFieldFlags = kAccPublic | kAccPrivate | kAccProtected |
kAccStatic | kAccFinal | kAccVolatile | kAccTransient | kAccSynthetic | kAccEnum;