xref: /aosp_15_r20/art/openjdkjvmti/ti_stack.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /* Copyright (C) 2016 The Android Open Source Project
2*795d594fSAndroid Build Coastguard Worker  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * This file implements interfaces from the file jvmti.h. This implementation
5*795d594fSAndroid Build Coastguard Worker  * is licensed under the same terms as the file jvmti.h.  The
6*795d594fSAndroid Build Coastguard Worker  * copyright and license information for the file jvmti.h follows.
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
9*795d594fSAndroid Build Coastguard Worker  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10*795d594fSAndroid Build Coastguard Worker  *
11*795d594fSAndroid Build Coastguard Worker  * This code is free software; you can redistribute it and/or modify it
12*795d594fSAndroid Build Coastguard Worker  * under the terms of the GNU General Public License version 2 only, as
13*795d594fSAndroid Build Coastguard Worker  * published by the Free Software Foundation.  Oracle designates this
14*795d594fSAndroid Build Coastguard Worker  * particular file as subject to the "Classpath" exception as provided
15*795d594fSAndroid Build Coastguard Worker  * by Oracle in the LICENSE file that accompanied this code.
16*795d594fSAndroid Build Coastguard Worker  *
17*795d594fSAndroid Build Coastguard Worker  * This code is distributed in the hope that it will be useful, but WITHOUT
18*795d594fSAndroid Build Coastguard Worker  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19*795d594fSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20*795d594fSAndroid Build Coastguard Worker  * version 2 for more details (a copy is included in the LICENSE file that
21*795d594fSAndroid Build Coastguard Worker  * accompanied this code).
22*795d594fSAndroid Build Coastguard Worker  *
23*795d594fSAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License version
24*795d594fSAndroid Build Coastguard Worker  * 2 along with this work; if not, write to the Free Software Foundation,
25*795d594fSAndroid Build Coastguard Worker  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26*795d594fSAndroid Build Coastguard Worker  *
27*795d594fSAndroid Build Coastguard Worker  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
28*795d594fSAndroid Build Coastguard Worker  * or visit www.oracle.com if you need additional information or have any
29*795d594fSAndroid Build Coastguard Worker  * questions.
30*795d594fSAndroid Build Coastguard Worker  */
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker #include "ti_stack.h"
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker #include <algorithm>
35*795d594fSAndroid Build Coastguard Worker #include <initializer_list>
36*795d594fSAndroid Build Coastguard Worker #include <list>
37*795d594fSAndroid Build Coastguard Worker #include <unordered_map>
38*795d594fSAndroid Build Coastguard Worker #include <vector>
39*795d594fSAndroid Build Coastguard Worker 
40*795d594fSAndroid Build Coastguard Worker #include "android-base/macros.h"
41*795d594fSAndroid Build Coastguard Worker #include "android-base/thread_annotations.h"
42*795d594fSAndroid Build Coastguard Worker #include "arch/context.h"
43*795d594fSAndroid Build Coastguard Worker #include "art_field-inl.h"
44*795d594fSAndroid Build Coastguard Worker #include "art_jvmti.h"
45*795d594fSAndroid Build Coastguard Worker #include "art_method-inl.h"
46*795d594fSAndroid Build Coastguard Worker #include "barrier.h"
47*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
48*795d594fSAndroid Build Coastguard Worker #include "base/locks.h"
49*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
50*795d594fSAndroid Build Coastguard Worker #include "base/mutex.h"
51*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
52*795d594fSAndroid Build Coastguard Worker #include "deopt_manager.h"
53*795d594fSAndroid Build Coastguard Worker #include "dex/code_item_accessors-inl.h"
54*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file.h"
55*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_annotations.h"
56*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_types.h"
57*795d594fSAndroid Build Coastguard Worker #include "dex/dex_instruction-inl.h"
58*795d594fSAndroid Build Coastguard Worker #include "dex/primitive.h"
59*795d594fSAndroid Build Coastguard Worker #include "events.h"
60*795d594fSAndroid Build Coastguard Worker #include "gc_root.h"
61*795d594fSAndroid Build Coastguard Worker #include "handle_scope-inl.h"
62*795d594fSAndroid Build Coastguard Worker #include "instrumentation.h"
63*795d594fSAndroid Build Coastguard Worker #include "interpreter/shadow_frame-inl.h"
64*795d594fSAndroid Build Coastguard Worker #include "interpreter/shadow_frame.h"
65*795d594fSAndroid Build Coastguard Worker #include "jni/jni_env_ext.h"
66*795d594fSAndroid Build Coastguard Worker #include "jni/jni_internal.h"
67*795d594fSAndroid Build Coastguard Worker #include "jvalue-inl.h"
68*795d594fSAndroid Build Coastguard Worker #include "jvalue.h"
69*795d594fSAndroid Build Coastguard Worker #include "jvmti.h"
70*795d594fSAndroid Build Coastguard Worker #include "mirror/class.h"
71*795d594fSAndroid Build Coastguard Worker #include "mirror/dex_cache.h"
72*795d594fSAndroid Build Coastguard Worker #include "nativehelper/scoped_local_ref.h"
73*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
74*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change.h"
75*795d594fSAndroid Build Coastguard Worker #include "stack.h"
76*795d594fSAndroid Build Coastguard Worker #include "thread-current-inl.h"
77*795d594fSAndroid Build Coastguard Worker #include "thread.h"
78*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
79*795d594fSAndroid Build Coastguard Worker #include "thread_pool.h"
80*795d594fSAndroid Build Coastguard Worker #include "thread_state.h"
81*795d594fSAndroid Build Coastguard Worker #include "ti_logging.h"
82*795d594fSAndroid Build Coastguard Worker #include "ti_thread.h"
83*795d594fSAndroid Build Coastguard Worker #include "well_known_classes-inl.h"
84*795d594fSAndroid Build Coastguard Worker 
85*795d594fSAndroid Build Coastguard Worker namespace openjdkjvmti {
86*795d594fSAndroid Build Coastguard Worker 
87*795d594fSAndroid Build Coastguard Worker template <typename FrameFn>
88*795d594fSAndroid Build Coastguard Worker struct GetStackTraceVisitor : public art::StackVisitor {
GetStackTraceVisitoropenjdkjvmti::GetStackTraceVisitor89*795d594fSAndroid Build Coastguard Worker   GetStackTraceVisitor(art::Thread* thread_in,
90*795d594fSAndroid Build Coastguard Worker                        size_t start_,
91*795d594fSAndroid Build Coastguard Worker                        size_t stop_,
92*795d594fSAndroid Build Coastguard Worker                        FrameFn fn_)
93*795d594fSAndroid Build Coastguard Worker       : StackVisitor(thread_in, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
94*795d594fSAndroid Build Coastguard Worker         fn(fn_),
95*795d594fSAndroid Build Coastguard Worker         start(start_),
96*795d594fSAndroid Build Coastguard Worker         stop(stop_) {}
97*795d594fSAndroid Build Coastguard Worker   GetStackTraceVisitor(const GetStackTraceVisitor&) = default;
98*795d594fSAndroid Build Coastguard Worker   GetStackTraceVisitor(GetStackTraceVisitor&&) noexcept = default;
99*795d594fSAndroid Build Coastguard Worker 
VisitFrameopenjdkjvmti::GetStackTraceVisitor100*795d594fSAndroid Build Coastguard Worker   bool VisitFrame() override REQUIRES_SHARED(art::Locks::mutator_lock_) {
101*795d594fSAndroid Build Coastguard Worker     art::ArtMethod* m = GetMethod();
102*795d594fSAndroid Build Coastguard Worker     if (m->IsRuntimeMethod()) {
103*795d594fSAndroid Build Coastguard Worker       return true;
104*795d594fSAndroid Build Coastguard Worker     }
105*795d594fSAndroid Build Coastguard Worker 
106*795d594fSAndroid Build Coastguard Worker     if (start == 0) {
107*795d594fSAndroid Build Coastguard Worker       m = m->GetInterfaceMethodIfProxy(art::kRuntimePointerSize);
108*795d594fSAndroid Build Coastguard Worker       jmethodID id = art::jni::EncodeArtMethod(m);
109*795d594fSAndroid Build Coastguard Worker 
110*795d594fSAndroid Build Coastguard Worker       uint32_t dex_pc = GetDexPc(false);
111*795d594fSAndroid Build Coastguard Worker       jlong dex_location = (dex_pc == art::dex::kDexNoIndex) ? -1 : static_cast<jlong>(dex_pc);
112*795d594fSAndroid Build Coastguard Worker 
113*795d594fSAndroid Build Coastguard Worker       jvmtiFrameInfo info = { id, dex_location };
114*795d594fSAndroid Build Coastguard Worker       fn(info);
115*795d594fSAndroid Build Coastguard Worker 
116*795d594fSAndroid Build Coastguard Worker       if (stop == 1) {
117*795d594fSAndroid Build Coastguard Worker         return false;  // We're done.
118*795d594fSAndroid Build Coastguard Worker       } else if (stop > 0) {
119*795d594fSAndroid Build Coastguard Worker         stop--;
120*795d594fSAndroid Build Coastguard Worker       }
121*795d594fSAndroid Build Coastguard Worker     } else {
122*795d594fSAndroid Build Coastguard Worker       start--;
123*795d594fSAndroid Build Coastguard Worker     }
124*795d594fSAndroid Build Coastguard Worker 
125*795d594fSAndroid Build Coastguard Worker     return true;
126*795d594fSAndroid Build Coastguard Worker   }
127*795d594fSAndroid Build Coastguard Worker 
128*795d594fSAndroid Build Coastguard Worker   FrameFn fn;
129*795d594fSAndroid Build Coastguard Worker   size_t start;
130*795d594fSAndroid Build Coastguard Worker   size_t stop;
131*795d594fSAndroid Build Coastguard Worker };
132*795d594fSAndroid Build Coastguard Worker 
GetOrCreateShadowFrame(bool * created_frame)133*795d594fSAndroid Build Coastguard Worker art::ShadowFrame* FindFrameAtDepthVisitor::GetOrCreateShadowFrame(bool* created_frame) {
134*795d594fSAndroid Build Coastguard Worker   art::ShadowFrame* cur = GetCurrentShadowFrame();
135*795d594fSAndroid Build Coastguard Worker   if (cur == nullptr) {
136*795d594fSAndroid Build Coastguard Worker     *created_frame = true;
137*795d594fSAndroid Build Coastguard Worker     art::ArtMethod* method = GetMethod();
138*795d594fSAndroid Build Coastguard Worker     const uint16_t num_regs = method->DexInstructionData().RegistersSize();
139*795d594fSAndroid Build Coastguard Worker     cur = GetThread()->FindOrCreateDebuggerShadowFrame(GetFrameId(),
140*795d594fSAndroid Build Coastguard Worker                                                        num_regs,
141*795d594fSAndroid Build Coastguard Worker                                                        method,
142*795d594fSAndroid Build Coastguard Worker                                                        GetDexPc());
143*795d594fSAndroid Build Coastguard Worker     DCHECK(cur != nullptr);
144*795d594fSAndroid Build Coastguard Worker   } else {
145*795d594fSAndroid Build Coastguard Worker     *created_frame = false;
146*795d594fSAndroid Build Coastguard Worker   }
147*795d594fSAndroid Build Coastguard Worker   return cur;
148*795d594fSAndroid Build Coastguard Worker }
149*795d594fSAndroid Build Coastguard Worker 
150*795d594fSAndroid Build Coastguard Worker template <typename FrameFn>
MakeStackTraceVisitor(art::Thread * thread_in,size_t start,size_t stop,FrameFn fn)151*795d594fSAndroid Build Coastguard Worker GetStackTraceVisitor<FrameFn> MakeStackTraceVisitor(art::Thread* thread_in,
152*795d594fSAndroid Build Coastguard Worker                                                     size_t start,
153*795d594fSAndroid Build Coastguard Worker                                                     size_t stop,
154*795d594fSAndroid Build Coastguard Worker                                                     FrameFn fn) {
155*795d594fSAndroid Build Coastguard Worker   return GetStackTraceVisitor<FrameFn>(thread_in, start, stop, fn);
156*795d594fSAndroid Build Coastguard Worker }
157*795d594fSAndroid Build Coastguard Worker 
158*795d594fSAndroid Build Coastguard Worker struct GetStackTraceVectorClosure : public art::Closure {
159*795d594fSAndroid Build Coastguard Worker  public:
GetStackTraceVectorClosureopenjdkjvmti::GetStackTraceVectorClosure160*795d594fSAndroid Build Coastguard Worker   GetStackTraceVectorClosure(size_t start, size_t stop)
161*795d594fSAndroid Build Coastguard Worker       : start_input(start),
162*795d594fSAndroid Build Coastguard Worker         stop_input(stop),
163*795d594fSAndroid Build Coastguard Worker         start_result(0),
164*795d594fSAndroid Build Coastguard Worker         stop_result(0) {}
165*795d594fSAndroid Build Coastguard Worker 
Runopenjdkjvmti::GetStackTraceVectorClosure166*795d594fSAndroid Build Coastguard Worker   void Run(art::Thread* self) override REQUIRES_SHARED(art::Locks::mutator_lock_) {
167*795d594fSAndroid Build Coastguard Worker     auto frames_fn = [&](jvmtiFrameInfo info) {
168*795d594fSAndroid Build Coastguard Worker       frames.push_back(info);
169*795d594fSAndroid Build Coastguard Worker     };
170*795d594fSAndroid Build Coastguard Worker     auto visitor = MakeStackTraceVisitor(self, start_input, stop_input, frames_fn);
171*795d594fSAndroid Build Coastguard Worker     visitor.WalkStack(/* include_transitions= */ false);
172*795d594fSAndroid Build Coastguard Worker 
173*795d594fSAndroid Build Coastguard Worker     start_result = visitor.start;
174*795d594fSAndroid Build Coastguard Worker     stop_result = visitor.stop;
175*795d594fSAndroid Build Coastguard Worker   }
176*795d594fSAndroid Build Coastguard Worker 
177*795d594fSAndroid Build Coastguard Worker   const size_t start_input;
178*795d594fSAndroid Build Coastguard Worker   const size_t stop_input;
179*795d594fSAndroid Build Coastguard Worker 
180*795d594fSAndroid Build Coastguard Worker   std::vector<jvmtiFrameInfo> frames;
181*795d594fSAndroid Build Coastguard Worker   size_t start_result;
182*795d594fSAndroid Build Coastguard Worker   size_t stop_result;
183*795d594fSAndroid Build Coastguard Worker };
184*795d594fSAndroid Build Coastguard Worker 
TranslateFrameVector(const std::vector<jvmtiFrameInfo> & frames,jint start_depth,size_t start_result,jint max_frame_count,jvmtiFrameInfo * frame_buffer,jint * count_ptr)185*795d594fSAndroid Build Coastguard Worker static jvmtiError TranslateFrameVector(const std::vector<jvmtiFrameInfo>& frames,
186*795d594fSAndroid Build Coastguard Worker                                        jint start_depth,
187*795d594fSAndroid Build Coastguard Worker                                        size_t start_result,
188*795d594fSAndroid Build Coastguard Worker                                        jint max_frame_count,
189*795d594fSAndroid Build Coastguard Worker                                        jvmtiFrameInfo* frame_buffer,
190*795d594fSAndroid Build Coastguard Worker                                        jint* count_ptr) {
191*795d594fSAndroid Build Coastguard Worker   size_t collected_frames = frames.size();
192*795d594fSAndroid Build Coastguard Worker 
193*795d594fSAndroid Build Coastguard Worker   // Assume we're here having collected something.
194*795d594fSAndroid Build Coastguard Worker   DCHECK_GT(max_frame_count, 0);
195*795d594fSAndroid Build Coastguard Worker 
196*795d594fSAndroid Build Coastguard Worker   // Frames from the top.
197*795d594fSAndroid Build Coastguard Worker   if (start_depth >= 0) {
198*795d594fSAndroid Build Coastguard Worker     if (start_result != 0) {
199*795d594fSAndroid Build Coastguard Worker       // Not enough frames.
200*795d594fSAndroid Build Coastguard Worker       return ERR(ILLEGAL_ARGUMENT);
201*795d594fSAndroid Build Coastguard Worker     }
202*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(collected_frames, static_cast<size_t>(max_frame_count));
203*795d594fSAndroid Build Coastguard Worker     if (frames.size() > 0) {
204*795d594fSAndroid Build Coastguard Worker       memcpy(frame_buffer, frames.data(), collected_frames * sizeof(jvmtiFrameInfo));
205*795d594fSAndroid Build Coastguard Worker     }
206*795d594fSAndroid Build Coastguard Worker     *count_ptr = static_cast<jint>(frames.size());
207*795d594fSAndroid Build Coastguard Worker     return ERR(NONE);
208*795d594fSAndroid Build Coastguard Worker   }
209*795d594fSAndroid Build Coastguard Worker 
210*795d594fSAndroid Build Coastguard Worker   // Frames from the bottom.
211*795d594fSAndroid Build Coastguard Worker   if (collected_frames < static_cast<size_t>(-start_depth)) {
212*795d594fSAndroid Build Coastguard Worker     return ERR(ILLEGAL_ARGUMENT);
213*795d594fSAndroid Build Coastguard Worker   }
214*795d594fSAndroid Build Coastguard Worker 
215*795d594fSAndroid Build Coastguard Worker   size_t count = std::min(static_cast<size_t>(-start_depth), static_cast<size_t>(max_frame_count));
216*795d594fSAndroid Build Coastguard Worker   memcpy(frame_buffer,
217*795d594fSAndroid Build Coastguard Worker          &frames.data()[collected_frames + start_depth],
218*795d594fSAndroid Build Coastguard Worker          count * sizeof(jvmtiFrameInfo));
219*795d594fSAndroid Build Coastguard Worker   *count_ptr = static_cast<jint>(count);
220*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
221*795d594fSAndroid Build Coastguard Worker }
222*795d594fSAndroid Build Coastguard Worker 
223*795d594fSAndroid Build Coastguard Worker struct GetStackTraceDirectClosure : public art::Closure {
224*795d594fSAndroid Build Coastguard Worker  public:
GetStackTraceDirectClosureopenjdkjvmti::GetStackTraceDirectClosure225*795d594fSAndroid Build Coastguard Worker   GetStackTraceDirectClosure(jvmtiFrameInfo* frame_buffer_, size_t start, size_t stop)
226*795d594fSAndroid Build Coastguard Worker       : frame_buffer(frame_buffer_),
227*795d594fSAndroid Build Coastguard Worker         start_input(start),
228*795d594fSAndroid Build Coastguard Worker         stop_input(stop),
229*795d594fSAndroid Build Coastguard Worker         index(0) {
230*795d594fSAndroid Build Coastguard Worker     DCHECK_GE(start_input, 0u);
231*795d594fSAndroid Build Coastguard Worker   }
232*795d594fSAndroid Build Coastguard Worker 
Runopenjdkjvmti::GetStackTraceDirectClosure233*795d594fSAndroid Build Coastguard Worker   void Run(art::Thread* self) override REQUIRES_SHARED(art::Locks::mutator_lock_) {
234*795d594fSAndroid Build Coastguard Worker     auto frames_fn = [&](jvmtiFrameInfo info) {
235*795d594fSAndroid Build Coastguard Worker       frame_buffer[index] = info;
236*795d594fSAndroid Build Coastguard Worker       ++index;
237*795d594fSAndroid Build Coastguard Worker     };
238*795d594fSAndroid Build Coastguard Worker     auto visitor = MakeStackTraceVisitor(self, start_input, stop_input, frames_fn);
239*795d594fSAndroid Build Coastguard Worker     visitor.WalkStack(/* include_transitions= */ false);
240*795d594fSAndroid Build Coastguard Worker   }
241*795d594fSAndroid Build Coastguard Worker 
242*795d594fSAndroid Build Coastguard Worker   jvmtiFrameInfo* frame_buffer;
243*795d594fSAndroid Build Coastguard Worker 
244*795d594fSAndroid Build Coastguard Worker   const size_t start_input;
245*795d594fSAndroid Build Coastguard Worker   const size_t stop_input;
246*795d594fSAndroid Build Coastguard Worker 
247*795d594fSAndroid Build Coastguard Worker   size_t index = 0;
248*795d594fSAndroid Build Coastguard Worker };
249*795d594fSAndroid Build Coastguard Worker 
GetStackTrace(jvmtiEnv * jvmti_env,jthread java_thread,jint start_depth,jint max_frame_count,jvmtiFrameInfo * frame_buffer,jint * count_ptr)250*795d594fSAndroid Build Coastguard Worker jvmtiError StackUtil::GetStackTrace(jvmtiEnv* jvmti_env,
251*795d594fSAndroid Build Coastguard Worker                                     jthread java_thread,
252*795d594fSAndroid Build Coastguard Worker                                     jint start_depth,
253*795d594fSAndroid Build Coastguard Worker                                     jint max_frame_count,
254*795d594fSAndroid Build Coastguard Worker                                     jvmtiFrameInfo* frame_buffer,
255*795d594fSAndroid Build Coastguard Worker                                     jint* count_ptr) {
256*795d594fSAndroid Build Coastguard Worker   // It is not great that we have to hold these locks for so long, but it is necessary to ensure
257*795d594fSAndroid Build Coastguard Worker   // that the thread isn't dying on us.
258*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(art::Thread::Current());
259*795d594fSAndroid Build Coastguard Worker   art::Locks::thread_list_lock_->ExclusiveLock(soa.Self());
260*795d594fSAndroid Build Coastguard Worker 
261*795d594fSAndroid Build Coastguard Worker   art::Thread* thread;
262*795d594fSAndroid Build Coastguard Worker   jvmtiError thread_error = ERR(INTERNAL);
263*795d594fSAndroid Build Coastguard Worker   if (!ThreadUtil::GetAliveNativeThread(java_thread, soa, &thread, &thread_error)) {
264*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(soa.Self());
265*795d594fSAndroid Build Coastguard Worker     return thread_error;
266*795d594fSAndroid Build Coastguard Worker   }
267*795d594fSAndroid Build Coastguard Worker   DCHECK(thread != nullptr);
268*795d594fSAndroid Build Coastguard Worker 
269*795d594fSAndroid Build Coastguard Worker   art::ThreadState state = thread->GetState();
270*795d594fSAndroid Build Coastguard Worker   if (state == art::ThreadState::kStarting || thread->IsStillStarting()) {
271*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(soa.Self());
272*795d594fSAndroid Build Coastguard Worker     return ERR(THREAD_NOT_ALIVE);
273*795d594fSAndroid Build Coastguard Worker   }
274*795d594fSAndroid Build Coastguard Worker 
275*795d594fSAndroid Build Coastguard Worker   if (max_frame_count < 0) {
276*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(soa.Self());
277*795d594fSAndroid Build Coastguard Worker     return ERR(ILLEGAL_ARGUMENT);
278*795d594fSAndroid Build Coastguard Worker   }
279*795d594fSAndroid Build Coastguard Worker   if (frame_buffer == nullptr || count_ptr == nullptr) {
280*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(soa.Self());
281*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
282*795d594fSAndroid Build Coastguard Worker   }
283*795d594fSAndroid Build Coastguard Worker 
284*795d594fSAndroid Build Coastguard Worker   if (max_frame_count == 0) {
285*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(soa.Self());
286*795d594fSAndroid Build Coastguard Worker     *count_ptr = 0;
287*795d594fSAndroid Build Coastguard Worker     return ERR(NONE);
288*795d594fSAndroid Build Coastguard Worker   }
289*795d594fSAndroid Build Coastguard Worker 
290*795d594fSAndroid Build Coastguard Worker   if (start_depth >= 0) {
291*795d594fSAndroid Build Coastguard Worker     // Fast path: Regular order of stack trace. Fill into the frame_buffer directly.
292*795d594fSAndroid Build Coastguard Worker     GetStackTraceDirectClosure closure(frame_buffer,
293*795d594fSAndroid Build Coastguard Worker                                        static_cast<size_t>(start_depth),
294*795d594fSAndroid Build Coastguard Worker                                        static_cast<size_t>(max_frame_count));
295*795d594fSAndroid Build Coastguard Worker     // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution.
296*795d594fSAndroid Build Coastguard Worker     if (!thread->RequestSynchronousCheckpoint(&closure)) {
297*795d594fSAndroid Build Coastguard Worker       return ERR(THREAD_NOT_ALIVE);
298*795d594fSAndroid Build Coastguard Worker     }
299*795d594fSAndroid Build Coastguard Worker     *count_ptr = static_cast<jint>(closure.index);
300*795d594fSAndroid Build Coastguard Worker     if (closure.index == 0) {
301*795d594fSAndroid Build Coastguard Worker       JVMTI_LOG(INFO, jvmti_env) << "The stack is not large enough for a start_depth of "
302*795d594fSAndroid Build Coastguard Worker                                  << start_depth << ".";
303*795d594fSAndroid Build Coastguard Worker       return ERR(ILLEGAL_ARGUMENT);
304*795d594fSAndroid Build Coastguard Worker     }
305*795d594fSAndroid Build Coastguard Worker     return ERR(NONE);
306*795d594fSAndroid Build Coastguard Worker   } else {
307*795d594fSAndroid Build Coastguard Worker     GetStackTraceVectorClosure closure(0, 0);
308*795d594fSAndroid Build Coastguard Worker     // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution.
309*795d594fSAndroid Build Coastguard Worker     if (!thread->RequestSynchronousCheckpoint(&closure)) {
310*795d594fSAndroid Build Coastguard Worker       return ERR(THREAD_NOT_ALIVE);
311*795d594fSAndroid Build Coastguard Worker     }
312*795d594fSAndroid Build Coastguard Worker 
313*795d594fSAndroid Build Coastguard Worker     return TranslateFrameVector(closure.frames,
314*795d594fSAndroid Build Coastguard Worker                                 start_depth,
315*795d594fSAndroid Build Coastguard Worker                                 closure.start_result,
316*795d594fSAndroid Build Coastguard Worker                                 max_frame_count,
317*795d594fSAndroid Build Coastguard Worker                                 frame_buffer,
318*795d594fSAndroid Build Coastguard Worker                                 count_ptr);
319*795d594fSAndroid Build Coastguard Worker   }
320*795d594fSAndroid Build Coastguard Worker }
321*795d594fSAndroid Build Coastguard Worker 
322*795d594fSAndroid Build Coastguard Worker template <typename Data>
323*795d594fSAndroid Build Coastguard Worker struct GetAllStackTracesVectorClosure : public art::Closure {
GetAllStackTracesVectorClosureopenjdkjvmti::GetAllStackTracesVectorClosure324*795d594fSAndroid Build Coastguard Worker   GetAllStackTracesVectorClosure(size_t stop, Data* data_)
325*795d594fSAndroid Build Coastguard Worker       : barrier(0), stop_input(stop), data(data_) {}
326*795d594fSAndroid Build Coastguard Worker 
Runopenjdkjvmti::GetAllStackTracesVectorClosure327*795d594fSAndroid Build Coastguard Worker   void Run(art::Thread* thread) override
328*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_)
329*795d594fSAndroid Build Coastguard Worker       REQUIRES(!data->mutex) {
330*795d594fSAndroid Build Coastguard Worker     art::Thread* self = art::Thread::Current();
331*795d594fSAndroid Build Coastguard Worker     Work(thread, self);
332*795d594fSAndroid Build Coastguard Worker     barrier.Pass(self);
333*795d594fSAndroid Build Coastguard Worker   }
334*795d594fSAndroid Build Coastguard Worker 
Workopenjdkjvmti::GetAllStackTracesVectorClosure335*795d594fSAndroid Build Coastguard Worker   void Work(art::Thread* thread, art::Thread* self)
336*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_)
337*795d594fSAndroid Build Coastguard Worker       REQUIRES(!data->mutex) {
338*795d594fSAndroid Build Coastguard Worker     // Skip threads that are still starting.
339*795d594fSAndroid Build Coastguard Worker     if (thread->IsStillStarting()) {
340*795d594fSAndroid Build Coastguard Worker       return;
341*795d594fSAndroid Build Coastguard Worker     }
342*795d594fSAndroid Build Coastguard Worker 
343*795d594fSAndroid Build Coastguard Worker     std::vector<jvmtiFrameInfo>* thread_frames = data->GetFrameStorageFor(self, thread);
344*795d594fSAndroid Build Coastguard Worker     if (thread_frames == nullptr) {
345*795d594fSAndroid Build Coastguard Worker       return;
346*795d594fSAndroid Build Coastguard Worker     }
347*795d594fSAndroid Build Coastguard Worker 
348*795d594fSAndroid Build Coastguard Worker     // Now collect the data.
349*795d594fSAndroid Build Coastguard Worker     auto frames_fn = [&](jvmtiFrameInfo info) {
350*795d594fSAndroid Build Coastguard Worker       thread_frames->push_back(info);
351*795d594fSAndroid Build Coastguard Worker     };
352*795d594fSAndroid Build Coastguard Worker     auto visitor = MakeStackTraceVisitor(thread, 0u, stop_input, frames_fn);
353*795d594fSAndroid Build Coastguard Worker     visitor.WalkStack(/* include_transitions= */ false);
354*795d594fSAndroid Build Coastguard Worker   }
355*795d594fSAndroid Build Coastguard Worker 
356*795d594fSAndroid Build Coastguard Worker   art::Barrier barrier;
357*795d594fSAndroid Build Coastguard Worker   const size_t stop_input;
358*795d594fSAndroid Build Coastguard Worker   Data* data;
359*795d594fSAndroid Build Coastguard Worker };
360*795d594fSAndroid Build Coastguard Worker 
361*795d594fSAndroid Build Coastguard Worker template <typename Data>
RunCheckpointAndWait(Data * data,size_t max_frame_count)362*795d594fSAndroid Build Coastguard Worker static void RunCheckpointAndWait(Data* data, size_t max_frame_count)
363*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(art::Locks::mutator_lock_) {
364*795d594fSAndroid Build Coastguard Worker   // Note: requires the mutator lock as the checkpoint requires the mutator lock.
365*795d594fSAndroid Build Coastguard Worker   GetAllStackTracesVectorClosure<Data> closure(max_frame_count, data);
366*795d594fSAndroid Build Coastguard Worker   // TODO(b/253671779): Replace this use of RunCheckpointUnchecked() with RunCheckpoint(). This is
367*795d594fSAndroid Build Coastguard Worker   // currently not possible, since the following undesirable call chain (abbreviated here) is then
368*795d594fSAndroid Build Coastguard Worker   // possible and exercised by current tests: (jvmti) GetAllStackTraces -> <this function> ->
369*795d594fSAndroid Build Coastguard Worker   // RunCheckpoint -> GetStackTraceVisitor -> EncodeMethodId -> Class::EnsureMethodIds ->
370*795d594fSAndroid Build Coastguard Worker   // Class::Alloc -> AllocObjectWithAllocator -> potentially suspends, or runs GC, etc. -> CHECK
371*795d594fSAndroid Build Coastguard Worker   // failure.
372*795d594fSAndroid Build Coastguard Worker   size_t barrier_count = art::Runtime::Current()->GetThreadList()->RunCheckpointUnchecked(&closure);
373*795d594fSAndroid Build Coastguard Worker   if (barrier_count == 0) {
374*795d594fSAndroid Build Coastguard Worker     return;
375*795d594fSAndroid Build Coastguard Worker   }
376*795d594fSAndroid Build Coastguard Worker   art::Thread* self = art::Thread::Current();
377*795d594fSAndroid Build Coastguard Worker   art::ScopedThreadStateChange tsc(self, art::ThreadState::kWaitingForCheckPointsToRun);
378*795d594fSAndroid Build Coastguard Worker   closure.barrier.Increment(self, barrier_count);
379*795d594fSAndroid Build Coastguard Worker }
380*795d594fSAndroid Build Coastguard Worker 
GetAllStackTraces(jvmtiEnv * env,jint max_frame_count,jvmtiStackInfo ** stack_info_ptr,jint * thread_count_ptr)381*795d594fSAndroid Build Coastguard Worker jvmtiError StackUtil::GetAllStackTraces(jvmtiEnv* env,
382*795d594fSAndroid Build Coastguard Worker                                         jint max_frame_count,
383*795d594fSAndroid Build Coastguard Worker                                         jvmtiStackInfo** stack_info_ptr,
384*795d594fSAndroid Build Coastguard Worker                                         jint* thread_count_ptr) {
385*795d594fSAndroid Build Coastguard Worker   if (max_frame_count < 0) {
386*795d594fSAndroid Build Coastguard Worker     return ERR(ILLEGAL_ARGUMENT);
387*795d594fSAndroid Build Coastguard Worker   }
388*795d594fSAndroid Build Coastguard Worker   if (stack_info_ptr == nullptr || thread_count_ptr == nullptr) {
389*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
390*795d594fSAndroid Build Coastguard Worker   }
391*795d594fSAndroid Build Coastguard Worker 
392*795d594fSAndroid Build Coastguard Worker   struct AllStackTracesData {
393*795d594fSAndroid Build Coastguard Worker     AllStackTracesData() : mutex("GetAllStackTraces", art::LockLevel::kAbortLock) {}
394*795d594fSAndroid Build Coastguard Worker     ~AllStackTracesData() {
395*795d594fSAndroid Build Coastguard Worker       JNIEnv* jni_env = art::Thread::Current()->GetJniEnv();
396*795d594fSAndroid Build Coastguard Worker       for (jthread global_thread_ref : thread_peers) {
397*795d594fSAndroid Build Coastguard Worker         jni_env->DeleteGlobalRef(global_thread_ref);
398*795d594fSAndroid Build Coastguard Worker       }
399*795d594fSAndroid Build Coastguard Worker     }
400*795d594fSAndroid Build Coastguard Worker 
401*795d594fSAndroid Build Coastguard Worker     std::vector<jvmtiFrameInfo>* GetFrameStorageFor(art::Thread* self, art::Thread* thread)
402*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(art::Locks::mutator_lock_)
403*795d594fSAndroid Build Coastguard Worker         REQUIRES(!mutex) {
404*795d594fSAndroid Build Coastguard Worker       art::MutexLock mu(self, mutex);
405*795d594fSAndroid Build Coastguard Worker 
406*795d594fSAndroid Build Coastguard Worker       threads.push_back(thread);
407*795d594fSAndroid Build Coastguard Worker 
408*795d594fSAndroid Build Coastguard Worker       jthread peer = art::Runtime::Current()->GetJavaVM()->AddGlobalRef(
409*795d594fSAndroid Build Coastguard Worker           self, thread->GetPeerFromOtherThread());
410*795d594fSAndroid Build Coastguard Worker       thread_peers.push_back(peer);
411*795d594fSAndroid Build Coastguard Worker 
412*795d594fSAndroid Build Coastguard Worker       frames.emplace_back(new std::vector<jvmtiFrameInfo>());
413*795d594fSAndroid Build Coastguard Worker       return frames.back().get();
414*795d594fSAndroid Build Coastguard Worker     }
415*795d594fSAndroid Build Coastguard Worker 
416*795d594fSAndroid Build Coastguard Worker     art::Mutex mutex;
417*795d594fSAndroid Build Coastguard Worker 
418*795d594fSAndroid Build Coastguard Worker     // Storage. Only access directly after completion.
419*795d594fSAndroid Build Coastguard Worker 
420*795d594fSAndroid Build Coastguard Worker     std::vector<art::Thread*> threads;
421*795d594fSAndroid Build Coastguard Worker     // "thread_peers" contains global references to their peers.
422*795d594fSAndroid Build Coastguard Worker     std::vector<jthread> thread_peers;
423*795d594fSAndroid Build Coastguard Worker 
424*795d594fSAndroid Build Coastguard Worker     std::vector<std::unique_ptr<std::vector<jvmtiFrameInfo>>> frames;
425*795d594fSAndroid Build Coastguard Worker   };
426*795d594fSAndroid Build Coastguard Worker 
427*795d594fSAndroid Build Coastguard Worker   AllStackTracesData data;
428*795d594fSAndroid Build Coastguard Worker   art::Thread* current = art::Thread::Current();
429*795d594fSAndroid Build Coastguard Worker   {
430*795d594fSAndroid Build Coastguard Worker     art::ScopedObjectAccess soa(current);
431*795d594fSAndroid Build Coastguard Worker     RunCheckpointAndWait(&data, static_cast<size_t>(max_frame_count));
432*795d594fSAndroid Build Coastguard Worker   }
433*795d594fSAndroid Build Coastguard Worker 
434*795d594fSAndroid Build Coastguard Worker   // Convert the data into our output format.
435*795d594fSAndroid Build Coastguard Worker 
436*795d594fSAndroid Build Coastguard Worker   // Note: we use an array of jvmtiStackInfo for convenience. The spec says we need to
437*795d594fSAndroid Build Coastguard Worker   //       allocate one big chunk for this and the actual frames, which means we need
438*795d594fSAndroid Build Coastguard Worker   //       to either be conservative or rearrange things later (the latter is implemented).
439*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<jvmtiStackInfo[]> stack_info_array(new jvmtiStackInfo[data.frames.size()]);
440*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<jvmtiFrameInfo[]>> frame_infos;
441*795d594fSAndroid Build Coastguard Worker   frame_infos.reserve(data.frames.size());
442*795d594fSAndroid Build Coastguard Worker 
443*795d594fSAndroid Build Coastguard Worker   // Now run through and add data for each thread.
444*795d594fSAndroid Build Coastguard Worker   size_t sum_frames = 0;
445*795d594fSAndroid Build Coastguard Worker   for (size_t index = 0; index < data.frames.size(); ++index) {
446*795d594fSAndroid Build Coastguard Worker     jvmtiStackInfo& stack_info = stack_info_array.get()[index];
447*795d594fSAndroid Build Coastguard Worker     memset(&stack_info, 0, sizeof(jvmtiStackInfo));
448*795d594fSAndroid Build Coastguard Worker 
449*795d594fSAndroid Build Coastguard Worker     const std::vector<jvmtiFrameInfo>& thread_frames = *data.frames[index].get();
450*795d594fSAndroid Build Coastguard Worker 
451*795d594fSAndroid Build Coastguard Worker     // For the time being, set the thread to null. We'll fix it up in the second stage.
452*795d594fSAndroid Build Coastguard Worker     stack_info.thread = nullptr;
453*795d594fSAndroid Build Coastguard Worker     stack_info.state = JVMTI_THREAD_STATE_SUSPENDED;
454*795d594fSAndroid Build Coastguard Worker 
455*795d594fSAndroid Build Coastguard Worker     size_t collected_frames = thread_frames.size();
456*795d594fSAndroid Build Coastguard Worker     if (max_frame_count == 0 || collected_frames == 0) {
457*795d594fSAndroid Build Coastguard Worker       stack_info.frame_count = 0;
458*795d594fSAndroid Build Coastguard Worker       stack_info.frame_buffer = nullptr;
459*795d594fSAndroid Build Coastguard Worker       continue;
460*795d594fSAndroid Build Coastguard Worker     }
461*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(collected_frames, static_cast<size_t>(max_frame_count));
462*795d594fSAndroid Build Coastguard Worker 
463*795d594fSAndroid Build Coastguard Worker     jvmtiFrameInfo* frame_info = new jvmtiFrameInfo[collected_frames];
464*795d594fSAndroid Build Coastguard Worker     frame_infos.emplace_back(frame_info);
465*795d594fSAndroid Build Coastguard Worker 
466*795d594fSAndroid Build Coastguard Worker     jint count;
467*795d594fSAndroid Build Coastguard Worker     jvmtiError translate_result = TranslateFrameVector(thread_frames,
468*795d594fSAndroid Build Coastguard Worker                                                        0,
469*795d594fSAndroid Build Coastguard Worker                                                        0,
470*795d594fSAndroid Build Coastguard Worker                                                        static_cast<jint>(collected_frames),
471*795d594fSAndroid Build Coastguard Worker                                                        frame_info,
472*795d594fSAndroid Build Coastguard Worker                                                        &count);
473*795d594fSAndroid Build Coastguard Worker     DCHECK(translate_result == JVMTI_ERROR_NONE);
474*795d594fSAndroid Build Coastguard Worker     stack_info.frame_count = static_cast<jint>(collected_frames);
475*795d594fSAndroid Build Coastguard Worker     stack_info.frame_buffer = frame_info;
476*795d594fSAndroid Build Coastguard Worker     sum_frames += static_cast<size_t>(count);
477*795d594fSAndroid Build Coastguard Worker   }
478*795d594fSAndroid Build Coastguard Worker 
479*795d594fSAndroid Build Coastguard Worker   // No errors, yet. Now put it all into an output buffer.
480*795d594fSAndroid Build Coastguard Worker   size_t rounded_stack_info_size = art::RoundUp(sizeof(jvmtiStackInfo) * data.frames.size(),
481*795d594fSAndroid Build Coastguard Worker                                                 alignof(jvmtiFrameInfo));
482*795d594fSAndroid Build Coastguard Worker   size_t chunk_size = rounded_stack_info_size + sum_frames * sizeof(jvmtiFrameInfo);
483*795d594fSAndroid Build Coastguard Worker   unsigned char* chunk_data;
484*795d594fSAndroid Build Coastguard Worker   jvmtiError alloc_result = env->Allocate(chunk_size, &chunk_data);
485*795d594fSAndroid Build Coastguard Worker   if (alloc_result != ERR(NONE)) {
486*795d594fSAndroid Build Coastguard Worker     return alloc_result;
487*795d594fSAndroid Build Coastguard Worker   }
488*795d594fSAndroid Build Coastguard Worker 
489*795d594fSAndroid Build Coastguard Worker   jvmtiStackInfo* stack_info = reinterpret_cast<jvmtiStackInfo*>(chunk_data);
490*795d594fSAndroid Build Coastguard Worker   // First copy in all the basic data.
491*795d594fSAndroid Build Coastguard Worker   memcpy(stack_info, stack_info_array.get(), sizeof(jvmtiStackInfo) * data.frames.size());
492*795d594fSAndroid Build Coastguard Worker 
493*795d594fSAndroid Build Coastguard Worker   // Now copy the frames and fix up the pointers.
494*795d594fSAndroid Build Coastguard Worker   jvmtiFrameInfo* frame_info = reinterpret_cast<jvmtiFrameInfo*>(
495*795d594fSAndroid Build Coastguard Worker       chunk_data + rounded_stack_info_size);
496*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; i < data.frames.size(); ++i) {
497*795d594fSAndroid Build Coastguard Worker     jvmtiStackInfo& old_stack_info = stack_info_array.get()[i];
498*795d594fSAndroid Build Coastguard Worker     jvmtiStackInfo& new_stack_info = stack_info[i];
499*795d594fSAndroid Build Coastguard Worker 
500*795d594fSAndroid Build Coastguard Worker     // Translate the global ref into a local ref.
501*795d594fSAndroid Build Coastguard Worker     new_stack_info.thread =
502*795d594fSAndroid Build Coastguard Worker         static_cast<JNIEnv*>(current->GetJniEnv())->NewLocalRef(data.thread_peers[i]);
503*795d594fSAndroid Build Coastguard Worker 
504*795d594fSAndroid Build Coastguard Worker     if (old_stack_info.frame_count > 0) {
505*795d594fSAndroid Build Coastguard Worker       // Only copy when there's data - leave the nullptr alone.
506*795d594fSAndroid Build Coastguard Worker       size_t frames_size = static_cast<size_t>(old_stack_info.frame_count) * sizeof(jvmtiFrameInfo);
507*795d594fSAndroid Build Coastguard Worker       memcpy(frame_info, old_stack_info.frame_buffer, frames_size);
508*795d594fSAndroid Build Coastguard Worker       new_stack_info.frame_buffer = frame_info;
509*795d594fSAndroid Build Coastguard Worker       frame_info += old_stack_info.frame_count;
510*795d594fSAndroid Build Coastguard Worker     }
511*795d594fSAndroid Build Coastguard Worker   }
512*795d594fSAndroid Build Coastguard Worker 
513*795d594fSAndroid Build Coastguard Worker   *stack_info_ptr = stack_info;
514*795d594fSAndroid Build Coastguard Worker   *thread_count_ptr = static_cast<jint>(data.frames.size());
515*795d594fSAndroid Build Coastguard Worker 
516*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
517*795d594fSAndroid Build Coastguard Worker }
518*795d594fSAndroid Build Coastguard Worker 
GetThreadListStackTraces(jvmtiEnv * env,jint thread_count,const jthread * thread_list,jint max_frame_count,jvmtiStackInfo ** stack_info_ptr)519*795d594fSAndroid Build Coastguard Worker jvmtiError StackUtil::GetThreadListStackTraces(jvmtiEnv* env,
520*795d594fSAndroid Build Coastguard Worker                                                jint thread_count,
521*795d594fSAndroid Build Coastguard Worker                                                const jthread* thread_list,
522*795d594fSAndroid Build Coastguard Worker                                                jint max_frame_count,
523*795d594fSAndroid Build Coastguard Worker                                                jvmtiStackInfo** stack_info_ptr) {
524*795d594fSAndroid Build Coastguard Worker   if (max_frame_count < 0) {
525*795d594fSAndroid Build Coastguard Worker     return ERR(ILLEGAL_ARGUMENT);
526*795d594fSAndroid Build Coastguard Worker   }
527*795d594fSAndroid Build Coastguard Worker   if (thread_count < 0) {
528*795d594fSAndroid Build Coastguard Worker     return ERR(ILLEGAL_ARGUMENT);
529*795d594fSAndroid Build Coastguard Worker   }
530*795d594fSAndroid Build Coastguard Worker   if (thread_count == 0) {
531*795d594fSAndroid Build Coastguard Worker     *stack_info_ptr = nullptr;
532*795d594fSAndroid Build Coastguard Worker     return ERR(NONE);
533*795d594fSAndroid Build Coastguard Worker   }
534*795d594fSAndroid Build Coastguard Worker   if (thread_list == nullptr || stack_info_ptr == nullptr) {
535*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
536*795d594fSAndroid Build Coastguard Worker   }
537*795d594fSAndroid Build Coastguard Worker 
538*795d594fSAndroid Build Coastguard Worker   art::Thread* current = art::Thread::Current();
539*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(current);      // Now we know we have the shared lock.
540*795d594fSAndroid Build Coastguard Worker 
541*795d594fSAndroid Build Coastguard Worker   struct SelectStackTracesData {
542*795d594fSAndroid Build Coastguard Worker     SelectStackTracesData() : mutex("GetSelectStackTraces", art::LockLevel::kAbortLock) {}
543*795d594fSAndroid Build Coastguard Worker 
544*795d594fSAndroid Build Coastguard Worker     std::vector<jvmtiFrameInfo>* GetFrameStorageFor(art::Thread* self, art::Thread* thread)
545*795d594fSAndroid Build Coastguard Worker               REQUIRES_SHARED(art::Locks::mutator_lock_)
546*795d594fSAndroid Build Coastguard Worker               REQUIRES(!mutex) {
547*795d594fSAndroid Build Coastguard Worker       art::ObjPtr<art::mirror::Object> peer = thread->GetPeerFromOtherThread();
548*795d594fSAndroid Build Coastguard Worker       for (size_t index = 0; index != handles.size(); ++index) {
549*795d594fSAndroid Build Coastguard Worker         if (peer == handles[index].Get()) {
550*795d594fSAndroid Build Coastguard Worker           // Found the thread.
551*795d594fSAndroid Build Coastguard Worker           art::MutexLock mu(self, mutex);
552*795d594fSAndroid Build Coastguard Worker 
553*795d594fSAndroid Build Coastguard Worker           thread_list_indices.push_back(index);
554*795d594fSAndroid Build Coastguard Worker 
555*795d594fSAndroid Build Coastguard Worker           frames.emplace_back(new std::vector<jvmtiFrameInfo>());
556*795d594fSAndroid Build Coastguard Worker           return frames.back().get();
557*795d594fSAndroid Build Coastguard Worker         }
558*795d594fSAndroid Build Coastguard Worker       }
559*795d594fSAndroid Build Coastguard Worker       return nullptr;
560*795d594fSAndroid Build Coastguard Worker     }
561*795d594fSAndroid Build Coastguard Worker 
562*795d594fSAndroid Build Coastguard Worker     art::Mutex mutex;
563*795d594fSAndroid Build Coastguard Worker 
564*795d594fSAndroid Build Coastguard Worker     // Selection data.
565*795d594fSAndroid Build Coastguard Worker 
566*795d594fSAndroid Build Coastguard Worker     std::vector<art::Handle<art::mirror::Object>> handles;
567*795d594fSAndroid Build Coastguard Worker 
568*795d594fSAndroid Build Coastguard Worker     // Storage. Only access directly after completion.
569*795d594fSAndroid Build Coastguard Worker 
570*795d594fSAndroid Build Coastguard Worker     std::vector<size_t> thread_list_indices;
571*795d594fSAndroid Build Coastguard Worker 
572*795d594fSAndroid Build Coastguard Worker     std::vector<std::unique_ptr<std::vector<jvmtiFrameInfo>>> frames;
573*795d594fSAndroid Build Coastguard Worker   };
574*795d594fSAndroid Build Coastguard Worker 
575*795d594fSAndroid Build Coastguard Worker   SelectStackTracesData data;
576*795d594fSAndroid Build Coastguard Worker 
577*795d594fSAndroid Build Coastguard Worker   // Decode all threads to raw pointers. Put them into a handle scope to avoid any moving GC bugs.
578*795d594fSAndroid Build Coastguard Worker   art::VariableSizedHandleScope hs(current);
579*795d594fSAndroid Build Coastguard Worker   for (jint i = 0; i != thread_count; ++i) {
580*795d594fSAndroid Build Coastguard Worker     if (thread_list[i] == nullptr) {
581*795d594fSAndroid Build Coastguard Worker       return ERR(INVALID_THREAD);
582*795d594fSAndroid Build Coastguard Worker     }
583*795d594fSAndroid Build Coastguard Worker     art::ObjPtr<art::mirror::Object> thread = soa.Decode<art::mirror::Object>(thread_list[i]);
584*795d594fSAndroid Build Coastguard Worker     if (!thread->InstanceOf(art::WellKnownClasses::java_lang_Thread.Get())) {
585*795d594fSAndroid Build Coastguard Worker       return ERR(INVALID_THREAD);
586*795d594fSAndroid Build Coastguard Worker     }
587*795d594fSAndroid Build Coastguard Worker     data.handles.push_back(hs.NewHandle(thread));
588*795d594fSAndroid Build Coastguard Worker   }
589*795d594fSAndroid Build Coastguard Worker 
590*795d594fSAndroid Build Coastguard Worker   RunCheckpointAndWait(&data, static_cast<size_t>(max_frame_count));
591*795d594fSAndroid Build Coastguard Worker 
592*795d594fSAndroid Build Coastguard Worker   // Convert the data into our output format.
593*795d594fSAndroid Build Coastguard Worker 
594*795d594fSAndroid Build Coastguard Worker   // Note: we use an array of jvmtiStackInfo for convenience. The spec says we need to
595*795d594fSAndroid Build Coastguard Worker   //       allocate one big chunk for this and the actual frames, which means we need
596*795d594fSAndroid Build Coastguard Worker   //       to either be conservative or rearrange things later (the latter is implemented).
597*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<jvmtiStackInfo[]> stack_info_array(new jvmtiStackInfo[data.frames.size()]);
598*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<jvmtiFrameInfo[]>> frame_infos;
599*795d594fSAndroid Build Coastguard Worker   frame_infos.reserve(data.frames.size());
600*795d594fSAndroid Build Coastguard Worker 
601*795d594fSAndroid Build Coastguard Worker   // Now run through and add data for each thread.
602*795d594fSAndroid Build Coastguard Worker   size_t sum_frames = 0;
603*795d594fSAndroid Build Coastguard Worker   for (size_t index = 0; index < data.frames.size(); ++index) {
604*795d594fSAndroid Build Coastguard Worker     jvmtiStackInfo& stack_info = stack_info_array.get()[index];
605*795d594fSAndroid Build Coastguard Worker     memset(&stack_info, 0, sizeof(jvmtiStackInfo));
606*795d594fSAndroid Build Coastguard Worker 
607*795d594fSAndroid Build Coastguard Worker     const std::vector<jvmtiFrameInfo>& thread_frames = *data.frames[index].get();
608*795d594fSAndroid Build Coastguard Worker 
609*795d594fSAndroid Build Coastguard Worker     // For the time being, set the thread to null. We don't have good ScopedLocalRef
610*795d594fSAndroid Build Coastguard Worker     // infrastructure.
611*795d594fSAndroid Build Coastguard Worker     stack_info.thread = nullptr;
612*795d594fSAndroid Build Coastguard Worker     stack_info.state = JVMTI_THREAD_STATE_SUSPENDED;
613*795d594fSAndroid Build Coastguard Worker 
614*795d594fSAndroid Build Coastguard Worker     size_t collected_frames = thread_frames.size();
615*795d594fSAndroid Build Coastguard Worker     if (max_frame_count == 0 || collected_frames == 0) {
616*795d594fSAndroid Build Coastguard Worker       stack_info.frame_count = 0;
617*795d594fSAndroid Build Coastguard Worker       stack_info.frame_buffer = nullptr;
618*795d594fSAndroid Build Coastguard Worker       continue;
619*795d594fSAndroid Build Coastguard Worker     }
620*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(collected_frames, static_cast<size_t>(max_frame_count));
621*795d594fSAndroid Build Coastguard Worker 
622*795d594fSAndroid Build Coastguard Worker     jvmtiFrameInfo* frame_info = new jvmtiFrameInfo[collected_frames];
623*795d594fSAndroid Build Coastguard Worker     frame_infos.emplace_back(frame_info);
624*795d594fSAndroid Build Coastguard Worker 
625*795d594fSAndroid Build Coastguard Worker     jint count;
626*795d594fSAndroid Build Coastguard Worker     jvmtiError translate_result = TranslateFrameVector(thread_frames,
627*795d594fSAndroid Build Coastguard Worker                                                        0,
628*795d594fSAndroid Build Coastguard Worker                                                        0,
629*795d594fSAndroid Build Coastguard Worker                                                        static_cast<jint>(collected_frames),
630*795d594fSAndroid Build Coastguard Worker                                                        frame_info,
631*795d594fSAndroid Build Coastguard Worker                                                        &count);
632*795d594fSAndroid Build Coastguard Worker     DCHECK(translate_result == JVMTI_ERROR_NONE);
633*795d594fSAndroid Build Coastguard Worker     stack_info.frame_count = static_cast<jint>(collected_frames);
634*795d594fSAndroid Build Coastguard Worker     stack_info.frame_buffer = frame_info;
635*795d594fSAndroid Build Coastguard Worker     sum_frames += static_cast<size_t>(count);
636*795d594fSAndroid Build Coastguard Worker   }
637*795d594fSAndroid Build Coastguard Worker 
638*795d594fSAndroid Build Coastguard Worker   // No errors, yet. Now put it all into an output buffer. Note that this is not frames.size(),
639*795d594fSAndroid Build Coastguard Worker   // potentially.
640*795d594fSAndroid Build Coastguard Worker   size_t rounded_stack_info_size = art::RoundUp(sizeof(jvmtiStackInfo) * thread_count,
641*795d594fSAndroid Build Coastguard Worker                                                 alignof(jvmtiFrameInfo));
642*795d594fSAndroid Build Coastguard Worker   size_t chunk_size = rounded_stack_info_size + sum_frames * sizeof(jvmtiFrameInfo);
643*795d594fSAndroid Build Coastguard Worker   unsigned char* chunk_data;
644*795d594fSAndroid Build Coastguard Worker   jvmtiError alloc_result = env->Allocate(chunk_size, &chunk_data);
645*795d594fSAndroid Build Coastguard Worker   if (alloc_result != ERR(NONE)) {
646*795d594fSAndroid Build Coastguard Worker     return alloc_result;
647*795d594fSAndroid Build Coastguard Worker   }
648*795d594fSAndroid Build Coastguard Worker 
649*795d594fSAndroid Build Coastguard Worker   jvmtiStackInfo* stack_info = reinterpret_cast<jvmtiStackInfo*>(chunk_data);
650*795d594fSAndroid Build Coastguard Worker   jvmtiFrameInfo* frame_info = reinterpret_cast<jvmtiFrameInfo*>(
651*795d594fSAndroid Build Coastguard Worker       chunk_data + rounded_stack_info_size);
652*795d594fSAndroid Build Coastguard Worker 
653*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; i < static_cast<size_t>(thread_count); ++i) {
654*795d594fSAndroid Build Coastguard Worker     // Check whether we found a running thread for this.
655*795d594fSAndroid Build Coastguard Worker     // Note: For simplicity, and with the expectation that the list is usually small, use a simple
656*795d594fSAndroid Build Coastguard Worker     //       search. (The list is *not* sorted!)
657*795d594fSAndroid Build Coastguard Worker     auto it = std::find(data.thread_list_indices.begin(), data.thread_list_indices.end(), i);
658*795d594fSAndroid Build Coastguard Worker     if (it == data.thread_list_indices.end()) {
659*795d594fSAndroid Build Coastguard Worker       // No native thread. Must be new or dead. We need to fill out the stack info now.
660*795d594fSAndroid Build Coastguard Worker       // (Need to read the Java "started" field to know whether this is starting or terminated.)
661*795d594fSAndroid Build Coastguard Worker       art::ObjPtr<art::mirror::Object> peer = soa.Decode<art::mirror::Object>(thread_list[i]);
662*795d594fSAndroid Build Coastguard Worker       art::ObjPtr<art::mirror::Class> klass = peer->GetClass();
663*795d594fSAndroid Build Coastguard Worker       art::ArtField* started_field = klass->FindDeclaredInstanceField("started", "Z");
664*795d594fSAndroid Build Coastguard Worker       CHECK(started_field != nullptr);
665*795d594fSAndroid Build Coastguard Worker       bool started = started_field->GetBoolean(peer) != 0;
666*795d594fSAndroid Build Coastguard Worker       constexpr jint kStartedState = JVMTI_JAVA_LANG_THREAD_STATE_NEW;
667*795d594fSAndroid Build Coastguard Worker       constexpr jint kTerminatedState = JVMTI_THREAD_STATE_TERMINATED |
668*795d594fSAndroid Build Coastguard Worker           JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED;
669*795d594fSAndroid Build Coastguard Worker       stack_info[i].thread = reinterpret_cast<JNIEnv*>(soa.Env())->NewLocalRef(thread_list[i]);
670*795d594fSAndroid Build Coastguard Worker       stack_info[i].state = started ? kTerminatedState : kStartedState;
671*795d594fSAndroid Build Coastguard Worker       stack_info[i].frame_count = 0;
672*795d594fSAndroid Build Coastguard Worker       stack_info[i].frame_buffer = nullptr;
673*795d594fSAndroid Build Coastguard Worker     } else {
674*795d594fSAndroid Build Coastguard Worker       // Had a native thread and frames.
675*795d594fSAndroid Build Coastguard Worker       size_t f_index = it - data.thread_list_indices.begin();
676*795d594fSAndroid Build Coastguard Worker 
677*795d594fSAndroid Build Coastguard Worker       jvmtiStackInfo& old_stack_info = stack_info_array.get()[f_index];
678*795d594fSAndroid Build Coastguard Worker       jvmtiStackInfo& new_stack_info = stack_info[i];
679*795d594fSAndroid Build Coastguard Worker 
680*795d594fSAndroid Build Coastguard Worker       memcpy(&new_stack_info, &old_stack_info, sizeof(jvmtiStackInfo));
681*795d594fSAndroid Build Coastguard Worker       new_stack_info.thread = reinterpret_cast<JNIEnv*>(soa.Env())->NewLocalRef(thread_list[i]);
682*795d594fSAndroid Build Coastguard Worker       if (old_stack_info.frame_count > 0) {
683*795d594fSAndroid Build Coastguard Worker         // Only copy when there's data - leave the nullptr alone.
684*795d594fSAndroid Build Coastguard Worker         size_t frames_size =
685*795d594fSAndroid Build Coastguard Worker             static_cast<size_t>(old_stack_info.frame_count) * sizeof(jvmtiFrameInfo);
686*795d594fSAndroid Build Coastguard Worker         memcpy(frame_info, old_stack_info.frame_buffer, frames_size);
687*795d594fSAndroid Build Coastguard Worker         new_stack_info.frame_buffer = frame_info;
688*795d594fSAndroid Build Coastguard Worker         frame_info += old_stack_info.frame_count;
689*795d594fSAndroid Build Coastguard Worker       }
690*795d594fSAndroid Build Coastguard Worker     }
691*795d594fSAndroid Build Coastguard Worker   }
692*795d594fSAndroid Build Coastguard Worker 
693*795d594fSAndroid Build Coastguard Worker   *stack_info_ptr = stack_info;
694*795d594fSAndroid Build Coastguard Worker 
695*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
696*795d594fSAndroid Build Coastguard Worker }
697*795d594fSAndroid Build Coastguard Worker 
698*795d594fSAndroid Build Coastguard Worker struct GetFrameCountClosure : public art::Closure {
699*795d594fSAndroid Build Coastguard Worker  public:
GetFrameCountClosureopenjdkjvmti::GetFrameCountClosure700*795d594fSAndroid Build Coastguard Worker   GetFrameCountClosure() : count(0) {}
701*795d594fSAndroid Build Coastguard Worker 
Runopenjdkjvmti::GetFrameCountClosure702*795d594fSAndroid Build Coastguard Worker   void Run(art::Thread* self) override REQUIRES_SHARED(art::Locks::mutator_lock_) {
703*795d594fSAndroid Build Coastguard Worker     // This is not StackVisitor::ComputeNumFrames, as runtime methods and transitions must not be
704*795d594fSAndroid Build Coastguard Worker     // counted.
705*795d594fSAndroid Build Coastguard Worker     art::StackVisitor::WalkStack(
706*795d594fSAndroid Build Coastguard Worker         [&](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(art::Locks::mutator_lock_) {
707*795d594fSAndroid Build Coastguard Worker           art::ArtMethod* m = stack_visitor->GetMethod();
708*795d594fSAndroid Build Coastguard Worker           if (m != nullptr && !m->IsRuntimeMethod()) {
709*795d594fSAndroid Build Coastguard Worker             count++;
710*795d594fSAndroid Build Coastguard Worker           }
711*795d594fSAndroid Build Coastguard Worker           return true;
712*795d594fSAndroid Build Coastguard Worker         },
713*795d594fSAndroid Build Coastguard Worker         self,
714*795d594fSAndroid Build Coastguard Worker         /* context= */ nullptr,
715*795d594fSAndroid Build Coastguard Worker         art::StackVisitor::StackWalkKind::kIncludeInlinedFrames);
716*795d594fSAndroid Build Coastguard Worker   }
717*795d594fSAndroid Build Coastguard Worker 
718*795d594fSAndroid Build Coastguard Worker   size_t count;
719*795d594fSAndroid Build Coastguard Worker };
720*795d594fSAndroid Build Coastguard Worker 
GetFrameCount(jvmtiEnv * env,jthread java_thread,jint * count_ptr)721*795d594fSAndroid Build Coastguard Worker jvmtiError StackUtil::GetFrameCount([[maybe_unused]] jvmtiEnv* env,
722*795d594fSAndroid Build Coastguard Worker                                     jthread java_thread,
723*795d594fSAndroid Build Coastguard Worker                                     jint* count_ptr) {
724*795d594fSAndroid Build Coastguard Worker   // It is not great that we have to hold these locks for so long, but it is necessary to ensure
725*795d594fSAndroid Build Coastguard Worker   // that the thread isn't dying on us.
726*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(art::Thread::Current());
727*795d594fSAndroid Build Coastguard Worker   art::Locks::thread_list_lock_->ExclusiveLock(soa.Self());
728*795d594fSAndroid Build Coastguard Worker 
729*795d594fSAndroid Build Coastguard Worker   art::Thread* thread;
730*795d594fSAndroid Build Coastguard Worker   jvmtiError thread_error = ERR(INTERNAL);
731*795d594fSAndroid Build Coastguard Worker   if (!ThreadUtil::GetAliveNativeThread(java_thread, soa, &thread, &thread_error)) {
732*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(soa.Self());
733*795d594fSAndroid Build Coastguard Worker     return thread_error;
734*795d594fSAndroid Build Coastguard Worker   }
735*795d594fSAndroid Build Coastguard Worker 
736*795d594fSAndroid Build Coastguard Worker   DCHECK(thread != nullptr);
737*795d594fSAndroid Build Coastguard Worker   art::ThreadState state = thread->GetState();
738*795d594fSAndroid Build Coastguard Worker   if (state == art::ThreadState::kStarting || thread->IsStillStarting()) {
739*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(soa.Self());
740*795d594fSAndroid Build Coastguard Worker     return ERR(THREAD_NOT_ALIVE);
741*795d594fSAndroid Build Coastguard Worker   }
742*795d594fSAndroid Build Coastguard Worker 
743*795d594fSAndroid Build Coastguard Worker   if (count_ptr == nullptr) {
744*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(soa.Self());
745*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
746*795d594fSAndroid Build Coastguard Worker   }
747*795d594fSAndroid Build Coastguard Worker 
748*795d594fSAndroid Build Coastguard Worker   GetFrameCountClosure closure;
749*795d594fSAndroid Build Coastguard Worker   // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution.
750*795d594fSAndroid Build Coastguard Worker   if (!thread->RequestSynchronousCheckpoint(&closure)) {
751*795d594fSAndroid Build Coastguard Worker     return ERR(THREAD_NOT_ALIVE);
752*795d594fSAndroid Build Coastguard Worker   }
753*795d594fSAndroid Build Coastguard Worker 
754*795d594fSAndroid Build Coastguard Worker   *count_ptr = closure.count;
755*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
756*795d594fSAndroid Build Coastguard Worker }
757*795d594fSAndroid Build Coastguard Worker 
758*795d594fSAndroid Build Coastguard Worker struct GetLocationClosure : public art::Closure {
759*795d594fSAndroid Build Coastguard Worker  public:
GetLocationClosureopenjdkjvmti::GetLocationClosure760*795d594fSAndroid Build Coastguard Worker   explicit GetLocationClosure(size_t n_in) : n(n_in), method(nullptr), dex_pc(0) {}
761*795d594fSAndroid Build Coastguard Worker 
Runopenjdkjvmti::GetLocationClosure762*795d594fSAndroid Build Coastguard Worker   void Run(art::Thread* self) override REQUIRES_SHARED(art::Locks::mutator_lock_) {
763*795d594fSAndroid Build Coastguard Worker     // Walks up the stack 'n' callers.
764*795d594fSAndroid Build Coastguard Worker     size_t count = 0u;
765*795d594fSAndroid Build Coastguard Worker     art::StackVisitor::WalkStack(
766*795d594fSAndroid Build Coastguard Worker         [&](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(art::Locks::mutator_lock_) {
767*795d594fSAndroid Build Coastguard Worker           art::ArtMethod* m = stack_visitor->GetMethod();
768*795d594fSAndroid Build Coastguard Worker           if (m != nullptr && !m->IsRuntimeMethod()) {
769*795d594fSAndroid Build Coastguard Worker             DCHECK(method == nullptr);
770*795d594fSAndroid Build Coastguard Worker             if (count == n) {
771*795d594fSAndroid Build Coastguard Worker               method = m;
772*795d594fSAndroid Build Coastguard Worker               dex_pc = stack_visitor->GetDexPc(/*abort_on_failure=*/false);
773*795d594fSAndroid Build Coastguard Worker               return false;
774*795d594fSAndroid Build Coastguard Worker             }
775*795d594fSAndroid Build Coastguard Worker             count++;
776*795d594fSAndroid Build Coastguard Worker           }
777*795d594fSAndroid Build Coastguard Worker           return true;
778*795d594fSAndroid Build Coastguard Worker         },
779*795d594fSAndroid Build Coastguard Worker         self,
780*795d594fSAndroid Build Coastguard Worker         /* context= */ nullptr,
781*795d594fSAndroid Build Coastguard Worker         art::StackVisitor::StackWalkKind::kIncludeInlinedFrames);
782*795d594fSAndroid Build Coastguard Worker   }
783*795d594fSAndroid Build Coastguard Worker 
784*795d594fSAndroid Build Coastguard Worker   const size_t n;
785*795d594fSAndroid Build Coastguard Worker   art::ArtMethod* method;
786*795d594fSAndroid Build Coastguard Worker   uint32_t dex_pc;
787*795d594fSAndroid Build Coastguard Worker };
788*795d594fSAndroid Build Coastguard Worker 
GetFrameLocation(jvmtiEnv * env,jthread java_thread,jint depth,jmethodID * method_ptr,jlocation * location_ptr)789*795d594fSAndroid Build Coastguard Worker jvmtiError StackUtil::GetFrameLocation([[maybe_unused]] jvmtiEnv* env,
790*795d594fSAndroid Build Coastguard Worker                                        jthread java_thread,
791*795d594fSAndroid Build Coastguard Worker                                        jint depth,
792*795d594fSAndroid Build Coastguard Worker                                        jmethodID* method_ptr,
793*795d594fSAndroid Build Coastguard Worker                                        jlocation* location_ptr) {
794*795d594fSAndroid Build Coastguard Worker   // It is not great that we have to hold these locks for so long, but it is necessary to ensure
795*795d594fSAndroid Build Coastguard Worker   // that the thread isn't dying on us.
796*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(art::Thread::Current());
797*795d594fSAndroid Build Coastguard Worker   art::Locks::thread_list_lock_->ExclusiveLock(soa.Self());
798*795d594fSAndroid Build Coastguard Worker 
799*795d594fSAndroid Build Coastguard Worker   art::Thread* thread;
800*795d594fSAndroid Build Coastguard Worker   jvmtiError thread_error = ERR(INTERNAL);
801*795d594fSAndroid Build Coastguard Worker   if (!ThreadUtil::GetAliveNativeThread(java_thread, soa, &thread, &thread_error)) {
802*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(soa.Self());
803*795d594fSAndroid Build Coastguard Worker     return thread_error;
804*795d594fSAndroid Build Coastguard Worker   }
805*795d594fSAndroid Build Coastguard Worker   DCHECK(thread != nullptr);
806*795d594fSAndroid Build Coastguard Worker 
807*795d594fSAndroid Build Coastguard Worker   art::ThreadState state = thread->GetState();
808*795d594fSAndroid Build Coastguard Worker   if (state == art::ThreadState::kStarting || thread->IsStillStarting()) {
809*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(soa.Self());
810*795d594fSAndroid Build Coastguard Worker     return ERR(THREAD_NOT_ALIVE);
811*795d594fSAndroid Build Coastguard Worker   }
812*795d594fSAndroid Build Coastguard Worker 
813*795d594fSAndroid Build Coastguard Worker   if (depth < 0) {
814*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(soa.Self());
815*795d594fSAndroid Build Coastguard Worker     return ERR(ILLEGAL_ARGUMENT);
816*795d594fSAndroid Build Coastguard Worker   }
817*795d594fSAndroid Build Coastguard Worker   if (method_ptr == nullptr || location_ptr == nullptr) {
818*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(soa.Self());
819*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
820*795d594fSAndroid Build Coastguard Worker   }
821*795d594fSAndroid Build Coastguard Worker 
822*795d594fSAndroid Build Coastguard Worker   GetLocationClosure closure(static_cast<size_t>(depth));
823*795d594fSAndroid Build Coastguard Worker   // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution.
824*795d594fSAndroid Build Coastguard Worker   if (!thread->RequestSynchronousCheckpoint(&closure)) {
825*795d594fSAndroid Build Coastguard Worker     return ERR(THREAD_NOT_ALIVE);
826*795d594fSAndroid Build Coastguard Worker   }
827*795d594fSAndroid Build Coastguard Worker 
828*795d594fSAndroid Build Coastguard Worker   if (closure.method == nullptr) {
829*795d594fSAndroid Build Coastguard Worker     return ERR(NO_MORE_FRAMES);
830*795d594fSAndroid Build Coastguard Worker   }
831*795d594fSAndroid Build Coastguard Worker 
832*795d594fSAndroid Build Coastguard Worker   *method_ptr = art::jni::EncodeArtMethod(closure.method);
833*795d594fSAndroid Build Coastguard Worker   if (closure.method->IsNative() || closure.method->IsProxyMethod()) {
834*795d594fSAndroid Build Coastguard Worker     *location_ptr = -1;
835*795d594fSAndroid Build Coastguard Worker   } else {
836*795d594fSAndroid Build Coastguard Worker     if (closure.dex_pc == art::dex::kDexNoIndex) {
837*795d594fSAndroid Build Coastguard Worker       return ERR(INTERNAL);
838*795d594fSAndroid Build Coastguard Worker     }
839*795d594fSAndroid Build Coastguard Worker     *location_ptr = static_cast<jlocation>(closure.dex_pc);
840*795d594fSAndroid Build Coastguard Worker   }
841*795d594fSAndroid Build Coastguard Worker 
842*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
843*795d594fSAndroid Build Coastguard Worker }
844*795d594fSAndroid Build Coastguard Worker 
845*795d594fSAndroid Build Coastguard Worker struct MonitorVisitor : public art::StackVisitor, public art::SingleRootVisitor {
846*795d594fSAndroid Build Coastguard Worker   // We need a context because VisitLocks needs it retrieve the monitor objects.
847*795d594fSAndroid Build Coastguard Worker   explicit MonitorVisitor(art::Thread* thread)
REQUIRES_SHAREDopenjdkjvmti::MonitorVisitor848*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_)
849*795d594fSAndroid Build Coastguard Worker       : art::StackVisitor(thread,
850*795d594fSAndroid Build Coastguard Worker                           art::Context::Create(),
851*795d594fSAndroid Build Coastguard Worker                           art::StackVisitor::StackWalkKind::kIncludeInlinedFrames),
852*795d594fSAndroid Build Coastguard Worker         hs(art::Thread::Current()),
853*795d594fSAndroid Build Coastguard Worker         current_stack_depth(0) {}
854*795d594fSAndroid Build Coastguard Worker 
~MonitorVisitoropenjdkjvmti::MonitorVisitor855*795d594fSAndroid Build Coastguard Worker   ~MonitorVisitor() {
856*795d594fSAndroid Build Coastguard Worker     delete context_;
857*795d594fSAndroid Build Coastguard Worker   }
858*795d594fSAndroid Build Coastguard Worker 
VisitFrameopenjdkjvmti::MonitorVisitor859*795d594fSAndroid Build Coastguard Worker   bool VisitFrame() override REQUIRES_SHARED(art::Locks::mutator_lock_) {
860*795d594fSAndroid Build Coastguard Worker     art::Locks::mutator_lock_->AssertSharedHeld(art::Thread::Current());
861*795d594fSAndroid Build Coastguard Worker     if (!GetMethod()->IsRuntimeMethod()) {
862*795d594fSAndroid Build Coastguard Worker       art::Monitor::VisitLocks(this, AppendOwnedMonitors, this);
863*795d594fSAndroid Build Coastguard Worker       ++current_stack_depth;
864*795d594fSAndroid Build Coastguard Worker     }
865*795d594fSAndroid Build Coastguard Worker     return true;
866*795d594fSAndroid Build Coastguard Worker   }
867*795d594fSAndroid Build Coastguard Worker 
AppendOwnedMonitorsopenjdkjvmti::MonitorVisitor868*795d594fSAndroid Build Coastguard Worker   static void AppendOwnedMonitors(art::ObjPtr<art::mirror::Object> owned_monitor, void* arg)
869*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
870*795d594fSAndroid Build Coastguard Worker     art::Locks::mutator_lock_->AssertSharedHeld(art::Thread::Current());
871*795d594fSAndroid Build Coastguard Worker     MonitorVisitor* visitor = reinterpret_cast<MonitorVisitor*>(arg);
872*795d594fSAndroid Build Coastguard Worker     // Filter out duplicates.
873*795d594fSAndroid Build Coastguard Worker     for (const art::Handle<art::mirror::Object>& monitor : visitor->monitors) {
874*795d594fSAndroid Build Coastguard Worker       if (monitor.Get() == owned_monitor) {
875*795d594fSAndroid Build Coastguard Worker         return;
876*795d594fSAndroid Build Coastguard Worker       }
877*795d594fSAndroid Build Coastguard Worker     }
878*795d594fSAndroid Build Coastguard Worker     visitor->monitors.push_back(visitor->hs.NewHandle(owned_monitor));
879*795d594fSAndroid Build Coastguard Worker     visitor->stack_depths.push_back(visitor->current_stack_depth);
880*795d594fSAndroid Build Coastguard Worker   }
881*795d594fSAndroid Build Coastguard Worker 
VisitRootopenjdkjvmti::MonitorVisitor882*795d594fSAndroid Build Coastguard Worker   void VisitRoot(art::mirror::Object* obj, [[maybe_unused]] const art::RootInfo& info) override
883*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
884*795d594fSAndroid Build Coastguard Worker     for (const art::Handle<art::mirror::Object>& m : monitors) {
885*795d594fSAndroid Build Coastguard Worker       if (m.Get() == obj) {
886*795d594fSAndroid Build Coastguard Worker         return;
887*795d594fSAndroid Build Coastguard Worker       }
888*795d594fSAndroid Build Coastguard Worker     }
889*795d594fSAndroid Build Coastguard Worker     monitors.push_back(hs.NewHandle(obj));
890*795d594fSAndroid Build Coastguard Worker     stack_depths.push_back(-1);
891*795d594fSAndroid Build Coastguard Worker   }
892*795d594fSAndroid Build Coastguard Worker 
893*795d594fSAndroid Build Coastguard Worker   art::VariableSizedHandleScope hs;
894*795d594fSAndroid Build Coastguard Worker   jint current_stack_depth;
895*795d594fSAndroid Build Coastguard Worker   std::vector<art::Handle<art::mirror::Object>> monitors;
896*795d594fSAndroid Build Coastguard Worker   std::vector<jint> stack_depths;
897*795d594fSAndroid Build Coastguard Worker };
898*795d594fSAndroid Build Coastguard Worker 
899*795d594fSAndroid Build Coastguard Worker template<typename Fn>
900*795d594fSAndroid Build Coastguard Worker struct MonitorInfoClosure : public art::Closure {
901*795d594fSAndroid Build Coastguard Worker  public:
MonitorInfoClosureopenjdkjvmti::MonitorInfoClosure902*795d594fSAndroid Build Coastguard Worker   explicit MonitorInfoClosure(Fn handle_results)
903*795d594fSAndroid Build Coastguard Worker       : err_(OK), handle_results_(handle_results) {}
904*795d594fSAndroid Build Coastguard Worker 
Runopenjdkjvmti::MonitorInfoClosure905*795d594fSAndroid Build Coastguard Worker   void Run(art::Thread* target) override REQUIRES_SHARED(art::Locks::mutator_lock_) {
906*795d594fSAndroid Build Coastguard Worker     art::Locks::mutator_lock_->AssertSharedHeld(art::Thread::Current());
907*795d594fSAndroid Build Coastguard Worker     // Find the monitors on the stack.
908*795d594fSAndroid Build Coastguard Worker     MonitorVisitor visitor(target);
909*795d594fSAndroid Build Coastguard Worker     visitor.WalkStack(/* include_transitions= */ false);
910*795d594fSAndroid Build Coastguard Worker     // Find any other monitors, including ones acquired in native code.
911*795d594fSAndroid Build Coastguard Worker     art::RootInfo root_info(art::kRootVMInternal);
912*795d594fSAndroid Build Coastguard Worker     target->GetJniEnv()->VisitMonitorRoots(&visitor, root_info);
913*795d594fSAndroid Build Coastguard Worker     err_ = handle_results_(visitor);
914*795d594fSAndroid Build Coastguard Worker   }
915*795d594fSAndroid Build Coastguard Worker 
GetErroropenjdkjvmti::MonitorInfoClosure916*795d594fSAndroid Build Coastguard Worker   jvmtiError GetError() {
917*795d594fSAndroid Build Coastguard Worker     return err_;
918*795d594fSAndroid Build Coastguard Worker   }
919*795d594fSAndroid Build Coastguard Worker 
920*795d594fSAndroid Build Coastguard Worker  private:
921*795d594fSAndroid Build Coastguard Worker   jvmtiError err_;
922*795d594fSAndroid Build Coastguard Worker   Fn handle_results_;
923*795d594fSAndroid Build Coastguard Worker };
924*795d594fSAndroid Build Coastguard Worker 
925*795d594fSAndroid Build Coastguard Worker 
926*795d594fSAndroid Build Coastguard Worker template <typename Fn>
GetOwnedMonitorInfoCommon(const art::ScopedObjectAccessAlreadyRunnable & soa,jthread thread,Fn handle_results)927*795d594fSAndroid Build Coastguard Worker static jvmtiError GetOwnedMonitorInfoCommon(const art::ScopedObjectAccessAlreadyRunnable& soa,
928*795d594fSAndroid Build Coastguard Worker                                             jthread thread,
929*795d594fSAndroid Build Coastguard Worker                                             Fn handle_results)
930*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(art::Locks::mutator_lock_) {
931*795d594fSAndroid Build Coastguard Worker   art::Thread* self = art::Thread::Current();
932*795d594fSAndroid Build Coastguard Worker   MonitorInfoClosure<Fn> closure(handle_results);
933*795d594fSAndroid Build Coastguard Worker   bool called_method = false;
934*795d594fSAndroid Build Coastguard Worker   {
935*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveLock(self);
936*795d594fSAndroid Build Coastguard Worker     art::Thread* target = nullptr;
937*795d594fSAndroid Build Coastguard Worker     jvmtiError err = ERR(INTERNAL);
938*795d594fSAndroid Build Coastguard Worker     if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) {
939*795d594fSAndroid Build Coastguard Worker       art::Locks::thread_list_lock_->ExclusiveUnlock(self);
940*795d594fSAndroid Build Coastguard Worker       return err;
941*795d594fSAndroid Build Coastguard Worker     }
942*795d594fSAndroid Build Coastguard Worker     if (target != self) {
943*795d594fSAndroid Build Coastguard Worker       called_method = true;
944*795d594fSAndroid Build Coastguard Worker       // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution.
945*795d594fSAndroid Build Coastguard Worker       // Since this deals with object references we need to avoid going to sleep.
946*795d594fSAndroid Build Coastguard Worker       art::ScopedAssertNoThreadSuspension sants("Getting owned monitor usage");
947*795d594fSAndroid Build Coastguard Worker       if (!target->RequestSynchronousCheckpoint(&closure, art::ThreadState::kRunnable)) {
948*795d594fSAndroid Build Coastguard Worker         return ERR(THREAD_NOT_ALIVE);
949*795d594fSAndroid Build Coastguard Worker       }
950*795d594fSAndroid Build Coastguard Worker     } else {
951*795d594fSAndroid Build Coastguard Worker       art::Locks::thread_list_lock_->ExclusiveUnlock(self);
952*795d594fSAndroid Build Coastguard Worker     }
953*795d594fSAndroid Build Coastguard Worker   }
954*795d594fSAndroid Build Coastguard Worker   // Cannot call the closure on the current thread if we have thread_list_lock since we need to call
955*795d594fSAndroid Build Coastguard Worker   // into the verifier which can cause the current thread to suspend for gc. Suspending would be a
956*795d594fSAndroid Build Coastguard Worker   // bad thing to do if we hold the ThreadListLock. For other threads since we are running it on a
957*795d594fSAndroid Build Coastguard Worker   // checkpoint we are fine but if the thread is the current one we need to drop the mutex first.
958*795d594fSAndroid Build Coastguard Worker   if (!called_method) {
959*795d594fSAndroid Build Coastguard Worker     closure.Run(self);
960*795d594fSAndroid Build Coastguard Worker   }
961*795d594fSAndroid Build Coastguard Worker   return closure.GetError();
962*795d594fSAndroid Build Coastguard Worker }
963*795d594fSAndroid Build Coastguard Worker 
GetOwnedMonitorStackDepthInfo(jvmtiEnv * env,jthread thread,jint * info_cnt,jvmtiMonitorStackDepthInfo ** info_ptr)964*795d594fSAndroid Build Coastguard Worker jvmtiError StackUtil::GetOwnedMonitorStackDepthInfo(jvmtiEnv* env,
965*795d594fSAndroid Build Coastguard Worker                                                     jthread thread,
966*795d594fSAndroid Build Coastguard Worker                                                     jint* info_cnt,
967*795d594fSAndroid Build Coastguard Worker                                                     jvmtiMonitorStackDepthInfo** info_ptr) {
968*795d594fSAndroid Build Coastguard Worker   if (info_cnt == nullptr || info_ptr == nullptr) {
969*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
970*795d594fSAndroid Build Coastguard Worker   }
971*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(art::Thread::Current());
972*795d594fSAndroid Build Coastguard Worker   std::vector<art::GcRoot<art::mirror::Object>> mons;
973*795d594fSAndroid Build Coastguard Worker   std::vector<uint32_t> depths;
974*795d594fSAndroid Build Coastguard Worker   auto handle_fun = [&] (MonitorVisitor& visitor) REQUIRES_SHARED(art::Locks::mutator_lock_) {
975*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < visitor.monitors.size(); i++) {
976*795d594fSAndroid Build Coastguard Worker       mons.push_back(art::GcRoot<art::mirror::Object>(visitor.monitors[i].Get()));
977*795d594fSAndroid Build Coastguard Worker       depths.push_back(visitor.stack_depths[i]);
978*795d594fSAndroid Build Coastguard Worker     }
979*795d594fSAndroid Build Coastguard Worker     return OK;
980*795d594fSAndroid Build Coastguard Worker   };
981*795d594fSAndroid Build Coastguard Worker   jvmtiError err = GetOwnedMonitorInfoCommon(soa, thread, handle_fun);
982*795d594fSAndroid Build Coastguard Worker   if (err != OK) {
983*795d594fSAndroid Build Coastguard Worker     return err;
984*795d594fSAndroid Build Coastguard Worker   }
985*795d594fSAndroid Build Coastguard Worker   auto nbytes = sizeof(jvmtiMonitorStackDepthInfo) * mons.size();
986*795d594fSAndroid Build Coastguard Worker   err = env->Allocate(nbytes, reinterpret_cast<unsigned char**>(info_ptr));
987*795d594fSAndroid Build Coastguard Worker   if (err != OK) {
988*795d594fSAndroid Build Coastguard Worker     return err;
989*795d594fSAndroid Build Coastguard Worker   }
990*795d594fSAndroid Build Coastguard Worker   *info_cnt = mons.size();
991*795d594fSAndroid Build Coastguard Worker   for (uint32_t i = 0; i < mons.size(); i++) {
992*795d594fSAndroid Build Coastguard Worker     (*info_ptr)[i] = {
993*795d594fSAndroid Build Coastguard Worker       soa.AddLocalReference<jobject>(mons[i].Read()),
994*795d594fSAndroid Build Coastguard Worker       static_cast<jint>(depths[i])
995*795d594fSAndroid Build Coastguard Worker     };
996*795d594fSAndroid Build Coastguard Worker   }
997*795d594fSAndroid Build Coastguard Worker   return err;
998*795d594fSAndroid Build Coastguard Worker }
999*795d594fSAndroid Build Coastguard Worker 
GetOwnedMonitorInfo(jvmtiEnv * env,jthread thread,jint * owned_monitor_count_ptr,jobject ** owned_monitors_ptr)1000*795d594fSAndroid Build Coastguard Worker jvmtiError StackUtil::GetOwnedMonitorInfo(jvmtiEnv* env,
1001*795d594fSAndroid Build Coastguard Worker                                           jthread thread,
1002*795d594fSAndroid Build Coastguard Worker                                           jint* owned_monitor_count_ptr,
1003*795d594fSAndroid Build Coastguard Worker                                           jobject** owned_monitors_ptr) {
1004*795d594fSAndroid Build Coastguard Worker   if (owned_monitor_count_ptr == nullptr || owned_monitors_ptr == nullptr) {
1005*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
1006*795d594fSAndroid Build Coastguard Worker   }
1007*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(art::Thread::Current());
1008*795d594fSAndroid Build Coastguard Worker   std::vector<art::GcRoot<art::mirror::Object>> mons;
1009*795d594fSAndroid Build Coastguard Worker   auto handle_fun = [&] (MonitorVisitor& visitor) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1010*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < visitor.monitors.size(); i++) {
1011*795d594fSAndroid Build Coastguard Worker       mons.push_back(art::GcRoot<art::mirror::Object>(visitor.monitors[i].Get()));
1012*795d594fSAndroid Build Coastguard Worker     }
1013*795d594fSAndroid Build Coastguard Worker     return OK;
1014*795d594fSAndroid Build Coastguard Worker   };
1015*795d594fSAndroid Build Coastguard Worker   jvmtiError err = GetOwnedMonitorInfoCommon(soa, thread, handle_fun);
1016*795d594fSAndroid Build Coastguard Worker   if (err != OK) {
1017*795d594fSAndroid Build Coastguard Worker     return err;
1018*795d594fSAndroid Build Coastguard Worker   }
1019*795d594fSAndroid Build Coastguard Worker   auto nbytes = sizeof(jobject) * mons.size();
1020*795d594fSAndroid Build Coastguard Worker   err = env->Allocate(nbytes, reinterpret_cast<unsigned char**>(owned_monitors_ptr));
1021*795d594fSAndroid Build Coastguard Worker   if (err != OK) {
1022*795d594fSAndroid Build Coastguard Worker     return err;
1023*795d594fSAndroid Build Coastguard Worker   }
1024*795d594fSAndroid Build Coastguard Worker   *owned_monitor_count_ptr = mons.size();
1025*795d594fSAndroid Build Coastguard Worker   for (uint32_t i = 0; i < mons.size(); i++) {
1026*795d594fSAndroid Build Coastguard Worker     (*owned_monitors_ptr)[i] = soa.AddLocalReference<jobject>(mons[i].Read());
1027*795d594fSAndroid Build Coastguard Worker   }
1028*795d594fSAndroid Build Coastguard Worker   return err;
1029*795d594fSAndroid Build Coastguard Worker }
1030*795d594fSAndroid Build Coastguard Worker 
NotifyFramePop(jvmtiEnv * env,jthread thread,jint depth)1031*795d594fSAndroid Build Coastguard Worker jvmtiError StackUtil::NotifyFramePop(jvmtiEnv* env, jthread thread, jint depth) {
1032*795d594fSAndroid Build Coastguard Worker   if (depth < 0) {
1033*795d594fSAndroid Build Coastguard Worker     return ERR(ILLEGAL_ARGUMENT);
1034*795d594fSAndroid Build Coastguard Worker   }
1035*795d594fSAndroid Build Coastguard Worker   ArtJvmTiEnv* tienv = ArtJvmTiEnv::AsArtJvmTiEnv(env);
1036*795d594fSAndroid Build Coastguard Worker   art::Thread* self = art::Thread::Current();
1037*795d594fSAndroid Build Coastguard Worker   art::Thread* target;
1038*795d594fSAndroid Build Coastguard Worker 
1039*795d594fSAndroid Build Coastguard Worker   ScopedNoUserCodeSuspension snucs(self);
1040*795d594fSAndroid Build Coastguard Worker   // From now on we know we cannot get suspended by user-code.
1041*795d594fSAndroid Build Coastguard Worker   // NB This does a SuspendCheck (during thread state change) so we need to make
1042*795d594fSAndroid Build Coastguard Worker   // sure we don't have the 'suspend_lock' locked here.
1043*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(self);
1044*795d594fSAndroid Build Coastguard Worker   art::Locks::thread_list_lock_->ExclusiveLock(self);
1045*795d594fSAndroid Build Coastguard Worker   jvmtiError err = ERR(INTERNAL);
1046*795d594fSAndroid Build Coastguard Worker   if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) {
1047*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(self);
1048*795d594fSAndroid Build Coastguard Worker     return err;
1049*795d594fSAndroid Build Coastguard Worker   }
1050*795d594fSAndroid Build Coastguard Worker   if (target != self) {
1051*795d594fSAndroid Build Coastguard Worker     // TODO This is part of the spec but we could easily avoid needing to do it.
1052*795d594fSAndroid Build Coastguard Worker     // We would just put all the logic into a sync-checkpoint.
1053*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_suspend_count_lock_->ExclusiveLock(self);
1054*795d594fSAndroid Build Coastguard Worker     if (target->GetUserCodeSuspendCount() == 0) {
1055*795d594fSAndroid Build Coastguard Worker       art::Locks::thread_suspend_count_lock_->ExclusiveUnlock(self);
1056*795d594fSAndroid Build Coastguard Worker       art::Locks::thread_list_lock_->ExclusiveUnlock(self);
1057*795d594fSAndroid Build Coastguard Worker       return ERR(THREAD_NOT_SUSPENDED);
1058*795d594fSAndroid Build Coastguard Worker     }
1059*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_suspend_count_lock_->ExclusiveUnlock(self);
1060*795d594fSAndroid Build Coastguard Worker   }
1061*795d594fSAndroid Build Coastguard Worker   // We hold the user_code_suspension_lock_ so the target thread is staying
1062*795d594fSAndroid Build Coastguard Worker   // suspended until we are done (unless it's 'self' in which case we don't care
1063*795d594fSAndroid Build Coastguard Worker   // since we aren't going to be returning).
1064*795d594fSAndroid Build Coastguard Worker   // TODO We could implement this using a synchronous checkpoint and not bother
1065*795d594fSAndroid Build Coastguard Worker   // with any of the suspension stuff. The spec does specifically say to return
1066*795d594fSAndroid Build Coastguard Worker   // THREAD_NOT_SUSPENDED though. Find the requested stack frame.
1067*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<art::Context> context(art::Context::Create());
1068*795d594fSAndroid Build Coastguard Worker   FindFrameAtDepthVisitor visitor(target, context.get(), depth);
1069*795d594fSAndroid Build Coastguard Worker   visitor.WalkStack();
1070*795d594fSAndroid Build Coastguard Worker   if (!visitor.FoundFrame()) {
1071*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(self);
1072*795d594fSAndroid Build Coastguard Worker     return ERR(NO_MORE_FRAMES);
1073*795d594fSAndroid Build Coastguard Worker   }
1074*795d594fSAndroid Build Coastguard Worker   art::ArtMethod* method = visitor.GetMethod();
1075*795d594fSAndroid Build Coastguard Worker   if (method->IsNative()) {
1076*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(self);
1077*795d594fSAndroid Build Coastguard Worker     return ERR(OPAQUE_FRAME);
1078*795d594fSAndroid Build Coastguard Worker   }
1079*795d594fSAndroid Build Coastguard Worker   // From here we are sure to succeed.
1080*795d594fSAndroid Build Coastguard Worker   bool needs_instrument = false;
1081*795d594fSAndroid Build Coastguard Worker   // Get/create a shadow frame
1082*795d594fSAndroid Build Coastguard Worker   art::ShadowFrame* shadow_frame =
1083*795d594fSAndroid Build Coastguard Worker       visitor.GetOrCreateShadowFrame(&needs_instrument);
1084*795d594fSAndroid Build Coastguard Worker   {
1085*795d594fSAndroid Build Coastguard Worker     art::WriterMutexLock lk(self, tienv->event_info_mutex_);
1086*795d594fSAndroid Build Coastguard Worker     if (LIKELY(!shadow_frame->NeedsNotifyPop())) {
1087*795d594fSAndroid Build Coastguard Worker       // Ensure we won't miss exceptions being thrown if we get jit-compiled. We
1088*795d594fSAndroid Build Coastguard Worker       // only do this for the first NotifyPopFrame.
1089*795d594fSAndroid Build Coastguard Worker       target->IncrementForceInterpreterCount();
1090*795d594fSAndroid Build Coastguard Worker 
1091*795d594fSAndroid Build Coastguard Worker       // Mark shadow frame as needs_notify_pop_
1092*795d594fSAndroid Build Coastguard Worker       shadow_frame->SetNotifyPop(true);
1093*795d594fSAndroid Build Coastguard Worker     }
1094*795d594fSAndroid Build Coastguard Worker     tienv->notify_frames.insert(shadow_frame);
1095*795d594fSAndroid Build Coastguard Worker   }
1096*795d594fSAndroid Build Coastguard Worker   // Make sure can we will go to the interpreter and use the shadow frames.
1097*795d594fSAndroid Build Coastguard Worker   if (needs_instrument) {
1098*795d594fSAndroid Build Coastguard Worker     art::FunctionClosure fc([](art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1099*795d594fSAndroid Build Coastguard Worker       DeoptManager::Get()->DeoptimizeThread(self);
1100*795d594fSAndroid Build Coastguard Worker     });
1101*795d594fSAndroid Build Coastguard Worker     target->RequestSynchronousCheckpoint(&fc);
1102*795d594fSAndroid Build Coastguard Worker   } else {
1103*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(self);
1104*795d594fSAndroid Build Coastguard Worker   }
1105*795d594fSAndroid Build Coastguard Worker   return OK;
1106*795d594fSAndroid Build Coastguard Worker }
1107*795d594fSAndroid Build Coastguard Worker 
1108*795d594fSAndroid Build Coastguard Worker namespace {
1109*795d594fSAndroid Build Coastguard Worker 
1110*795d594fSAndroid Build Coastguard Worker enum class NonStandardExitType {
1111*795d594fSAndroid Build Coastguard Worker   kPopFrame,
1112*795d594fSAndroid Build Coastguard Worker   kForceReturn,
1113*795d594fSAndroid Build Coastguard Worker };
1114*795d594fSAndroid Build Coastguard Worker 
1115*795d594fSAndroid Build Coastguard Worker template<NonStandardExitType kExitType>
1116*795d594fSAndroid Build Coastguard Worker class NonStandardExitFrames {
1117*795d594fSAndroid Build Coastguard Worker  public:
NonStandardExitFrames(art::Thread * self,jvmtiEnv * env,jthread thread)1118*795d594fSAndroid Build Coastguard Worker   NonStandardExitFrames(art::Thread* self, jvmtiEnv* env, jthread thread)
1119*795d594fSAndroid Build Coastguard Worker       REQUIRES(!art::Locks::thread_suspend_count_lock_)
1120*795d594fSAndroid Build Coastguard Worker       ACQUIRE_SHARED(art::Locks::mutator_lock_)
1121*795d594fSAndroid Build Coastguard Worker       ACQUIRE(art::Locks::thread_list_lock_, art::Locks::user_code_suspension_lock_)
1122*795d594fSAndroid Build Coastguard Worker       : snucs_(self) {
1123*795d594fSAndroid Build Coastguard Worker     // We keep the user-code-suspend-count lock.
1124*795d594fSAndroid Build Coastguard Worker     art::Locks::user_code_suspension_lock_->AssertExclusiveHeld(self);
1125*795d594fSAndroid Build Coastguard Worker 
1126*795d594fSAndroid Build Coastguard Worker     // From now on we know we cannot get suspended by user-code.
1127*795d594fSAndroid Build Coastguard Worker     // NB This does a SuspendCheck (during thread state change) so we need to make sure we don't
1128*795d594fSAndroid Build Coastguard Worker     // have the 'suspend_lock' locked here.
1129*795d594fSAndroid Build Coastguard Worker     old_state_ = self->TransitionFromSuspendedToRunnable();
1130*795d594fSAndroid Build Coastguard Worker     art::ScopedObjectAccessUnchecked soau(self);
1131*795d594fSAndroid Build Coastguard Worker 
1132*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveLock(self);
1133*795d594fSAndroid Build Coastguard Worker 
1134*795d594fSAndroid Build Coastguard Worker     if (!ThreadUtil::GetAliveNativeThread(thread, soau, &target_, &result_)) {
1135*795d594fSAndroid Build Coastguard Worker       return;
1136*795d594fSAndroid Build Coastguard Worker     }
1137*795d594fSAndroid Build Coastguard Worker     {
1138*795d594fSAndroid Build Coastguard Worker       art::MutexLock tscl_mu(self, *art::Locks::thread_suspend_count_lock_);
1139*795d594fSAndroid Build Coastguard Worker       if (target_ != self && target_->GetUserCodeSuspendCount() == 0) {
1140*795d594fSAndroid Build Coastguard Worker         // We cannot be the current thread for this function.
1141*795d594fSAndroid Build Coastguard Worker         result_ = ERR(THREAD_NOT_SUSPENDED);
1142*795d594fSAndroid Build Coastguard Worker         return;
1143*795d594fSAndroid Build Coastguard Worker       }
1144*795d594fSAndroid Build Coastguard Worker     }
1145*795d594fSAndroid Build Coastguard Worker     JvmtiGlobalTLSData* tls_data = ThreadUtil::GetGlobalTLSData(target_);
1146*795d594fSAndroid Build Coastguard Worker     constexpr art::StackVisitor::StackWalkKind kWalkKind =
1147*795d594fSAndroid Build Coastguard Worker         art::StackVisitor::StackWalkKind::kIncludeInlinedFrames;
1148*795d594fSAndroid Build Coastguard Worker     if (tls_data != nullptr &&
1149*795d594fSAndroid Build Coastguard Worker         tls_data->disable_pop_frame_depth != JvmtiGlobalTLSData::kNoDisallowedPopFrame &&
1150*795d594fSAndroid Build Coastguard Worker         tls_data->disable_pop_frame_depth ==
1151*795d594fSAndroid Build Coastguard Worker             art::StackVisitor::ComputeNumFrames(target_, kWalkKind)) {
1152*795d594fSAndroid Build Coastguard Worker       JVMTI_LOG(WARNING, env) << "Disallowing frame pop due to in-progress class-load/prepare. "
1153*795d594fSAndroid Build Coastguard Worker                               << "Frame at depth " << tls_data->disable_pop_frame_depth << " was "
1154*795d594fSAndroid Build Coastguard Worker                               << "marked as un-poppable by the jvmti plugin. See b/117615146 for "
1155*795d594fSAndroid Build Coastguard Worker                               << "more information.";
1156*795d594fSAndroid Build Coastguard Worker       result_ = ERR(OPAQUE_FRAME);
1157*795d594fSAndroid Build Coastguard Worker       return;
1158*795d594fSAndroid Build Coastguard Worker     }
1159*795d594fSAndroid Build Coastguard Worker     // We hold the user_code_suspension_lock_ so the target thread is staying suspended until we are
1160*795d594fSAndroid Build Coastguard Worker     // done.
1161*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<art::Context> context(art::Context::Create());
1162*795d594fSAndroid Build Coastguard Worker     FindFrameAtDepthVisitor final_frame(target_, context.get(), 0);
1163*795d594fSAndroid Build Coastguard Worker     FindFrameAtDepthVisitor penultimate_frame(target_, context.get(), 1);
1164*795d594fSAndroid Build Coastguard Worker     final_frame.WalkStack();
1165*795d594fSAndroid Build Coastguard Worker     penultimate_frame.WalkStack();
1166*795d594fSAndroid Build Coastguard Worker 
1167*795d594fSAndroid Build Coastguard Worker     if (!final_frame.FoundFrame() || !penultimate_frame.FoundFrame()) {
1168*795d594fSAndroid Build Coastguard Worker       // Cannot do it if there is only one frame!
1169*795d594fSAndroid Build Coastguard Worker       JVMTI_LOG(INFO, env) << "Can not pop final frame off of a stack";
1170*795d594fSAndroid Build Coastguard Worker       result_ = ERR(NO_MORE_FRAMES);
1171*795d594fSAndroid Build Coastguard Worker       return;
1172*795d594fSAndroid Build Coastguard Worker     }
1173*795d594fSAndroid Build Coastguard Worker 
1174*795d594fSAndroid Build Coastguard Worker     art::ArtMethod* called_method = final_frame.GetMethod();
1175*795d594fSAndroid Build Coastguard Worker     art::ArtMethod* calling_method = penultimate_frame.GetMethod();
1176*795d594fSAndroid Build Coastguard Worker     if (!CheckFunctions(env, calling_method, called_method)) {
1177*795d594fSAndroid Build Coastguard Worker       return;
1178*795d594fSAndroid Build Coastguard Worker     }
1179*795d594fSAndroid Build Coastguard Worker     DCHECK(!called_method->IsNative()) << called_method->PrettyMethod();
1180*795d594fSAndroid Build Coastguard Worker 
1181*795d594fSAndroid Build Coastguard Worker     // From here we are sure to succeed.
1182*795d594fSAndroid Build Coastguard Worker     result_ = OK;
1183*795d594fSAndroid Build Coastguard Worker 
1184*795d594fSAndroid Build Coastguard Worker     // Get/create a shadow frame
1185*795d594fSAndroid Build Coastguard Worker     final_frame_ = final_frame.GetOrCreateShadowFrame(&created_final_frame_);
1186*795d594fSAndroid Build Coastguard Worker     penultimate_frame_ =
1187*795d594fSAndroid Build Coastguard Worker         (calling_method->IsNative()
1188*795d594fSAndroid Build Coastguard Worker              ? nullptr
1189*795d594fSAndroid Build Coastguard Worker              : penultimate_frame.GetOrCreateShadowFrame(&created_penultimate_frame_));
1190*795d594fSAndroid Build Coastguard Worker 
1191*795d594fSAndroid Build Coastguard Worker     final_frame_id_ = final_frame.GetFrameId();
1192*795d594fSAndroid Build Coastguard Worker     penultimate_frame_id_ = penultimate_frame.GetFrameId();
1193*795d594fSAndroid Build Coastguard Worker 
1194*795d594fSAndroid Build Coastguard Worker     CHECK_NE(final_frame_, penultimate_frame_) << "Frames at different depths not different!";
1195*795d594fSAndroid Build Coastguard Worker   }
1196*795d594fSAndroid Build Coastguard Worker 
1197*795d594fSAndroid Build Coastguard Worker   bool CheckFunctions(jvmtiEnv* env, art::ArtMethod* calling, art::ArtMethod* called)
1198*795d594fSAndroid Build Coastguard Worker       REQUIRES(art::Locks::thread_list_lock_, art::Locks::user_code_suspension_lock_)
1199*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_);
1200*795d594fSAndroid Build Coastguard Worker 
RELEASE_SHARED(art::Locks::mutator_lock_)1201*795d594fSAndroid Build Coastguard Worker   ~NonStandardExitFrames() RELEASE_SHARED(art::Locks::mutator_lock_)
1202*795d594fSAndroid Build Coastguard Worker       REQUIRES(!art::Locks::thread_list_lock_)
1203*795d594fSAndroid Build Coastguard Worker       RELEASE(art::Locks::user_code_suspension_lock_) {
1204*795d594fSAndroid Build Coastguard Worker     art::Thread* self = art::Thread::Current();
1205*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(old_state_, art::ThreadState::kNative)
1206*795d594fSAndroid Build Coastguard Worker         << "Unexpected thread state on entering PopFrame!";
1207*795d594fSAndroid Build Coastguard Worker     self->TransitionFromRunnableToSuspended(old_state_);
1208*795d594fSAndroid Build Coastguard Worker   }
1209*795d594fSAndroid Build Coastguard Worker 
1210*795d594fSAndroid Build Coastguard Worker   ScopedNoUserCodeSuspension snucs_;
1211*795d594fSAndroid Build Coastguard Worker   art::ShadowFrame* final_frame_ GUARDED_BY(art::Locks::user_code_suspension_lock_) = nullptr;
1212*795d594fSAndroid Build Coastguard Worker   art::ShadowFrame* penultimate_frame_ GUARDED_BY(art::Locks::user_code_suspension_lock_) = nullptr;
1213*795d594fSAndroid Build Coastguard Worker   bool created_final_frame_ GUARDED_BY(art::Locks::user_code_suspension_lock_) = false;
1214*795d594fSAndroid Build Coastguard Worker   bool created_penultimate_frame_ GUARDED_BY(art::Locks::user_code_suspension_lock_) = false;
1215*795d594fSAndroid Build Coastguard Worker   uint32_t final_frame_id_ GUARDED_BY(art::Locks::user_code_suspension_lock_) = -1;
1216*795d594fSAndroid Build Coastguard Worker   uint32_t penultimate_frame_id_ GUARDED_BY(art::Locks::user_code_suspension_lock_) = -1;
1217*795d594fSAndroid Build Coastguard Worker   art::Thread* target_ GUARDED_BY(art::Locks::thread_list_lock_) = nullptr;
1218*795d594fSAndroid Build Coastguard Worker   art::ThreadState old_state_ = art::ThreadState::kTerminated;
1219*795d594fSAndroid Build Coastguard Worker   jvmtiError result_ = ERR(INTERNAL);
1220*795d594fSAndroid Build Coastguard Worker };
1221*795d594fSAndroid Build Coastguard Worker 
1222*795d594fSAndroid Build Coastguard Worker template <>
CheckFunctions(jvmtiEnv * env,art::ArtMethod * calling,art::ArtMethod * called)1223*795d594fSAndroid Build Coastguard Worker bool NonStandardExitFrames<NonStandardExitType::kForceReturn>::CheckFunctions(
1224*795d594fSAndroid Build Coastguard Worker     jvmtiEnv* env, [[maybe_unused]] art::ArtMethod* calling, art::ArtMethod* called) {
1225*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(called->IsNative())) {
1226*795d594fSAndroid Build Coastguard Worker     result_ = ERR(OPAQUE_FRAME);
1227*795d594fSAndroid Build Coastguard Worker     JVMTI_LOG(INFO, env) << "Cannot force early return from " << called->PrettyMethod()
1228*795d594fSAndroid Build Coastguard Worker                          << " because it is native.";
1229*795d594fSAndroid Build Coastguard Worker     return false;
1230*795d594fSAndroid Build Coastguard Worker   } else {
1231*795d594fSAndroid Build Coastguard Worker     return true;
1232*795d594fSAndroid Build Coastguard Worker   }
1233*795d594fSAndroid Build Coastguard Worker }
1234*795d594fSAndroid Build Coastguard Worker 
1235*795d594fSAndroid Build Coastguard Worker template <>
CheckFunctions(jvmtiEnv * env,art::ArtMethod * calling,art::ArtMethod * called)1236*795d594fSAndroid Build Coastguard Worker bool NonStandardExitFrames<NonStandardExitType::kPopFrame>::CheckFunctions(
1237*795d594fSAndroid Build Coastguard Worker     jvmtiEnv* env, art::ArtMethod* calling, art::ArtMethod* called) {
1238*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(calling->IsNative() || called->IsNative())) {
1239*795d594fSAndroid Build Coastguard Worker     result_ = ERR(OPAQUE_FRAME);
1240*795d594fSAndroid Build Coastguard Worker     JVMTI_LOG(INFO, env) << "Cannot force early return from " << called->PrettyMethod() << " to "
1241*795d594fSAndroid Build Coastguard Worker                          << calling->PrettyMethod() << " because at least one of them is native.";
1242*795d594fSAndroid Build Coastguard Worker     return false;
1243*795d594fSAndroid Build Coastguard Worker   } else {
1244*795d594fSAndroid Build Coastguard Worker     return true;
1245*795d594fSAndroid Build Coastguard Worker   }
1246*795d594fSAndroid Build Coastguard Worker }
1247*795d594fSAndroid Build Coastguard Worker 
1248*795d594fSAndroid Build Coastguard Worker class SetupMethodExitEvents {
1249*795d594fSAndroid Build Coastguard Worker  public:
SetupMethodExitEvents(art::Thread * self,EventHandler * event_handler,jthread target)1250*795d594fSAndroid Build Coastguard Worker   SetupMethodExitEvents(art::Thread* self,
1251*795d594fSAndroid Build Coastguard Worker                         EventHandler* event_handler,
1252*795d594fSAndroid Build Coastguard Worker                         jthread target) REQUIRES(!art::Locks::mutator_lock_,
1253*795d594fSAndroid Build Coastguard Worker                                                  !art::Locks::user_code_suspension_lock_,
1254*795d594fSAndroid Build Coastguard Worker                                                  !art::Locks::thread_list_lock_)
1255*795d594fSAndroid Build Coastguard Worker       : self_(self), event_handler_(event_handler), target_(target) {
1256*795d594fSAndroid Build Coastguard Worker     DCHECK(target != nullptr);
1257*795d594fSAndroid Build Coastguard Worker     art::Locks::mutator_lock_->AssertNotHeld(self_);
1258*795d594fSAndroid Build Coastguard Worker     art::Locks::user_code_suspension_lock_->AssertNotHeld(self_);
1259*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->AssertNotHeld(self_);
1260*795d594fSAndroid Build Coastguard Worker     event_handler_->SetInternalEvent(
1261*795d594fSAndroid Build Coastguard Worker         target_, ArtJvmtiEvent::kForceEarlyReturnUpdateReturnValue, JVMTI_ENABLE);
1262*795d594fSAndroid Build Coastguard Worker   }
1263*795d594fSAndroid Build Coastguard Worker 
1264*795d594fSAndroid Build Coastguard Worker   ~SetupMethodExitEvents() REQUIRES(!art::Locks::mutator_lock_,
1265*795d594fSAndroid Build Coastguard Worker                                     !art::Locks::user_code_suspension_lock_,
1266*795d594fSAndroid Build Coastguard Worker                                     !art::Locks::thread_list_lock_) {
1267*795d594fSAndroid Build Coastguard Worker     art::Locks::mutator_lock_->AssertNotHeld(self_);
1268*795d594fSAndroid Build Coastguard Worker     art::Locks::user_code_suspension_lock_->AssertNotHeld(self_);
1269*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->AssertNotHeld(self_);
1270*795d594fSAndroid Build Coastguard Worker     if (failed_) {
1271*795d594fSAndroid Build Coastguard Worker       event_handler_->SetInternalEvent(
1272*795d594fSAndroid Build Coastguard Worker           target_, ArtJvmtiEvent::kForceEarlyReturnUpdateReturnValue, JVMTI_DISABLE);
1273*795d594fSAndroid Build Coastguard Worker     }
1274*795d594fSAndroid Build Coastguard Worker   }
1275*795d594fSAndroid Build Coastguard Worker 
NotifyFailure()1276*795d594fSAndroid Build Coastguard Worker   void NotifyFailure() {
1277*795d594fSAndroid Build Coastguard Worker     failed_ = true;
1278*795d594fSAndroid Build Coastguard Worker   }
1279*795d594fSAndroid Build Coastguard Worker 
1280*795d594fSAndroid Build Coastguard Worker  private:
1281*795d594fSAndroid Build Coastguard Worker   art::Thread* self_;
1282*795d594fSAndroid Build Coastguard Worker   EventHandler* event_handler_;
1283*795d594fSAndroid Build Coastguard Worker   jthread target_;
1284*795d594fSAndroid Build Coastguard Worker   bool failed_ = false;
1285*795d594fSAndroid Build Coastguard Worker };
1286*795d594fSAndroid Build Coastguard Worker 
1287*795d594fSAndroid Build Coastguard Worker template <typename T>
1288*795d594fSAndroid Build Coastguard Worker void AddDelayedMethodExitEvent(EventHandler* handler, art::ShadowFrame* frame, T value)
1289*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(art::Locks::mutator_lock_)
1290*795d594fSAndroid Build Coastguard Worker     REQUIRES(art::Locks::user_code_suspension_lock_, art::Locks::thread_list_lock_);
1291*795d594fSAndroid Build Coastguard Worker 
1292*795d594fSAndroid Build Coastguard Worker template <typename T>
AddDelayedMethodExitEvent(EventHandler * handler,art::ShadowFrame * frame,T value)1293*795d594fSAndroid Build Coastguard Worker void AddDelayedMethodExitEvent(EventHandler* handler, art::ShadowFrame* frame, T value) {
1294*795d594fSAndroid Build Coastguard Worker   art::JValue val = art::JValue::FromPrimitive(value);
1295*795d594fSAndroid Build Coastguard Worker   jvalue jval{ .j = val.GetJ() };
1296*795d594fSAndroid Build Coastguard Worker   handler->AddDelayedNonStandardExitEvent(frame, false, jval);
1297*795d594fSAndroid Build Coastguard Worker }
1298*795d594fSAndroid Build Coastguard Worker 
1299*795d594fSAndroid Build Coastguard Worker template <>
AddDelayedMethodExitEvent(EventHandler * handler,art::ShadowFrame * frame,std::nullptr_t null_val)1300*795d594fSAndroid Build Coastguard Worker void AddDelayedMethodExitEvent<std::nullptr_t>(EventHandler* handler,
1301*795d594fSAndroid Build Coastguard Worker                                                art::ShadowFrame* frame,
1302*795d594fSAndroid Build Coastguard Worker                                                [[maybe_unused]] std::nullptr_t null_val) {
1303*795d594fSAndroid Build Coastguard Worker   jvalue jval;
1304*795d594fSAndroid Build Coastguard Worker   memset(&jval, 0, sizeof(jval));
1305*795d594fSAndroid Build Coastguard Worker   handler->AddDelayedNonStandardExitEvent(frame, false, jval);
1306*795d594fSAndroid Build Coastguard Worker }
1307*795d594fSAndroid Build Coastguard Worker 
1308*795d594fSAndroid Build Coastguard Worker template <>
AddDelayedMethodExitEvent(EventHandler * handler,art::ShadowFrame * frame,jobject obj)1309*795d594fSAndroid Build Coastguard Worker void AddDelayedMethodExitEvent<jobject>(EventHandler* handler,
1310*795d594fSAndroid Build Coastguard Worker                                         art::ShadowFrame* frame,
1311*795d594fSAndroid Build Coastguard Worker                                         jobject obj) {
1312*795d594fSAndroid Build Coastguard Worker   jvalue jval{ .l = art::Thread::Current()->GetJniEnv()->NewGlobalRef(obj) };
1313*795d594fSAndroid Build Coastguard Worker   handler->AddDelayedNonStandardExitEvent(frame, true, jval);
1314*795d594fSAndroid Build Coastguard Worker }
1315*795d594fSAndroid Build Coastguard Worker 
1316*795d594fSAndroid Build Coastguard Worker template <typename T>
1317*795d594fSAndroid Build Coastguard Worker bool ValidReturnType(art::Thread* self, art::ObjPtr<art::mirror::Class> return_type, T value)
1318*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(art::Locks::mutator_lock_)
1319*795d594fSAndroid Build Coastguard Worker         REQUIRES(art::Locks::user_code_suspension_lock_, art::Locks::thread_list_lock_);
1320*795d594fSAndroid Build Coastguard Worker 
1321*795d594fSAndroid Build Coastguard Worker #define SIMPLE_VALID_RETURN_TYPE(type, ...)                                                       \
1322*795d594fSAndroid Build Coastguard Worker   template <>                                                                                     \
1323*795d594fSAndroid Build Coastguard Worker   bool ValidReturnType<type>([[maybe_unused]] art::Thread * self,                                 \
1324*795d594fSAndroid Build Coastguard Worker                              art::ObjPtr<art::mirror::Class> return_type,                         \
1325*795d594fSAndroid Build Coastguard Worker                              [[maybe_unused]] type value) {                                       \
1326*795d594fSAndroid Build Coastguard Worker     static constexpr std::initializer_list<art::Primitive::Type> types{__VA_ARGS__};              \
1327*795d594fSAndroid Build Coastguard Worker     return std::find(types.begin(), types.end(), return_type->GetPrimitiveType()) != types.end(); \
1328*795d594fSAndroid Build Coastguard Worker   }
1329*795d594fSAndroid Build Coastguard Worker 
1330*795d594fSAndroid Build Coastguard Worker SIMPLE_VALID_RETURN_TYPE(jlong, art::Primitive::kPrimLong);
1331*795d594fSAndroid Build Coastguard Worker SIMPLE_VALID_RETURN_TYPE(jfloat, art::Primitive::kPrimFloat);
1332*795d594fSAndroid Build Coastguard Worker SIMPLE_VALID_RETURN_TYPE(jdouble, art::Primitive::kPrimDouble);
1333*795d594fSAndroid Build Coastguard Worker SIMPLE_VALID_RETURN_TYPE(nullptr_t, art::Primitive::kPrimVoid);
1334*795d594fSAndroid Build Coastguard Worker SIMPLE_VALID_RETURN_TYPE(jint,
1335*795d594fSAndroid Build Coastguard Worker                          art::Primitive::kPrimInt,
1336*795d594fSAndroid Build Coastguard Worker                          art::Primitive::kPrimChar,
1337*795d594fSAndroid Build Coastguard Worker                          art::Primitive::kPrimBoolean,
1338*795d594fSAndroid Build Coastguard Worker                          art::Primitive::kPrimShort,
1339*795d594fSAndroid Build Coastguard Worker                          art::Primitive::kPrimByte);
1340*795d594fSAndroid Build Coastguard Worker #undef SIMPLE_VALID_RETURN_TYPE
1341*795d594fSAndroid Build Coastguard Worker 
1342*795d594fSAndroid Build Coastguard Worker template <>
ValidReturnType(art::Thread * self,art::ObjPtr<art::mirror::Class> return_type,jobject return_value)1343*795d594fSAndroid Build Coastguard Worker bool ValidReturnType<jobject>(art::Thread* self,
1344*795d594fSAndroid Build Coastguard Worker                               art::ObjPtr<art::mirror::Class> return_type,
1345*795d594fSAndroid Build Coastguard Worker                               jobject return_value) {
1346*795d594fSAndroid Build Coastguard Worker   if (return_type->IsPrimitive()) {
1347*795d594fSAndroid Build Coastguard Worker     return false;
1348*795d594fSAndroid Build Coastguard Worker   }
1349*795d594fSAndroid Build Coastguard Worker   if (return_value == nullptr) {
1350*795d594fSAndroid Build Coastguard Worker     // Null can be used for anything.
1351*795d594fSAndroid Build Coastguard Worker     return true;
1352*795d594fSAndroid Build Coastguard Worker   }
1353*795d594fSAndroid Build Coastguard Worker   return return_type->IsAssignableFrom(self->DecodeJObject(return_value)->GetClass());
1354*795d594fSAndroid Build Coastguard Worker }
1355*795d594fSAndroid Build Coastguard Worker 
1356*795d594fSAndroid Build Coastguard Worker }  // namespace
1357*795d594fSAndroid Build Coastguard Worker 
PopFrame(jvmtiEnv * env,jthread thread)1358*795d594fSAndroid Build Coastguard Worker jvmtiError StackUtil::PopFrame(jvmtiEnv* env, jthread thread) {
1359*795d594fSAndroid Build Coastguard Worker   art::Thread* self = art::Thread::Current();
1360*795d594fSAndroid Build Coastguard Worker   NonStandardExitFrames<NonStandardExitType::kPopFrame> frames(self, env, thread);
1361*795d594fSAndroid Build Coastguard Worker   if (frames.result_ != OK) {
1362*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(self);
1363*795d594fSAndroid Build Coastguard Worker     return frames.result_;
1364*795d594fSAndroid Build Coastguard Worker   }
1365*795d594fSAndroid Build Coastguard Worker   // Tell the shadow-frame to return immediately and skip all exit events.
1366*795d594fSAndroid Build Coastguard Worker   frames.penultimate_frame_->SetForceRetryInstruction(true);
1367*795d594fSAndroid Build Coastguard Worker   frames.final_frame_->SetForcePopFrame(true);
1368*795d594fSAndroid Build Coastguard Worker   frames.final_frame_->SetSkipMethodExitEvents(true);
1369*795d594fSAndroid Build Coastguard Worker   if (frames.created_final_frame_ || frames.created_penultimate_frame_) {
1370*795d594fSAndroid Build Coastguard Worker     art::FunctionClosure fc([](art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_){
1371*795d594fSAndroid Build Coastguard Worker       DeoptManager::Get()->DeoptimizeThread(self);
1372*795d594fSAndroid Build Coastguard Worker     });
1373*795d594fSAndroid Build Coastguard Worker     frames.target_->RequestSynchronousCheckpoint(&fc);
1374*795d594fSAndroid Build Coastguard Worker   } else {
1375*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(self);
1376*795d594fSAndroid Build Coastguard Worker   }
1377*795d594fSAndroid Build Coastguard Worker   return OK;
1378*795d594fSAndroid Build Coastguard Worker }
1379*795d594fSAndroid Build Coastguard Worker 
1380*795d594fSAndroid Build Coastguard Worker template <typename T>
1381*795d594fSAndroid Build Coastguard Worker jvmtiError
ForceEarlyReturn(jvmtiEnv * env,EventHandler * event_handler,jthread thread,T value)1382*795d594fSAndroid Build Coastguard Worker StackUtil::ForceEarlyReturn(jvmtiEnv* env, EventHandler* event_handler, jthread thread, T value) {
1383*795d594fSAndroid Build Coastguard Worker   art::Thread* self = art::Thread::Current();
1384*795d594fSAndroid Build Coastguard Worker   // We don't want to use the null == current-thread idiom since for events (that we use internally
1385*795d594fSAndroid Build Coastguard Worker   // to implement force-early-return) we instead have null == all threads. Instead just get the
1386*795d594fSAndroid Build Coastguard Worker   // current jthread if needed.
1387*795d594fSAndroid Build Coastguard Worker   ScopedLocalRef<jthread> cur_thread(self->GetJniEnv(), nullptr);
1388*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(thread == nullptr)) {
1389*795d594fSAndroid Build Coastguard Worker     art::ScopedObjectAccess soa(self);
1390*795d594fSAndroid Build Coastguard Worker     cur_thread.reset(soa.AddLocalReference<jthread>(self->GetPeer()));
1391*795d594fSAndroid Build Coastguard Worker     thread = cur_thread.get();
1392*795d594fSAndroid Build Coastguard Worker   }
1393*795d594fSAndroid Build Coastguard Worker   // This sets up the exit events we implement early return using before we have the locks and
1394*795d594fSAndroid Build Coastguard Worker   // thanks to destructor ordering will tear them down if something goes wrong.
1395*795d594fSAndroid Build Coastguard Worker   SetupMethodExitEvents smee(self, event_handler, thread);
1396*795d594fSAndroid Build Coastguard Worker   NonStandardExitFrames<NonStandardExitType::kForceReturn> frames(self, env, thread);
1397*795d594fSAndroid Build Coastguard Worker   if (frames.result_ != OK) {
1398*795d594fSAndroid Build Coastguard Worker     smee.NotifyFailure();
1399*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(self);
1400*795d594fSAndroid Build Coastguard Worker     return frames.result_;
1401*795d594fSAndroid Build Coastguard Worker   } else if (!ValidReturnType<T>(
1402*795d594fSAndroid Build Coastguard Worker                  self, frames.final_frame_->GetMethod()->ResolveReturnType(), value)) {
1403*795d594fSAndroid Build Coastguard Worker     smee.NotifyFailure();
1404*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(self);
1405*795d594fSAndroid Build Coastguard Worker     return ERR(TYPE_MISMATCH);
1406*795d594fSAndroid Build Coastguard Worker   } else if (frames.final_frame_->GetForcePopFrame()) {
1407*795d594fSAndroid Build Coastguard Worker     // TODO We should really support this.
1408*795d594fSAndroid Build Coastguard Worker     smee.NotifyFailure();
1409*795d594fSAndroid Build Coastguard Worker     std::string thread_name;
1410*795d594fSAndroid Build Coastguard Worker     frames.target_->GetThreadName(thread_name);
1411*795d594fSAndroid Build Coastguard Worker     JVMTI_LOG(WARNING, env) << "PopFrame or force-return already pending on thread " << thread_name;
1412*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(self);
1413*795d594fSAndroid Build Coastguard Worker     return ERR(OPAQUE_FRAME);
1414*795d594fSAndroid Build Coastguard Worker   }
1415*795d594fSAndroid Build Coastguard Worker   // Tell the shadow-frame to return immediately and skip all exit events.
1416*795d594fSAndroid Build Coastguard Worker   frames.final_frame_->SetForcePopFrame(true);
1417*795d594fSAndroid Build Coastguard Worker   AddDelayedMethodExitEvent<T>(event_handler, frames.final_frame_, value);
1418*795d594fSAndroid Build Coastguard Worker   if (frames.created_final_frame_ || frames.created_penultimate_frame_) {
1419*795d594fSAndroid Build Coastguard Worker     art::FunctionClosure fc([](art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_){
1420*795d594fSAndroid Build Coastguard Worker       DeoptManager::Get()->DeoptimizeThread(self);
1421*795d594fSAndroid Build Coastguard Worker     });
1422*795d594fSAndroid Build Coastguard Worker     frames.target_->RequestSynchronousCheckpoint(&fc);
1423*795d594fSAndroid Build Coastguard Worker   } else {
1424*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(self);
1425*795d594fSAndroid Build Coastguard Worker   }
1426*795d594fSAndroid Build Coastguard Worker   return OK;
1427*795d594fSAndroid Build Coastguard Worker }
1428*795d594fSAndroid Build Coastguard Worker 
1429*795d594fSAndroid Build Coastguard Worker // Instantiate the ForceEarlyReturn templates.
1430*795d594fSAndroid Build Coastguard Worker template jvmtiError StackUtil::ForceEarlyReturn(jvmtiEnv*, EventHandler*, jthread, jint);
1431*795d594fSAndroid Build Coastguard Worker template jvmtiError StackUtil::ForceEarlyReturn(jvmtiEnv*, EventHandler*, jthread, jlong);
1432*795d594fSAndroid Build Coastguard Worker template jvmtiError StackUtil::ForceEarlyReturn(jvmtiEnv*, EventHandler*, jthread, jfloat);
1433*795d594fSAndroid Build Coastguard Worker template jvmtiError StackUtil::ForceEarlyReturn(jvmtiEnv*, EventHandler*, jthread, jdouble);
1434*795d594fSAndroid Build Coastguard Worker template jvmtiError StackUtil::ForceEarlyReturn(jvmtiEnv*, EventHandler*, jthread, jobject);
1435*795d594fSAndroid Build Coastguard Worker template jvmtiError StackUtil::ForceEarlyReturn(jvmtiEnv*, EventHandler*, jthread, nullptr_t);
1436*795d594fSAndroid Build Coastguard Worker 
1437*795d594fSAndroid Build Coastguard Worker }  // namespace openjdkjvmti
1438