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