1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_OPTIMIZING_INLINER_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_INLINER_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 21*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_types.h" 22*795d594fSAndroid Build Coastguard Worker #include "dex/invoke_type.h" 23*795d594fSAndroid Build Coastguard Worker #include "jit/profiling_info.h" 24*795d594fSAndroid Build Coastguard Worker #include "optimization.h" 25*795d594fSAndroid Build Coastguard Worker #include "profile/profile_compilation_info.h" 26*795d594fSAndroid Build Coastguard Worker 27*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 28*795d594fSAndroid Build Coastguard Worker 29*795d594fSAndroid Build Coastguard Worker class CodeGenerator; 30*795d594fSAndroid Build Coastguard Worker class DexCompilationUnit; 31*795d594fSAndroid Build Coastguard Worker class HGraph; 32*795d594fSAndroid Build Coastguard Worker class HInvoke; 33*795d594fSAndroid Build Coastguard Worker class OptimizingCompilerStats; 34*795d594fSAndroid Build Coastguard Worker 35*795d594fSAndroid Build Coastguard Worker class HInliner : public HOptimization { 36*795d594fSAndroid Build Coastguard Worker public: 37*795d594fSAndroid Build Coastguard Worker HInliner(HGraph* outer_graph, 38*795d594fSAndroid Build Coastguard Worker HGraph* outermost_graph, 39*795d594fSAndroid Build Coastguard Worker CodeGenerator* codegen, 40*795d594fSAndroid Build Coastguard Worker const DexCompilationUnit& outer_compilation_unit, 41*795d594fSAndroid Build Coastguard Worker const DexCompilationUnit& caller_compilation_unit, 42*795d594fSAndroid Build Coastguard Worker OptimizingCompilerStats* stats, 43*795d594fSAndroid Build Coastguard Worker size_t total_number_of_dex_registers, 44*795d594fSAndroid Build Coastguard Worker size_t total_number_of_instructions, 45*795d594fSAndroid Build Coastguard Worker HInliner* parent, 46*795d594fSAndroid Build Coastguard Worker HEnvironment* caller_environment, 47*795d594fSAndroid Build Coastguard Worker size_t depth, 48*795d594fSAndroid Build Coastguard Worker bool try_catch_inlining_allowed, 49*795d594fSAndroid Build Coastguard Worker const char* name = kInlinerPassName) HOptimization(outer_graph,name,stats)50*795d594fSAndroid Build Coastguard Worker : HOptimization(outer_graph, name, stats), 51*795d594fSAndroid Build Coastguard Worker outermost_graph_(outermost_graph), 52*795d594fSAndroid Build Coastguard Worker outer_compilation_unit_(outer_compilation_unit), 53*795d594fSAndroid Build Coastguard Worker caller_compilation_unit_(caller_compilation_unit), 54*795d594fSAndroid Build Coastguard Worker codegen_(codegen), 55*795d594fSAndroid Build Coastguard Worker total_number_of_dex_registers_(total_number_of_dex_registers), 56*795d594fSAndroid Build Coastguard Worker total_number_of_instructions_(total_number_of_instructions), 57*795d594fSAndroid Build Coastguard Worker parent_(parent), 58*795d594fSAndroid Build Coastguard Worker caller_environment_(caller_environment), 59*795d594fSAndroid Build Coastguard Worker depth_(depth), 60*795d594fSAndroid Build Coastguard Worker inlining_budget_(0), 61*795d594fSAndroid Build Coastguard Worker try_catch_inlining_allowed_(try_catch_inlining_allowed), 62*795d594fSAndroid Build Coastguard Worker run_extra_type_propagation_(false), 63*795d594fSAndroid Build Coastguard Worker inline_stats_(nullptr) {} 64*795d594fSAndroid Build Coastguard Worker 65*795d594fSAndroid Build Coastguard Worker bool Run() override; 66*795d594fSAndroid Build Coastguard Worker 67*795d594fSAndroid Build Coastguard Worker static constexpr const char* kInlinerPassName = "inliner"; 68*795d594fSAndroid Build Coastguard Worker GetParent()69*795d594fSAndroid Build Coastguard Worker const HInliner* GetParent() const { return parent_; } GetCallerEnvironment()70*795d594fSAndroid Build Coastguard Worker const HEnvironment* GetCallerEnvironment() const { return caller_environment_; } 71*795d594fSAndroid Build Coastguard Worker GetOutermostGraph()72*795d594fSAndroid Build Coastguard Worker const HGraph* GetOutermostGraph() const { return outermost_graph_; } GetGraph()73*795d594fSAndroid Build Coastguard Worker const HGraph* GetGraph() const { return graph_; } 74*795d594fSAndroid Build Coastguard Worker 75*795d594fSAndroid Build Coastguard Worker private: 76*795d594fSAndroid Build Coastguard Worker enum InlineCacheType { 77*795d594fSAndroid Build Coastguard Worker kInlineCacheNoData = 0, 78*795d594fSAndroid Build Coastguard Worker kInlineCacheUninitialized = 1, 79*795d594fSAndroid Build Coastguard Worker kInlineCacheMonomorphic = 2, 80*795d594fSAndroid Build Coastguard Worker kInlineCachePolymorphic = 3, 81*795d594fSAndroid Build Coastguard Worker kInlineCacheMegamorphic = 4, 82*795d594fSAndroid Build Coastguard Worker kInlineCacheMissingTypes = 5 83*795d594fSAndroid Build Coastguard Worker }; 84*795d594fSAndroid Build Coastguard Worker 85*795d594fSAndroid Build Coastguard Worker bool TryInline(HInvoke* invoke_instruction); 86*795d594fSAndroid Build Coastguard Worker 87*795d594fSAndroid Build Coastguard Worker // Try to inline `resolved_method` in place of `invoke_instruction`. `do_rtp` is whether 88*795d594fSAndroid Build Coastguard Worker // reference type propagation can run after the inlining. If the inlining is successful, this 89*795d594fSAndroid Build Coastguard Worker // method will replace and remove the `invoke_instruction`. 90*795d594fSAndroid Build Coastguard Worker bool TryInlineAndReplace(HInvoke* invoke_instruction, 91*795d594fSAndroid Build Coastguard Worker ArtMethod* resolved_method, 92*795d594fSAndroid Build Coastguard Worker ReferenceTypeInfo receiver_type, 93*795d594fSAndroid Build Coastguard Worker bool do_rtp, 94*795d594fSAndroid Build Coastguard Worker bool is_speculative) 95*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 96*795d594fSAndroid Build Coastguard Worker 97*795d594fSAndroid Build Coastguard Worker bool TryBuildAndInline(HInvoke* invoke_instruction, 98*795d594fSAndroid Build Coastguard Worker ArtMethod* resolved_method, 99*795d594fSAndroid Build Coastguard Worker ReferenceTypeInfo receiver_type, 100*795d594fSAndroid Build Coastguard Worker HInstruction** return_replacement, 101*795d594fSAndroid Build Coastguard Worker bool is_speculative) 102*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 103*795d594fSAndroid Build Coastguard Worker 104*795d594fSAndroid Build Coastguard Worker bool TryBuildAndInlineHelper(HInvoke* invoke_instruction, 105*795d594fSAndroid Build Coastguard Worker ArtMethod* resolved_method, 106*795d594fSAndroid Build Coastguard Worker ReferenceTypeInfo receiver_type, 107*795d594fSAndroid Build Coastguard Worker HInstruction** return_replacement, 108*795d594fSAndroid Build Coastguard Worker bool is_speculative) 109*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 110*795d594fSAndroid Build Coastguard Worker 111*795d594fSAndroid Build Coastguard Worker // Substitutes parameters in the callee graph with their values from the caller. 112*795d594fSAndroid Build Coastguard Worker void SubstituteArguments(HGraph* callee_graph, 113*795d594fSAndroid Build Coastguard Worker HInvoke* invoke_instruction, 114*795d594fSAndroid Build Coastguard Worker ReferenceTypeInfo receiver_type, 115*795d594fSAndroid Build Coastguard Worker const DexCompilationUnit& dex_compilation_unit) 116*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 117*795d594fSAndroid Build Coastguard Worker 118*795d594fSAndroid Build Coastguard Worker // Run simple optimizations on `callee_graph`. 119*795d594fSAndroid Build Coastguard Worker void RunOptimizations(HGraph* callee_graph, 120*795d594fSAndroid Build Coastguard Worker HEnvironment* caller_environment, 121*795d594fSAndroid Build Coastguard Worker const dex::CodeItem* code_item, 122*795d594fSAndroid Build Coastguard Worker const DexCompilationUnit& dex_compilation_unit, 123*795d594fSAndroid Build Coastguard Worker bool try_catch_inlining_allowed_for_recursive_inline) 124*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 125*795d594fSAndroid Build Coastguard Worker 126*795d594fSAndroid Build Coastguard Worker // Try to recognize known simple patterns and replace invoke call with appropriate instructions. 127*795d594fSAndroid Build Coastguard Worker bool TryPatternSubstitution(HInvoke* invoke_instruction, 128*795d594fSAndroid Build Coastguard Worker ArtMethod* method, 129*795d594fSAndroid Build Coastguard Worker const CodeItemDataAccessor& accessor, 130*795d594fSAndroid Build Coastguard Worker HInstruction** return_replacement) 131*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 132*795d594fSAndroid Build Coastguard Worker 133*795d594fSAndroid Build Coastguard Worker // Returns whether inlining is allowed based on ART semantics. 134*795d594fSAndroid Build Coastguard Worker bool IsInliningAllowed(art::ArtMethod* method, const CodeItemDataAccessor& accessor) const 135*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 136*795d594fSAndroid Build Coastguard Worker 137*795d594fSAndroid Build Coastguard Worker 138*795d594fSAndroid Build Coastguard Worker // Returns whether ART supports inlining this method. 139*795d594fSAndroid Build Coastguard Worker // 140*795d594fSAndroid Build Coastguard Worker // Some methods are not supported because they have features for which inlining 141*795d594fSAndroid Build Coastguard Worker // is not implemented. For example, we do not currently support inlining throw 142*795d594fSAndroid Build Coastguard Worker // instructions into a try block. 143*795d594fSAndroid Build Coastguard Worker bool IsInliningSupported(const HInvoke* invoke_instruction, 144*795d594fSAndroid Build Coastguard Worker art::ArtMethod* method, 145*795d594fSAndroid Build Coastguard Worker const CodeItemDataAccessor& accessor) const 146*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 147*795d594fSAndroid Build Coastguard Worker 148*795d594fSAndroid Build Coastguard Worker // Returns whether inlining is encouraged. 149*795d594fSAndroid Build Coastguard Worker // 150*795d594fSAndroid Build Coastguard Worker // For example, this checks whether the function has grown too large and 151*795d594fSAndroid Build Coastguard Worker // inlining should be prevented. 152*795d594fSAndroid Build Coastguard Worker bool IsInliningEncouraged(const HInvoke* invoke_instruction, 153*795d594fSAndroid Build Coastguard Worker art::ArtMethod* method, 154*795d594fSAndroid Build Coastguard Worker const CodeItemDataAccessor& accessor) const 155*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 156*795d594fSAndroid Build Coastguard Worker 157*795d594fSAndroid Build Coastguard Worker // Inspects the body of a method (callee_graph) and returns whether it can be 158*795d594fSAndroid Build Coastguard Worker // inlined. 159*795d594fSAndroid Build Coastguard Worker // 160*795d594fSAndroid Build Coastguard Worker // This checks for instructions and constructs that we do not support 161*795d594fSAndroid Build Coastguard Worker // inlining, such as inlining a throw instruction into a try block. 162*795d594fSAndroid Build Coastguard Worker bool CanInlineBody(const HGraph* callee_graph, 163*795d594fSAndroid Build Coastguard Worker HInvoke* invoke, 164*795d594fSAndroid Build Coastguard Worker size_t* out_number_of_instructions, 165*795d594fSAndroid Build Coastguard Worker bool is_speculative) const 166*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 167*795d594fSAndroid Build Coastguard Worker 168*795d594fSAndroid Build Coastguard Worker // Create a new HInstanceFieldGet. 169*795d594fSAndroid Build Coastguard Worker HInstanceFieldGet* CreateInstanceFieldGet(uint32_t field_index, 170*795d594fSAndroid Build Coastguard Worker ArtMethod* referrer, 171*795d594fSAndroid Build Coastguard Worker HInstruction* obj); 172*795d594fSAndroid Build Coastguard Worker // Create a new HInstanceFieldSet. 173*795d594fSAndroid Build Coastguard Worker HInstanceFieldSet* CreateInstanceFieldSet(uint32_t field_index, 174*795d594fSAndroid Build Coastguard Worker ArtMethod* referrer, 175*795d594fSAndroid Build Coastguard Worker HInstruction* obj, 176*795d594fSAndroid Build Coastguard Worker HInstruction* value, 177*795d594fSAndroid Build Coastguard Worker bool* is_final = nullptr); 178*795d594fSAndroid Build Coastguard Worker 179*795d594fSAndroid Build Coastguard Worker // Try inlining the invoke instruction using inline caches. 180*795d594fSAndroid Build Coastguard Worker bool TryInlineFromInlineCache(HInvoke* invoke_instruction) 181*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 182*795d594fSAndroid Build Coastguard Worker 183*795d594fSAndroid Build Coastguard Worker // Try inlining the invoke instruction using CHA. 184*795d594fSAndroid Build Coastguard Worker bool TryInlineFromCHA(HInvoke* invoke_instruction) 185*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 186*795d594fSAndroid Build Coastguard Worker 187*795d594fSAndroid Build Coastguard Worker // When we fail inlining `invoke_instruction`, we will try to devirtualize the 188*795d594fSAndroid Build Coastguard Worker // call. 189*795d594fSAndroid Build Coastguard Worker bool TryDevirtualize(HInvoke* invoke_instruction, 190*795d594fSAndroid Build Coastguard Worker ArtMethod* method, 191*795d594fSAndroid Build Coastguard Worker HInvoke** replacement) 192*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 193*795d594fSAndroid Build Coastguard Worker 194*795d594fSAndroid Build Coastguard Worker // Try getting the inline cache from JIT code cache. 195*795d594fSAndroid Build Coastguard Worker // Return true if the inline cache was successfully allocated and the 196*795d594fSAndroid Build Coastguard Worker // invoke info was found in the profile info. 197*795d594fSAndroid Build Coastguard Worker InlineCacheType GetInlineCacheJIT( 198*795d594fSAndroid Build Coastguard Worker HInvoke* invoke_instruction, 199*795d594fSAndroid Build Coastguard Worker /*out*/StackHandleScope<InlineCache::kIndividualCacheSize>* classes) 200*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 201*795d594fSAndroid Build Coastguard Worker 202*795d594fSAndroid Build Coastguard Worker // Try getting the inline cache from AOT offline profile. 203*795d594fSAndroid Build Coastguard Worker // Return true if the inline cache was successfully allocated and the 204*795d594fSAndroid Build Coastguard Worker // invoke info was found in the profile info. 205*795d594fSAndroid Build Coastguard Worker InlineCacheType GetInlineCacheAOT( 206*795d594fSAndroid Build Coastguard Worker HInvoke* invoke_instruction, 207*795d594fSAndroid Build Coastguard Worker /*out*/StackHandleScope<InlineCache::kIndividualCacheSize>* classes) 208*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 209*795d594fSAndroid Build Coastguard Worker 210*795d594fSAndroid Build Coastguard Worker // Compute the inline cache type. 211*795d594fSAndroid Build Coastguard Worker static InlineCacheType GetInlineCacheType( 212*795d594fSAndroid Build Coastguard Worker const StackHandleScope<InlineCache::kIndividualCacheSize>& classes) 213*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 214*795d594fSAndroid Build Coastguard Worker 215*795d594fSAndroid Build Coastguard Worker // Try to inline the target of a monomorphic call. If successful, the code 216*795d594fSAndroid Build Coastguard Worker // in the graph will look like: 217*795d594fSAndroid Build Coastguard Worker // if (receiver.getClass() != ic.GetMonomorphicType()) deopt 218*795d594fSAndroid Build Coastguard Worker // ... // inlined code 219*795d594fSAndroid Build Coastguard Worker bool TryInlineMonomorphicCall(HInvoke* invoke_instruction, 220*795d594fSAndroid Build Coastguard Worker const StackHandleScope<InlineCache::kIndividualCacheSize>& classes) 221*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 222*795d594fSAndroid Build Coastguard Worker 223*795d594fSAndroid Build Coastguard Worker // Try to inline targets of a polymorphic call. 224*795d594fSAndroid Build Coastguard Worker bool TryInlinePolymorphicCall(HInvoke* invoke_instruction, 225*795d594fSAndroid Build Coastguard Worker const StackHandleScope<InlineCache::kIndividualCacheSize>& classes) 226*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 227*795d594fSAndroid Build Coastguard Worker 228*795d594fSAndroid Build Coastguard Worker bool TryInlinePolymorphicCallToSameTarget( 229*795d594fSAndroid Build Coastguard Worker HInvoke* invoke_instruction, 230*795d594fSAndroid Build Coastguard Worker const StackHandleScope<InlineCache::kIndividualCacheSize>& classes) 231*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 232*795d594fSAndroid Build Coastguard Worker 233*795d594fSAndroid Build Coastguard Worker // Returns whether or not we should use only polymorphic inlining with no deoptimizations. 234*795d594fSAndroid Build Coastguard Worker bool UseOnlyPolymorphicInliningWithNoDeopt(); 235*795d594fSAndroid Build Coastguard Worker 236*795d594fSAndroid Build Coastguard Worker // Try CHA-based devirtualization to change virtual method calls into 237*795d594fSAndroid Build Coastguard Worker // direct calls. 238*795d594fSAndroid Build Coastguard Worker // Returns the actual method that resolved_method can be devirtualized to. 239*795d594fSAndroid Build Coastguard Worker ArtMethod* FindMethodFromCHA(ArtMethod* resolved_method) 240*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 241*795d594fSAndroid Build Coastguard Worker 242*795d594fSAndroid Build Coastguard Worker // Add a CHA guard for a CHA-based devirtualized call. A CHA guard checks a 243*795d594fSAndroid Build Coastguard Worker // should_deoptimize flag and if it's true, does deoptimization. 244*795d594fSAndroid Build Coastguard Worker void AddCHAGuard(HInstruction* invoke_instruction, 245*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc, 246*795d594fSAndroid Build Coastguard Worker HInstruction* cursor, 247*795d594fSAndroid Build Coastguard Worker HBasicBlock* bb_cursor); 248*795d594fSAndroid Build Coastguard Worker 249*795d594fSAndroid Build Coastguard Worker HInstanceFieldGet* BuildGetReceiverClass(ClassLinker* class_linker, 250*795d594fSAndroid Build Coastguard Worker HInstruction* receiver, 251*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc) const 252*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 253*795d594fSAndroid Build Coastguard Worker 254*795d594fSAndroid Build Coastguard Worker void MaybeRunReferenceTypePropagation(HInstruction* replacement, 255*795d594fSAndroid Build Coastguard Worker HInvoke* invoke_instruction) 256*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 257*795d594fSAndroid Build Coastguard Worker 258*795d594fSAndroid Build Coastguard Worker void FixUpReturnReferenceType(ArtMethod* resolved_method, HInstruction* return_replacement) 259*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 260*795d594fSAndroid Build Coastguard Worker 261*795d594fSAndroid Build Coastguard Worker bool ArgumentTypesMoreSpecific(HInvoke* invoke_instruction, ArtMethod* resolved_method) 262*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 263*795d594fSAndroid Build Coastguard Worker 264*795d594fSAndroid Build Coastguard Worker bool ReturnTypeMoreSpecific(HInstruction* return_replacement, HInvoke* invoke_instruction) 265*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 266*795d594fSAndroid Build Coastguard Worker 267*795d594fSAndroid Build Coastguard Worker // Add a type guard on the given `receiver`. This will add to the graph: 268*795d594fSAndroid Build Coastguard Worker // i0 = HFieldGet(receiver, klass) 269*795d594fSAndroid Build Coastguard Worker // i1 = HLoadClass(class_index, is_referrer) 270*795d594fSAndroid Build Coastguard Worker // i2 = HNotEqual(i0, i1) 271*795d594fSAndroid Build Coastguard Worker // 272*795d594fSAndroid Build Coastguard Worker // And if `with_deoptimization` is true: 273*795d594fSAndroid Build Coastguard Worker // HDeoptimize(i2) 274*795d594fSAndroid Build Coastguard Worker // 275*795d594fSAndroid Build Coastguard Worker // The method returns the `HNotEqual`, that will be used for polymorphic inlining. 276*795d594fSAndroid Build Coastguard Worker HInstruction* AddTypeGuard(HInstruction* receiver, 277*795d594fSAndroid Build Coastguard Worker HInstruction* cursor, 278*795d594fSAndroid Build Coastguard Worker HBasicBlock* bb_cursor, 279*795d594fSAndroid Build Coastguard Worker dex::TypeIndex class_index, 280*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> klass, 281*795d594fSAndroid Build Coastguard Worker HInstruction* invoke_instruction, 282*795d594fSAndroid Build Coastguard Worker bool with_deoptimization) 283*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 284*795d594fSAndroid Build Coastguard Worker 285*795d594fSAndroid Build Coastguard Worker /* 286*795d594fSAndroid Build Coastguard Worker * Ad-hoc implementation for implementing a diamond pattern in the graph for 287*795d594fSAndroid Build Coastguard Worker * polymorphic inlining: 288*795d594fSAndroid Build Coastguard Worker * 1) `compare` becomes the input of the new `HIf`. 289*795d594fSAndroid Build Coastguard Worker * 2) Everything up until `invoke_instruction` is in the then branch (could 290*795d594fSAndroid Build Coastguard Worker * contain multiple blocks). 291*795d594fSAndroid Build Coastguard Worker * 3) `invoke_instruction` is moved to the otherwise block. 292*795d594fSAndroid Build Coastguard Worker * 4) If `return_replacement` is not null, the merge block will have 293*795d594fSAndroid Build Coastguard Worker * a phi whose inputs are `return_replacement` and `invoke_instruction`. 294*795d594fSAndroid Build Coastguard Worker * 295*795d594fSAndroid Build Coastguard Worker * Before: 296*795d594fSAndroid Build Coastguard Worker * Block1 297*795d594fSAndroid Build Coastguard Worker * compare 298*795d594fSAndroid Build Coastguard Worker * ... 299*795d594fSAndroid Build Coastguard Worker * invoke_instruction 300*795d594fSAndroid Build Coastguard Worker * 301*795d594fSAndroid Build Coastguard Worker * After: 302*795d594fSAndroid Build Coastguard Worker * Block1 303*795d594fSAndroid Build Coastguard Worker * compare 304*795d594fSAndroid Build Coastguard Worker * if 305*795d594fSAndroid Build Coastguard Worker * / \ 306*795d594fSAndroid Build Coastguard Worker * / \ 307*795d594fSAndroid Build Coastguard Worker * Then block Otherwise block 308*795d594fSAndroid Build Coastguard Worker * ... invoke_instruction 309*795d594fSAndroid Build Coastguard Worker * \ / 310*795d594fSAndroid Build Coastguard Worker * \ / 311*795d594fSAndroid Build Coastguard Worker * Merge block 312*795d594fSAndroid Build Coastguard Worker * phi(return_replacement, invoke_instruction) 313*795d594fSAndroid Build Coastguard Worker */ 314*795d594fSAndroid Build Coastguard Worker void CreateDiamondPatternForPolymorphicInline(HInstruction* compare, 315*795d594fSAndroid Build Coastguard Worker HInstruction* return_replacement, 316*795d594fSAndroid Build Coastguard Worker HInstruction* invoke_instruction); 317*795d594fSAndroid Build Coastguard Worker 318*795d594fSAndroid Build Coastguard Worker // Update the inlining budget based on `total_number_of_instructions_`. 319*795d594fSAndroid Build Coastguard Worker void UpdateInliningBudget(); 320*795d594fSAndroid Build Coastguard Worker 321*795d594fSAndroid Build Coastguard Worker // Count the number of calls of `method` being inlined recursively. 322*795d594fSAndroid Build Coastguard Worker size_t CountRecursiveCallsOf(ArtMethod* method) const; 323*795d594fSAndroid Build Coastguard Worker 324*795d594fSAndroid Build Coastguard Worker // Pretty-print for spaces during logging. 325*795d594fSAndroid Build Coastguard Worker std::string DepthString(int line) const; 326*795d594fSAndroid Build Coastguard Worker 327*795d594fSAndroid Build Coastguard Worker HGraph* const outermost_graph_; 328*795d594fSAndroid Build Coastguard Worker const DexCompilationUnit& outer_compilation_unit_; 329*795d594fSAndroid Build Coastguard Worker const DexCompilationUnit& caller_compilation_unit_; 330*795d594fSAndroid Build Coastguard Worker CodeGenerator* const codegen_; 331*795d594fSAndroid Build Coastguard Worker const size_t total_number_of_dex_registers_; 332*795d594fSAndroid Build Coastguard Worker size_t total_number_of_instructions_; 333*795d594fSAndroid Build Coastguard Worker 334*795d594fSAndroid Build Coastguard Worker // The 'parent' inliner, that means the inlining optimization that requested 335*795d594fSAndroid Build Coastguard Worker // `graph_` to be inlined. 336*795d594fSAndroid Build Coastguard Worker const HInliner* const parent_; 337*795d594fSAndroid Build Coastguard Worker const HEnvironment* const caller_environment_; 338*795d594fSAndroid Build Coastguard Worker const size_t depth_; 339*795d594fSAndroid Build Coastguard Worker 340*795d594fSAndroid Build Coastguard Worker // The budget left for inlining, in number of instructions. 341*795d594fSAndroid Build Coastguard Worker size_t inlining_budget_; 342*795d594fSAndroid Build Coastguard Worker 343*795d594fSAndroid Build Coastguard Worker // States if we are allowing try catch inlining to occur at this particular instance of inlining. 344*795d594fSAndroid Build Coastguard Worker bool try_catch_inlining_allowed_; 345*795d594fSAndroid Build Coastguard Worker 346*795d594fSAndroid Build Coastguard Worker // True if we need to run type propagation to type guards we inserted. 347*795d594fSAndroid Build Coastguard Worker bool run_extra_type_propagation_; 348*795d594fSAndroid Build Coastguard Worker 349*795d594fSAndroid Build Coastguard Worker // Used to record stats about optimizations on the inlined graph. 350*795d594fSAndroid Build Coastguard Worker // If the inlining is successful, these stats are merged to the caller graph's stats. 351*795d594fSAndroid Build Coastguard Worker OptimizingCompilerStats* inline_stats_; 352*795d594fSAndroid Build Coastguard Worker 353*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(HInliner); 354*795d594fSAndroid Build Coastguard Worker }; 355*795d594fSAndroid Build Coastguard Worker 356*795d594fSAndroid Build Coastguard Worker } // namespace art 357*795d594fSAndroid Build Coastguard Worker 358*795d594fSAndroid Build Coastguard Worker #endif // ART_COMPILER_OPTIMIZING_INLINER_H_ 359