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 #include "inliner.h"
18 
19 #include "art_method-inl.h"
20 #include "base/enums.h"
21 #include "base/logging.h"
22 #include "builder.h"
23 #include "class_linker.h"
24 #include "class_root.h"
25 #include "constant_folding.h"
26 #include "data_type-inl.h"
27 #include "dead_code_elimination.h"
28 #include "dex/inline_method_analyser.h"
29 #include "dex/verification_results.h"
30 #include "dex/verified_method.h"
31 #include "driver/compiler_options.h"
32 #include "driver/dex_compilation_unit.h"
33 #include "instruction_simplifier.h"
34 #include "intrinsics.h"
35 #include "jit/jit.h"
36 #include "jit/jit_code_cache.h"
37 #include "mirror/class_loader.h"
38 #include "mirror/dex_cache.h"
39 #include "mirror/object_array-alloc-inl.h"
40 #include "mirror/object_array-inl.h"
41 #include "nodes.h"
42 #include "reference_type_propagation.h"
43 #include "register_allocator_linear_scan.h"
44 #include "scoped_thread_state_change-inl.h"
45 #include "sharpening.h"
46 #include "ssa_builder.h"
47 #include "ssa_phi_elimination.h"
48 #include "thread.h"
49 
50 namespace art {
51 
52 // Instruction limit to control memory.
53 static constexpr size_t kMaximumNumberOfTotalInstructions = 1024;
54 
55 // Maximum number of instructions for considering a method small,
56 // which we will always try to inline if the other non-instruction limits
57 // are not reached.
58 static constexpr size_t kMaximumNumberOfInstructionsForSmallMethod = 3;
59 
60 // Limit the number of dex registers that we accumulate while inlining
61 // to avoid creating large amount of nested environments.
62 static constexpr size_t kMaximumNumberOfCumulatedDexRegisters = 32;
63 
64 // Limit recursive call inlining, which do not benefit from too
65 // much inlining compared to code locality.
66 static constexpr size_t kMaximumNumberOfRecursiveCalls = 4;
67 
68 // Controls the use of inline caches in AOT mode.
69 static constexpr bool kUseAOTInlineCaches = true;
70 
71 // We check for line numbers to make sure the DepthString implementation
72 // aligns the output nicely.
73 #define LOG_INTERNAL(msg) \
74   static_assert(__LINE__ > 10, "Unhandled line number"); \
75   static_assert(__LINE__ < 10000, "Unhandled line number"); \
76   VLOG(compiler) << DepthString(__LINE__) << msg
77 
78 #define LOG_TRY() LOG_INTERNAL("Try inlinining call: ")
79 #define LOG_NOTE() LOG_INTERNAL("Note: ")
80 #define LOG_SUCCESS() LOG_INTERNAL("Success: ")
81 #define LOG_FAIL(stats_ptr, stat) MaybeRecordStat(stats_ptr, stat); LOG_INTERNAL("Fail: ")
82 #define LOG_FAIL_NO_STAT() LOG_INTERNAL("Fail: ")
83 
DepthString(int line) const84 std::string HInliner::DepthString(int line) const {
85   std::string value;
86   // Indent according to the inlining depth.
87   size_t count = depth_;
88   // Line numbers get printed in the log, so add a space if the log's line is less
89   // than 1000, and two if less than 100. 10 cannot be reached as it's the copyright.
90   if (!kIsTargetBuild) {
91     if (line < 100) {
92       value += " ";
93     }
94     if (line < 1000) {
95       value += " ";
96     }
97     // Safeguard if this file reaches more than 10000 lines.
98     DCHECK_LT(line, 10000);
99   }
100   for (size_t i = 0; i < count; ++i) {
101     value += "  ";
102   }
103   return value;
104 }
105 
CountNumberOfInstructions(HGraph * graph)106 static size_t CountNumberOfInstructions(HGraph* graph) {
107   size_t number_of_instructions = 0;
108   for (HBasicBlock* block : graph->GetReversePostOrderSkipEntryBlock()) {
109     for (HInstructionIterator instr_it(block->GetInstructions());
110          !instr_it.Done();
111          instr_it.Advance()) {
112       ++number_of_instructions;
113     }
114   }
115   return number_of_instructions;
116 }
117 
UpdateInliningBudget()118 void HInliner::UpdateInliningBudget() {
119   if (total_number_of_instructions_ >= kMaximumNumberOfTotalInstructions) {
120     // Always try to inline small methods.
121     inlining_budget_ = kMaximumNumberOfInstructionsForSmallMethod;
122   } else {
123     inlining_budget_ = std::max(
124         kMaximumNumberOfInstructionsForSmallMethod,
125         kMaximumNumberOfTotalInstructions - total_number_of_instructions_);
126   }
127 }
128 
Run()129 bool HInliner::Run() {
130   if (codegen_->GetCompilerOptions().GetInlineMaxCodeUnits() == 0) {
131     // Inlining effectively disabled.
132     return false;
133   } else if (graph_->IsDebuggable()) {
134     // For simplicity, we currently never inline when the graph is debuggable. This avoids
135     // doing some logic in the runtime to discover if a method could have been inlined.
136     return false;
137   }
138 
139   bool didInline = false;
140 
141   // Initialize the number of instructions for the method being compiled. Recursive calls
142   // to HInliner::Run have already updated the instruction count.
143   if (outermost_graph_ == graph_) {
144     total_number_of_instructions_ = CountNumberOfInstructions(graph_);
145   }
146 
147   UpdateInliningBudget();
148   DCHECK_NE(total_number_of_instructions_, 0u);
149   DCHECK_NE(inlining_budget_, 0u);
150 
151   // If we're compiling with a core image (which is only used for
152   // test purposes), honor inlining directives in method names:
153   // - if a method's name contains the substring "$noinline$", do not
154   //   inline that method;
155   // - if a method's name contains the substring "$inline$", ensure
156   //   that this method is actually inlined.
157   // We limit the latter to AOT compilation, as the JIT may or may not inline
158   // depending on the state of classes at runtime.
159   const bool honor_noinline_directives = codegen_->GetCompilerOptions().CompilingWithCoreImage();
160   const bool honor_inline_directives =
161       honor_noinline_directives && Runtime::Current()->IsAotCompiler();
162 
163   // Keep a copy of all blocks when starting the visit.
164   ArenaVector<HBasicBlock*> blocks = graph_->GetReversePostOrder();
165   DCHECK(!blocks.empty());
166   // Because we are changing the graph when inlining,
167   // we just iterate over the blocks of the outer method.
168   // This avoids doing the inlining work again on the inlined blocks.
169   for (HBasicBlock* block : blocks) {
170     for (HInstruction* instruction = block->GetFirstInstruction(); instruction != nullptr;) {
171       HInstruction* next = instruction->GetNext();
172       HInvoke* call = instruction->AsInvoke();
173       // As long as the call is not intrinsified, it is worth trying to inline.
174       if (call != nullptr && call->GetIntrinsic() == Intrinsics::kNone) {
175         if (honor_noinline_directives) {
176           // Debugging case: directives in method names control or assert on inlining.
177           std::string callee_name = outer_compilation_unit_.GetDexFile()->PrettyMethod(
178               call->GetDexMethodIndex(), /* with_signature= */ false);
179           // Tests prevent inlining by having $noinline$ in their method names.
180           if (callee_name.find("$noinline$") == std::string::npos) {
181             if (TryInline(call)) {
182               didInline = true;
183             } else if (honor_inline_directives) {
184               bool should_have_inlined = (callee_name.find("$inline$") != std::string::npos);
185               CHECK(!should_have_inlined) << "Could not inline " << callee_name;
186             }
187           }
188         } else {
189           DCHECK(!honor_inline_directives);
190           // Normal case: try to inline.
191           if (TryInline(call)) {
192             didInline = true;
193           }
194         }
195       }
196       instruction = next;
197     }
198   }
199 
200   return didInline;
201 }
202 
IsMethodOrDeclaringClassFinal(ArtMethod * method)203 static bool IsMethodOrDeclaringClassFinal(ArtMethod* method)
204     REQUIRES_SHARED(Locks::mutator_lock_) {
205   return method->IsFinal() || method->GetDeclaringClass()->IsFinal();
206 }
207 
208 /**
209  * Given the `resolved_method` looked up in the dex cache, try to find
210  * the actual runtime target of an interface or virtual call.
211  * Return nullptr if the runtime target cannot be proven.
212  */
FindVirtualOrInterfaceTarget(HInvoke * invoke,ArtMethod * resolved_method)213 static ArtMethod* FindVirtualOrInterfaceTarget(HInvoke* invoke, ArtMethod* resolved_method)
214     REQUIRES_SHARED(Locks::mutator_lock_) {
215   if (IsMethodOrDeclaringClassFinal(resolved_method)) {
216     // No need to lookup further, the resolved method will be the target.
217     return resolved_method;
218   }
219 
220   HInstruction* receiver = invoke->InputAt(0);
221   if (receiver->IsNullCheck()) {
222     // Due to multiple levels of inlining within the same pass, it might be that
223     // null check does not have the reference type of the actual receiver.
224     receiver = receiver->InputAt(0);
225   }
226   ReferenceTypeInfo info = receiver->GetReferenceTypeInfo();
227   DCHECK(info.IsValid()) << "Invalid RTI for " << receiver->DebugName();
228   if (!info.IsExact()) {
229     // We currently only support inlining with known receivers.
230     // TODO: Remove this check, we should be able to inline final methods
231     // on unknown receivers.
232     return nullptr;
233   } else if (info.GetTypeHandle()->IsInterface()) {
234     // Statically knowing that the receiver has an interface type cannot
235     // help us find what is the target method.
236     return nullptr;
237   } else if (!resolved_method->GetDeclaringClass()->IsAssignableFrom(info.GetTypeHandle().Get())) {
238     // The method that we're trying to call is not in the receiver's class or super classes.
239     return nullptr;
240   } else if (info.GetTypeHandle()->IsErroneous()) {
241     // If the type is erroneous, do not go further, as we are going to query the vtable or
242     // imt table, that we can only safely do on non-erroneous classes.
243     return nullptr;
244   }
245 
246   ClassLinker* cl = Runtime::Current()->GetClassLinker();
247   PointerSize pointer_size = cl->GetImagePointerSize();
248   if (invoke->IsInvokeInterface()) {
249     resolved_method = info.GetTypeHandle()->FindVirtualMethodForInterface(
250         resolved_method, pointer_size);
251   } else {
252     DCHECK(invoke->IsInvokeVirtual());
253     resolved_method = info.GetTypeHandle()->FindVirtualMethodForVirtual(
254         resolved_method, pointer_size);
255   }
256 
257   if (resolved_method == nullptr) {
258     // The information we had on the receiver was not enough to find
259     // the target method. Since we check above the exact type of the receiver,
260     // the only reason this can happen is an IncompatibleClassChangeError.
261     return nullptr;
262   } else if (!resolved_method->IsInvokable()) {
263     // The information we had on the receiver was not enough to find
264     // the target method. Since we check above the exact type of the receiver,
265     // the only reason this can happen is an IncompatibleClassChangeError.
266     return nullptr;
267   } else if (IsMethodOrDeclaringClassFinal(resolved_method)) {
268     // A final method has to be the target method.
269     return resolved_method;
270   } else if (info.IsExact()) {
271     // If we found a method and the receiver's concrete type is statically
272     // known, we know for sure the target.
273     return resolved_method;
274   } else {
275     // Even if we did find a method, the receiver type was not enough to
276     // statically find the runtime target.
277     return nullptr;
278   }
279 }
280 
FindMethodIndexIn(ArtMethod * method,const DexFile & dex_file,uint32_t name_and_signature_index)281 static uint32_t FindMethodIndexIn(ArtMethod* method,
282                                   const DexFile& dex_file,
283                                   uint32_t name_and_signature_index)
284     REQUIRES_SHARED(Locks::mutator_lock_) {
285   if (IsSameDexFile(*method->GetDexFile(), dex_file)) {
286     return method->GetDexMethodIndex();
287   } else {
288     return method->FindDexMethodIndexInOtherDexFile(dex_file, name_and_signature_index);
289   }
290 }
291 
FindClassIndexIn(ObjPtr<mirror::Class> cls,const DexCompilationUnit & compilation_unit)292 static dex::TypeIndex FindClassIndexIn(ObjPtr<mirror::Class> cls,
293                                        const DexCompilationUnit& compilation_unit)
294     REQUIRES_SHARED(Locks::mutator_lock_) {
295   const DexFile& dex_file = *compilation_unit.GetDexFile();
296   dex::TypeIndex index;
297   if (cls->GetDexCache() == nullptr) {
298     DCHECK(cls->IsArrayClass()) << cls->PrettyClass();
299     index = cls->FindTypeIndexInOtherDexFile(dex_file);
300   } else if (!cls->GetDexTypeIndex().IsValid()) {
301     DCHECK(cls->IsProxyClass()) << cls->PrettyClass();
302     // TODO: deal with proxy classes.
303   } else if (IsSameDexFile(cls->GetDexFile(), dex_file)) {
304     DCHECK_EQ(cls->GetDexCache(), compilation_unit.GetDexCache().Get());
305     index = cls->GetDexTypeIndex();
306   } else {
307     index = cls->FindTypeIndexInOtherDexFile(dex_file);
308     // We cannot guarantee the entry will resolve to the same class,
309     // as there may be different class loaders. So only return the index if it's
310     // the right class already resolved with the class loader.
311     if (index.IsValid()) {
312       ObjPtr<mirror::Class> resolved = compilation_unit.GetClassLinker()->LookupResolvedType(
313           index, compilation_unit.GetDexCache().Get(), compilation_unit.GetClassLoader().Get());
314       if (resolved != cls) {
315         index = dex::TypeIndex::Invalid();
316       }
317     }
318   }
319 
320   return index;
321 }
322 
323 class ScopedProfilingInfoInlineUse {
324  public:
ScopedProfilingInfoInlineUse(ArtMethod * method,Thread * self)325   explicit ScopedProfilingInfoInlineUse(ArtMethod* method, Thread* self)
326       : method_(method),
327         self_(self),
328         // Fetch the profiling info ahead of using it. If it's null when fetching,
329         // we should not call JitCodeCache::DoneInlining.
330         profiling_info_(
331             Runtime::Current()->GetJit()->GetCodeCache()->NotifyCompilerUse(method, self)) {
332   }
333 
~ScopedProfilingInfoInlineUse()334   ~ScopedProfilingInfoInlineUse() {
335     if (profiling_info_ != nullptr) {
336       PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
337       DCHECK_EQ(profiling_info_, method_->GetProfilingInfo(pointer_size));
338       Runtime::Current()->GetJit()->GetCodeCache()->DoneCompilerUse(method_, self_);
339     }
340   }
341 
GetProfilingInfo() const342   ProfilingInfo* GetProfilingInfo() const { return profiling_info_; }
343 
344  private:
345   ArtMethod* const method_;
346   Thread* const self_;
347   ProfilingInfo* const profiling_info_;
348 };
349 
GetInlineCacheType(const Handle<mirror::ObjectArray<mirror::Class>> & classes)350 HInliner::InlineCacheType HInliner::GetInlineCacheType(
351     const Handle<mirror::ObjectArray<mirror::Class>>& classes)
352   REQUIRES_SHARED(Locks::mutator_lock_) {
353   uint8_t number_of_types = 0;
354   for (; number_of_types < InlineCache::kIndividualCacheSize; ++number_of_types) {
355     if (classes->Get(number_of_types) == nullptr) {
356       break;
357     }
358   }
359 
360   if (number_of_types == 0) {
361     return kInlineCacheUninitialized;
362   } else if (number_of_types == 1) {
363     return kInlineCacheMonomorphic;
364   } else if (number_of_types == InlineCache::kIndividualCacheSize) {
365     return kInlineCacheMegamorphic;
366   } else {
367     return kInlineCachePolymorphic;
368   }
369 }
370 
GetMonomorphicType(Handle<mirror::ObjectArray<mirror::Class>> classes)371 static ObjPtr<mirror::Class> GetMonomorphicType(Handle<mirror::ObjectArray<mirror::Class>> classes)
372     REQUIRES_SHARED(Locks::mutator_lock_) {
373   DCHECK(classes->Get(0) != nullptr);
374   return classes->Get(0);
375 }
376 
TryCHADevirtualization(ArtMethod * resolved_method)377 ArtMethod* HInliner::TryCHADevirtualization(ArtMethod* resolved_method) {
378   if (!resolved_method->HasSingleImplementation()) {
379     return nullptr;
380   }
381   if (Runtime::Current()->IsAotCompiler()) {
382     // No CHA-based devirtulization for AOT compiler (yet).
383     return nullptr;
384   }
385   if (Runtime::Current()->IsZygote()) {
386     // No CHA-based devirtulization for Zygote, as it compiles with
387     // offline information.
388     return nullptr;
389   }
390   if (outermost_graph_->IsCompilingOsr()) {
391     // We do not support HDeoptimize in OSR methods.
392     return nullptr;
393   }
394   PointerSize pointer_size = caller_compilation_unit_.GetClassLinker()->GetImagePointerSize();
395   ArtMethod* single_impl = resolved_method->GetSingleImplementation(pointer_size);
396   if (single_impl == nullptr) {
397     return nullptr;
398   }
399   if (single_impl->IsProxyMethod()) {
400     // Proxy method is a generic invoker that's not worth
401     // devirtualizing/inlining. It also causes issues when the proxy
402     // method is in another dex file if we try to rewrite invoke-interface to
403     // invoke-virtual because a proxy method doesn't have a real dex file.
404     return nullptr;
405   }
406   if (!single_impl->GetDeclaringClass()->IsResolved()) {
407     // There's a race with the class loading, which updates the CHA info
408     // before setting the class to resolved. So we just bail for this
409     // rare occurence.
410     return nullptr;
411   }
412   return single_impl;
413 }
414 
IsMethodUnverified(const CompilerOptions & compiler_options,ArtMethod * method)415 static bool IsMethodUnverified(const CompilerOptions& compiler_options, ArtMethod* method)
416     REQUIRES_SHARED(Locks::mutator_lock_) {
417   if (!method->GetDeclaringClass()->IsVerified()) {
418     if (Runtime::Current()->UseJitCompilation()) {
419       // We're at runtime, we know this is cold code if the class
420       // is not verified, so don't bother analyzing.
421       return true;
422     }
423     uint16_t class_def_idx = method->GetDeclaringClass()->GetDexClassDefIndex();
424     if (!compiler_options.IsMethodVerifiedWithoutFailures(method->GetDexMethodIndex(),
425                                                           class_def_idx,
426                                                           *method->GetDexFile())) {
427       // Method has soft or hard failures, don't analyze.
428       return true;
429     }
430   }
431   return false;
432 }
433 
AlwaysThrows(const CompilerOptions & compiler_options,ArtMethod * method)434 static bool AlwaysThrows(const CompilerOptions& compiler_options, ArtMethod* method)
435     REQUIRES_SHARED(Locks::mutator_lock_) {
436   DCHECK(method != nullptr);
437   // Skip non-compilable and unverified methods.
438   if (!method->IsCompilable() || IsMethodUnverified(compiler_options, method)) {
439     return false;
440   }
441   // Skip native methods, methods with try blocks, and methods that are too large.
442   CodeItemDataAccessor accessor(method->DexInstructionData());
443   if (!accessor.HasCodeItem() ||
444       accessor.TriesSize() != 0 ||
445       accessor.InsnsSizeInCodeUnits() > kMaximumNumberOfTotalInstructions) {
446     return false;
447   }
448   // Scan for exits.
449   bool throw_seen = false;
450   for (const DexInstructionPcPair& pair : accessor) {
451     switch (pair.Inst().Opcode()) {
452       case Instruction::RETURN:
453       case Instruction::RETURN_VOID:
454       case Instruction::RETURN_WIDE:
455       case Instruction::RETURN_OBJECT:
456       case Instruction::RETURN_VOID_NO_BARRIER:
457         return false;  // found regular control flow back
458       case Instruction::THROW:
459         throw_seen = true;
460         break;
461       default:
462         break;
463     }
464   }
465   return throw_seen;
466 }
467 
FindActualCallTarget(HInvoke * invoke_instruction,bool * cha_devirtualize)468 ArtMethod* HInliner::FindActualCallTarget(HInvoke* invoke_instruction, bool* cha_devirtualize) {
469   ArtMethod* resolved_method = invoke_instruction->GetResolvedMethod();
470   DCHECK(resolved_method != nullptr);
471 
472   ArtMethod* actual_method = nullptr;
473   if (invoke_instruction->IsInvokeStaticOrDirect()) {
474     actual_method = resolved_method;
475   } else {
476     // Check if we can statically find the method.
477     actual_method = FindVirtualOrInterfaceTarget(invoke_instruction, resolved_method);
478   }
479 
480   if (actual_method == nullptr) {
481     ArtMethod* method = TryCHADevirtualization(resolved_method);
482     if (method != nullptr) {
483       *cha_devirtualize = true;
484       actual_method = method;
485       LOG_NOTE() << "Try CHA-based inlining of " << actual_method->PrettyMethod();
486     }
487   }
488 
489   return actual_method;
490 }
491 
TryInline(HInvoke * invoke_instruction)492 bool HInliner::TryInline(HInvoke* invoke_instruction) {
493   if (invoke_instruction->IsInvokeUnresolved() ||
494       invoke_instruction->IsInvokePolymorphic() ||
495       invoke_instruction->IsInvokeCustom()) {
496     return false;  // Don't bother to move further if we know the method is unresolved or the
497                    // invocation is polymorphic (invoke-{polymorphic,custom}).
498   }
499 
500   ScopedObjectAccess soa(Thread::Current());
501   uint32_t method_index = invoke_instruction->GetDexMethodIndex();
502   const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile();
503   LOG_TRY() << caller_dex_file.PrettyMethod(method_index);
504 
505   ArtMethod* resolved_method = invoke_instruction->GetResolvedMethod();
506   if (resolved_method == nullptr) {
507     DCHECK(invoke_instruction->IsInvokeStaticOrDirect());
508     DCHECK(invoke_instruction->AsInvokeStaticOrDirect()->IsStringInit());
509     LOG_FAIL_NO_STAT() << "Not inlining a String.<init> method";
510     return false;
511   }
512 
513   bool cha_devirtualize = false;
514   ArtMethod* actual_method = FindActualCallTarget(invoke_instruction, &cha_devirtualize);
515 
516   // If we didn't find a method, see if we can inline from the inline caches.
517   if (actual_method == nullptr) {
518     DCHECK(!invoke_instruction->IsInvokeStaticOrDirect());
519 
520     return TryInlineFromInlineCache(caller_dex_file, invoke_instruction, resolved_method);
521   }
522 
523   // Single target.
524   bool result = TryInlineAndReplace(invoke_instruction,
525                                     actual_method,
526                                     ReferenceTypeInfo::CreateInvalid(),
527                                     /* do_rtp= */ true,
528                                     cha_devirtualize);
529   if (result) {
530     // Successfully inlined.
531     if (!invoke_instruction->IsInvokeStaticOrDirect()) {
532       if (cha_devirtualize) {
533         // Add dependency due to devirtualization. We've assumed resolved_method
534         // has single implementation.
535         outermost_graph_->AddCHASingleImplementationDependency(resolved_method);
536         MaybeRecordStat(stats_, MethodCompilationStat::kCHAInline);
537       } else {
538         MaybeRecordStat(stats_, MethodCompilationStat::kInlinedInvokeVirtualOrInterface);
539       }
540     }
541   } else if (!cha_devirtualize && AlwaysThrows(codegen_->GetCompilerOptions(), actual_method)) {
542     // Set always throws property for non-inlined method call with single target
543     // (unless it was obtained through CHA, because that would imply we have
544     // to add the CHA dependency, which seems not worth it).
545     invoke_instruction->SetAlwaysThrows(true);
546   }
547   return result;
548 }
549 
AllocateInlineCacheHolder(const DexCompilationUnit & compilation_unit,StackHandleScope<1> * hs)550 static Handle<mirror::ObjectArray<mirror::Class>> AllocateInlineCacheHolder(
551     const DexCompilationUnit& compilation_unit,
552     StackHandleScope<1>* hs)
553     REQUIRES_SHARED(Locks::mutator_lock_) {
554   Thread* self = Thread::Current();
555   ClassLinker* class_linker = compilation_unit.GetClassLinker();
556   Handle<mirror::ObjectArray<mirror::Class>> inline_cache = hs->NewHandle(
557       mirror::ObjectArray<mirror::Class>::Alloc(
558           self,
559           GetClassRoot<mirror::ObjectArray<mirror::Class>>(class_linker),
560           InlineCache::kIndividualCacheSize));
561   if (inline_cache == nullptr) {
562     // We got an OOME. Just clear the exception, and don't inline.
563     DCHECK(self->IsExceptionPending());
564     self->ClearException();
565     VLOG(compiler) << "Out of memory in the compiler when trying to inline";
566   }
567   return inline_cache;
568 }
569 
UseOnlyPolymorphicInliningWithNoDeopt()570 bool HInliner::UseOnlyPolymorphicInliningWithNoDeopt() {
571   // If we are compiling AOT or OSR, pretend the call using inline caches is polymorphic and
572   // do not generate a deopt.
573   //
574   // For AOT:
575   //    Generating a deopt does not ensure that we will actually capture the new types;
576   //    and the danger is that we could be stuck in a loop with "forever" deoptimizations.
577   //    Take for example the following scenario:
578   //      - we capture the inline cache in one run
579   //      - the next run, we deoptimize because we miss a type check, but the method
580   //        never becomes hot again
581   //    In this case, the inline cache will not be updated in the profile and the AOT code
582   //    will keep deoptimizing.
583   //    Another scenario is if we use profile compilation for a process which is not allowed
584   //    to JIT (e.g. system server). If we deoptimize we will run interpreted code for the
585   //    rest of the lifetime.
586   // TODO(calin):
587   //    This is a compromise because we will most likely never update the inline cache
588   //    in the profile (unless there's another reason to deopt). So we might be stuck with
589   //    a sub-optimal inline cache.
590   //    We could be smarter when capturing inline caches to mitigate this.
591   //    (e.g. by having different thresholds for new and old methods).
592   //
593   // For OSR:
594   //     We may come from the interpreter and it may have seen different receiver types.
595   return Runtime::Current()->IsAotCompiler() || outermost_graph_->IsCompilingOsr();
596 }
TryInlineFromInlineCache(const DexFile & caller_dex_file,HInvoke * invoke_instruction,ArtMethod * resolved_method)597 bool HInliner::TryInlineFromInlineCache(const DexFile& caller_dex_file,
598                                         HInvoke* invoke_instruction,
599                                         ArtMethod* resolved_method)
600     REQUIRES_SHARED(Locks::mutator_lock_) {
601   if (Runtime::Current()->IsAotCompiler() && !kUseAOTInlineCaches) {
602     return false;
603   }
604 
605   StackHandleScope<1> hs(Thread::Current());
606   Handle<mirror::ObjectArray<mirror::Class>> inline_cache;
607   // The Zygote JIT compiles based on a profile, so we shouldn't use runtime inline caches
608   // for it.
609   InlineCacheType inline_cache_type =
610       (Runtime::Current()->IsAotCompiler() || Runtime::Current()->IsZygote())
611           ? GetInlineCacheAOT(caller_dex_file, invoke_instruction, &hs, &inline_cache)
612           : GetInlineCacheJIT(invoke_instruction, &hs, &inline_cache);
613 
614   switch (inline_cache_type) {
615     case kInlineCacheNoData: {
616       LOG_FAIL_NO_STAT()
617           << "No inline cache information for call to "
618           << caller_dex_file.PrettyMethod(invoke_instruction->GetDexMethodIndex());
619       return false;
620     }
621 
622     case kInlineCacheUninitialized: {
623       LOG_FAIL_NO_STAT()
624           << "Interface or virtual call to "
625           << caller_dex_file.PrettyMethod(invoke_instruction->GetDexMethodIndex())
626           << " is not hit and not inlined";
627       return false;
628     }
629 
630     case kInlineCacheMonomorphic: {
631       MaybeRecordStat(stats_, MethodCompilationStat::kMonomorphicCall);
632       if (UseOnlyPolymorphicInliningWithNoDeopt()) {
633         return TryInlinePolymorphicCall(invoke_instruction, resolved_method, inline_cache);
634       } else {
635         return TryInlineMonomorphicCall(invoke_instruction, resolved_method, inline_cache);
636       }
637     }
638 
639     case kInlineCachePolymorphic: {
640       MaybeRecordStat(stats_, MethodCompilationStat::kPolymorphicCall);
641       return TryInlinePolymorphicCall(invoke_instruction, resolved_method, inline_cache);
642     }
643 
644     case kInlineCacheMegamorphic: {
645       LOG_FAIL_NO_STAT()
646           << "Interface or virtual call to "
647           << caller_dex_file.PrettyMethod(invoke_instruction->GetDexMethodIndex())
648           << " is megamorphic and not inlined";
649       MaybeRecordStat(stats_, MethodCompilationStat::kMegamorphicCall);
650       return false;
651     }
652 
653     case kInlineCacheMissingTypes: {
654       LOG_FAIL_NO_STAT()
655           << "Interface or virtual call to "
656           << caller_dex_file.PrettyMethod(invoke_instruction->GetDexMethodIndex())
657           << " is missing types and not inlined";
658       return false;
659     }
660   }
661   UNREACHABLE();
662 }
663 
GetInlineCacheJIT(HInvoke * invoke_instruction,StackHandleScope<1> * hs,Handle<mirror::ObjectArray<mirror::Class>> * inline_cache)664 HInliner::InlineCacheType HInliner::GetInlineCacheJIT(
665     HInvoke* invoke_instruction,
666     StackHandleScope<1>* hs,
667     /*out*/Handle<mirror::ObjectArray<mirror::Class>>* inline_cache)
668     REQUIRES_SHARED(Locks::mutator_lock_) {
669   DCHECK(Runtime::Current()->UseJitCompilation());
670 
671   ArtMethod* caller = graph_->GetArtMethod();
672   // Under JIT, we should always know the caller.
673   DCHECK(caller != nullptr);
674   ScopedProfilingInfoInlineUse spiis(caller, Thread::Current());
675   ProfilingInfo* profiling_info = spiis.GetProfilingInfo();
676 
677   if (profiling_info == nullptr) {
678     return kInlineCacheNoData;
679   }
680 
681   *inline_cache = AllocateInlineCacheHolder(caller_compilation_unit_, hs);
682   if (inline_cache->Get() == nullptr) {
683     // We can't extract any data if we failed to allocate;
684     return kInlineCacheNoData;
685   } else {
686     Runtime::Current()->GetJit()->GetCodeCache()->CopyInlineCacheInto(
687         *profiling_info->GetInlineCache(invoke_instruction->GetDexPc()),
688         *inline_cache);
689     return GetInlineCacheType(*inline_cache);
690   }
691 }
692 
GetInlineCacheAOT(const DexFile & caller_dex_file,HInvoke * invoke_instruction,StackHandleScope<1> * hs,Handle<mirror::ObjectArray<mirror::Class>> * inline_cache)693 HInliner::InlineCacheType HInliner::GetInlineCacheAOT(
694     const DexFile& caller_dex_file,
695     HInvoke* invoke_instruction,
696     StackHandleScope<1>* hs,
697     /*out*/Handle<mirror::ObjectArray<mirror::Class>>* inline_cache)
698     REQUIRES_SHARED(Locks::mutator_lock_) {
699   const ProfileCompilationInfo* pci = codegen_->GetCompilerOptions().GetProfileCompilationInfo();
700   if (pci == nullptr) {
701     return kInlineCacheNoData;
702   }
703 
704   std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> offline_profile =
705       pci->GetHotMethodInfo(MethodReference(
706           &caller_dex_file, caller_compilation_unit_.GetDexMethodIndex()));
707   if (offline_profile == nullptr) {
708     return kInlineCacheNoData;  // no profile information for this invocation.
709   }
710 
711   *inline_cache = AllocateInlineCacheHolder(caller_compilation_unit_, hs);
712   if (inline_cache == nullptr) {
713     // We can't extract any data if we failed to allocate;
714     return kInlineCacheNoData;
715   } else {
716     return ExtractClassesFromOfflineProfile(invoke_instruction,
717                                             *(offline_profile.get()),
718                                             *inline_cache);
719   }
720 }
721 
ExtractClassesFromOfflineProfile(const HInvoke * invoke_instruction,const ProfileCompilationInfo::OfflineProfileMethodInfo & offline_profile,Handle<mirror::ObjectArray<mirror::Class>> inline_cache)722 HInliner::InlineCacheType HInliner::ExtractClassesFromOfflineProfile(
723     const HInvoke* invoke_instruction,
724     const ProfileCompilationInfo::OfflineProfileMethodInfo& offline_profile,
725     /*out*/Handle<mirror::ObjectArray<mirror::Class>> inline_cache)
726     REQUIRES_SHARED(Locks::mutator_lock_) {
727   const auto it = offline_profile.inline_caches->find(invoke_instruction->GetDexPc());
728   if (it == offline_profile.inline_caches->end()) {
729     return kInlineCacheUninitialized;
730   }
731 
732   const ProfileCompilationInfo::DexPcData& dex_pc_data = it->second;
733 
734   if (dex_pc_data.is_missing_types) {
735     return kInlineCacheMissingTypes;
736   }
737   if (dex_pc_data.is_megamorphic) {
738     return kInlineCacheMegamorphic;
739   }
740 
741   DCHECK_LE(dex_pc_data.classes.size(), InlineCache::kIndividualCacheSize);
742   Thread* self = Thread::Current();
743   // We need to resolve the class relative to the containing dex file.
744   // So first, build a mapping from the index of dex file in the profile to
745   // its dex cache. This will avoid repeating the lookup when walking over
746   // the inline cache types.
747   std::vector<ObjPtr<mirror::DexCache>> dex_profile_index_to_dex_cache(
748         offline_profile.dex_references.size());
749   for (size_t i = 0; i < offline_profile.dex_references.size(); i++) {
750     bool found = false;
751     for (const DexFile* dex_file : codegen_->GetCompilerOptions().GetDexFilesForOatFile()) {
752       if (offline_profile.dex_references[i].MatchesDex(dex_file)) {
753         dex_profile_index_to_dex_cache[i] =
754             caller_compilation_unit_.GetClassLinker()->FindDexCache(self, *dex_file);
755         found = true;
756       }
757     }
758     if (!found) {
759       VLOG(compiler) << "Could not find profiled dex file: " << offline_profile.dex_references[i];
760       return kInlineCacheMissingTypes;
761     }
762   }
763 
764   // Walk over the classes and resolve them. If we cannot find a type we return
765   // kInlineCacheMissingTypes.
766   int ic_index = 0;
767   for (const ProfileCompilationInfo::ClassReference& class_ref : dex_pc_data.classes) {
768     ObjPtr<mirror::DexCache> dex_cache =
769         dex_profile_index_to_dex_cache[class_ref.dex_profile_index];
770     DCHECK(dex_cache != nullptr);
771 
772     if (!dex_cache->GetDexFile()->IsTypeIndexValid(class_ref.type_index)) {
773       VLOG(compiler) << "Profile data corrupt: type index " << class_ref.type_index
774             << "is invalid in location" << dex_cache->GetDexFile()->GetLocation();
775       return kInlineCacheNoData;
776     }
777     ObjPtr<mirror::Class> clazz = caller_compilation_unit_.GetClassLinker()->LookupResolvedType(
778           class_ref.type_index,
779           dex_cache,
780           caller_compilation_unit_.GetClassLoader().Get());
781     if (clazz != nullptr) {
782       inline_cache->Set(ic_index++, clazz);
783     } else {
784       VLOG(compiler) << "Could not resolve class from inline cache in AOT mode "
785           << caller_compilation_unit_.GetDexFile()->PrettyMethod(
786               invoke_instruction->GetDexMethodIndex()) << " : "
787           << caller_compilation_unit_
788               .GetDexFile()->StringByTypeIdx(class_ref.type_index);
789       return kInlineCacheMissingTypes;
790     }
791   }
792   return GetInlineCacheType(inline_cache);
793 }
794 
BuildGetReceiverClass(ClassLinker * class_linker,HInstruction * receiver,uint32_t dex_pc) const795 HInstanceFieldGet* HInliner::BuildGetReceiverClass(ClassLinker* class_linker,
796                                                    HInstruction* receiver,
797                                                    uint32_t dex_pc) const {
798   ArtField* field = GetClassRoot<mirror::Object>(class_linker)->GetInstanceField(0);
799   DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_");
800   HInstanceFieldGet* result = new (graph_->GetAllocator()) HInstanceFieldGet(
801       receiver,
802       field,
803       DataType::Type::kReference,
804       field->GetOffset(),
805       field->IsVolatile(),
806       field->GetDexFieldIndex(),
807       field->GetDeclaringClass()->GetDexClassDefIndex(),
808       *field->GetDexFile(),
809       dex_pc);
810   // The class of a field is effectively final, and does not have any memory dependencies.
811   result->SetSideEffects(SideEffects::None());
812   return result;
813 }
814 
ResolveMethodFromInlineCache(Handle<mirror::Class> klass,ArtMethod * resolved_method,HInstruction * invoke_instruction,PointerSize pointer_size)815 static ArtMethod* ResolveMethodFromInlineCache(Handle<mirror::Class> klass,
816                                                ArtMethod* resolved_method,
817                                                HInstruction* invoke_instruction,
818                                                PointerSize pointer_size)
819     REQUIRES_SHARED(Locks::mutator_lock_) {
820   if (Runtime::Current()->IsAotCompiler()) {
821     // We can get unrelated types when working with profiles (corruption,
822     // systme updates, or anyone can write to it). So first check if the class
823     // actually implements the declaring class of the method that is being
824     // called in bytecode.
825     // Note: the lookup methods used below require to have assignable types.
826     if (!resolved_method->GetDeclaringClass()->IsAssignableFrom(klass.Get())) {
827       return nullptr;
828     }
829   }
830 
831   if (invoke_instruction->IsInvokeInterface()) {
832     resolved_method = klass->FindVirtualMethodForInterface(resolved_method, pointer_size);
833   } else {
834     DCHECK(invoke_instruction->IsInvokeVirtual());
835     resolved_method = klass->FindVirtualMethodForVirtual(resolved_method, pointer_size);
836   }
837   DCHECK(resolved_method != nullptr);
838   return resolved_method;
839 }
840 
TryInlineMonomorphicCall(HInvoke * invoke_instruction,ArtMethod * resolved_method,Handle<mirror::ObjectArray<mirror::Class>> classes)841 bool HInliner::TryInlineMonomorphicCall(HInvoke* invoke_instruction,
842                                         ArtMethod* resolved_method,
843                                         Handle<mirror::ObjectArray<mirror::Class>> classes) {
844   DCHECK(invoke_instruction->IsInvokeVirtual() || invoke_instruction->IsInvokeInterface())
845       << invoke_instruction->DebugName();
846 
847   dex::TypeIndex class_index = FindClassIndexIn(
848       GetMonomorphicType(classes), caller_compilation_unit_);
849   if (!class_index.IsValid()) {
850     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedDexCache)
851         << "Call to " << ArtMethod::PrettyMethod(resolved_method)
852         << " from inline cache is not inlined because its class is not"
853         << " accessible to the caller";
854     return false;
855   }
856 
857   ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker();
858   PointerSize pointer_size = class_linker->GetImagePointerSize();
859   Handle<mirror::Class> monomorphic_type = handles_->NewHandle(GetMonomorphicType(classes));
860   resolved_method = ResolveMethodFromInlineCache(
861       monomorphic_type, resolved_method, invoke_instruction, pointer_size);
862 
863   LOG_NOTE() << "Try inline monomorphic call to " << resolved_method->PrettyMethod();
864   if (resolved_method == nullptr) {
865     // Bogus AOT profile, bail.
866     DCHECK(Runtime::Current()->IsAotCompiler());
867     return false;
868   }
869 
870   HInstruction* receiver = invoke_instruction->InputAt(0);
871   HInstruction* cursor = invoke_instruction->GetPrevious();
872   HBasicBlock* bb_cursor = invoke_instruction->GetBlock();
873   if (!TryInlineAndReplace(invoke_instruction,
874                            resolved_method,
875                            ReferenceTypeInfo::Create(monomorphic_type, /* is_exact= */ true),
876                            /* do_rtp= */ false,
877                            /* cha_devirtualize= */ false)) {
878     return false;
879   }
880 
881   // We successfully inlined, now add a guard.
882   AddTypeGuard(receiver,
883                cursor,
884                bb_cursor,
885                class_index,
886                monomorphic_type,
887                invoke_instruction,
888                /* with_deoptimization= */ true);
889 
890   // Run type propagation to get the guard typed, and eventually propagate the
891   // type of the receiver.
892   ReferenceTypePropagation rtp_fixup(graph_,
893                                      outer_compilation_unit_.GetClassLoader(),
894                                      outer_compilation_unit_.GetDexCache(),
895                                      handles_,
896                                      /* is_first_run= */ false);
897   rtp_fixup.Run();
898 
899   MaybeRecordStat(stats_, MethodCompilationStat::kInlinedMonomorphicCall);
900   return true;
901 }
902 
AddCHAGuard(HInstruction * invoke_instruction,uint32_t dex_pc,HInstruction * cursor,HBasicBlock * bb_cursor)903 void HInliner::AddCHAGuard(HInstruction* invoke_instruction,
904                            uint32_t dex_pc,
905                            HInstruction* cursor,
906                            HBasicBlock* bb_cursor) {
907   HShouldDeoptimizeFlag* deopt_flag = new (graph_->GetAllocator())
908       HShouldDeoptimizeFlag(graph_->GetAllocator(), dex_pc);
909   HInstruction* compare = new (graph_->GetAllocator()) HNotEqual(
910       deopt_flag, graph_->GetIntConstant(0, dex_pc));
911   HInstruction* deopt = new (graph_->GetAllocator()) HDeoptimize(
912       graph_->GetAllocator(), compare, DeoptimizationKind::kCHA, dex_pc);
913 
914   if (cursor != nullptr) {
915     bb_cursor->InsertInstructionAfter(deopt_flag, cursor);
916   } else {
917     bb_cursor->InsertInstructionBefore(deopt_flag, bb_cursor->GetFirstInstruction());
918   }
919   bb_cursor->InsertInstructionAfter(compare, deopt_flag);
920   bb_cursor->InsertInstructionAfter(deopt, compare);
921 
922   // Add receiver as input to aid CHA guard optimization later.
923   deopt_flag->AddInput(invoke_instruction->InputAt(0));
924   DCHECK_EQ(deopt_flag->InputCount(), 1u);
925   deopt->CopyEnvironmentFrom(invoke_instruction->GetEnvironment());
926   outermost_graph_->IncrementNumberOfCHAGuards();
927 }
928 
AddTypeGuard(HInstruction * receiver,HInstruction * cursor,HBasicBlock * bb_cursor,dex::TypeIndex class_index,Handle<mirror::Class> klass,HInstruction * invoke_instruction,bool with_deoptimization)929 HInstruction* HInliner::AddTypeGuard(HInstruction* receiver,
930                                      HInstruction* cursor,
931                                      HBasicBlock* bb_cursor,
932                                      dex::TypeIndex class_index,
933                                      Handle<mirror::Class> klass,
934                                      HInstruction* invoke_instruction,
935                                      bool with_deoptimization) {
936   ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker();
937   HInstanceFieldGet* receiver_class = BuildGetReceiverClass(
938       class_linker, receiver, invoke_instruction->GetDexPc());
939   if (cursor != nullptr) {
940     bb_cursor->InsertInstructionAfter(receiver_class, cursor);
941   } else {
942     bb_cursor->InsertInstructionBefore(receiver_class, bb_cursor->GetFirstInstruction());
943   }
944 
945   const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile();
946   bool is_referrer;
947   ArtMethod* outermost_art_method = outermost_graph_->GetArtMethod();
948   if (outermost_art_method == nullptr) {
949     DCHECK(Runtime::Current()->IsAotCompiler());
950     // We are in AOT mode and we don't have an ART method to determine
951     // if the inlined method belongs to the referrer. Assume it doesn't.
952     is_referrer = false;
953   } else {
954     is_referrer = klass.Get() == outermost_art_method->GetDeclaringClass();
955   }
956 
957   // Note that we will just compare the classes, so we don't need Java semantics access checks.
958   // Note that the type index and the dex file are relative to the method this type guard is
959   // inlined into.
960   HLoadClass* load_class = new (graph_->GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
961                                                                    class_index,
962                                                                    caller_dex_file,
963                                                                    klass,
964                                                                    is_referrer,
965                                                                    invoke_instruction->GetDexPc(),
966                                                                    /* needs_access_check= */ false);
967   HLoadClass::LoadKind kind = HSharpening::ComputeLoadClassKind(
968       load_class, codegen_, caller_compilation_unit_);
969   DCHECK(kind != HLoadClass::LoadKind::kInvalid)
970       << "We should always be able to reference a class for inline caches";
971   // Load kind must be set before inserting the instruction into the graph.
972   load_class->SetLoadKind(kind);
973   bb_cursor->InsertInstructionAfter(load_class, receiver_class);
974   // In AOT mode, we will most likely load the class from BSS, which will involve a call
975   // to the runtime. In this case, the load instruction will need an environment so copy
976   // it from the invoke instruction.
977   if (load_class->NeedsEnvironment()) {
978     DCHECK(Runtime::Current()->IsAotCompiler());
979     load_class->CopyEnvironmentFrom(invoke_instruction->GetEnvironment());
980   }
981 
982   HNotEqual* compare = new (graph_->GetAllocator()) HNotEqual(load_class, receiver_class);
983   bb_cursor->InsertInstructionAfter(compare, load_class);
984   if (with_deoptimization) {
985     HDeoptimize* deoptimize = new (graph_->GetAllocator()) HDeoptimize(
986         graph_->GetAllocator(),
987         compare,
988         receiver,
989         Runtime::Current()->IsAotCompiler()
990             ? DeoptimizationKind::kAotInlineCache
991             : DeoptimizationKind::kJitInlineCache,
992         invoke_instruction->GetDexPc());
993     bb_cursor->InsertInstructionAfter(deoptimize, compare);
994     deoptimize->CopyEnvironmentFrom(invoke_instruction->GetEnvironment());
995     DCHECK_EQ(invoke_instruction->InputAt(0), receiver);
996     receiver->ReplaceUsesDominatedBy(deoptimize, deoptimize);
997     deoptimize->SetReferenceTypeInfo(receiver->GetReferenceTypeInfo());
998   }
999   return compare;
1000 }
1001 
TryInlinePolymorphicCall(HInvoke * invoke_instruction,ArtMethod * resolved_method,Handle<mirror::ObjectArray<mirror::Class>> classes)1002 bool HInliner::TryInlinePolymorphicCall(HInvoke* invoke_instruction,
1003                                         ArtMethod* resolved_method,
1004                                         Handle<mirror::ObjectArray<mirror::Class>> classes) {
1005   DCHECK(invoke_instruction->IsInvokeVirtual() || invoke_instruction->IsInvokeInterface())
1006       << invoke_instruction->DebugName();
1007 
1008   if (TryInlinePolymorphicCallToSameTarget(invoke_instruction, resolved_method, classes)) {
1009     return true;
1010   }
1011 
1012   ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker();
1013   PointerSize pointer_size = class_linker->GetImagePointerSize();
1014 
1015   bool all_targets_inlined = true;
1016   bool one_target_inlined = false;
1017   for (size_t i = 0; i < InlineCache::kIndividualCacheSize; ++i) {
1018     if (classes->Get(i) == nullptr) {
1019       break;
1020     }
1021     ArtMethod* method = nullptr;
1022 
1023     Handle<mirror::Class> handle = handles_->NewHandle(classes->Get(i));
1024     method = ResolveMethodFromInlineCache(
1025         handle, resolved_method, invoke_instruction, pointer_size);
1026     if (method == nullptr) {
1027       DCHECK(Runtime::Current()->IsAotCompiler());
1028       // AOT profile is bogus. This loop expects to iterate over all entries,
1029       // so just just continue.
1030       all_targets_inlined = false;
1031       continue;
1032     }
1033 
1034     HInstruction* receiver = invoke_instruction->InputAt(0);
1035     HInstruction* cursor = invoke_instruction->GetPrevious();
1036     HBasicBlock* bb_cursor = invoke_instruction->GetBlock();
1037 
1038     dex::TypeIndex class_index = FindClassIndexIn(handle.Get(), caller_compilation_unit_);
1039     HInstruction* return_replacement = nullptr;
1040     LOG_NOTE() << "Try inline polymorphic call to " << method->PrettyMethod();
1041     if (!class_index.IsValid() ||
1042         !TryBuildAndInline(invoke_instruction,
1043                            method,
1044                            ReferenceTypeInfo::Create(handle, /* is_exact= */ true),
1045                            &return_replacement)) {
1046       all_targets_inlined = false;
1047     } else {
1048       one_target_inlined = true;
1049 
1050       LOG_SUCCESS() << "Polymorphic call to " << ArtMethod::PrettyMethod(resolved_method)
1051                     << " has inlined " << ArtMethod::PrettyMethod(method);
1052 
1053       // If we have inlined all targets before, and this receiver is the last seen,
1054       // we deoptimize instead of keeping the original invoke instruction.
1055       bool deoptimize = !UseOnlyPolymorphicInliningWithNoDeopt() &&
1056           all_targets_inlined &&
1057           (i != InlineCache::kIndividualCacheSize - 1) &&
1058           (classes->Get(i + 1) == nullptr);
1059 
1060       HInstruction* compare = AddTypeGuard(receiver,
1061                                            cursor,
1062                                            bb_cursor,
1063                                            class_index,
1064                                            handle,
1065                                            invoke_instruction,
1066                                            deoptimize);
1067       if (deoptimize) {
1068         if (return_replacement != nullptr) {
1069           invoke_instruction->ReplaceWith(return_replacement);
1070         }
1071         invoke_instruction->GetBlock()->RemoveInstruction(invoke_instruction);
1072         // Because the inline cache data can be populated concurrently, we force the end of the
1073         // iteration. Otherwise, we could see a new receiver type.
1074         break;
1075       } else {
1076         CreateDiamondPatternForPolymorphicInline(compare, return_replacement, invoke_instruction);
1077       }
1078     }
1079   }
1080 
1081   if (!one_target_inlined) {
1082     LOG_FAIL_NO_STAT()
1083         << "Call to " << ArtMethod::PrettyMethod(resolved_method)
1084         << " from inline cache is not inlined because none"
1085         << " of its targets could be inlined";
1086     return false;
1087   }
1088 
1089   MaybeRecordStat(stats_, MethodCompilationStat::kInlinedPolymorphicCall);
1090 
1091   // Run type propagation to get the guards typed.
1092   ReferenceTypePropagation rtp_fixup(graph_,
1093                                      outer_compilation_unit_.GetClassLoader(),
1094                                      outer_compilation_unit_.GetDexCache(),
1095                                      handles_,
1096                                      /* is_first_run= */ false);
1097   rtp_fixup.Run();
1098   return true;
1099 }
1100 
CreateDiamondPatternForPolymorphicInline(HInstruction * compare,HInstruction * return_replacement,HInstruction * invoke_instruction)1101 void HInliner::CreateDiamondPatternForPolymorphicInline(HInstruction* compare,
1102                                                         HInstruction* return_replacement,
1103                                                         HInstruction* invoke_instruction) {
1104   uint32_t dex_pc = invoke_instruction->GetDexPc();
1105   HBasicBlock* cursor_block = compare->GetBlock();
1106   HBasicBlock* original_invoke_block = invoke_instruction->GetBlock();
1107   ArenaAllocator* allocator = graph_->GetAllocator();
1108 
1109   // Spit the block after the compare: `cursor_block` will now be the start of the diamond,
1110   // and the returned block is the start of the then branch (that could contain multiple blocks).
1111   HBasicBlock* then = cursor_block->SplitAfterForInlining(compare);
1112 
1113   // Split the block containing the invoke before and after the invoke. The returned block
1114   // of the split before will contain the invoke and will be the otherwise branch of
1115   // the diamond. The returned block of the split after will be the merge block
1116   // of the diamond.
1117   HBasicBlock* end_then = invoke_instruction->GetBlock();
1118   HBasicBlock* otherwise = end_then->SplitBeforeForInlining(invoke_instruction);
1119   HBasicBlock* merge = otherwise->SplitAfterForInlining(invoke_instruction);
1120 
1121   // If the methods we are inlining return a value, we create a phi in the merge block
1122   // that will have the `invoke_instruction and the `return_replacement` as inputs.
1123   if (return_replacement != nullptr) {
1124     HPhi* phi = new (allocator) HPhi(
1125         allocator, kNoRegNumber, 0, HPhi::ToPhiType(invoke_instruction->GetType()), dex_pc);
1126     merge->AddPhi(phi);
1127     invoke_instruction->ReplaceWith(phi);
1128     phi->AddInput(return_replacement);
1129     phi->AddInput(invoke_instruction);
1130   }
1131 
1132   // Add the control flow instructions.
1133   otherwise->AddInstruction(new (allocator) HGoto(dex_pc));
1134   end_then->AddInstruction(new (allocator) HGoto(dex_pc));
1135   cursor_block->AddInstruction(new (allocator) HIf(compare, dex_pc));
1136 
1137   // Add the newly created blocks to the graph.
1138   graph_->AddBlock(then);
1139   graph_->AddBlock(otherwise);
1140   graph_->AddBlock(merge);
1141 
1142   // Set up successor (and implictly predecessor) relations.
1143   cursor_block->AddSuccessor(otherwise);
1144   cursor_block->AddSuccessor(then);
1145   end_then->AddSuccessor(merge);
1146   otherwise->AddSuccessor(merge);
1147 
1148   // Set up dominance information.
1149   then->SetDominator(cursor_block);
1150   cursor_block->AddDominatedBlock(then);
1151   otherwise->SetDominator(cursor_block);
1152   cursor_block->AddDominatedBlock(otherwise);
1153   merge->SetDominator(cursor_block);
1154   cursor_block->AddDominatedBlock(merge);
1155 
1156   // Update the revert post order.
1157   size_t index = IndexOfElement(graph_->reverse_post_order_, cursor_block);
1158   MakeRoomFor(&graph_->reverse_post_order_, 1, index);
1159   graph_->reverse_post_order_[++index] = then;
1160   index = IndexOfElement(graph_->reverse_post_order_, end_then);
1161   MakeRoomFor(&graph_->reverse_post_order_, 2, index);
1162   graph_->reverse_post_order_[++index] = otherwise;
1163   graph_->reverse_post_order_[++index] = merge;
1164 
1165 
1166   graph_->UpdateLoopAndTryInformationOfNewBlock(
1167       then, original_invoke_block, /* replace_if_back_edge= */ false);
1168   graph_->UpdateLoopAndTryInformationOfNewBlock(
1169       otherwise, original_invoke_block, /* replace_if_back_edge= */ false);
1170 
1171   // In case the original invoke location was a back edge, we need to update
1172   // the loop to now have the merge block as a back edge.
1173   graph_->UpdateLoopAndTryInformationOfNewBlock(
1174       merge, original_invoke_block, /* replace_if_back_edge= */ true);
1175 }
1176 
TryInlinePolymorphicCallToSameTarget(HInvoke * invoke_instruction,ArtMethod * resolved_method,Handle<mirror::ObjectArray<mirror::Class>> classes)1177 bool HInliner::TryInlinePolymorphicCallToSameTarget(
1178     HInvoke* invoke_instruction,
1179     ArtMethod* resolved_method,
1180     Handle<mirror::ObjectArray<mirror::Class>> classes) {
1181   // This optimization only works under JIT for now.
1182   if (!Runtime::Current()->UseJitCompilation()) {
1183     return false;
1184   }
1185 
1186   ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker();
1187   PointerSize pointer_size = class_linker->GetImagePointerSize();
1188 
1189   DCHECK(resolved_method != nullptr);
1190   ArtMethod* actual_method = nullptr;
1191   size_t method_index = invoke_instruction->IsInvokeVirtual()
1192       ? invoke_instruction->AsInvokeVirtual()->GetVTableIndex()
1193       : invoke_instruction->AsInvokeInterface()->GetImtIndex();
1194 
1195   // Check whether we are actually calling the same method among
1196   // the different types seen.
1197   for (size_t i = 0; i < InlineCache::kIndividualCacheSize; ++i) {
1198     if (classes->Get(i) == nullptr) {
1199       break;
1200     }
1201     ArtMethod* new_method = nullptr;
1202     if (invoke_instruction->IsInvokeInterface()) {
1203       new_method = classes->Get(i)->GetImt(pointer_size)->Get(
1204           method_index, pointer_size);
1205       if (new_method->IsRuntimeMethod()) {
1206         // Bail out as soon as we see a conflict trampoline in one of the target's
1207         // interface table.
1208         return false;
1209       }
1210     } else {
1211       DCHECK(invoke_instruction->IsInvokeVirtual());
1212       new_method = classes->Get(i)->GetEmbeddedVTableEntry(method_index, pointer_size);
1213     }
1214     DCHECK(new_method != nullptr);
1215     if (actual_method == nullptr) {
1216       actual_method = new_method;
1217     } else if (actual_method != new_method) {
1218       // Different methods, bailout.
1219       return false;
1220     }
1221   }
1222 
1223   HInstruction* receiver = invoke_instruction->InputAt(0);
1224   HInstruction* cursor = invoke_instruction->GetPrevious();
1225   HBasicBlock* bb_cursor = invoke_instruction->GetBlock();
1226 
1227   HInstruction* return_replacement = nullptr;
1228   if (!TryBuildAndInline(invoke_instruction,
1229                          actual_method,
1230                          ReferenceTypeInfo::CreateInvalid(),
1231                          &return_replacement)) {
1232     return false;
1233   }
1234 
1235   // We successfully inlined, now add a guard.
1236   HInstanceFieldGet* receiver_class = BuildGetReceiverClass(
1237       class_linker, receiver, invoke_instruction->GetDexPc());
1238 
1239   DataType::Type type = Is64BitInstructionSet(graph_->GetInstructionSet())
1240       ? DataType::Type::kInt64
1241       : DataType::Type::kInt32;
1242   HClassTableGet* class_table_get = new (graph_->GetAllocator()) HClassTableGet(
1243       receiver_class,
1244       type,
1245       invoke_instruction->IsInvokeVirtual() ? HClassTableGet::TableKind::kVTable
1246                                             : HClassTableGet::TableKind::kIMTable,
1247       method_index,
1248       invoke_instruction->GetDexPc());
1249 
1250   HConstant* constant;
1251   if (type == DataType::Type::kInt64) {
1252     constant = graph_->GetLongConstant(
1253         reinterpret_cast<intptr_t>(actual_method), invoke_instruction->GetDexPc());
1254   } else {
1255     constant = graph_->GetIntConstant(
1256         reinterpret_cast<intptr_t>(actual_method), invoke_instruction->GetDexPc());
1257   }
1258 
1259   HNotEqual* compare = new (graph_->GetAllocator()) HNotEqual(class_table_get, constant);
1260   if (cursor != nullptr) {
1261     bb_cursor->InsertInstructionAfter(receiver_class, cursor);
1262   } else {
1263     bb_cursor->InsertInstructionBefore(receiver_class, bb_cursor->GetFirstInstruction());
1264   }
1265   bb_cursor->InsertInstructionAfter(class_table_get, receiver_class);
1266   bb_cursor->InsertInstructionAfter(compare, class_table_get);
1267 
1268   if (outermost_graph_->IsCompilingOsr()) {
1269     CreateDiamondPatternForPolymorphicInline(compare, return_replacement, invoke_instruction);
1270   } else {
1271     HDeoptimize* deoptimize = new (graph_->GetAllocator()) HDeoptimize(
1272         graph_->GetAllocator(),
1273         compare,
1274         receiver,
1275         DeoptimizationKind::kJitSameTarget,
1276         invoke_instruction->GetDexPc());
1277     bb_cursor->InsertInstructionAfter(deoptimize, compare);
1278     deoptimize->CopyEnvironmentFrom(invoke_instruction->GetEnvironment());
1279     if (return_replacement != nullptr) {
1280       invoke_instruction->ReplaceWith(return_replacement);
1281     }
1282     receiver->ReplaceUsesDominatedBy(deoptimize, deoptimize);
1283     invoke_instruction->GetBlock()->RemoveInstruction(invoke_instruction);
1284     deoptimize->SetReferenceTypeInfo(receiver->GetReferenceTypeInfo());
1285   }
1286 
1287   // Run type propagation to get the guard typed.
1288   ReferenceTypePropagation rtp_fixup(graph_,
1289                                      outer_compilation_unit_.GetClassLoader(),
1290                                      outer_compilation_unit_.GetDexCache(),
1291                                      handles_,
1292                                      /* is_first_run= */ false);
1293   rtp_fixup.Run();
1294 
1295   MaybeRecordStat(stats_, MethodCompilationStat::kInlinedPolymorphicCall);
1296 
1297   LOG_SUCCESS() << "Inlined same polymorphic target " << actual_method->PrettyMethod();
1298   return true;
1299 }
1300 
TryInlineAndReplace(HInvoke * invoke_instruction,ArtMethod * method,ReferenceTypeInfo receiver_type,bool do_rtp,bool cha_devirtualize)1301 bool HInliner::TryInlineAndReplace(HInvoke* invoke_instruction,
1302                                    ArtMethod* method,
1303                                    ReferenceTypeInfo receiver_type,
1304                                    bool do_rtp,
1305                                    bool cha_devirtualize) {
1306   DCHECK(!invoke_instruction->IsIntrinsic());
1307   HInstruction* return_replacement = nullptr;
1308   uint32_t dex_pc = invoke_instruction->GetDexPc();
1309   HInstruction* cursor = invoke_instruction->GetPrevious();
1310   HBasicBlock* bb_cursor = invoke_instruction->GetBlock();
1311   bool should_remove_invoke_instruction = false;
1312 
1313   // If invoke_instruction is devirtualized to a different method, give intrinsics
1314   // another chance before we try to inline it.
1315   if (invoke_instruction->GetResolvedMethod() != method && method->IsIntrinsic()) {
1316     MaybeRecordStat(stats_, MethodCompilationStat::kIntrinsicRecognized);
1317     if (invoke_instruction->IsInvokeInterface()) {
1318       // We don't intrinsify an invoke-interface directly.
1319       // Replace the invoke-interface with an invoke-virtual.
1320       HInvokeVirtual* new_invoke = new (graph_->GetAllocator()) HInvokeVirtual(
1321           graph_->GetAllocator(),
1322           invoke_instruction->GetNumberOfArguments(),
1323           invoke_instruction->GetType(),
1324           invoke_instruction->GetDexPc(),
1325           invoke_instruction->GetDexMethodIndex(),  // Use interface method's dex method index.
1326           method,
1327           method->GetMethodIndex());
1328       DCHECK_NE(new_invoke->GetIntrinsic(), Intrinsics::kNone);
1329       HInputsRef inputs = invoke_instruction->GetInputs();
1330       for (size_t index = 0; index != inputs.size(); ++index) {
1331         new_invoke->SetArgumentAt(index, inputs[index]);
1332       }
1333       invoke_instruction->GetBlock()->InsertInstructionBefore(new_invoke, invoke_instruction);
1334       new_invoke->CopyEnvironmentFrom(invoke_instruction->GetEnvironment());
1335       if (invoke_instruction->GetType() == DataType::Type::kReference) {
1336         new_invoke->SetReferenceTypeInfo(invoke_instruction->GetReferenceTypeInfo());
1337       }
1338       return_replacement = new_invoke;
1339       // invoke_instruction is replaced with new_invoke.
1340       should_remove_invoke_instruction = true;
1341     } else {
1342       invoke_instruction->SetResolvedMethod(method);
1343     }
1344   } else if (!TryBuildAndInline(invoke_instruction, method, receiver_type, &return_replacement)) {
1345     if (invoke_instruction->IsInvokeInterface()) {
1346       DCHECK(!method->IsProxyMethod());
1347       // Turn an invoke-interface into an invoke-virtual. An invoke-virtual is always
1348       // better than an invoke-interface because:
1349       // 1) In the best case, the interface call has one more indirection (to fetch the IMT).
1350       // 2) We will not go to the conflict trampoline with an invoke-virtual.
1351       // TODO: Consider sharpening once it is not dependent on the compiler driver.
1352 
1353       if (method->IsDefault() && !method->IsCopied()) {
1354         // Changing to invoke-virtual cannot be done on an original default method
1355         // since it's not in any vtable. Devirtualization by exact type/inline-cache
1356         // always uses a method in the iftable which is never an original default
1357         // method.
1358         // On the other hand, inlining an original default method by CHA is fine.
1359         DCHECK(cha_devirtualize);
1360         return false;
1361       }
1362 
1363       const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile();
1364       uint32_t dex_method_index = FindMethodIndexIn(
1365           method, caller_dex_file, invoke_instruction->GetDexMethodIndex());
1366       if (dex_method_index == dex::kDexNoIndex) {
1367         return false;
1368       }
1369       HInvokeVirtual* new_invoke = new (graph_->GetAllocator()) HInvokeVirtual(
1370           graph_->GetAllocator(),
1371           invoke_instruction->GetNumberOfArguments(),
1372           invoke_instruction->GetType(),
1373           invoke_instruction->GetDexPc(),
1374           dex_method_index,
1375           method,
1376           method->GetMethodIndex());
1377       HInputsRef inputs = invoke_instruction->GetInputs();
1378       for (size_t index = 0; index != inputs.size(); ++index) {
1379         new_invoke->SetArgumentAt(index, inputs[index]);
1380       }
1381       invoke_instruction->GetBlock()->InsertInstructionBefore(new_invoke, invoke_instruction);
1382       new_invoke->CopyEnvironmentFrom(invoke_instruction->GetEnvironment());
1383       if (invoke_instruction->GetType() == DataType::Type::kReference) {
1384         new_invoke->SetReferenceTypeInfo(invoke_instruction->GetReferenceTypeInfo());
1385       }
1386       return_replacement = new_invoke;
1387       // invoke_instruction is replaced with new_invoke.
1388       should_remove_invoke_instruction = true;
1389     } else {
1390       // TODO: Consider sharpening an invoke virtual once it is not dependent on the
1391       // compiler driver.
1392       return false;
1393     }
1394   } else {
1395     // invoke_instruction is inlined.
1396     should_remove_invoke_instruction = true;
1397   }
1398 
1399   if (cha_devirtualize) {
1400     AddCHAGuard(invoke_instruction, dex_pc, cursor, bb_cursor);
1401   }
1402   if (return_replacement != nullptr) {
1403     invoke_instruction->ReplaceWith(return_replacement);
1404   }
1405   if (should_remove_invoke_instruction) {
1406     invoke_instruction->GetBlock()->RemoveInstruction(invoke_instruction);
1407   }
1408   FixUpReturnReferenceType(method, return_replacement);
1409   if (do_rtp && ReturnTypeMoreSpecific(invoke_instruction, return_replacement)) {
1410     // Actual return value has a more specific type than the method's declared
1411     // return type. Run RTP again on the outer graph to propagate it.
1412     ReferenceTypePropagation(graph_,
1413                              outer_compilation_unit_.GetClassLoader(),
1414                              outer_compilation_unit_.GetDexCache(),
1415                              handles_,
1416                              /* is_first_run= */ false).Run();
1417   }
1418   return true;
1419 }
1420 
CountRecursiveCallsOf(ArtMethod * method) const1421 size_t HInliner::CountRecursiveCallsOf(ArtMethod* method) const {
1422   const HInliner* current = this;
1423   size_t count = 0;
1424   do {
1425     if (current->graph_->GetArtMethod() == method) {
1426       ++count;
1427     }
1428     current = current->parent_;
1429   } while (current != nullptr);
1430   return count;
1431 }
1432 
MayInline(const CompilerOptions & compiler_options,const DexFile & inlined_from,const DexFile & inlined_into)1433 static inline bool MayInline(const CompilerOptions& compiler_options,
1434                              const DexFile& inlined_from,
1435                              const DexFile& inlined_into) {
1436   // We're not allowed to inline across dex files if we're the no-inline-from dex file.
1437   if (!IsSameDexFile(inlined_from, inlined_into) &&
1438       ContainsElement(compiler_options.GetNoInlineFromDexFile(), &inlined_from)) {
1439     return false;
1440   }
1441 
1442   return true;
1443 }
1444 
1445 // Returns whether inlining is allowed based on ART semantics.
IsInliningAllowed(ArtMethod * method,const CodeItemDataAccessor & accessor) const1446 bool HInliner::IsInliningAllowed(ArtMethod* method, const CodeItemDataAccessor& accessor) const {
1447   if (!accessor.HasCodeItem()) {
1448     LOG_FAIL_NO_STAT()
1449         << "Method " << method->PrettyMethod() << " is not inlined because it is native";
1450     return false;
1451   }
1452 
1453   if (!method->IsCompilable()) {
1454     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedNotVerified)
1455         << "Method " << method->PrettyMethod()
1456         << " has soft failures un-handled by the compiler, so it cannot be inlined";
1457     return false;
1458   }
1459 
1460   if (IsMethodUnverified(codegen_->GetCompilerOptions(), method)) {
1461     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedNotVerified)
1462         << "Method " << method->PrettyMethod()
1463         << " couldn't be verified, so it cannot be inlined";
1464     return false;
1465   }
1466 
1467   return true;
1468 }
1469 
1470 // Returns whether ART supports inlining this method.
1471 //
1472 // Some methods are not supported because they have features for which inlining
1473 // is not implemented. For example, we do not currently support inlining throw
1474 // instructions into a try block.
IsInliningSupported(const HInvoke * invoke_instruction,ArtMethod * method,const CodeItemDataAccessor & accessor) const1475 bool HInliner::IsInliningSupported(const HInvoke* invoke_instruction,
1476                                    ArtMethod* method,
1477                                    const CodeItemDataAccessor& accessor) const {
1478   if (method->IsProxyMethod()) {
1479     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedProxy)
1480         << "Method " << method->PrettyMethod()
1481         << " is not inlined because of unimplemented inline support for proxy methods.";
1482     return false;
1483   }
1484 
1485   if (accessor.TriesSize() != 0) {
1486     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedTryCatch)
1487         << "Method " << method->PrettyMethod() << " is not inlined because of try block";
1488     return false;
1489   }
1490 
1491   if (invoke_instruction->IsInvokeStaticOrDirect() &&
1492       invoke_instruction->AsInvokeStaticOrDirect()->IsStaticWithImplicitClinitCheck()) {
1493     // Case of a static method that cannot be inlined because it implicitly
1494     // requires an initialization check of its declaring class.
1495     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedDexCache)
1496         << "Method " << method->PrettyMethod()
1497         << " is not inlined because it is static and requires a clinit"
1498         << " check that cannot be emitted due to Dex cache limitations";
1499     return false;
1500   }
1501 
1502   return true;
1503 }
1504 
1505 // Returns whether our resource limits allow inlining this method.
IsInliningBudgetAvailable(ArtMethod * method,const CodeItemDataAccessor & accessor) const1506 bool HInliner::IsInliningBudgetAvailable(ArtMethod* method,
1507                                          const CodeItemDataAccessor& accessor) const {
1508   if (CountRecursiveCallsOf(method) > kMaximumNumberOfRecursiveCalls) {
1509     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedRecursiveBudget)
1510         << "Method "
1511         << method->PrettyMethod()
1512         << " is not inlined because it has reached its recursive call budget.";
1513     return false;
1514   }
1515 
1516   size_t inline_max_code_units = codegen_->GetCompilerOptions().GetInlineMaxCodeUnits();
1517   if (accessor.InsnsSizeInCodeUnits() > inline_max_code_units) {
1518     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedCodeItem)
1519         << "Method " << method->PrettyMethod()
1520         << " is not inlined because its code item is too big: "
1521         << accessor.InsnsSizeInCodeUnits()
1522         << " > "
1523         << inline_max_code_units;
1524     return false;
1525   }
1526 
1527   return true;
1528 }
1529 
TryBuildAndInline(HInvoke * invoke_instruction,ArtMethod * method,ReferenceTypeInfo receiver_type,HInstruction ** return_replacement)1530 bool HInliner::TryBuildAndInline(HInvoke* invoke_instruction,
1531                                  ArtMethod* method,
1532                                  ReferenceTypeInfo receiver_type,
1533                                  HInstruction** return_replacement) {
1534   // Check whether we're allowed to inline. The outermost compilation unit is the relevant
1535   // dex file here (though the transitivity of an inline chain would allow checking the caller).
1536   if (!MayInline(codegen_->GetCompilerOptions(),
1537                  *method->GetDexFile(),
1538                  *outer_compilation_unit_.GetDexFile())) {
1539     if (TryPatternSubstitution(invoke_instruction, method, return_replacement)) {
1540       LOG_SUCCESS() << "Successfully replaced pattern of invoke "
1541                     << method->PrettyMethod();
1542       MaybeRecordStat(stats_, MethodCompilationStat::kReplacedInvokeWithSimplePattern);
1543       return true;
1544     }
1545     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedWont)
1546         << "Won't inline " << method->PrettyMethod() << " in "
1547         << outer_compilation_unit_.GetDexFile()->GetLocation() << " ("
1548         << caller_compilation_unit_.GetDexFile()->GetLocation() << ") from "
1549         << method->GetDexFile()->GetLocation();
1550     return false;
1551   }
1552 
1553   CodeItemDataAccessor accessor(method->DexInstructionData());
1554 
1555   if (!IsInliningAllowed(method, accessor)) {
1556     return false;
1557   }
1558 
1559   if (!IsInliningSupported(invoke_instruction, method, accessor)) {
1560     return false;
1561   }
1562 
1563   if (!IsInliningBudgetAvailable(method, accessor)) {
1564     return false;
1565   }
1566 
1567   if (!TryBuildAndInlineHelper(
1568           invoke_instruction, method, receiver_type, return_replacement)) {
1569     return false;
1570   }
1571 
1572   LOG_SUCCESS() << method->PrettyMethod();
1573   MaybeRecordStat(stats_, MethodCompilationStat::kInlinedInvoke);
1574   return true;
1575 }
1576 
GetInvokeInputForArgVRegIndex(HInvoke * invoke_instruction,size_t arg_vreg_index)1577 static HInstruction* GetInvokeInputForArgVRegIndex(HInvoke* invoke_instruction,
1578                                                    size_t arg_vreg_index)
1579     REQUIRES_SHARED(Locks::mutator_lock_) {
1580   size_t input_index = 0;
1581   for (size_t i = 0; i < arg_vreg_index; ++i, ++input_index) {
1582     DCHECK_LT(input_index, invoke_instruction->GetNumberOfArguments());
1583     if (DataType::Is64BitType(invoke_instruction->InputAt(input_index)->GetType())) {
1584       ++i;
1585       DCHECK_NE(i, arg_vreg_index);
1586     }
1587   }
1588   DCHECK_LT(input_index, invoke_instruction->GetNumberOfArguments());
1589   return invoke_instruction->InputAt(input_index);
1590 }
1591 
1592 // Try to recognize known simple patterns and replace invoke call with appropriate instructions.
TryPatternSubstitution(HInvoke * invoke_instruction,ArtMethod * resolved_method,HInstruction ** return_replacement)1593 bool HInliner::TryPatternSubstitution(HInvoke* invoke_instruction,
1594                                       ArtMethod* resolved_method,
1595                                       HInstruction** return_replacement) {
1596   InlineMethod inline_method;
1597   if (!InlineMethodAnalyser::AnalyseMethodCode(resolved_method, &inline_method)) {
1598     return false;
1599   }
1600 
1601   switch (inline_method.opcode) {
1602     case kInlineOpNop:
1603       DCHECK_EQ(invoke_instruction->GetType(), DataType::Type::kVoid);
1604       *return_replacement = nullptr;
1605       break;
1606     case kInlineOpReturnArg:
1607       *return_replacement = GetInvokeInputForArgVRegIndex(invoke_instruction,
1608                                                           inline_method.d.return_data.arg);
1609       break;
1610     case kInlineOpNonWideConst:
1611       if (resolved_method->GetShorty()[0] == 'L') {
1612         DCHECK_EQ(inline_method.d.data, 0u);
1613         *return_replacement = graph_->GetNullConstant();
1614       } else {
1615         *return_replacement = graph_->GetIntConstant(static_cast<int32_t>(inline_method.d.data));
1616       }
1617       break;
1618     case kInlineOpIGet: {
1619       const InlineIGetIPutData& data = inline_method.d.ifield_data;
1620       if (data.method_is_static || data.object_arg != 0u) {
1621         // TODO: Needs null check.
1622         return false;
1623       }
1624       HInstruction* obj = GetInvokeInputForArgVRegIndex(invoke_instruction, data.object_arg);
1625       HInstanceFieldGet* iget = CreateInstanceFieldGet(data.field_idx, resolved_method, obj);
1626       DCHECK_EQ(iget->GetFieldOffset().Uint32Value(), data.field_offset);
1627       DCHECK_EQ(iget->IsVolatile() ? 1u : 0u, data.is_volatile);
1628       invoke_instruction->GetBlock()->InsertInstructionBefore(iget, invoke_instruction);
1629       *return_replacement = iget;
1630       break;
1631     }
1632     case kInlineOpIPut: {
1633       const InlineIGetIPutData& data = inline_method.d.ifield_data;
1634       if (data.method_is_static || data.object_arg != 0u) {
1635         // TODO: Needs null check.
1636         return false;
1637       }
1638       HInstruction* obj = GetInvokeInputForArgVRegIndex(invoke_instruction, data.object_arg);
1639       HInstruction* value = GetInvokeInputForArgVRegIndex(invoke_instruction, data.src_arg);
1640       HInstanceFieldSet* iput = CreateInstanceFieldSet(data.field_idx, resolved_method, obj, value);
1641       DCHECK_EQ(iput->GetFieldOffset().Uint32Value(), data.field_offset);
1642       DCHECK_EQ(iput->IsVolatile() ? 1u : 0u, data.is_volatile);
1643       invoke_instruction->GetBlock()->InsertInstructionBefore(iput, invoke_instruction);
1644       if (data.return_arg_plus1 != 0u) {
1645         size_t return_arg = data.return_arg_plus1 - 1u;
1646         *return_replacement = GetInvokeInputForArgVRegIndex(invoke_instruction, return_arg);
1647       }
1648       break;
1649     }
1650     case kInlineOpConstructor: {
1651       const InlineConstructorData& data = inline_method.d.constructor_data;
1652       // Get the indexes to arrays for easier processing.
1653       uint16_t iput_field_indexes[] = {
1654           data.iput0_field_index, data.iput1_field_index, data.iput2_field_index
1655       };
1656       uint16_t iput_args[] = { data.iput0_arg, data.iput1_arg, data.iput2_arg };
1657       static_assert(arraysize(iput_args) == arraysize(iput_field_indexes), "Size mismatch");
1658       // Count valid field indexes.
1659       size_t number_of_iputs = 0u;
1660       while (number_of_iputs != arraysize(iput_field_indexes) &&
1661           iput_field_indexes[number_of_iputs] != DexFile::kDexNoIndex16) {
1662         // Check that there are no duplicate valid field indexes.
1663         DCHECK_EQ(0, std::count(iput_field_indexes + number_of_iputs + 1,
1664                                 iput_field_indexes + arraysize(iput_field_indexes),
1665                                 iput_field_indexes[number_of_iputs]));
1666         ++number_of_iputs;
1667       }
1668       // Check that there are no valid field indexes in the rest of the array.
1669       DCHECK_EQ(0, std::count_if(iput_field_indexes + number_of_iputs,
1670                                  iput_field_indexes + arraysize(iput_field_indexes),
1671                                  [](uint16_t index) { return index != DexFile::kDexNoIndex16; }));
1672 
1673       // Create HInstanceFieldSet for each IPUT that stores non-zero data.
1674       HInstruction* obj = GetInvokeInputForArgVRegIndex(invoke_instruction,
1675                                                         /* arg_vreg_index= */ 0u);
1676       bool needs_constructor_barrier = false;
1677       for (size_t i = 0; i != number_of_iputs; ++i) {
1678         HInstruction* value = GetInvokeInputForArgVRegIndex(invoke_instruction, iput_args[i]);
1679         if (!value->IsConstant() || !value->AsConstant()->IsZeroBitPattern()) {
1680           uint16_t field_index = iput_field_indexes[i];
1681           bool is_final;
1682           HInstanceFieldSet* iput =
1683               CreateInstanceFieldSet(field_index, resolved_method, obj, value, &is_final);
1684           invoke_instruction->GetBlock()->InsertInstructionBefore(iput, invoke_instruction);
1685 
1686           // Check whether the field is final. If it is, we need to add a barrier.
1687           if (is_final) {
1688             needs_constructor_barrier = true;
1689           }
1690         }
1691       }
1692       if (needs_constructor_barrier) {
1693         // See DexCompilationUnit::RequiresConstructorBarrier for more details.
1694         DCHECK(obj != nullptr) << "only non-static methods can have a constructor fence";
1695 
1696         HConstructorFence* constructor_fence =
1697             new (graph_->GetAllocator()) HConstructorFence(obj, kNoDexPc, graph_->GetAllocator());
1698         invoke_instruction->GetBlock()->InsertInstructionBefore(constructor_fence,
1699                                                                 invoke_instruction);
1700       }
1701       *return_replacement = nullptr;
1702       break;
1703     }
1704     default:
1705       LOG(FATAL) << "UNREACHABLE";
1706       UNREACHABLE();
1707   }
1708   return true;
1709 }
1710 
CreateInstanceFieldGet(uint32_t field_index,ArtMethod * referrer,HInstruction * obj)1711 HInstanceFieldGet* HInliner::CreateInstanceFieldGet(uint32_t field_index,
1712                                                     ArtMethod* referrer,
1713                                                     HInstruction* obj)
1714     REQUIRES_SHARED(Locks::mutator_lock_) {
1715   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1716   ArtField* resolved_field =
1717       class_linker->LookupResolvedField(field_index, referrer, /* is_static= */ false);
1718   DCHECK(resolved_field != nullptr);
1719   HInstanceFieldGet* iget = new (graph_->GetAllocator()) HInstanceFieldGet(
1720       obj,
1721       resolved_field,
1722       DataType::FromShorty(resolved_field->GetTypeDescriptor()[0]),
1723       resolved_field->GetOffset(),
1724       resolved_field->IsVolatile(),
1725       field_index,
1726       resolved_field->GetDeclaringClass()->GetDexClassDefIndex(),
1727       *referrer->GetDexFile(),
1728       // Read barrier generates a runtime call in slow path and we need a valid
1729       // dex pc for the associated stack map. 0 is bogus but valid. Bug: 26854537.
1730       /* dex_pc= */ 0);
1731   if (iget->GetType() == DataType::Type::kReference) {
1732     // Use the same dex_cache that we used for field lookup as the hint_dex_cache.
1733     Handle<mirror::DexCache> dex_cache = handles_->NewHandle(referrer->GetDexCache());
1734     ReferenceTypePropagation rtp(graph_,
1735                                  outer_compilation_unit_.GetClassLoader(),
1736                                  dex_cache,
1737                                  handles_,
1738                                  /* is_first_run= */ false);
1739     rtp.Visit(iget);
1740   }
1741   return iget;
1742 }
1743 
CreateInstanceFieldSet(uint32_t field_index,ArtMethod * referrer,HInstruction * obj,HInstruction * value,bool * is_final)1744 HInstanceFieldSet* HInliner::CreateInstanceFieldSet(uint32_t field_index,
1745                                                     ArtMethod* referrer,
1746                                                     HInstruction* obj,
1747                                                     HInstruction* value,
1748                                                     bool* is_final)
1749     REQUIRES_SHARED(Locks::mutator_lock_) {
1750   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1751   ArtField* resolved_field =
1752       class_linker->LookupResolvedField(field_index, referrer, /* is_static= */ false);
1753   DCHECK(resolved_field != nullptr);
1754   if (is_final != nullptr) {
1755     // This information is needed only for constructors.
1756     DCHECK(referrer->IsConstructor());
1757     *is_final = resolved_field->IsFinal();
1758   }
1759   HInstanceFieldSet* iput = new (graph_->GetAllocator()) HInstanceFieldSet(
1760       obj,
1761       value,
1762       resolved_field,
1763       DataType::FromShorty(resolved_field->GetTypeDescriptor()[0]),
1764       resolved_field->GetOffset(),
1765       resolved_field->IsVolatile(),
1766       field_index,
1767       resolved_field->GetDeclaringClass()->GetDexClassDefIndex(),
1768       *referrer->GetDexFile(),
1769       // Read barrier generates a runtime call in slow path and we need a valid
1770       // dex pc for the associated stack map. 0 is bogus but valid. Bug: 26854537.
1771       /* dex_pc= */ 0);
1772   return iput;
1773 }
1774 
1775 template <typename T>
NewHandleIfDifferent(ObjPtr<T> object,Handle<T> hint,VariableSizedHandleScope * handles)1776 static inline Handle<T> NewHandleIfDifferent(ObjPtr<T> object,
1777                                              Handle<T> hint,
1778                                              VariableSizedHandleScope* handles)
1779     REQUIRES_SHARED(Locks::mutator_lock_) {
1780   return (object != hint.Get()) ? handles->NewHandle(object) : hint;
1781 }
1782 
CanEncodeInlinedMethodInStackMap(const DexFile & caller_dex_file,ArtMethod * callee)1783 static bool CanEncodeInlinedMethodInStackMap(const DexFile& caller_dex_file, ArtMethod* callee)
1784     REQUIRES_SHARED(Locks::mutator_lock_) {
1785   if (!Runtime::Current()->IsAotCompiler()) {
1786     // JIT can always encode methods in stack maps.
1787     return true;
1788   }
1789   if (IsSameDexFile(caller_dex_file, *callee->GetDexFile())) {
1790     return true;
1791   }
1792   // TODO(ngeoffray): Support more AOT cases for inlining:
1793   // - methods in multidex
1794   // - methods in boot image for on-device non-PIC compilation.
1795   return false;
1796 }
1797 
1798   // Substitutes parameters in the callee graph with their values from the caller.
SubstituteArguments(HGraph * callee_graph,HInvoke * invoke_instruction,ReferenceTypeInfo receiver_type,const DexCompilationUnit & dex_compilation_unit)1799 void HInliner::SubstituteArguments(HGraph* callee_graph,
1800                                    HInvoke* invoke_instruction,
1801                                    ReferenceTypeInfo receiver_type,
1802                                    const DexCompilationUnit& dex_compilation_unit) {
1803   ArtMethod* const resolved_method = callee_graph->GetArtMethod();
1804   size_t parameter_index = 0;
1805   bool run_rtp = false;
1806   for (HInstructionIterator instructions(callee_graph->GetEntryBlock()->GetInstructions());
1807        !instructions.Done();
1808        instructions.Advance()) {
1809     HInstruction* current = instructions.Current();
1810     if (current->IsParameterValue()) {
1811       HInstruction* argument = invoke_instruction->InputAt(parameter_index);
1812       if (argument->IsNullConstant()) {
1813         current->ReplaceWith(callee_graph->GetNullConstant());
1814       } else if (argument->IsIntConstant()) {
1815         current->ReplaceWith(callee_graph->GetIntConstant(argument->AsIntConstant()->GetValue()));
1816       } else if (argument->IsLongConstant()) {
1817         current->ReplaceWith(callee_graph->GetLongConstant(argument->AsLongConstant()->GetValue()));
1818       } else if (argument->IsFloatConstant()) {
1819         current->ReplaceWith(
1820             callee_graph->GetFloatConstant(argument->AsFloatConstant()->GetValue()));
1821       } else if (argument->IsDoubleConstant()) {
1822         current->ReplaceWith(
1823             callee_graph->GetDoubleConstant(argument->AsDoubleConstant()->GetValue()));
1824       } else if (argument->GetType() == DataType::Type::kReference) {
1825         if (!resolved_method->IsStatic() && parameter_index == 0 && receiver_type.IsValid()) {
1826           run_rtp = true;
1827           current->SetReferenceTypeInfo(receiver_type);
1828         } else {
1829           current->SetReferenceTypeInfo(argument->GetReferenceTypeInfo());
1830         }
1831         current->AsParameterValue()->SetCanBeNull(argument->CanBeNull());
1832       }
1833       ++parameter_index;
1834     }
1835   }
1836 
1837   // We have replaced formal arguments with actual arguments. If actual types
1838   // are more specific than the declared ones, run RTP again on the inner graph.
1839   if (run_rtp || ArgumentTypesMoreSpecific(invoke_instruction, resolved_method)) {
1840     ReferenceTypePropagation(callee_graph,
1841                              outer_compilation_unit_.GetClassLoader(),
1842                              dex_compilation_unit.GetDexCache(),
1843                              handles_,
1844                              /* is_first_run= */ false).Run();
1845   }
1846 }
1847 
1848 // Returns whether we can inline the callee_graph into the target_block.
1849 //
1850 // This performs a combination of semantics checks, compiler support checks, and
1851 // resource limit checks.
1852 //
1853 // If this function returns true, it will also set out_number_of_instructions to
1854 // the number of instructions in the inlined body.
CanInlineBody(const HGraph * callee_graph,const HBasicBlock * target_block,size_t * out_number_of_instructions) const1855 bool HInliner::CanInlineBody(const HGraph* callee_graph,
1856                              const HBasicBlock* target_block,
1857                              size_t* out_number_of_instructions) const {
1858   const DexFile& callee_dex_file = callee_graph->GetDexFile();
1859   ArtMethod* const resolved_method = callee_graph->GetArtMethod();
1860   const uint32_t method_index = resolved_method->GetMethodIndex();
1861   const bool same_dex_file =
1862       IsSameDexFile(*outer_compilation_unit_.GetDexFile(), *resolved_method->GetDexFile());
1863 
1864   HBasicBlock* exit_block = callee_graph->GetExitBlock();
1865   if (exit_block == nullptr) {
1866     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedInfiniteLoop)
1867         << "Method " << callee_dex_file.PrettyMethod(method_index)
1868         << " could not be inlined because it has an infinite loop";
1869     return false;
1870   }
1871 
1872   bool has_one_return = false;
1873   for (HBasicBlock* predecessor : exit_block->GetPredecessors()) {
1874     if (predecessor->GetLastInstruction()->IsThrow()) {
1875       if (target_block->IsTryBlock()) {
1876         // TODO(ngeoffray): Support adding HTryBoundary in Hgraph::InlineInto.
1877         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedTryCatch)
1878             << "Method " << callee_dex_file.PrettyMethod(method_index)
1879             << " could not be inlined because one branch always throws and"
1880             << " caller is in a try/catch block";
1881         return false;
1882       } else if (graph_->GetExitBlock() == nullptr) {
1883         // TODO(ngeoffray): Support adding HExit in the caller graph.
1884         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedInfiniteLoop)
1885             << "Method " << callee_dex_file.PrettyMethod(method_index)
1886             << " could not be inlined because one branch always throws and"
1887             << " caller does not have an exit block";
1888         return false;
1889       } else if (graph_->HasIrreducibleLoops()) {
1890         // TODO(ngeoffray): Support re-computing loop information to graphs with
1891         // irreducible loops?
1892         VLOG(compiler) << "Method " << callee_dex_file.PrettyMethod(method_index)
1893                        << " could not be inlined because one branch always throws and"
1894                        << " caller has irreducible loops";
1895         return false;
1896       }
1897     } else {
1898       has_one_return = true;
1899     }
1900   }
1901 
1902   if (!has_one_return) {
1903     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedAlwaysThrows)
1904         << "Method " << callee_dex_file.PrettyMethod(method_index)
1905         << " could not be inlined because it always throws";
1906     return false;
1907   }
1908 
1909   size_t number_of_instructions = 0;
1910   // Skip the entry block, it does not contain instructions that prevent inlining.
1911   for (HBasicBlock* block : callee_graph->GetReversePostOrderSkipEntryBlock()) {
1912     if (block->IsLoopHeader()) {
1913       if (block->GetLoopInformation()->IsIrreducible()) {
1914         // Don't inline methods with irreducible loops, they could prevent some
1915         // optimizations to run.
1916         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedIrreducibleLoop)
1917             << "Method " << callee_dex_file.PrettyMethod(method_index)
1918             << " could not be inlined because it contains an irreducible loop";
1919         return false;
1920       }
1921       if (!block->GetLoopInformation()->HasExitEdge()) {
1922         // Don't inline methods with loops without exit, since they cause the
1923         // loop information to be computed incorrectly when updating after
1924         // inlining.
1925         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedLoopWithoutExit)
1926             << "Method " << callee_dex_file.PrettyMethod(method_index)
1927             << " could not be inlined because it contains a loop with no exit";
1928         return false;
1929       }
1930     }
1931 
1932     for (HInstructionIterator instr_it(block->GetInstructions());
1933          !instr_it.Done();
1934          instr_it.Advance()) {
1935       if (++number_of_instructions >= inlining_budget_) {
1936         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedInstructionBudget)
1937             << "Method " << callee_dex_file.PrettyMethod(method_index)
1938             << " is not inlined because the outer method has reached"
1939             << " its instruction budget limit.";
1940         return false;
1941       }
1942       HInstruction* current = instr_it.Current();
1943       if (current->NeedsEnvironment() &&
1944           (total_number_of_dex_registers_ >= kMaximumNumberOfCumulatedDexRegisters)) {
1945         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedEnvironmentBudget)
1946             << "Method " << callee_dex_file.PrettyMethod(method_index)
1947             << " is not inlined because its caller has reached"
1948             << " its environment budget limit.";
1949         return false;
1950       }
1951 
1952       if (current->NeedsEnvironment() &&
1953           !CanEncodeInlinedMethodInStackMap(*caller_compilation_unit_.GetDexFile(),
1954                                             resolved_method)) {
1955         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedStackMaps)
1956             << "Method " << callee_dex_file.PrettyMethod(method_index)
1957             << " could not be inlined because " << current->DebugName()
1958             << " needs an environment, is in a different dex file"
1959             << ", and cannot be encoded in the stack maps.";
1960         return false;
1961       }
1962 
1963       if (!same_dex_file && current->NeedsDexCacheOfDeclaringClass()) {
1964         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedDexCache)
1965             << "Method " << callee_dex_file.PrettyMethod(method_index)
1966             << " could not be inlined because " << current->DebugName()
1967             << " it is in a different dex file and requires access to the dex cache";
1968         return false;
1969       }
1970 
1971       if (current->IsUnresolvedStaticFieldGet() ||
1972           current->IsUnresolvedInstanceFieldGet() ||
1973           current->IsUnresolvedStaticFieldSet() ||
1974           current->IsUnresolvedInstanceFieldSet()) {
1975         // Entrypoint for unresolved fields does not handle inlined frames.
1976         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedUnresolvedEntrypoint)
1977             << "Method " << callee_dex_file.PrettyMethod(method_index)
1978             << " could not be inlined because it is using an unresolved"
1979             << " entrypoint";
1980         return false;
1981       }
1982     }
1983   }
1984 
1985   *out_number_of_instructions = number_of_instructions;
1986   return true;
1987 }
1988 
TryBuildAndInlineHelper(HInvoke * invoke_instruction,ArtMethod * resolved_method,ReferenceTypeInfo receiver_type,HInstruction ** return_replacement)1989 bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction,
1990                                        ArtMethod* resolved_method,
1991                                        ReferenceTypeInfo receiver_type,
1992                                        HInstruction** return_replacement) {
1993   DCHECK(!(resolved_method->IsStatic() && receiver_type.IsValid()));
1994   const dex::CodeItem* code_item = resolved_method->GetCodeItem();
1995   const DexFile& callee_dex_file = *resolved_method->GetDexFile();
1996   uint32_t method_index = resolved_method->GetDexMethodIndex();
1997   CodeItemDebugInfoAccessor code_item_accessor(resolved_method->DexInstructionDebugInfo());
1998   ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker();
1999   Handle<mirror::DexCache> dex_cache = NewHandleIfDifferent(resolved_method->GetDexCache(),
2000                                                             caller_compilation_unit_.GetDexCache(),
2001                                                             handles_);
2002   Handle<mirror::ClassLoader> class_loader =
2003       NewHandleIfDifferent(resolved_method->GetDeclaringClass()->GetClassLoader(),
2004                            caller_compilation_unit_.GetClassLoader(),
2005                            handles_);
2006 
2007   Handle<mirror::Class> compiling_class = handles_->NewHandle(resolved_method->GetDeclaringClass());
2008   DexCompilationUnit dex_compilation_unit(
2009       class_loader,
2010       class_linker,
2011       callee_dex_file,
2012       code_item,
2013       resolved_method->GetDeclaringClass()->GetDexClassDefIndex(),
2014       method_index,
2015       resolved_method->GetAccessFlags(),
2016       /* verified_method= */ nullptr,
2017       dex_cache,
2018       compiling_class);
2019 
2020   InvokeType invoke_type = invoke_instruction->GetInvokeType();
2021   if (invoke_type == kInterface) {
2022     // We have statically resolved the dispatch. To please the class linker
2023     // at runtime, we change this call as if it was a virtual call.
2024     invoke_type = kVirtual;
2025   }
2026 
2027   bool caller_dead_reference_safe = graph_->IsDeadReferenceSafe();
2028   const dex::ClassDef& callee_class = resolved_method->GetClassDef();
2029   // MethodContainsRSensitiveAccess is currently slow, but HasDeadReferenceSafeAnnotation()
2030   // is currently rarely true.
2031   bool callee_dead_reference_safe =
2032       annotations::HasDeadReferenceSafeAnnotation(callee_dex_file, callee_class)
2033       && !annotations::MethodContainsRSensitiveAccess(callee_dex_file, callee_class, method_index);
2034 
2035   const int32_t caller_instruction_counter = graph_->GetCurrentInstructionId();
2036   HGraph* callee_graph = new (graph_->GetAllocator()) HGraph(
2037       graph_->GetAllocator(),
2038       graph_->GetArenaStack(),
2039       callee_dex_file,
2040       method_index,
2041       codegen_->GetCompilerOptions().GetInstructionSet(),
2042       invoke_type,
2043       callee_dead_reference_safe,
2044       graph_->IsDebuggable(),
2045       /* osr= */ false,
2046       /* is_shared_jit_code= */ graph_->IsCompilingForSharedJitCode(),
2047       /* baseline= */ graph_->IsCompilingBaseline(),
2048       /* start_instruction_id= */ caller_instruction_counter);
2049   callee_graph->SetArtMethod(resolved_method);
2050 
2051   // When they are needed, allocate `inline_stats_` on the Arena instead
2052   // of on the stack, as Clang might produce a stack frame too large
2053   // for this function, that would not fit the requirements of the
2054   // `-Wframe-larger-than` option.
2055   if (stats_ != nullptr) {
2056     // Reuse one object for all inline attempts from this caller to keep Arena memory usage low.
2057     if (inline_stats_ == nullptr) {
2058       void* storage = graph_->GetAllocator()->Alloc<OptimizingCompilerStats>(kArenaAllocMisc);
2059       inline_stats_ = new (storage) OptimizingCompilerStats;
2060     } else {
2061       inline_stats_->Reset();
2062     }
2063   }
2064   HGraphBuilder builder(callee_graph,
2065                         code_item_accessor,
2066                         &dex_compilation_unit,
2067                         &outer_compilation_unit_,
2068                         codegen_,
2069                         inline_stats_,
2070                         resolved_method->GetQuickenedInfo(),
2071                         handles_);
2072 
2073   if (builder.BuildGraph() != kAnalysisSuccess) {
2074     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedCannotBuild)
2075         << "Method " << callee_dex_file.PrettyMethod(method_index)
2076         << " could not be built, so cannot be inlined";
2077     return false;
2078   }
2079 
2080   SubstituteArguments(callee_graph, invoke_instruction, receiver_type, dex_compilation_unit);
2081 
2082   RunOptimizations(callee_graph, code_item, dex_compilation_unit);
2083 
2084   size_t number_of_instructions = 0;
2085   if (!CanInlineBody(callee_graph, invoke_instruction->GetBlock(), &number_of_instructions)) {
2086     return false;
2087   }
2088 
2089   DCHECK_EQ(caller_instruction_counter, graph_->GetCurrentInstructionId())
2090       << "No instructions can be added to the outer graph while inner graph is being built";
2091 
2092   // Inline the callee graph inside the caller graph.
2093   const int32_t callee_instruction_counter = callee_graph->GetCurrentInstructionId();
2094   graph_->SetCurrentInstructionId(callee_instruction_counter);
2095   *return_replacement = callee_graph->InlineInto(graph_, invoke_instruction);
2096   // Update our budget for other inlining attempts in `caller_graph`.
2097   total_number_of_instructions_ += number_of_instructions;
2098   UpdateInliningBudget();
2099 
2100   DCHECK_EQ(callee_instruction_counter, callee_graph->GetCurrentInstructionId())
2101       << "No instructions can be added to the inner graph during inlining into the outer graph";
2102 
2103   if (stats_ != nullptr) {
2104     DCHECK(inline_stats_ != nullptr);
2105     inline_stats_->AddTo(stats_);
2106   }
2107 
2108   if (caller_dead_reference_safe && !callee_dead_reference_safe) {
2109     // Caller was dead reference safe, but is not anymore, since we inlined dead
2110     // reference unsafe code. Prior transformations remain valid, since they did not
2111     // affect the inlined code.
2112     graph_->MarkDeadReferenceUnsafe();
2113   }
2114 
2115   return true;
2116 }
2117 
RunOptimizations(HGraph * callee_graph,const dex::CodeItem * code_item,const DexCompilationUnit & dex_compilation_unit)2118 void HInliner::RunOptimizations(HGraph* callee_graph,
2119                                 const dex::CodeItem* code_item,
2120                                 const DexCompilationUnit& dex_compilation_unit) {
2121   // Note: if the outermost_graph_ is being compiled OSR, we should not run any
2122   // optimization that could lead to a HDeoptimize. The following optimizations do not.
2123   HDeadCodeElimination dce(callee_graph, inline_stats_, "dead_code_elimination$inliner");
2124   HConstantFolding fold(callee_graph, "constant_folding$inliner");
2125   InstructionSimplifier simplify(callee_graph, codegen_, inline_stats_);
2126 
2127   HOptimization* optimizations[] = {
2128     &simplify,
2129     &fold,
2130     &dce,
2131   };
2132 
2133   for (size_t i = 0; i < arraysize(optimizations); ++i) {
2134     HOptimization* optimization = optimizations[i];
2135     optimization->Run();
2136   }
2137 
2138   // Bail early for pathological cases on the environment (for example recursive calls,
2139   // or too large environment).
2140   if (total_number_of_dex_registers_ >= kMaximumNumberOfCumulatedDexRegisters) {
2141     LOG_NOTE() << "Calls in " << callee_graph->GetArtMethod()->PrettyMethod()
2142              << " will not be inlined because the outer method has reached"
2143              << " its environment budget limit.";
2144     return;
2145   }
2146 
2147   // Bail early if we know we already are over the limit.
2148   size_t number_of_instructions = CountNumberOfInstructions(callee_graph);
2149   if (number_of_instructions > inlining_budget_) {
2150     LOG_NOTE() << "Calls in " << callee_graph->GetArtMethod()->PrettyMethod()
2151              << " will not be inlined because the outer method has reached"
2152              << " its instruction budget limit. " << number_of_instructions;
2153     return;
2154   }
2155 
2156   CodeItemDataAccessor accessor(callee_graph->GetDexFile(), code_item);
2157   HInliner inliner(callee_graph,
2158                    outermost_graph_,
2159                    codegen_,
2160                    outer_compilation_unit_,
2161                    dex_compilation_unit,
2162                    handles_,
2163                    inline_stats_,
2164                    total_number_of_dex_registers_ + accessor.RegistersSize(),
2165                    total_number_of_instructions_ + number_of_instructions,
2166                    this,
2167                    depth_ + 1);
2168   inliner.Run();
2169 }
2170 
IsReferenceTypeRefinement(ReferenceTypeInfo declared_rti,bool declared_can_be_null,HInstruction * actual_obj)2171 static bool IsReferenceTypeRefinement(ReferenceTypeInfo declared_rti,
2172                                       bool declared_can_be_null,
2173                                       HInstruction* actual_obj)
2174     REQUIRES_SHARED(Locks::mutator_lock_) {
2175   if (declared_can_be_null && !actual_obj->CanBeNull()) {
2176     return true;
2177   }
2178 
2179   ReferenceTypeInfo actual_rti = actual_obj->GetReferenceTypeInfo();
2180   return (actual_rti.IsExact() && !declared_rti.IsExact()) ||
2181           declared_rti.IsStrictSupertypeOf(actual_rti);
2182 }
2183 
GetClassRTI(ObjPtr<mirror::Class> klass)2184 ReferenceTypeInfo HInliner::GetClassRTI(ObjPtr<mirror::Class> klass) {
2185   return ReferenceTypePropagation::IsAdmissible(klass)
2186       ? ReferenceTypeInfo::Create(handles_->NewHandle(klass))
2187       : graph_->GetInexactObjectRti();
2188 }
2189 
ArgumentTypesMoreSpecific(HInvoke * invoke_instruction,ArtMethod * resolved_method)2190 bool HInliner::ArgumentTypesMoreSpecific(HInvoke* invoke_instruction, ArtMethod* resolved_method) {
2191   // If this is an instance call, test whether the type of the `this` argument
2192   // is more specific than the class which declares the method.
2193   if (!resolved_method->IsStatic()) {
2194     if (IsReferenceTypeRefinement(GetClassRTI(resolved_method->GetDeclaringClass()),
2195                                   /* declared_can_be_null= */ false,
2196                                   invoke_instruction->InputAt(0u))) {
2197       return true;
2198     }
2199   }
2200 
2201   // Iterate over the list of parameter types and test whether any of the
2202   // actual inputs has a more specific reference type than the type declared in
2203   // the signature.
2204   const dex::TypeList* param_list = resolved_method->GetParameterTypeList();
2205   for (size_t param_idx = 0,
2206               input_idx = resolved_method->IsStatic() ? 0 : 1,
2207               e = (param_list == nullptr ? 0 : param_list->Size());
2208        param_idx < e;
2209        ++param_idx, ++input_idx) {
2210     HInstruction* input = invoke_instruction->InputAt(input_idx);
2211     if (input->GetType() == DataType::Type::kReference) {
2212       ObjPtr<mirror::Class> param_cls = resolved_method->LookupResolvedClassFromTypeIndex(
2213           param_list->GetTypeItem(param_idx).type_idx_);
2214       if (IsReferenceTypeRefinement(GetClassRTI(param_cls),
2215                                     /* declared_can_be_null= */ true,
2216                                     input)) {
2217         return true;
2218       }
2219     }
2220   }
2221 
2222   return false;
2223 }
2224 
ReturnTypeMoreSpecific(HInvoke * invoke_instruction,HInstruction * return_replacement)2225 bool HInliner::ReturnTypeMoreSpecific(HInvoke* invoke_instruction,
2226                                       HInstruction* return_replacement) {
2227   // Check the integrity of reference types and run another type propagation if needed.
2228   if (return_replacement != nullptr) {
2229     if (return_replacement->GetType() == DataType::Type::kReference) {
2230       // Test if the return type is a refinement of the declared return type.
2231       if (IsReferenceTypeRefinement(invoke_instruction->GetReferenceTypeInfo(),
2232                                     /* declared_can_be_null= */ true,
2233                                     return_replacement)) {
2234         return true;
2235       } else if (return_replacement->IsInstanceFieldGet()) {
2236         HInstanceFieldGet* field_get = return_replacement->AsInstanceFieldGet();
2237         if (field_get->GetFieldInfo().GetField() ==
2238                 GetClassRoot<mirror::Object>()->GetInstanceField(0)) {
2239           return true;
2240         }
2241       }
2242     } else if (return_replacement->IsInstanceOf()) {
2243       // Inlining InstanceOf into an If may put a tighter bound on reference types.
2244       return true;
2245     }
2246   }
2247 
2248   return false;
2249 }
2250 
FixUpReturnReferenceType(ArtMethod * resolved_method,HInstruction * return_replacement)2251 void HInliner::FixUpReturnReferenceType(ArtMethod* resolved_method,
2252                                         HInstruction* return_replacement) {
2253   if (return_replacement != nullptr) {
2254     if (return_replacement->GetType() == DataType::Type::kReference) {
2255       if (!return_replacement->GetReferenceTypeInfo().IsValid()) {
2256         // Make sure that we have a valid type for the return. We may get an invalid one when
2257         // we inline invokes with multiple branches and create a Phi for the result.
2258         // TODO: we could be more precise by merging the phi inputs but that requires
2259         // some functionality from the reference type propagation.
2260         DCHECK(return_replacement->IsPhi());
2261         ObjPtr<mirror::Class> cls = resolved_method->LookupResolvedReturnType();
2262         return_replacement->SetReferenceTypeInfo(GetClassRTI(cls));
2263       }
2264     }
2265   }
2266 }
2267 
2268 }  // namespace art
2269