• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_RUNTIME_INSTRUMENTATION_INL_H_
18 #define ART_RUNTIME_INSTRUMENTATION_INL_H_
19 
20 #include "instrumentation.h"
21 
22 #include "art_method-inl.h"
23 #include "entrypoints/runtime_asm_entrypoints.h"
24 #include "gc/heap.h"
25 #include "jit/jit.h"
26 #include "runtime.h"
27 
28 namespace art HIDDEN {
29 namespace instrumentation {
30 
CanUseAotCode(const void * quick_code)31 inline bool Instrumentation::CanUseAotCode(const void* quick_code) {
32   if (quick_code == nullptr) {
33     return false;
34   }
35   Runtime* runtime = Runtime::Current();
36   // For simplicity, we never use AOT code for debuggable.
37   if (runtime->IsJavaDebuggable()) {
38     return false;
39   }
40 
41   if (runtime->IsNativeDebuggable()) {
42     DCHECK(runtime->UseJitCompilation() && runtime->GetJit()->JitAtFirstUse());
43     // If we are doing native debugging, ignore application's AOT code,
44     // since we want to JIT it (at first use) with extra stackmaps for native
45     // debugging. We keep however all AOT code from the boot image,
46     // since the JIT-at-first-use is blocking and would result in non-negligible
47     // startup performance impact.
48     return runtime->GetHeap()->IsInBootImageOatFile(quick_code);
49   }
50 
51   return true;
52 }
53 
GetInitialEntrypoint(uint32_t method_access_flags,const void * aot_code)54 inline const void* Instrumentation::GetInitialEntrypoint(uint32_t method_access_flags,
55                                                          const void* aot_code) {
56   if (!ArtMethod::IsInvokable(method_access_flags)) {
57     return GetQuickToInterpreterBridge();
58   }
59 
60   // Special case if we need an initialization check.
61   if (ArtMethod::NeedsClinitCheckBeforeCall(method_access_flags)) {
62     // If we have code but the method needs a class initialization check before calling that code,
63     // install the resolution stub that will perform the check. It will be replaced by the proper
64     // entry point by `ClassLinker::FixupStaticTrampolines()` after initializing class.
65     // Note: This mimics the logic in image_writer.cc that installs the resolution stub only
66     // if we have compiled code or we can execute nterp, and the method needs a class
67     // initialization check.
68     return (aot_code != nullptr || ArtMethod::IsNative(method_access_flags))
69         ? GetQuickResolutionStub()
70         : GetQuickToInterpreterBridge();
71   }
72 
73   // Use the provided AOT code if possible.
74   if (CanUseAotCode(aot_code)) {
75     return aot_code;
76   }
77 
78   // Use default entrypoints.
79   return ArtMethod::IsNative(method_access_flags) ? GetQuickGenericJniStub()
80                                                   : GetQuickToInterpreterBridge();
81 }
82 
83 
InitialEntrypointNeedsInstrumentationStubs()84 inline bool Instrumentation::InitialEntrypointNeedsInstrumentationStubs() {
85   return IsForcedInterpretOnly() || EntryExitStubsInstalled();
86 }
87 
InitializeMethodsCode(ArtMethod * method,const void * entrypoint,PointerSize pointer_size)88 inline void Instrumentation::InitializeMethodsCode(ArtMethod* method,
89                                                    const void* entrypoint,
90                                                    PointerSize pointer_size) {
91   if (kIsDebugBuild) {
92     // Entrypoint should be uninitialized.
93     CHECK(method->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size) == nullptr)
94         << method->PrettyMethod();
95     // We initialize the entrypoint while loading the class, well before the class
96     // is verified and Nterp entrypoint is allowed. We prefer to check for resolved
97     // because a verified class may lose its "verified" status (by becoming erroneous)
98     // but the resolved status is always kept (as "resolved erroneous" if needed).
99     CHECK(!method->GetDeclaringClass()->IsResolved());
100     CHECK_NE(entrypoint, interpreter::GetNterpEntryPoint()) << method->PrettyMethod();
101     if (InitialEntrypointNeedsInstrumentationStubs()) {
102       const void* expected =
103           method->IsNative() ? GetQuickGenericJniStub() : GetQuickToInterpreterBridge();
104       CHECK_EQ(entrypoint, expected) << method->PrettyMethod() << " " << method->IsNative();
105     } else if (method->NeedsClinitCheckBeforeCall()) {
106       if (method->IsNative()) {
107         CHECK_EQ(entrypoint, GetQuickResolutionStub());
108       } else {
109         // We do not have the original `aot_code` to determine which entrypoint to expect.
110         CHECK(entrypoint == GetQuickResolutionStub() ||
111               entrypoint == GetQuickToInterpreterBridge());
112       }
113     } else {
114       bool is_stub = (entrypoint == GetQuickToInterpreterBridge()) ||
115                      (entrypoint == GetQuickGenericJniStub()) ||
116                      (entrypoint == GetQuickResolutionStub());
117       const void* aot_code = is_stub ? nullptr : entrypoint;
118       const void* initial = GetInitialEntrypoint(method->GetAccessFlags(), aot_code);
119       CHECK_EQ(initial, entrypoint)
120           << method->PrettyMethod() << " 0x" << std::hex << method->GetAccessFlags();
121     }
122   }
123   method->SetEntryPointFromQuickCompiledCodePtrSize(entrypoint, pointer_size);
124 }
125 
126 }  // namespace instrumentation
127 }  // namespace art
128 
129 #endif  // ART_RUNTIME_INSTRUMENTATION_INL_H_
130