| Nicolas Geoffray | e53798a | 2014-12-01 10:31:54 +0000 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2014 The Android Open Source Project | 
 | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
 | 16 |  | 
 | 17 | #ifndef ART_COMPILER_OPTIMIZING_INLINER_H_ | 
 | 18 | #define ART_COMPILER_OPTIMIZING_INLINER_H_ | 
 | 19 |  | 
| David Sehr | 9e734c7 | 2018-01-04 17:56:19 -0800 | [diff] [blame] | 20 | #include "dex/dex_file_types.h" | 
| David Sehr | 8c0961f | 2018-01-23 16:11:38 -0800 | [diff] [blame] | 21 | #include "dex/invoke_type.h" | 
| Andreas Gampe | 8cf9cb3 | 2017-07-19 09:28:38 -0700 | [diff] [blame] | 22 | #include "optimization.h" | 
| David Sehr | 82d046e | 2018-04-23 08:14:19 -0700 | [diff] [blame] | 23 | #include "profile/profile_compilation_info.h" | 
| Nicolas Geoffray | e53798a | 2014-12-01 10:31:54 +0000 | [diff] [blame] | 24 |  | 
 | 25 | namespace art { | 
 | 26 |  | 
| Vladimir Marko | dc151b2 | 2015-10-15 18:02:30 +0100 | [diff] [blame] | 27 | class CodeGenerator; | 
| Nicolas Geoffray | e53798a | 2014-12-01 10:31:54 +0000 | [diff] [blame] | 28 | class CompilerDriver; | 
 | 29 | class DexCompilationUnit; | 
 | 30 | class HGraph; | 
 | 31 | class HInvoke; | 
 | 32 | class OptimizingCompilerStats; | 
 | 33 |  | 
 | 34 | class HInliner : public HOptimization { | 
 | 35 |  public: | 
 | 36 |   HInliner(HGraph* outer_graph, | 
| Nicolas Geoffray | 73be1e8 | 2015-09-17 15:22:56 +0100 | [diff] [blame] | 37 |            HGraph* outermost_graph, | 
| Vladimir Marko | dc151b2 | 2015-10-15 18:02:30 +0100 | [diff] [blame] | 38 |            CodeGenerator* codegen, | 
| Nicolas Geoffray | e53798a | 2014-12-01 10:31:54 +0000 | [diff] [blame] | 39 |            const DexCompilationUnit& outer_compilation_unit, | 
| Nicolas Geoffray | 9437b78 | 2015-03-25 10:08:51 +0000 | [diff] [blame] | 40 |            const DexCompilationUnit& caller_compilation_unit, | 
| Nicolas Geoffray | e53798a | 2014-12-01 10:31:54 +0000 | [diff] [blame] | 41 |            CompilerDriver* compiler_driver, | 
| Mathieu Chartier | e8a3c57 | 2016-10-11 16:52:17 -0700 | [diff] [blame] | 42 |            VariableSizedHandleScope* handles, | 
| Nicolas Geoffray | ef87c5d | 2015-01-30 12:41:14 +0000 | [diff] [blame] | 43 |            OptimizingCompilerStats* stats, | 
| Nicolas Geoffray | 5949fa0 | 2015-12-18 10:57:10 +0000 | [diff] [blame] | 44 |            size_t total_number_of_dex_registers, | 
| Nicolas Geoffray | f6d4668 | 2017-02-28 17:41:45 +0000 | [diff] [blame] | 45 |            size_t total_number_of_instructions, | 
 | 46 |            HInliner* parent, | 
| Aart Bik | 2ca10eb | 2017-11-15 15:17:53 -0800 | [diff] [blame] | 47 |            size_t depth = 0, | 
 | 48 |            const char* name = kInlinerPassName) | 
 | 49 |       : HOptimization(outer_graph, name, stats), | 
| Nicolas Geoffray | 73be1e8 | 2015-09-17 15:22:56 +0100 | [diff] [blame] | 50 |         outermost_graph_(outermost_graph), | 
| Nicolas Geoffray | e53798a | 2014-12-01 10:31:54 +0000 | [diff] [blame] | 51 |         outer_compilation_unit_(outer_compilation_unit), | 
| Nicolas Geoffray | 9437b78 | 2015-03-25 10:08:51 +0000 | [diff] [blame] | 52 |         caller_compilation_unit_(caller_compilation_unit), | 
| Vladimir Marko | dc151b2 | 2015-10-15 18:02:30 +0100 | [diff] [blame] | 53 |         codegen_(codegen), | 
| Nicolas Geoffray | e53798a | 2014-12-01 10:31:54 +0000 | [diff] [blame] | 54 |         compiler_driver_(compiler_driver), | 
| Nicolas Geoffray | 5949fa0 | 2015-12-18 10:57:10 +0000 | [diff] [blame] | 55 |         total_number_of_dex_registers_(total_number_of_dex_registers), | 
| Nicolas Geoffray | f6d4668 | 2017-02-28 17:41:45 +0000 | [diff] [blame] | 56 |         total_number_of_instructions_(total_number_of_instructions), | 
 | 57 |         parent_(parent), | 
| Nicolas Geoffray | 454a481 | 2015-06-09 10:37:32 +0100 | [diff] [blame] | 58 |         depth_(depth), | 
| Nicolas Geoffray | f6d4668 | 2017-02-28 17:41:45 +0000 | [diff] [blame] | 59 |         inlining_budget_(0), | 
| Vladimir Marko | 438709f | 2017-02-23 18:56:13 +0000 | [diff] [blame] | 60 |         handles_(handles), | 
 | 61 |         inline_stats_(nullptr) {} | 
| Nicolas Geoffray | e53798a | 2014-12-01 10:31:54 +0000 | [diff] [blame] | 62 |  | 
| Aart Bik | 2477320 | 2018-04-26 10:28:51 -0700 | [diff] [blame] | 63 |   bool Run() OVERRIDE; | 
| Nicolas Geoffray | e53798a | 2014-12-01 10:31:54 +0000 | [diff] [blame] | 64 |  | 
| Andreas Gampe | 7c3952f | 2015-02-19 18:21:24 -0800 | [diff] [blame] | 65 |   static constexpr const char* kInlinerPassName = "inliner"; | 
 | 66 |  | 
| Nicolas Geoffray | e53798a | 2014-12-01 10:31:54 +0000 | [diff] [blame] | 67 |  private: | 
| Calin Juravle | 13439f0 | 2017-02-21 01:17:21 -0800 | [diff] [blame] | 68 |   enum InlineCacheType { | 
 | 69 |     kInlineCacheNoData = 0, | 
 | 70 |     kInlineCacheUninitialized = 1, | 
 | 71 |     kInlineCacheMonomorphic = 2, | 
 | 72 |     kInlineCachePolymorphic = 3, | 
 | 73 |     kInlineCacheMegamorphic = 4, | 
 | 74 |     kInlineCacheMissingTypes = 5 | 
 | 75 |   }; | 
 | 76 |  | 
| Nicolas Geoffray | e418dda | 2015-08-11 20:03:09 -0700 | [diff] [blame] | 77 |   bool TryInline(HInvoke* invoke_instruction); | 
| Nicolas Geoffray | 73be1e8 | 2015-09-17 15:22:56 +0100 | [diff] [blame] | 78 |  | 
 | 79 |   // Try to inline `resolved_method` in place of `invoke_instruction`. `do_rtp` is whether | 
| Nicolas Geoffray | 55bd749 | 2016-02-16 15:37:12 +0000 | [diff] [blame] | 80 |   // reference type propagation can run after the inlining. If the inlining is successful, this | 
| Mingyao Yang | 063fc77 | 2016-08-02 11:02:54 -0700 | [diff] [blame] | 81 |   // method will replace and remove the `invoke_instruction`. If `cha_devirtualize` is true, | 
 | 82 |   // a CHA guard needs to be added for the inlining. | 
 | 83 |   bool TryInlineAndReplace(HInvoke* invoke_instruction, | 
 | 84 |                            ArtMethod* resolved_method, | 
| Nicolas Geoffray | 0f001b7 | 2017-01-04 16:46:23 +0000 | [diff] [blame] | 85 |                            ReferenceTypeInfo receiver_type, | 
| Mingyao Yang | 063fc77 | 2016-08-02 11:02:54 -0700 | [diff] [blame] | 86 |                            bool do_rtp, | 
 | 87 |                            bool cha_devirtualize) | 
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 88 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
| Nicolas Geoffray | 73be1e8 | 2015-09-17 15:22:56 +0100 | [diff] [blame] | 89 |  | 
| Nicolas Geoffray | 55bd749 | 2016-02-16 15:37:12 +0000 | [diff] [blame] | 90 |   bool TryBuildAndInline(HInvoke* invoke_instruction, | 
 | 91 |                          ArtMethod* resolved_method, | 
| Nicolas Geoffray | 0f001b7 | 2017-01-04 16:46:23 +0000 | [diff] [blame] | 92 |                          ReferenceTypeInfo receiver_type, | 
| Nicolas Geoffray | 55bd749 | 2016-02-16 15:37:12 +0000 | [diff] [blame] | 93 |                          HInstruction** return_replacement) | 
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 94 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
| Nicolas Geoffray | 55bd749 | 2016-02-16 15:37:12 +0000 | [diff] [blame] | 95 |  | 
 | 96 |   bool TryBuildAndInlineHelper(HInvoke* invoke_instruction, | 
 | 97 |                                ArtMethod* resolved_method, | 
| Nicolas Geoffray | 0f001b7 | 2017-01-04 16:46:23 +0000 | [diff] [blame] | 98 |                                ReferenceTypeInfo receiver_type, | 
| Nicolas Geoffray | 55bd749 | 2016-02-16 15:37:12 +0000 | [diff] [blame] | 99 |                                bool same_dex_file, | 
 | 100 |                                HInstruction** return_replacement); | 
 | 101 |  | 
| Roland Levillain | a3aef2e | 2016-04-06 17:45:58 +0100 | [diff] [blame] | 102 |   // Run simple optimizations on `callee_graph`. | 
| Nicolas Geoffray | f6d4668 | 2017-02-28 17:41:45 +0000 | [diff] [blame] | 103 |   void RunOptimizations(HGraph* callee_graph, | 
 | 104 |                         const DexFile::CodeItem* code_item, | 
 | 105 |                         const DexCompilationUnit& dex_compilation_unit) | 
 | 106 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
| Roland Levillain | a3aef2e | 2016-04-06 17:45:58 +0100 | [diff] [blame] | 107 |  | 
| Vladimir Marko | be10e8e | 2016-01-22 12:09:44 +0000 | [diff] [blame] | 108 |   // Try to recognize known simple patterns and replace invoke call with appropriate instructions. | 
| Nicolas Geoffray | 55bd749 | 2016-02-16 15:37:12 +0000 | [diff] [blame] | 109 |   bool TryPatternSubstitution(HInvoke* invoke_instruction, | 
 | 110 |                               ArtMethod* resolved_method, | 
 | 111 |                               HInstruction** return_replacement) | 
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 112 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
| Vladimir Marko | be10e8e | 2016-01-22 12:09:44 +0000 | [diff] [blame] | 113 |  | 
 | 114 |   // Create a new HInstanceFieldGet. | 
| Vladimir Marko | f44d36c | 2017-03-14 14:18:46 +0000 | [diff] [blame] | 115 |   HInstanceFieldGet* CreateInstanceFieldGet(uint32_t field_index, | 
 | 116 |                                             ArtMethod* referrer, | 
| Vladimir Marko | be10e8e | 2016-01-22 12:09:44 +0000 | [diff] [blame] | 117 |                                             HInstruction* obj); | 
 | 118 |   // Create a new HInstanceFieldSet. | 
| Vladimir Marko | f44d36c | 2017-03-14 14:18:46 +0000 | [diff] [blame] | 119 |   HInstanceFieldSet* CreateInstanceFieldSet(uint32_t field_index, | 
 | 120 |                                             ArtMethod* referrer, | 
| Vladimir Marko | be10e8e | 2016-01-22 12:09:44 +0000 | [diff] [blame] | 121 |                                             HInstruction* obj, | 
| Vladimir Marko | f44d36c | 2017-03-14 14:18:46 +0000 | [diff] [blame] | 122 |                                             HInstruction* value, | 
 | 123 |                                             bool* is_final = nullptr); | 
| Vladimir Marko | be10e8e | 2016-01-22 12:09:44 +0000 | [diff] [blame] | 124 |  | 
| Calin Juravle | 13439f0 | 2017-02-21 01:17:21 -0800 | [diff] [blame] | 125 |   // Try inlining the invoke instruction using inline caches. | 
 | 126 |   bool TryInlineFromInlineCache( | 
 | 127 |       const DexFile& caller_dex_file, | 
 | 128 |       HInvoke* invoke_instruction, | 
 | 129 |       ArtMethod* resolved_method) | 
 | 130 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
 | 131 |  | 
 | 132 |   // Try getting the inline cache from JIT code cache. | 
 | 133 |   // Return true if the inline cache was successfully allocated and the | 
 | 134 |   // invoke info was found in the profile info. | 
 | 135 |   InlineCacheType GetInlineCacheJIT( | 
 | 136 |       HInvoke* invoke_instruction, | 
 | 137 |       StackHandleScope<1>* hs, | 
 | 138 |       /*out*/Handle<mirror::ObjectArray<mirror::Class>>* inline_cache) | 
 | 139 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
 | 140 |  | 
 | 141 |   // Try getting the inline cache from AOT offline profile. | 
 | 142 |   // Return true if the inline cache was successfully allocated and the | 
 | 143 |   // invoke info was found in the profile info. | 
 | 144 |   InlineCacheType GetInlineCacheAOT(const DexFile& caller_dex_file, | 
 | 145 |       HInvoke* invoke_instruction, | 
 | 146 |       StackHandleScope<1>* hs, | 
 | 147 |       /*out*/Handle<mirror::ObjectArray<mirror::Class>>* inline_cache) | 
 | 148 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
 | 149 |  | 
 | 150 |   // Extract the mirror classes from the offline profile and add them to the `inline_cache`. | 
 | 151 |   // Note that even if we have profile data for the invoke the inline_cache might contain | 
 | 152 |   // only null entries if the types cannot be resolved. | 
 | 153 |   InlineCacheType ExtractClassesFromOfflineProfile( | 
 | 154 |       const HInvoke* invoke_instruction, | 
 | 155 |       const ProfileCompilationInfo::OfflineProfileMethodInfo& offline_profile, | 
 | 156 |       /*out*/Handle<mirror::ObjectArray<mirror::Class>> inline_cache) | 
 | 157 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
 | 158 |  | 
 | 159 |   // Compute the inline cache type. | 
 | 160 |   InlineCacheType GetInlineCacheType( | 
 | 161 |       const Handle<mirror::ObjectArray<mirror::Class>>& classes) | 
 | 162 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
 | 163 |  | 
| Nicolas Geoffray | 73be1e8 | 2015-09-17 15:22:56 +0100 | [diff] [blame] | 164 |   // Try to inline the target of a monomorphic call. If successful, the code | 
 | 165 |   // in the graph will look like: | 
 | 166 |   // if (receiver.getClass() != ic.GetMonomorphicType()) deopt | 
 | 167 |   // ... // inlined code | 
 | 168 |   bool TryInlineMonomorphicCall(HInvoke* invoke_instruction, | 
 | 169 |                                 ArtMethod* resolved_method, | 
| Nicolas Geoffray | e51ca8b | 2016-11-22 14:49:31 +0000 | [diff] [blame] | 170 |                                 Handle<mirror::ObjectArray<mirror::Class>> classes) | 
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 171 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
| Nicolas Geoffray | 73be1e8 | 2015-09-17 15:22:56 +0100 | [diff] [blame] | 172 |  | 
| Nicolas Geoffray | 916cc1d | 2016-02-18 11:12:31 +0000 | [diff] [blame] | 173 |   // Try to inline targets of a polymorphic call. | 
| Nicolas Geoffray | 73be1e8 | 2015-09-17 15:22:56 +0100 | [diff] [blame] | 174 |   bool TryInlinePolymorphicCall(HInvoke* invoke_instruction, | 
 | 175 |                                 ArtMethod* resolved_method, | 
| Nicolas Geoffray | e51ca8b | 2016-11-22 14:49:31 +0000 | [diff] [blame] | 176 |                                 Handle<mirror::ObjectArray<mirror::Class>> classes) | 
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 177 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
| Nicolas Geoffray | 73be1e8 | 2015-09-17 15:22:56 +0100 | [diff] [blame] | 178 |  | 
| Nicolas Geoffray | 916cc1d | 2016-02-18 11:12:31 +0000 | [diff] [blame] | 179 |   bool TryInlinePolymorphicCallToSameTarget(HInvoke* invoke_instruction, | 
 | 180 |                                             ArtMethod* resolved_method, | 
| Nicolas Geoffray | e51ca8b | 2016-11-22 14:49:31 +0000 | [diff] [blame] | 181 |                                             Handle<mirror::ObjectArray<mirror::Class>> classes) | 
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 182 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
| Nicolas Geoffray | 916cc1d | 2016-02-18 11:12:31 +0000 | [diff] [blame] | 183 |  | 
| Calin Juravle | af44e6c | 2017-05-23 14:24:55 -0700 | [diff] [blame] | 184 |   // Returns whether or not we should use only polymorphic inlining with no deoptimizations. | 
 | 185 |   bool UseOnlyPolymorphicInliningWithNoDeopt(); | 
 | 186 |  | 
| Mingyao Yang | 063fc77 | 2016-08-02 11:02:54 -0700 | [diff] [blame] | 187 |   // Try CHA-based devirtualization to change virtual method calls into | 
 | 188 |   // direct calls. | 
 | 189 |   // Returns the actual method that resolved_method can be devirtualized to. | 
 | 190 |   ArtMethod* TryCHADevirtualization(ArtMethod* resolved_method) | 
 | 191 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
 | 192 |  | 
 | 193 |   // Add a CHA guard for a CHA-based devirtualized call. A CHA guard checks a | 
 | 194 |   // should_deoptimize flag and if it's true, does deoptimization. | 
 | 195 |   void AddCHAGuard(HInstruction* invoke_instruction, | 
 | 196 |                    uint32_t dex_pc, | 
 | 197 |                    HInstruction* cursor, | 
 | 198 |                    HBasicBlock* bb_cursor); | 
| Nicolas Geoffray | 916cc1d | 2016-02-18 11:12:31 +0000 | [diff] [blame] | 199 |  | 
| Nicolas Geoffray | a42363f | 2015-12-17 14:57:09 +0000 | [diff] [blame] | 200 |   HInstanceFieldGet* BuildGetReceiverClass(ClassLinker* class_linker, | 
 | 201 |                                            HInstruction* receiver, | 
 | 202 |                                            uint32_t dex_pc) const | 
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 203 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
| Nicolas Geoffray | a42363f | 2015-12-17 14:57:09 +0000 | [diff] [blame] | 204 |  | 
| David Brazdil | 94ab38f | 2016-06-21 17:48:19 +0100 | [diff] [blame] | 205 |   void FixUpReturnReferenceType(ArtMethod* resolved_method, HInstruction* return_replacement) | 
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 206 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
| David Brazdil | 94ab38f | 2016-06-21 17:48:19 +0100 | [diff] [blame] | 207 |  | 
 | 208 |   // Creates an instance of ReferenceTypeInfo from `klass` if `klass` is | 
 | 209 |   // admissible (see ReferenceTypePropagation::IsAdmissible for details). | 
 | 210 |   // Otherwise returns inexact Object RTI. | 
| Vladimir Marko | b45528c | 2017-07-27 14:14:28 +0100 | [diff] [blame] | 211 |   ReferenceTypeInfo GetClassRTI(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); | 
| David Brazdil | 94ab38f | 2016-06-21 17:48:19 +0100 | [diff] [blame] | 212 |  | 
 | 213 |   bool ArgumentTypesMoreSpecific(HInvoke* invoke_instruction, ArtMethod* resolved_method) | 
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 214 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
| David Brazdil | 94ab38f | 2016-06-21 17:48:19 +0100 | [diff] [blame] | 215 |  | 
 | 216 |   bool ReturnTypeMoreSpecific(HInvoke* invoke_instruction, HInstruction* return_replacement) | 
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 217 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
| Vladimir Marko | be10e8e | 2016-01-22 12:09:44 +0000 | [diff] [blame] | 218 |  | 
| Nicolas Geoffray | 916cc1d | 2016-02-18 11:12:31 +0000 | [diff] [blame] | 219 |   // Add a type guard on the given `receiver`. This will add to the graph: | 
 | 220 |   // i0 = HFieldGet(receiver, klass) | 
 | 221 |   // i1 = HLoadClass(class_index, is_referrer) | 
 | 222 |   // i2 = HNotEqual(i0, i1) | 
 | 223 |   // | 
 | 224 |   // And if `with_deoptimization` is true: | 
 | 225 |   // HDeoptimize(i2) | 
 | 226 |   // | 
 | 227 |   // The method returns the `HNotEqual`, that will be used for polymorphic inlining. | 
 | 228 |   HInstruction* AddTypeGuard(HInstruction* receiver, | 
 | 229 |                              HInstruction* cursor, | 
 | 230 |                              HBasicBlock* bb_cursor, | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 231 |                              dex::TypeIndex class_index, | 
| Nicolas Geoffray | 5247c08 | 2017-01-13 14:17:29 +0000 | [diff] [blame] | 232 |                              Handle<mirror::Class> klass, | 
| Nicolas Geoffray | 916cc1d | 2016-02-18 11:12:31 +0000 | [diff] [blame] | 233 |                              HInstruction* invoke_instruction, | 
 | 234 |                              bool with_deoptimization) | 
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 235 |     REQUIRES_SHARED(Locks::mutator_lock_); | 
| Nicolas Geoffray | 916cc1d | 2016-02-18 11:12:31 +0000 | [diff] [blame] | 236 |  | 
 | 237 |   /* | 
 | 238 |    * Ad-hoc implementation for implementing a diamond pattern in the graph for | 
 | 239 |    * polymorphic inlining: | 
 | 240 |    * 1) `compare` becomes the input of the new `HIf`. | 
 | 241 |    * 2) Everything up until `invoke_instruction` is in the then branch (could | 
 | 242 |    *    contain multiple blocks). | 
 | 243 |    * 3) `invoke_instruction` is moved to the otherwise block. | 
 | 244 |    * 4) If `return_replacement` is not null, the merge block will have | 
 | 245 |    *    a phi whose inputs are `return_replacement` and `invoke_instruction`. | 
 | 246 |    * | 
 | 247 |    * Before: | 
 | 248 |    *             Block1 | 
 | 249 |    *             compare | 
 | 250 |    *              ... | 
 | 251 |    *         invoke_instruction | 
 | 252 |    * | 
 | 253 |    * After: | 
 | 254 |    *            Block1 | 
 | 255 |    *            compare | 
 | 256 |    *              if | 
 | 257 |    *          /        \ | 
 | 258 |    *         /          \ | 
 | 259 |    *   Then block    Otherwise block | 
 | 260 |    *      ...       invoke_instruction | 
 | 261 |    *       \              / | 
 | 262 |    *        \            / | 
 | 263 |    *          Merge block | 
 | 264 |    *  phi(return_replacement, invoke_instruction) | 
 | 265 |    */ | 
 | 266 |   void CreateDiamondPatternForPolymorphicInline(HInstruction* compare, | 
 | 267 |                                                 HInstruction* return_replacement, | 
 | 268 |                                                 HInstruction* invoke_instruction); | 
 | 269 |  | 
| Nicolas Geoffray | f6d4668 | 2017-02-28 17:41:45 +0000 | [diff] [blame] | 270 |   // Update the inlining budget based on `total_number_of_instructions_`. | 
 | 271 |   void UpdateInliningBudget(); | 
 | 272 |  | 
 | 273 |   // Count the number of calls of `method` being inlined recursively. | 
 | 274 |   size_t CountRecursiveCallsOf(ArtMethod* method) const; | 
 | 275 |  | 
 | 276 |   // Pretty-print for spaces during logging. | 
 | 277 |   std::string DepthString(int line) const; | 
 | 278 |  | 
| Nicolas Geoffray | 73be1e8 | 2015-09-17 15:22:56 +0100 | [diff] [blame] | 279 |   HGraph* const outermost_graph_; | 
| Nicolas Geoffray | e53798a | 2014-12-01 10:31:54 +0000 | [diff] [blame] | 280 |   const DexCompilationUnit& outer_compilation_unit_; | 
| Nicolas Geoffray | 9437b78 | 2015-03-25 10:08:51 +0000 | [diff] [blame] | 281 |   const DexCompilationUnit& caller_compilation_unit_; | 
| Vladimir Marko | dc151b2 | 2015-10-15 18:02:30 +0100 | [diff] [blame] | 282 |   CodeGenerator* const codegen_; | 
| Nicolas Geoffray | e53798a | 2014-12-01 10:31:54 +0000 | [diff] [blame] | 283 |   CompilerDriver* const compiler_driver_; | 
| Nicolas Geoffray | 5949fa0 | 2015-12-18 10:57:10 +0000 | [diff] [blame] | 284 |   const size_t total_number_of_dex_registers_; | 
| Nicolas Geoffray | f6d4668 | 2017-02-28 17:41:45 +0000 | [diff] [blame] | 285 |   size_t total_number_of_instructions_; | 
 | 286 |  | 
 | 287 |   // The 'parent' inliner, that means the inlinigng optimization that requested | 
 | 288 |   // `graph_` to be inlined. | 
 | 289 |   const HInliner* const parent_; | 
| Nicolas Geoffray | ef87c5d | 2015-01-30 12:41:14 +0000 | [diff] [blame] | 290 |   const size_t depth_; | 
| Nicolas Geoffray | f6d4668 | 2017-02-28 17:41:45 +0000 | [diff] [blame] | 291 |  | 
 | 292 |   // The budget left for inlining, in number of instructions. | 
 | 293 |   size_t inlining_budget_; | 
| Mathieu Chartier | e8a3c57 | 2016-10-11 16:52:17 -0700 | [diff] [blame] | 294 |   VariableSizedHandleScope* const handles_; | 
| Nicolas Geoffray | e53798a | 2014-12-01 10:31:54 +0000 | [diff] [blame] | 295 |  | 
| Vladimir Marko | 438709f | 2017-02-23 18:56:13 +0000 | [diff] [blame] | 296 |   // Used to record stats about optimizations on the inlined graph. | 
 | 297 |   // If the inlining is successful, these stats are merged to the caller graph's stats. | 
 | 298 |   OptimizingCompilerStats* inline_stats_; | 
 | 299 |  | 
| Nicolas Geoffray | e53798a | 2014-12-01 10:31:54 +0000 | [diff] [blame] | 300 |   DISALLOW_COPY_AND_ASSIGN(HInliner); | 
 | 301 | }; | 
 | 302 |  | 
 | 303 | }  // namespace art | 
 | 304 |  | 
 | 305 | #endif  // ART_COMPILER_OPTIMIZING_INLINER_H_ |