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 346a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersclass BasicBlock; 35b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogersstruct CallInfo; 366a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersclass 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 /** 6887b7c52ac660119b8dea46967974b76c86d0750bVladimir Marko * Check whether a particular method index corresponds to an intrinsic or special function. 6987b7c52ac660119b8dea46967974b76c86d0750bVladimir Marko */ 7087b7c52ac660119b8dea46967974b76c86d0750bVladimir Marko InlineMethodFlags IsIntrinsicOrSpecial(uint32_t method_index) LOCKS_EXCLUDED(lock_); 7187b7c52ac660119b8dea46967974b76c86d0750bVladimir Marko 7287b7c52ac660119b8dea46967974b76c86d0750bVladimir Marko /** 735c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Check whether a particular method index corresponds to an intrinsic function. 745c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 757071c8d5885175a746723a3b38a347855965be08Yixin Shou bool IsIntrinsic(uint32_t method_index, InlineMethod* intrinsic) LOCKS_EXCLUDED(lock_); 765c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 775c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 785c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Generate code for an intrinsic function invocation. 795c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 80e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko bool GenIntrinsic(Mir2Lir* backend, CallInfo* info) LOCKS_EXCLUDED(lock_); 815c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 825816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko /** 835816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko * Check whether a particular method index corresponds to a special function. 845816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko */ 855816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko bool IsSpecial(uint32_t method_index) LOCKS_EXCLUDED(lock_); 865816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko 875816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko /** 885816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko * Generate code for a special function. 895816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko */ 909820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko bool GenSpecial(Mir2Lir* backend, uint32_t method_idx) LOCKS_EXCLUDED(lock_); 919820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko 929820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko /** 939820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko * Try to inline an invoke. 949820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko */ 959820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko bool GenInline(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, uint32_t method_idx) 969820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko LOCKS_EXCLUDED(lock_); 975816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko 985c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 99848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao * Gets the thread pointer entrypoint offset for a string init method index and pointer size. 100848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao */ 101848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao uint32_t GetOffsetForStringInit(uint32_t method_index, size_t pointer_size) 102848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao LOCKS_EXCLUDED(lock_); 103848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao 104848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao /** 105848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao * Check whether a particular method index is a string init. 106848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao */ 107848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao bool IsStringInitMethodIndex(uint32_t method_index) LOCKS_EXCLUDED(lock_); 108848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao 109848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao /** 1105c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * To avoid multiple lookups of a class by its descriptor, we cache its 1115c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * type index in the IndexCache. These are the indexes into the IndexCache 1125c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * class_indexes array. 1135c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 1145c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko enum ClassCacheIndex : uint8_t { // unit8_t to save space, make larger if needed 1155c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheFirst = 0, 1165c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheBoolean = kClassCacheFirst, 1175c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheByte, 1185c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheChar, 1195c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheShort, 1205c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheInt, 1215c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheLong, 1225c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheFloat, 1235c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheDouble, 1245c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheVoid, 125848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kClassCacheJavaLangByteArray, 126848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kClassCacheJavaLangCharArray, 127848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kClassCacheJavaLangIntArray, 1285c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangObject, 1294ee7a665e7f9cd2c5ace2d6304e33f64067b209fFred Shih kClassCacheJavaLangRefReference, 1305c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangString, 131848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kClassCacheJavaLangStringBuffer, 132848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kClassCacheJavaLangStringBuilder, 133848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kClassCacheJavaLangStringFactory, 1345c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangDouble, 1355c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangFloat, 1365c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangInteger, 1375c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangLong, 1385c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangShort, 1395c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangMath, 1405c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangStrictMath, 1415c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheJavaLangThread, 142848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kClassCacheJavaNioCharsetCharset, 1435c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheLibcoreIoMemory, 1445c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheSunMiscUnsafe, 14570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov kClassCacheJavaLangSystem, 1465c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kClassCacheLast 1475c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 1485c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 1495c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 1505c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * To avoid multiple lookups of a method name string, we cache its string 1515c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * index in the IndexCache. These are the indexes into the IndexCache 1525c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * name_indexes array. 1535c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 1545c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko enum NameCacheIndex : uint8_t { // unit8_t to save space, make larger if needed 1555c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheFirst = 0, 15623abec955e2e733999a1e2c30e4e384e46e5dde4Serban Constantinescu kNameCacheReverse = kNameCacheFirst, 15723abec955e2e733999a1e2c30e4e384e46e5dde4Serban Constantinescu kNameCacheReverseBytes, 1585c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheDoubleToRawLongBits, 1595c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheLongBitsToDouble, 1605c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheFloatToRawIntBits, 1615c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheIntBitsToFloat, 1625c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheAbs, 1635c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheMax, 1645c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheMin, 1655c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheSqrt, 1662eba1fa7e9e5f91e18ae3778d529520bd2c78d55Serban Constantinescu kNameCacheCeil, 1672eba1fa7e9e5f91e18ae3778d529520bd2c78d55Serban Constantinescu kNameCacheFloor, 1682eba1fa7e9e5f91e18ae3778d529520bd2c78d55Serban Constantinescu kNameCacheRint, 1692eba1fa7e9e5f91e18ae3778d529520bd2c78d55Serban Constantinescu kNameCacheRound, 170cd48f2d86197d4fe87cc88077bc4af5ba66e5295Mathieu Chartier kNameCacheReferenceGetReferent, 1715c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheCharAt, 1725c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheCompareTo, 173848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kNameCacheGetCharsNoCheck, 1745c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheIsEmpty, 1755c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheIndexOf, 1765c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheLength, 177848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kNameCacheInit, 178848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kNameCacheNewStringFromBytes, 179848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kNameCacheNewStringFromChars, 180848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kNameCacheNewStringFromString, 1815c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheCurrentThread, 1825c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePeekByte, 1835c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePeekIntNative, 1845c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePeekLongNative, 1855c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePeekShortNative, 1865c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePokeByte, 1875c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePokeIntNative, 1885c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePokeLongNative, 1895c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePokeShortNative, 1905c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheCompareAndSwapInt, 1911c282e2b9a9b432e132b2c332f861cad9feb4a73Vladimir Marko kNameCacheCompareAndSwapLong, 1925c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheCompareAndSwapObject, 1935c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetInt, 1945c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetIntVolatile, 1955c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutInt, 1965c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutIntVolatile, 1975c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutOrderedInt, 1985c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetLong, 1995c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetLongVolatile, 2005c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutLong, 2015c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutLongVolatile, 2025c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutOrderedLong, 2035c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetObject, 2045c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheGetObjectVolatile, 2055c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutObject, 2065c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutObjectVolatile, 2075c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCachePutOrderedObject, 20870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov kNameCacheArrayCopy, 2095c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kNameCacheLast 2105c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 2115c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 2125c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 2135c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * To avoid multiple lookups of a method signature, we cache its proto 2145c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * index in the IndexCache. These are the indexes into the IndexCache 2155c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * proto_indexes array. 2165c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 2175c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko enum ProtoCacheIndex : uint8_t { // unit8_t to save space, make larger if needed 2185c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheFirst = 0, 2195c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheI_I = kProtoCacheFirst, 2205c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJ_J, 2215c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheS_S, 2225c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheD_D, 22323abec955e2e733999a1e2c30e4e384e46e5dde4Serban Constantinescu kProtoCacheDD_D, 224dbb17e378b538133750e56375bbdbb217db7b248Yixin Shou kProtoCacheF_F, 22523abec955e2e733999a1e2c30e4e384e46e5dde4Serban Constantinescu kProtoCacheFF_F, 2265c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheD_J, 2275c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJ_D, 2285c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheF_I, 2295c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheI_F, 2305c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheII_I, 2315c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheI_C, 2325c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheString_I, 2335c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCache_Z, 2345c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCache_I, 2354ee7a665e7f9cd2c5ace2d6304e33f64067b209fFred Shih kProtoCache_Object, 2365c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCache_Thread, 2375c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJ_B, 2385c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJ_I, 2395c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJ_S, 2405c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJB_V, 2415c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJI_V, 24223abec955e2e733999a1e2c30e4e384e46e5dde4Serban Constantinescu kProtoCacheJJ_J, 2435c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJJ_V, 2445c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheJS_V, 2455c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJII_Z, 2461c282e2b9a9b432e132b2c332f861cad9feb4a73Vladimir Marko kProtoCacheObjectJJJ_Z, 2475c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJObjectObject_Z, 2485c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJ_I, 2495c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJI_V, 2505c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJ_J, 2515c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJJ_V, 2525c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJ_Object, 2535c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheObjectJObject_V, 25470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov kProtoCacheCharArrayICharArrayII_V, 255848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheIICharArrayI_V, 256848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheByteArrayIII_String, 257848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheIICharArray_String, 258848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheString_String, 259848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCache_V, 260848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheByteArray_V, 261848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheByteArrayI_V, 262848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheByteArrayII_V, 263848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheByteArrayIII_V, 264848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheByteArrayIIString_V, 265848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheByteArrayString_V, 266848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheByteArrayIICharset_V, 267848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheByteArrayCharset_V, 268848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheCharArray_V, 269848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheCharArrayII_V, 270848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheIICharArray_V, 271848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheIntArrayII_V, 272848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheString_V, 273848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheStringBuffer_V, 274848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kProtoCacheStringBuilder_V, 2755c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko kProtoCacheLast 2765c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 2775c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 278b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogers private: 2795c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 2805c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The maximum number of method parameters we support in the ProtoDef. 2815c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 2825c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static constexpr uint32_t kProtoMaxParams = 6; 2835c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 2845c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 2855c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The method signature (proto) definition using cached class indexes. 2865c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The return_type and params are used with the IndexCache to look up 2875c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * appropriate class indexes to be passed to DexFile::FindProtoId(). 2885c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 2895c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko struct ProtoDef { 2905c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ClassCacheIndex return_type; 2915c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko uint8_t param_count; 2925c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ClassCacheIndex params[kProtoMaxParams]; 2935c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 2945c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 2955c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 2965c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The method definition using cached class, name and proto indexes. 2975c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The class index, method name index and proto index are used with 2985c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * IndexCache to look up appropriate parameters for DexFile::FindMethodId(). 2995c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 3005c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko struct MethodDef { 3015c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ClassCacheIndex declaring_class; 3025c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko NameCacheIndex name; 3035c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ProtoCacheIndex proto; 3045c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 3055c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3065c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 3075c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * The definition of an intrinsic function binds the method definition 3085c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * to an Intrinsic. 3095c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 3105c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko struct IntrinsicDef { 3115c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko MethodDef method_def; 3125816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko InlineMethod intrinsic; 3135c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 3145c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3155c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /** 3165c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Cache for class, method name and method signature indexes used during 3175c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * intrinsic function lookup to avoid multiple lookups of the same items. 3185c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * 3195c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Many classes have multiple intrinsics and/or they are used in multiple 3205c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * method signatures and we want to avoid repeated lookups since they are 3215c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * not exactly cheap. The method names and method signatures are sometimes 3225c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * reused and therefore cached as well. 3235c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 3245c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko struct IndexCache { 3255c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko IndexCache(); 3265c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3275c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko uint32_t class_indexes[kClassCacheLast - kClassCacheFirst]; 3285c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko uint32_t name_indexes[kNameCacheLast - kNameCacheFirst]; 3295c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko uint32_t proto_indexes[kProtoCacheLast - kProtoCacheFirst]; 3305c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko }; 3315c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3325816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko static const char* const kClassCacheNames[]; 3335816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko static const char* const kNameCacheNames[]; 3345c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static const ProtoDef kProtoCacheDefs[]; 335867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko static const IntrinsicDef kIntrinsicMethods[]; 3365c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3375c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static const uint32_t kIndexNotFound = static_cast<uint32_t>(-1); 3385c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static const uint32_t kIndexUnresolved = static_cast<uint32_t>(-2); 3395c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3405c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static uint32_t FindClassIndex(const DexFile* dex_file, IndexCache* cache, 3415c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ClassCacheIndex index); 3425c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static uint32_t FindNameIndex(const DexFile* dex_file, IndexCache* cache, 3435c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko NameCacheIndex index); 3445c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static uint32_t FindProtoIndex(const DexFile* dex_file, IndexCache* cache, 3455c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko ProtoCacheIndex index); 3465c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko static uint32_t FindMethodIndex(const DexFile* dex_file, IndexCache* cache, 3475c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko const MethodDef& method_def); 3485c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 349867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko /** 350867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko * Find all known intrinsic methods in the dex_file and cache their indices. 351867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko * 352867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko * Only DexFileToMethodInlinerMap may call this function to initialize the inliner. 353867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko */ 354e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko void FindIntrinsics(const DexFile* dex_file) EXCLUSIVE_LOCKS_REQUIRED(lock_); 355867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko 356867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko friend class DexFileToMethodInlinerMap; 3575c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3582bc47809febcf36369dd40877b8226318642b428Vladimir Marko bool AddInlineMethod(int32_t method_idx, const InlineMethod& method) LOCKS_EXCLUDED(lock_); 3592bc47809febcf36369dd40877b8226318642b428Vladimir Marko 3609820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko static bool GenInlineConst(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, 3619820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko MIR* move_result, const InlineMethod& method); 3629820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko static bool GenInlineReturnArg(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, 3639820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko MIR* move_result, const InlineMethod& method); 3649820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko static bool GenInlineIGet(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, 3656a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers MIR* move_result, const InlineMethod& method); 3669820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko static bool GenInlineIPut(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, 3676a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers MIR* move_result, const InlineMethod& method); 3689820b7c1dc70e75ad405b9e6e63578fa9fe94e94Vladimir Marko 369e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko ReaderWriterMutex lock_; 3705c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko /* 3715c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Maps method indexes (for the particular DexFile) to Intrinsic defintions. 3725c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */ 373dce164adfbf679d7ec9c9dc778fa3fb596011740Ian Rogers SafeMap<uint32_t, InlineMethod> inline_methods_ GUARDED_BY(lock_); 3745c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko const DexFile* dex_file_; 375867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko 376867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir Marko DISALLOW_COPY_AND_ASSIGN(DexFileMethodInliner); 3775c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko}; 3785c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3795c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko} // namespace art 3805c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko 3815c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko#endif // ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_ 382