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