dex_file_method_inliner.h revision 23abec955e2e733999a1e2c30e4e384e46e5dde4
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" 26e3e0260c23d8999b9433715ac7ee5296ee2fd633Vladimir Marko#include "quick/inline_method_analyser.h" 275c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 285c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Markonamespace art { 295c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 302bc47809febcf36369dd40877b8226318642b428Vladimir Markonamespace verifier { 312bc47809febcf36369dd40877b8226318642b428Vladimir Markoclass MethodVerifier; 322bc47809febcf36369dd40877b8226318642b428Vladimir Marko} // namespace verifier 332bc47809febcf36369dd40877b8226318642b428Vladimir Marko 349820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Markostruct BasicBlock; 35b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogersstruct CallInfo; 369820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Markostruct MIR; 379820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Markoclass MIRGraph; 385c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Markoclass Mir2Lir; 395c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 405c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko/** 415c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Handles inlining of methods from a particular DexFile. 425c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * 435c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Intrinsics are a special case of inline methods. The DexFile indices for 445c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * all the supported intrinsic methods are looked up once by the FindIntrinsics 455c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * function and cached by this class for quick lookup by the method index. 465c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * 475c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * TODO: Detect short methods (at least getters, setters and empty functions) 485c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * from the verifier and mark them for inlining. Inline these methods early 495c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * during compilation to allow further optimizations. Similarly, provide 505c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * additional information about intrinsics to the early phases of compilation. 515c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 525c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Markoclass DexFileMethodInliner { 535c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko public: 54867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko DexFileMethodInliner(); 55867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko ~DexFileMethodInliner(); 565c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 575c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 585816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko * Analyse method code to determine if the method is a candidate for inlining. 595816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko * If it is, record its data for later. 605816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko * 6184c072c348006d87a370ad6e746e2d976cbe62f2Vladimir Marko * @param verifier the method verifier holding data about the method to analyse. 6284c072c348006d87a370ad6e746e2d976cbe62f2Vladimir Marko * @return true if the method is a candidate for inlining, false otherwise. 635816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko */ 642bc47809febcf36369dd40877b8226318642b428Vladimir Marko bool AnalyseMethodCode(verifier::MethodVerifier* verifier) 652bc47809febcf36369dd40877b8226318642b428Vladimir Marko SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCKS_EXCLUDED(lock_); 665816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko 675816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko /** 685c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Check whether a particular method index corresponds to an intrinsic function. 695c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 707071c8d5885175a746723a3b38a347855965be08Yixin Shou bool IsIntrinsic(uint32_t method_index, InlineMethod* intrinsic) LOCKS_EXCLUDED(lock_); 715c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 725c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 735c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Generate code for an intrinsic function invocation. 745c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 75e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko bool GenIntrinsic(Mir2Lir* backend, CallInfo* info) LOCKS_EXCLUDED(lock_); 765c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 775816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko /** 785816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko * Check whether a particular method index corresponds to a special function. 795816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko */ 805816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko bool IsSpecial(uint32_t method_index) LOCKS_EXCLUDED(lock_); 815816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko 825816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko /** 835816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko * Generate code for a special function. 845816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko */ 859820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko bool GenSpecial(Mir2Lir* backend, uint32_t method_idx) LOCKS_EXCLUDED(lock_); 869820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko 879820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko /** 889820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko * Try to inline an invoke. 899820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko */ 909820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko bool GenInline(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, uint32_t method_idx) 919820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko LOCKS_EXCLUDED(lock_); 925816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko 935c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 945c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * To avoid multiple lookups of a class by its descriptor, we cache its 955c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * type index in the IndexCache. These are the indexes into the IndexCache 965c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * class_indexes array. 975c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 985c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko enum ClassCacheIndex : uint8_t { // unit8_t to save space, make larger if needed 995c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheFirst = 0, 1005c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheBoolean = kClassCacheFirst, 1015c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheByte, 1025c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheChar, 1035c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheShort, 1045c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheInt, 1055c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheLong, 1065c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheFloat, 1075c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheDouble, 1085c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheVoid, 1095c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangObject, 1105c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangString, 1115c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangDouble, 1125c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangFloat, 1135c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangInteger, 1145c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangLong, 1155c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangShort, 1165c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangMath, 1175c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangStrictMath, 1185c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangThread, 1195c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheLibcoreIoMemory, 1205c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheSunMiscUnsafe, 1215c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheLast 1225c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 1235c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 1245c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 1255c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * To avoid multiple lookups of a method name string, we cache its string 1265c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * index in the IndexCache. These are the indexes into the IndexCache 1275c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * name_indexes array. 1285c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 1295c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko enum NameCacheIndex : uint8_t { // unit8_t to save space, make larger if needed 1305c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheFirst = 0, 13123abec955e2e733999a1e2c30e4e384e46e5dde4Serban Constantinescu kNameCacheReverse = kNameCacheFirst, 13223abec955e2e733999a1e2c30e4e384e46e5dde4Serban Constantinescu kNameCacheReverseBytes, 1335c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheDoubleToRawLongBits, 1345c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheLongBitsToDouble, 1355c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheFloatToRawIntBits, 1365c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheIntBitsToFloat, 1375c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheAbs, 1385c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheMax, 1395c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheMin, 1405c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheSqrt, 1415c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheCharAt, 1425c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheCompareTo, 1435c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheIsEmpty, 1445c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheIndexOf, 1455c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheLength, 1465c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheCurrentThread, 1475c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePeekByte, 1485c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePeekIntNative, 1495c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePeekLongNative, 1505c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePeekShortNative, 1515c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePokeByte, 1525c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePokeIntNative, 1535c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePokeLongNative, 1545c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePokeShortNative, 1555c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheCompareAndSwapInt, 1561c282e2b9a9b432e132b2c332f861cad9feb4a73Vladimir Marko kNameCacheCompareAndSwapLong, 1575c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheCompareAndSwapObject, 1585c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetInt, 1595c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetIntVolatile, 1605c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutInt, 1615c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutIntVolatile, 1625c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutOrderedInt, 1635c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetLong, 1645c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetLongVolatile, 1655c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutLong, 1665c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutLongVolatile, 1675c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutOrderedLong, 1685c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetObject, 1695c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetObjectVolatile, 1705c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutObject, 1715c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutObjectVolatile, 1725c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutOrderedObject, 1735c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheLast 1745c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 1755c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 1765c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 1775c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * To avoid multiple lookups of a method signature, we cache its proto 1785c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * index in the IndexCache. These are the indexes into the IndexCache 1795c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * proto_indexes array. 1805c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 1815c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko enum ProtoCacheIndex : uint8_t { // unit8_t to save space, make larger if needed 1825c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheFirst = 0, 1835c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheI_I = kProtoCacheFirst, 1845c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJ_J, 1855c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheS_S, 1865c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheD_D, 18723abec955e2e733999a1e2c30e4e384e46e5dde4Serban Constantinescu kProtoCacheDD_D, 188dbb17e378b538133750e56375bbdbb217db7b248Yixin Shou kProtoCacheF_F, 18923abec955e2e733999a1e2c30e4e384e46e5dde4Serban Constantinescu kProtoCacheFF_F, 1905c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheD_J, 1915c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJ_D, 1925c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheF_I, 1935c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheI_F, 1945c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheII_I, 1955c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheI_C, 1965c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheString_I, 1975c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCache_Z, 1985c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCache_I, 1995c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCache_Thread, 2005c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJ_B, 2015c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJ_I, 2025c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJ_S, 2035c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJB_V, 2045c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJI_V, 20523abec955e2e733999a1e2c30e4e384e46e5dde4Serban Constantinescu kProtoCacheJJ_J, 2065c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJJ_V, 2075c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJS_V, 2085c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJII_Z, 2091c282e2b9a9b432e132b2c332f861cad9feb4a73Vladimir Marko kProtoCacheObjectJJJ_Z, 2105c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJObjectObject_Z, 2115c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJ_I, 2125c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJI_V, 2135c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJ_J, 2145c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJJ_V, 2155c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJ_Object, 2165c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJObject_V, 2175c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheLast 2185c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 2195c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 220b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogers private: 2215c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 2225c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The maximum number of method parameters we support in the ProtoDef. 2235c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 2245c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static constexpr uint32_t kProtoMaxParams = 6; 2255c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 2265c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 2275c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The method signature (proto) definition using cached class indexes. 2285c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The return_type and params are used with the IndexCache to look up 2295c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * appropriate class indexes to be passed to DexFile::FindProtoId(). 2305c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 2315c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko struct ProtoDef { 2325c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ClassCacheIndex return_type; 2335c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko uint8_t param_count; 2345c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ClassCacheIndex params[kProtoMaxParams]; 2355c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 2365c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 2375c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 2385c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The method definition using cached class, name and proto indexes. 2395c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The class index, method name index and proto index are used with 2405c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * IndexCache to look up appropriate parameters for DexFile::FindMethodId(). 2415c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 2425c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko struct MethodDef { 2435c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ClassCacheIndex declaring_class; 2445c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko NameCacheIndex name; 2455c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ProtoCacheIndex proto; 2465c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 2475c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 2485c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 2495c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The definition of an intrinsic function binds the method definition 2505c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * to an Intrinsic. 2515c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 2525c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko struct IntrinsicDef { 2535c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko MethodDef method_def; 2545816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko InlineMethod intrinsic; 2555c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 2565c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 2575c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 2585c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Cache for class, method name and method signature indexes used during 2595c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * intrinsic function lookup to avoid multiple lookups of the same items. 2605c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * 2615c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Many classes have multiple intrinsics and/or they are used in multiple 2625c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * method signatures and we want to avoid repeated lookups since they are 2635c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * not exactly cheap. The method names and method signatures are sometimes 2645c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * reused and therefore cached as well. 2655c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 2665c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko struct IndexCache { 2675c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko IndexCache(); 2685c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 2695c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko uint32_t class_indexes[kClassCacheLast - kClassCacheFirst]; 2705c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko uint32_t name_indexes[kNameCacheLast - kNameCacheFirst]; 2715c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko uint32_t proto_indexes[kProtoCacheLast - kProtoCacheFirst]; 2725c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 2735c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 2745816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko static const char* const kClassCacheNames[]; 2755816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko static const char* const kNameCacheNames[]; 2765c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static const ProtoDef kProtoCacheDefs[]; 277867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko static const IntrinsicDef kIntrinsicMethods[]; 2785c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 2795c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static const uint32_t kIndexNotFound = static_cast<uint32_t>(-1); 2805c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static const uint32_t kIndexUnresolved = static_cast<uint32_t>(-2); 2815c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 2825c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static uint32_t FindClassIndex(const DexFile* dex_file, IndexCache* cache, 2835c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ClassCacheIndex index); 2845c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static uint32_t FindNameIndex(const DexFile* dex_file, IndexCache* cache, 2855c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko NameCacheIndex index); 2865c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static uint32_t FindProtoIndex(const DexFile* dex_file, IndexCache* cache, 2875c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ProtoCacheIndex index); 2885c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static uint32_t FindMethodIndex(const DexFile* dex_file, IndexCache* cache, 2895c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko const MethodDef& method_def); 2905c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 291867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko /** 292867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko * Find all known intrinsic methods in the dex_file and cache their indices. 293867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko * 294867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko * Only DexFileToMethodInlinerMap may call this function to initialize the inliner. 295867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko */ 296e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko void FindIntrinsics(const DexFile* dex_file) EXCLUSIVE_LOCKS_REQUIRED(lock_); 297867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko 298867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko friend class DexFileToMethodInlinerMap; 2995c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3002bc47809febcf36369dd40877b8226318642b428Vladimir Marko bool AddInlineMethod(int32_t method_idx, const InlineMethod& method) LOCKS_EXCLUDED(lock_); 3012bc47809febcf36369dd40877b8226318642b428Vladimir Marko 3029820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko static bool GenInlineConst(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, 3039820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko MIR* move_result, const InlineMethod& method); 3049820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko static bool GenInlineReturnArg(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, 3059820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko MIR* move_result, const InlineMethod& method); 3069820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko static bool GenInlineIGet(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, 3079820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko MIR* move_result, const InlineMethod& method, uint32_t method_idx); 3089820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko static bool GenInlineIPut(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, 309e1fced1d1805caec04b6e97d2b01a4977c6785c6Vladimir Marko MIR* move_result, const InlineMethod& method, uint32_t method_idx); 3109820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko 311e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko ReaderWriterMutex lock_; 3125c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /* 3135c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Maps method indexes (for the particular DexFile) to Intrinsic defintions. 3145c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 315dce164adfbf679d7ec9c9dc778fa3fb596011740Ian Rogers SafeMap<uint32_t, InlineMethod> inline_methods_ GUARDED_BY(lock_); 3165c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko const DexFile* dex_file_; 317867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko 318867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko DISALLOW_COPY_AND_ASSIGN(DexFileMethodInliner); 3195c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko}; 3205c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3215c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko} // namespace art 3225c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3235c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko#endif // ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_ 324