dex_file_method_inliner.h revision b48b9eb6d181a1f52e2e605cf26a21505f1d46ed
15c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko/* 25c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Copyright (C) 2013 The Android Open Source Project 35c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * 45c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Licensed under the Apache License, Version 2.0 (the "License"); 55c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * you may not use this file except in compliance with the License. 65c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * You may obtain a copy of the License at 75c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * 85c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * http://www.apache.org/licenses/LICENSE-2.0 95c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * 105c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Unless required by applicable law or agreed to in writing, software 115c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * distributed under the License is distributed on an "AS IS" BASIS, 125c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * See the License for the specific language governing permissions and 145c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * limitations under the License. 155c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 165c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 175c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko#ifndef ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_ 185c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko#define ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_ 195c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 205c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko#include <stdint.h> 21e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko#include "base/mutex.h" 22e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko#include "base/macros.h" 23dce164adfbf679d7ec9c9dc778fa3fb596011740Ian Rogers#include "safe_map.h" 245816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko#include "dex/compiler_enums.h" 255816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko#include "dex_file.h" 26e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko#include "locks.h" 275c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 285c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Markonamespace art { 295c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 302bc47809febcf36369dd40877b8226318642b428Vladimir Markonamespace verifier { 312bc47809febcf36369dd40877b8226318642b428Vladimir Markoclass MethodVerifier; 322bc47809febcf36369dd40877b8226318642b428Vladimir Marko} // namespace verifier 332bc47809febcf36369dd40877b8226318642b428Vladimir Marko 34b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogersstruct CallInfo; 355c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Markoclass Mir2Lir; 365c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 375816ed48bc339c983b40dc493e96b97821ce7966Vladimir Markoenum InlineMethodOpcode : uint16_t { 385c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicDoubleCvt, 395c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicFloatCvt, 405c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicReverseBytes, 415c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicAbsInt, 425c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicAbsLong, 43dbb17e378b538133750e56375bbdbb217db7b248Yixin Shou kIntrinsicAbsFloat, 44dbb17e378b538133750e56375bbdbb217db7b248Yixin Shou kIntrinsicAbsDouble, 455c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicMinMaxInt, 465c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicSqrt, 475c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicCharAt, 485c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicCompareTo, 495c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicIsEmptyOrLength, 505c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicIndexOf, 515c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicCurrentThread, 525c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicPeek, 535c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicPoke, 541c282e2b9a9b432e132b2c332f861cad9feb4a73Vladimir Marko kIntrinsicCas, 555c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicUnsafeGet, 565c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicUnsafePut, 575816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko 585816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko kInlineOpNop, 595816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko kInlineOpReturnArg, 603bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru kInlineOpNonWideConst, 615816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko kInlineOpIGet, 625816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko kInlineOpIPut, 635816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko}; 64b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogersstd::ostream& operator<<(std::ostream& os, const InlineMethodOpcode& rhs); 655816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko 66dce164adfbf679d7ec9c9dc778fa3fb596011740Ian Rogersenum InlineMethodFlags : uint16_t { 67dce164adfbf679d7ec9c9dc778fa3fb596011740Ian Rogers kNoInlineMethodFlags = 0x0000, 68dce164adfbf679d7ec9c9dc778fa3fb596011740Ian Rogers kInlineIntrinsic = 0x0001, 69dce164adfbf679d7ec9c9dc778fa3fb596011740Ian Rogers kInlineSpecial = 0x0002, 705816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko}; 715816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko 722bc47809febcf36369dd40877b8226318642b428Vladimir Marko// IntrinsicFlags are stored in InlineMethod::d::raw_data 735c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Markoenum IntrinsicFlags { 745c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicFlagNone = 0, 755c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 765c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko // kIntrinsicMinMaxInt 775c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicFlagMax = kIntrinsicFlagNone, 785c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicFlagMin = 1, 795c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 805c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko // kIntrinsicIsEmptyOrLength 815c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicFlagLength = kIntrinsicFlagNone, 82b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogers kIntrinsicFlagIsEmpty = kIntrinsicFlagMin, 835c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 845c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko // kIntrinsicIndexOf 85b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogers kIntrinsicFlagBase0 = kIntrinsicFlagMin, 865c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 871c282e2b9a9b432e132b2c332f861cad9feb4a73Vladimir Marko // kIntrinsicUnsafeGet, kIntrinsicUnsafePut, kIntrinsicUnsafeCas 88b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogers kIntrinsicFlagIsLong = kIntrinsicFlagMin, 891c282e2b9a9b432e132b2c332f861cad9feb4a73Vladimir Marko // kIntrinsicUnsafeGet, kIntrinsicUnsafePut 905c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicFlagIsVolatile = 2, 911c282e2b9a9b432e132b2c332f861cad9feb4a73Vladimir Marko // kIntrinsicUnsafePut, kIntrinsicUnsafeCas 925c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicFlagIsObject = 4, 931c282e2b9a9b432e132b2c332f861cad9feb4a73Vladimir Marko // kIntrinsicUnsafePut 945c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kIntrinsicFlagIsOrdered = 8, 955c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko}; 965c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 975816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko// Check that OpSize fits into 3 bits (at least the values the inliner uses). 985816ed48bc339c983b40dc493e96b97821ce7966Vladimir MarkoCOMPILE_ASSERT(kWord < 8 && kLong < 8 && kSingle < 8 && kDouble < 8 && kUnsignedHalf < 8 && 995816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko kSignedHalf < 8 && kUnsignedByte < 8 && kSignedByte < 8, op_size_field_too_narrow); 1005816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko 1012bc47809febcf36369dd40877b8226318642b428Vladimir Markostruct InlineIGetIPutData { 1022bc47809febcf36369dd40877b8226318642b428Vladimir Marko uint16_t op_size : 3; // OpSize 1032bc47809febcf36369dd40877b8226318642b428Vladimir Marko uint16_t is_object : 1; 1042bc47809febcf36369dd40877b8226318642b428Vladimir Marko uint16_t object_arg : 4; 1052bc47809febcf36369dd40877b8226318642b428Vladimir Marko uint16_t src_arg : 4; // iput only 1062bc47809febcf36369dd40877b8226318642b428Vladimir Marko uint16_t method_is_static : 1; 1072bc47809febcf36369dd40877b8226318642b428Vladimir Marko uint16_t reserved : 3; 1082bc47809febcf36369dd40877b8226318642b428Vladimir Marko uint16_t field_idx; 1092bc47809febcf36369dd40877b8226318642b428Vladimir Marko uint32_t is_volatile : 1; 1102bc47809febcf36369dd40877b8226318642b428Vladimir Marko uint32_t field_offset : 31; 1115dc5727261e87ba8a418e2d0e970c75f67e4ab79Vladimir Marko}; 1122bc47809febcf36369dd40877b8226318642b428Vladimir MarkoCOMPILE_ASSERT(sizeof(InlineIGetIPutData) == sizeof(uint64_t), InvalidSizeOfInlineIGetIPutData); 1132bc47809febcf36369dd40877b8226318642b428Vladimir Marko 1142bc47809febcf36369dd40877b8226318642b428Vladimir Markostruct InlineReturnArgData { 1152bc47809febcf36369dd40877b8226318642b428Vladimir Marko uint16_t arg; 1162bc47809febcf36369dd40877b8226318642b428Vladimir Marko uint16_t op_size : 3; // OpSize 1172bc47809febcf36369dd40877b8226318642b428Vladimir Marko uint16_t is_object : 1; 1182bc47809febcf36369dd40877b8226318642b428Vladimir Marko uint16_t reserved : 12; 1192bc47809febcf36369dd40877b8226318642b428Vladimir Marko uint32_t reserved2; 1202bc47809febcf36369dd40877b8226318642b428Vladimir Marko}; 1212bc47809febcf36369dd40877b8226318642b428Vladimir MarkoCOMPILE_ASSERT(sizeof(InlineReturnArgData) == sizeof(uint64_t), InvalidSizeOfInlineReturnArgData); 1222bc47809febcf36369dd40877b8226318642b428Vladimir Marko 1232bc47809febcf36369dd40877b8226318642b428Vladimir Markostruct InlineMethod { 1242bc47809febcf36369dd40877b8226318642b428Vladimir Marko InlineMethodOpcode opcode; 1252bc47809febcf36369dd40877b8226318642b428Vladimir Marko InlineMethodFlags flags; 1262bc47809febcf36369dd40877b8226318642b428Vladimir Marko union { 1272bc47809febcf36369dd40877b8226318642b428Vladimir Marko uint64_t data; 1282bc47809febcf36369dd40877b8226318642b428Vladimir Marko InlineIGetIPutData ifield_data; 1292bc47809febcf36369dd40877b8226318642b428Vladimir Marko InlineReturnArgData return_data; 1305816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko } d; 1315816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko}; 1325c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 1335c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko/** 1345c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Handles inlining of methods from a particular DexFile. 1355c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * 1365c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Intrinsics are a special case of inline methods. The DexFile indices for 1375c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * all the supported intrinsic methods are looked up once by the FindIntrinsics 1385c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * function and cached by this class for quick lookup by the method index. 1395c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * 1405c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * TODO: Detect short methods (at least getters, setters and empty functions) 1415c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * from the verifier and mark them for inlining. Inline these methods early 1425c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * during compilation to allow further optimizations. Similarly, provide 1435c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * additional information about intrinsics to the early phases of compilation. 1445c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 1455c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Markoclass DexFileMethodInliner { 1465c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko public: 147867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko DexFileMethodInliner(); 148867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko ~DexFileMethodInliner(); 1495c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 1505c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 1515816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko * Analyse method code to determine if the method is a candidate for inlining. 1525816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko * If it is, record its data for later. 1535816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko * 15484c072c348006d87a370ad6e746e2d976cbe62f2Vladimir Marko * @param verifier the method verifier holding data about the method to analyse. 15584c072c348006d87a370ad6e746e2d976cbe62f2Vladimir Marko * @return true if the method is a candidate for inlining, false otherwise. 1565816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko */ 1572bc47809febcf36369dd40877b8226318642b428Vladimir Marko bool AnalyseMethodCode(verifier::MethodVerifier* verifier) 1582bc47809febcf36369dd40877b8226318642b428Vladimir Marko SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCKS_EXCLUDED(lock_); 1595816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko 1605816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko /** 16184c072c348006d87a370ad6e746e2d976cbe62f2Vladimir Marko * Analyse method code to determine if the method is a candidate for inlining. 16284c072c348006d87a370ad6e746e2d976cbe62f2Vladimir Marko * If it is, record the inlining data. 16384c072c348006d87a370ad6e746e2d976cbe62f2Vladimir Marko * 16484c072c348006d87a370ad6e746e2d976cbe62f2Vladimir Marko * @param verifier the method verifier holding data about the method to analyse. 16584c072c348006d87a370ad6e746e2d976cbe62f2Vladimir Marko * @param method placeholder for the inline method data. 16684c072c348006d87a370ad6e746e2d976cbe62f2Vladimir Marko * @return true if the method is a candidate for inlining, false otherwise. 16784c072c348006d87a370ad6e746e2d976cbe62f2Vladimir Marko */ 16884c072c348006d87a370ad6e746e2d976cbe62f2Vladimir Marko bool AnalyseMethodCode(verifier::MethodVerifier* verifier, InlineMethod* method) 16984c072c348006d87a370ad6e746e2d976cbe62f2Vladimir Marko SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCKS_EXCLUDED(lock_); 17084c072c348006d87a370ad6e746e2d976cbe62f2Vladimir Marko 17184c072c348006d87a370ad6e746e2d976cbe62f2Vladimir Marko /** 1725c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Check whether a particular method index corresponds to an intrinsic function. 1735c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 174e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko bool IsIntrinsic(uint32_t method_index) LOCKS_EXCLUDED(lock_); 1755c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 1765c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 1775c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Generate code for an intrinsic function invocation. 1785c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 179e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko bool GenIntrinsic(Mir2Lir* backend, CallInfo* info) LOCKS_EXCLUDED(lock_); 1805c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 1815816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko /** 1825816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko * Check whether a particular method index corresponds to a special function. 1835816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko */ 1845816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko bool IsSpecial(uint32_t method_index) LOCKS_EXCLUDED(lock_); 1855816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko 1865816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko /** 1875816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko * Generate code for a special function. 1885816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko */ 1895816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko bool GenSpecial(Mir2Lir* backend, uint32_t method_idx); 1905816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko 1915c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 1925c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * To avoid multiple lookups of a class by its descriptor, we cache its 1935c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * type index in the IndexCache. These are the indexes into the IndexCache 1945c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * class_indexes array. 1955c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 1965c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko enum ClassCacheIndex : uint8_t { // unit8_t to save space, make larger if needed 1975c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheFirst = 0, 1985c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheBoolean = kClassCacheFirst, 1995c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheByte, 2005c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheChar, 2015c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheShort, 2025c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheInt, 2035c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheLong, 2045c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheFloat, 2055c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheDouble, 2065c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheVoid, 2075c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangObject, 2085c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangString, 2095c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangDouble, 2105c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangFloat, 2115c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangInteger, 2125c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangLong, 2135c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangShort, 2145c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangMath, 2155c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangStrictMath, 2165c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangThread, 2175c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheLibcoreIoMemory, 2185c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheSunMiscUnsafe, 2195c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheLast 2205c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 2215c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 2225c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 2235c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * To avoid multiple lookups of a method name string, we cache its string 2245c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * index in the IndexCache. These are the indexes into the IndexCache 2255c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * name_indexes array. 2265c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 2275c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko enum NameCacheIndex : uint8_t { // unit8_t to save space, make larger if needed 2285c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheFirst = 0, 2295c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheReverseBytes = kNameCacheFirst, 2305c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheDoubleToRawLongBits, 2315c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheLongBitsToDouble, 2325c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheFloatToRawIntBits, 2335c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheIntBitsToFloat, 2345c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheAbs, 2355c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheMax, 2365c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheMin, 2375c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheSqrt, 2385c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheCharAt, 2395c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheCompareTo, 2405c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheIsEmpty, 2415c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheIndexOf, 2425c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheLength, 2435c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheCurrentThread, 2445c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePeekByte, 2455c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePeekIntNative, 2465c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePeekLongNative, 2475c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePeekShortNative, 2485c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePokeByte, 2495c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePokeIntNative, 2505c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePokeLongNative, 2515c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePokeShortNative, 2525c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheCompareAndSwapInt, 2531c282e2b9a9b432e132b2c332f861cad9feb4a73Vladimir Marko kNameCacheCompareAndSwapLong, 2545c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheCompareAndSwapObject, 2555c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetInt, 2565c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetIntVolatile, 2575c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutInt, 2585c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutIntVolatile, 2595c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutOrderedInt, 2605c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetLong, 2615c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetLongVolatile, 2625c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutLong, 2635c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutLongVolatile, 2645c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutOrderedLong, 2655c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetObject, 2665c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetObjectVolatile, 2675c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutObject, 2685c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutObjectVolatile, 2695c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutOrderedObject, 2705c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheLast 2715c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 2725c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 2735c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 2745c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * To avoid multiple lookups of a method signature, we cache its proto 2755c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * index in the IndexCache. These are the indexes into the IndexCache 2765c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * proto_indexes array. 2775c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 2785c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko enum ProtoCacheIndex : uint8_t { // unit8_t to save space, make larger if needed 2795c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheFirst = 0, 2805c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheI_I = kProtoCacheFirst, 2815c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJ_J, 2825c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheS_S, 2835c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheD_D, 284dbb17e378b538133750e56375bbdbb217db7b248Yixin Shou kProtoCacheF_F, 2855c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheD_J, 2865c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJ_D, 2875c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheF_I, 2885c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheI_F, 2895c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheII_I, 2905c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheI_C, 2915c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheString_I, 2925c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCache_Z, 2935c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCache_I, 2945c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCache_Thread, 2955c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJ_B, 2965c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJ_I, 2975c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJ_S, 2985c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJB_V, 2995c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJI_V, 3005c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJJ_V, 3015c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJS_V, 3025c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJII_Z, 3031c282e2b9a9b432e132b2c332f861cad9feb4a73Vladimir Marko kProtoCacheObjectJJJ_Z, 3045c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJObjectObject_Z, 3055c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJ_I, 3065c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJI_V, 3075c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJ_J, 3085c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJJ_V, 3095c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJ_Object, 3105c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJObject_V, 3115c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheLast 3125c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 3135c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 314b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogers private: 3155c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 3165c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The maximum number of method parameters we support in the ProtoDef. 3175c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 3185c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static constexpr uint32_t kProtoMaxParams = 6; 3195c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3205c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 3215c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The method signature (proto) definition using cached class indexes. 3225c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The return_type and params are used with the IndexCache to look up 3235c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * appropriate class indexes to be passed to DexFile::FindProtoId(). 3245c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 3255c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko struct ProtoDef { 3265c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ClassCacheIndex return_type; 3275c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko uint8_t param_count; 3285c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ClassCacheIndex params[kProtoMaxParams]; 3295c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 3305c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3315c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 3325c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The method definition using cached class, name and proto indexes. 3335c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The class index, method name index and proto index are used with 3345c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * IndexCache to look up appropriate parameters for DexFile::FindMethodId(). 3355c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 3365c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko struct MethodDef { 3375c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ClassCacheIndex declaring_class; 3385c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko NameCacheIndex name; 3395c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ProtoCacheIndex proto; 3405c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 3415c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3425c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 3435c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The definition of an intrinsic function binds the method definition 3445c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * to an Intrinsic. 3455c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 3465c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko struct IntrinsicDef { 3475c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko MethodDef method_def; 3485816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko InlineMethod intrinsic; 3495c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 3505c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3515c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 3525c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Cache for class, method name and method signature indexes used during 3535c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * intrinsic function lookup to avoid multiple lookups of the same items. 3545c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * 3555c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Many classes have multiple intrinsics and/or they are used in multiple 3565c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * method signatures and we want to avoid repeated lookups since they are 3575c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * not exactly cheap. The method names and method signatures are sometimes 3585c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * reused and therefore cached as well. 3595c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 3605c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko struct IndexCache { 3615c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko IndexCache(); 3625c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3635c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko uint32_t class_indexes[kClassCacheLast - kClassCacheFirst]; 3645c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko uint32_t name_indexes[kNameCacheLast - kNameCacheFirst]; 3655c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko uint32_t proto_indexes[kProtoCacheLast - kProtoCacheFirst]; 3665c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 3675c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3685816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko static const char* const kClassCacheNames[]; 3695816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko static const char* const kNameCacheNames[]; 3705c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static const ProtoDef kProtoCacheDefs[]; 371867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko static const IntrinsicDef kIntrinsicMethods[]; 3725c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3735c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static const uint32_t kIndexNotFound = static_cast<uint32_t>(-1); 3745c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static const uint32_t kIndexUnresolved = static_cast<uint32_t>(-2); 3755c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3765c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static uint32_t FindClassIndex(const DexFile* dex_file, IndexCache* cache, 3775c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ClassCacheIndex index); 3785c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static uint32_t FindNameIndex(const DexFile* dex_file, IndexCache* cache, 3795c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko NameCacheIndex index); 3805c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static uint32_t FindProtoIndex(const DexFile* dex_file, IndexCache* cache, 3815c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ProtoCacheIndex index); 3825c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static uint32_t FindMethodIndex(const DexFile* dex_file, IndexCache* cache, 3835c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko const MethodDef& method_def); 3845c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 385867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko /** 386867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko * Find all known intrinsic methods in the dex_file and cache their indices. 387867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko * 388867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko * Only DexFileToMethodInlinerMap may call this function to initialize the inliner. 389867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko */ 390e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko void FindIntrinsics(const DexFile* dex_file) EXCLUSIVE_LOCKS_REQUIRED(lock_); 391867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko 392867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko friend class DexFileToMethodInlinerMap; 3935c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3942bc47809febcf36369dd40877b8226318642b428Vladimir Marko bool AddInlineMethod(int32_t method_idx, const InlineMethod& method) LOCKS_EXCLUDED(lock_); 3952bc47809febcf36369dd40877b8226318642b428Vladimir Marko 3962bc47809febcf36369dd40877b8226318642b428Vladimir Marko static bool AnalyseReturnMethod(const DexFile::CodeItem* code_item, InlineMethod* result); 3972bc47809febcf36369dd40877b8226318642b428Vladimir Marko static bool AnalyseConstMethod(const DexFile::CodeItem* code_item, InlineMethod* result); 3982bc47809febcf36369dd40877b8226318642b428Vladimir Marko static bool AnalyseIGetMethod(verifier::MethodVerifier* verifier, InlineMethod* result) 3992bc47809febcf36369dd40877b8226318642b428Vladimir Marko SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 4002bc47809febcf36369dd40877b8226318642b428Vladimir Marko static bool AnalyseIPutMethod(verifier::MethodVerifier* verifier, InlineMethod* result) 4012bc47809febcf36369dd40877b8226318642b428Vladimir Marko SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 4025816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko 403e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko ReaderWriterMutex lock_; 4045c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /* 4055c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Maps method indexes (for the particular DexFile) to Intrinsic defintions. 4065c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 407dce164adfbf679d7ec9c9dc778fa3fb596011740Ian Rogers SafeMap<uint32_t, InlineMethod> inline_methods_ GUARDED_BY(lock_); 4085c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko const DexFile* dex_file_; 409867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko 410867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko DISALLOW_COPY_AND_ASSIGN(DexFileMethodInliner); 4115c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko}; 4125c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 4135c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko} // namespace art 4145c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 4155c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko#endif // ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_ 416