xref: /aosp_15_r20/art/runtime/debugger.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2008 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "debugger.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <sys/uio.h>
20*795d594fSAndroid Build Coastguard Worker 
21*795d594fSAndroid Build Coastguard Worker #include <functional>
22*795d594fSAndroid Build Coastguard Worker #include <memory>
23*795d594fSAndroid Build Coastguard Worker #include <set>
24*795d594fSAndroid Build Coastguard Worker #include <vector>
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker #include "android-base/macros.h"
27*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker #include "arch/context.h"
30*795d594fSAndroid Build Coastguard Worker #include "art_field-inl.h"
31*795d594fSAndroid Build Coastguard Worker #include "art_method-inl.h"
32*795d594fSAndroid Build Coastguard Worker #include "base/endian_utils.h"
33*795d594fSAndroid Build Coastguard Worker #include "base/logging.h"
34*795d594fSAndroid Build Coastguard Worker #include "base/memory_tool.h"
35*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
36*795d594fSAndroid Build Coastguard Worker #include "base/safe_map.h"
37*795d594fSAndroid Build Coastguard Worker #include "base/strlcpy.h"
38*795d594fSAndroid Build Coastguard Worker #include "base/time_utils.h"
39*795d594fSAndroid Build Coastguard Worker #include "class_linker-inl.h"
40*795d594fSAndroid Build Coastguard Worker #include "class_linker.h"
41*795d594fSAndroid Build Coastguard Worker #include "dex/descriptors_names.h"
42*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file-inl.h"
43*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_annotations.h"
44*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_types.h"
45*795d594fSAndroid Build Coastguard Worker #include "dex/dex_instruction.h"
46*795d594fSAndroid Build Coastguard Worker #include "dex/utf.h"
47*795d594fSAndroid Build Coastguard Worker #include "entrypoints/runtime_asm_entrypoints.h"
48*795d594fSAndroid Build Coastguard Worker #include "gc/accounting/card_table-inl.h"
49*795d594fSAndroid Build Coastguard Worker #include "gc/allocation_record.h"
50*795d594fSAndroid Build Coastguard Worker #include "gc/gc_cause.h"
51*795d594fSAndroid Build Coastguard Worker #include "gc/scoped_gc_critical_section.h"
52*795d594fSAndroid Build Coastguard Worker #include "gc/space/bump_pointer_space-walk-inl.h"
53*795d594fSAndroid Build Coastguard Worker #include "gc/space/large_object_space.h"
54*795d594fSAndroid Build Coastguard Worker #include "gc/space/space-inl.h"
55*795d594fSAndroid Build Coastguard Worker #include "handle_scope-inl.h"
56*795d594fSAndroid Build Coastguard Worker #include "instrumentation.h"
57*795d594fSAndroid Build Coastguard Worker #include "jni/jni_internal.h"
58*795d594fSAndroid Build Coastguard Worker #include "jvalue-inl.h"
59*795d594fSAndroid Build Coastguard Worker #include "mirror/array-alloc-inl.h"
60*795d594fSAndroid Build Coastguard Worker #include "mirror/class-alloc-inl.h"
61*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
62*795d594fSAndroid Build Coastguard Worker #include "mirror/class.h"
63*795d594fSAndroid Build Coastguard Worker #include "mirror/class_loader.h"
64*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
65*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-inl.h"
66*795d594fSAndroid Build Coastguard Worker #include "mirror/string-alloc-inl.h"
67*795d594fSAndroid Build Coastguard Worker #include "mirror/string-inl.h"
68*795d594fSAndroid Build Coastguard Worker #include "mirror/throwable.h"
69*795d594fSAndroid Build Coastguard Worker #include "nativehelper/scoped_local_ref.h"
70*795d594fSAndroid Build Coastguard Worker #include "nativehelper/scoped_primitive_array.h"
71*795d594fSAndroid Build Coastguard Worker #include "oat/oat_file.h"
72*795d594fSAndroid Build Coastguard Worker #include "obj_ptr-inl.h"
73*795d594fSAndroid Build Coastguard Worker #include "reflection.h"
74*795d594fSAndroid Build Coastguard Worker #include "reflective_handle.h"
75*795d594fSAndroid Build Coastguard Worker #include "reflective_handle_scope-inl.h"
76*795d594fSAndroid Build Coastguard Worker #include "runtime-inl.h"
77*795d594fSAndroid Build Coastguard Worker #include "runtime_callbacks.h"
78*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
79*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change.h"
80*795d594fSAndroid Build Coastguard Worker #include "stack.h"
81*795d594fSAndroid Build Coastguard Worker #include "thread.h"
82*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
83*795d594fSAndroid Build Coastguard Worker #include "thread_pool.h"
84*795d594fSAndroid Build Coastguard Worker #include "well_known_classes.h"
85*795d594fSAndroid Build Coastguard Worker 
86*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
87*795d594fSAndroid Build Coastguard Worker 
88*795d594fSAndroid Build Coastguard Worker using android::base::StringPrintf;
89*795d594fSAndroid Build Coastguard Worker 
90*795d594fSAndroid Build Coastguard Worker // Limit alloc_record_count to the 2BE value (64k-1) that is the limit of the current protocol.
CappedAllocRecordCount(size_t alloc_record_count)91*795d594fSAndroid Build Coastguard Worker static uint16_t CappedAllocRecordCount(size_t alloc_record_count) {
92*795d594fSAndroid Build Coastguard Worker   const size_t cap = 0xffff;
93*795d594fSAndroid Build Coastguard Worker   if (alloc_record_count > cap) {
94*795d594fSAndroid Build Coastguard Worker     return cap;
95*795d594fSAndroid Build Coastguard Worker   }
96*795d594fSAndroid Build Coastguard Worker   return alloc_record_count;
97*795d594fSAndroid Build Coastguard Worker }
98*795d594fSAndroid Build Coastguard Worker 
99*795d594fSAndroid Build Coastguard Worker // JDWP is allowed unless the Zygote forbids it.
100*795d594fSAndroid Build Coastguard Worker static bool gJdwpAllowed = true;
101*795d594fSAndroid Build Coastguard Worker 
102*795d594fSAndroid Build Coastguard Worker static bool gDdmThreadNotification = false;
103*795d594fSAndroid Build Coastguard Worker 
104*795d594fSAndroid Build Coastguard Worker // DDMS GC-related settings.
105*795d594fSAndroid Build Coastguard Worker static Dbg::HpifWhen gDdmHpifWhen = Dbg::HPIF_WHEN_NEVER;
106*795d594fSAndroid Build Coastguard Worker static Dbg::HpsgWhen gDdmHpsgWhen = Dbg::HPSG_WHEN_NEVER;
107*795d594fSAndroid Build Coastguard Worker static Dbg::HpsgWhat gDdmHpsgWhat;
108*795d594fSAndroid Build Coastguard Worker static Dbg::HpsgWhen gDdmNhsgWhen = Dbg::HPSG_WHEN_NEVER;
109*795d594fSAndroid Build Coastguard Worker static Dbg::HpsgWhat gDdmNhsgWhat;
110*795d594fSAndroid Build Coastguard Worker 
111*795d594fSAndroid Build Coastguard Worker Dbg::DbgThreadLifecycleCallback Dbg::thread_lifecycle_callback_;
112*795d594fSAndroid Build Coastguard Worker 
GcDidFinish()113*795d594fSAndroid Build Coastguard Worker void Dbg::GcDidFinish() {
114*795d594fSAndroid Build Coastguard Worker   if (gDdmHpifWhen != HPIF_WHEN_NEVER) {
115*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(Thread::Current());
116*795d594fSAndroid Build Coastguard Worker     VLOG(jdwp) << "Sending heap info to DDM";
117*795d594fSAndroid Build Coastguard Worker     DdmSendHeapInfo(gDdmHpifWhen);
118*795d594fSAndroid Build Coastguard Worker   }
119*795d594fSAndroid Build Coastguard Worker   if (gDdmHpsgWhen != HPSG_WHEN_NEVER) {
120*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(Thread::Current());
121*795d594fSAndroid Build Coastguard Worker     VLOG(jdwp) << "Dumping heap to DDM";
122*795d594fSAndroid Build Coastguard Worker     DdmSendHeapSegments(false);
123*795d594fSAndroid Build Coastguard Worker   }
124*795d594fSAndroid Build Coastguard Worker   if (gDdmNhsgWhen != HPSG_WHEN_NEVER) {
125*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(Thread::Current());
126*795d594fSAndroid Build Coastguard Worker     VLOG(jdwp) << "Dumping native heap to DDM";
127*795d594fSAndroid Build Coastguard Worker     DdmSendHeapSegments(true);
128*795d594fSAndroid Build Coastguard Worker   }
129*795d594fSAndroid Build Coastguard Worker }
130*795d594fSAndroid Build Coastguard Worker 
SetJdwpAllowed(bool allowed)131*795d594fSAndroid Build Coastguard Worker void Dbg::SetJdwpAllowed(bool allowed) {
132*795d594fSAndroid Build Coastguard Worker   gJdwpAllowed = allowed;
133*795d594fSAndroid Build Coastguard Worker }
134*795d594fSAndroid Build Coastguard Worker 
IsJdwpAllowed()135*795d594fSAndroid Build Coastguard Worker bool Dbg::IsJdwpAllowed() {
136*795d594fSAndroid Build Coastguard Worker   return gJdwpAllowed;
137*795d594fSAndroid Build Coastguard Worker }
138*795d594fSAndroid Build Coastguard Worker 
139*795d594fSAndroid Build Coastguard Worker // Do we need to deoptimize the stack to handle an exception?
IsForcedInterpreterNeededForExceptionImpl(Thread * thread)140*795d594fSAndroid Build Coastguard Worker bool Dbg::IsForcedInterpreterNeededForExceptionImpl(Thread* thread) {
141*795d594fSAndroid Build Coastguard Worker   // Deoptimization is required if at least one method in the stack needs it. However we
142*795d594fSAndroid Build Coastguard Worker   // skip frames that will be unwound (thus not executed).
143*795d594fSAndroid Build Coastguard Worker   bool needs_deoptimization = false;
144*795d594fSAndroid Build Coastguard Worker   StackVisitor::WalkStack(
145*795d594fSAndroid Build Coastguard Worker       [&](art::StackVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
146*795d594fSAndroid Build Coastguard Worker         // The visitor is meant to be used when handling exception from compiled code only.
147*795d594fSAndroid Build Coastguard Worker         CHECK(!visitor->IsShadowFrame()) << "We only expect to visit compiled frame: "
148*795d594fSAndroid Build Coastguard Worker                                          << ArtMethod::PrettyMethod(visitor->GetMethod());
149*795d594fSAndroid Build Coastguard Worker         ArtMethod* method = visitor->GetMethod();
150*795d594fSAndroid Build Coastguard Worker         if (method == nullptr) {
151*795d594fSAndroid Build Coastguard Worker           // We reach an upcall and don't need to deoptimize this part of the stack (ManagedFragment)
152*795d594fSAndroid Build Coastguard Worker           // so we can stop the visit.
153*795d594fSAndroid Build Coastguard Worker           DCHECK(!needs_deoptimization);
154*795d594fSAndroid Build Coastguard Worker           return false;
155*795d594fSAndroid Build Coastguard Worker         }
156*795d594fSAndroid Build Coastguard Worker         if (Runtime::Current()->GetInstrumentation()->InterpretOnly()) {
157*795d594fSAndroid Build Coastguard Worker           // We found a compiled frame in the stack but instrumentation is set to interpret
158*795d594fSAndroid Build Coastguard Worker           // everything: we need to deoptimize.
159*795d594fSAndroid Build Coastguard Worker           needs_deoptimization = true;
160*795d594fSAndroid Build Coastguard Worker           return false;
161*795d594fSAndroid Build Coastguard Worker         }
162*795d594fSAndroid Build Coastguard Worker         if (Runtime::Current()->GetInstrumentation()->IsDeoptimized(method)) {
163*795d594fSAndroid Build Coastguard Worker           // We found a deoptimized method in the stack.
164*795d594fSAndroid Build Coastguard Worker           needs_deoptimization = true;
165*795d594fSAndroid Build Coastguard Worker           return false;
166*795d594fSAndroid Build Coastguard Worker         }
167*795d594fSAndroid Build Coastguard Worker         ShadowFrame* frame = visitor->GetThread()->FindDebuggerShadowFrame(visitor->GetFrameId());
168*795d594fSAndroid Build Coastguard Worker         if (frame != nullptr) {
169*795d594fSAndroid Build Coastguard Worker           // The debugger allocated a ShadowFrame to update a variable in the stack: we need to
170*795d594fSAndroid Build Coastguard Worker           // deoptimize the stack to execute (and deallocate) this frame.
171*795d594fSAndroid Build Coastguard Worker           needs_deoptimization = true;
172*795d594fSAndroid Build Coastguard Worker           return false;
173*795d594fSAndroid Build Coastguard Worker         }
174*795d594fSAndroid Build Coastguard Worker         return true;
175*795d594fSAndroid Build Coastguard Worker       },
176*795d594fSAndroid Build Coastguard Worker       thread,
177*795d594fSAndroid Build Coastguard Worker       /* context= */ nullptr,
178*795d594fSAndroid Build Coastguard Worker       art::StackVisitor::StackWalkKind::kIncludeInlinedFrames,
179*795d594fSAndroid Build Coastguard Worker       /* check_suspended */ true,
180*795d594fSAndroid Build Coastguard Worker       /* include_transitions */ true);
181*795d594fSAndroid Build Coastguard Worker   return needs_deoptimization;
182*795d594fSAndroid Build Coastguard Worker }
183*795d594fSAndroid Build Coastguard Worker 
184*795d594fSAndroid Build Coastguard Worker 
DdmHandleChunk(JNIEnv * env,uint32_t type,const ArrayRef<const jbyte> & data,uint32_t * out_type,std::vector<uint8_t> * out_data)185*795d594fSAndroid Build Coastguard Worker bool Dbg::DdmHandleChunk(JNIEnv* env,
186*795d594fSAndroid Build Coastguard Worker                          uint32_t type,
187*795d594fSAndroid Build Coastguard Worker                          const ArrayRef<const jbyte>& data,
188*795d594fSAndroid Build Coastguard Worker                          /*out*/uint32_t* out_type,
189*795d594fSAndroid Build Coastguard Worker                          /*out*/std::vector<uint8_t>* out_data) {
190*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(env);
191*795d594fSAndroid Build Coastguard Worker   StackHandleScope<1u> hs(soa.Self());
192*795d594fSAndroid Build Coastguard Worker   Handle<mirror::ByteArray> data_array =
193*795d594fSAndroid Build Coastguard Worker       hs.NewHandle(mirror::ByteArray::Alloc(soa.Self(), data.size()));
194*795d594fSAndroid Build Coastguard Worker   if (data_array == nullptr) {
195*795d594fSAndroid Build Coastguard Worker     LOG(WARNING) << "byte[] allocation failed: " << data.size();
196*795d594fSAndroid Build Coastguard Worker     env->ExceptionClear();
197*795d594fSAndroid Build Coastguard Worker     return false;
198*795d594fSAndroid Build Coastguard Worker   }
199*795d594fSAndroid Build Coastguard Worker   memcpy(data_array->GetData(), data.data(), data.size());
200*795d594fSAndroid Build Coastguard Worker   // Call "private static Chunk dispatch(int type, byte[] data, int offset, int length)".
201*795d594fSAndroid Build Coastguard Worker   ArtMethod* dispatch = WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_dispatch;
202*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Object> chunk = dispatch->InvokeStatic<'L', 'I', 'L', 'I', 'I'>(
203*795d594fSAndroid Build Coastguard Worker       soa.Self(), type, data_array.Get(), 0, static_cast<jint>(data.size()));
204*795d594fSAndroid Build Coastguard Worker   if (soa.Self()->IsExceptionPending()) {
205*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << StringPrintf("Exception thrown by dispatcher for 0x%08x", type) << std::endl
206*795d594fSAndroid Build Coastguard Worker               << soa.Self()->GetException()->Dump();
207*795d594fSAndroid Build Coastguard Worker     soa.Self()->ClearException();
208*795d594fSAndroid Build Coastguard Worker     return false;
209*795d594fSAndroid Build Coastguard Worker   }
210*795d594fSAndroid Build Coastguard Worker 
211*795d594fSAndroid Build Coastguard Worker   if (chunk == nullptr) {
212*795d594fSAndroid Build Coastguard Worker     return false;
213*795d594fSAndroid Build Coastguard Worker   }
214*795d594fSAndroid Build Coastguard Worker 
215*795d594fSAndroid Build Coastguard Worker   /*
216*795d594fSAndroid Build Coastguard Worker    * Pull the pieces out of the chunk.  We copy the results into a
217*795d594fSAndroid Build Coastguard Worker    * newly-allocated buffer that the caller can free.  We don't want to
218*795d594fSAndroid Build Coastguard Worker    * continue using the Chunk object because nothing has a reference to it.
219*795d594fSAndroid Build Coastguard Worker    *
220*795d594fSAndroid Build Coastguard Worker    * We could avoid this by returning type/data/offset/length and having
221*795d594fSAndroid Build Coastguard Worker    * the caller be aware of the object lifetime issues, but that
222*795d594fSAndroid Build Coastguard Worker    * integrates the JDWP code more tightly into the rest of the runtime, and doesn't work
223*795d594fSAndroid Build Coastguard Worker    * if we have responses for multiple chunks.
224*795d594fSAndroid Build Coastguard Worker    *
225*795d594fSAndroid Build Coastguard Worker    * So we're pretty much stuck with copying data around multiple times.
226*795d594fSAndroid Build Coastguard Worker    */
227*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::ByteArray> reply_data = ObjPtr<mirror::ByteArray>::DownCast(
228*795d594fSAndroid Build Coastguard Worker       WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_data->GetObject(chunk));
229*795d594fSAndroid Build Coastguard Worker   jint offset = WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_offset->GetInt(chunk);
230*795d594fSAndroid Build Coastguard Worker   jint length = WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_length->GetInt(chunk);
231*795d594fSAndroid Build Coastguard Worker   *out_type = WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_type->GetInt(chunk);
232*795d594fSAndroid Build Coastguard Worker 
233*795d594fSAndroid Build Coastguard Worker   VLOG(jdwp) << StringPrintf("DDM reply: type=0x%08x data=%p offset=%d length=%d",
234*795d594fSAndroid Build Coastguard Worker                              type,
235*795d594fSAndroid Build Coastguard Worker                              reply_data.Ptr(),
236*795d594fSAndroid Build Coastguard Worker                              offset,
237*795d594fSAndroid Build Coastguard Worker                              length);
238*795d594fSAndroid Build Coastguard Worker 
239*795d594fSAndroid Build Coastguard Worker   if (reply_data == nullptr) {
240*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << "Null reply data";
241*795d594fSAndroid Build Coastguard Worker     return false;
242*795d594fSAndroid Build Coastguard Worker   }
243*795d594fSAndroid Build Coastguard Worker 
244*795d594fSAndroid Build Coastguard Worker   jint reply_length = reply_data->GetLength();
245*795d594fSAndroid Build Coastguard Worker   if (offset < 0 || offset > reply_length || length < 0 || length > reply_length - offset) {
246*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << "Invalid reply data range: offset=" << offset << ", length=" << length
247*795d594fSAndroid Build Coastguard Worker               << " reply_length=" << reply_length;
248*795d594fSAndroid Build Coastguard Worker     return false;
249*795d594fSAndroid Build Coastguard Worker   }
250*795d594fSAndroid Build Coastguard Worker 
251*795d594fSAndroid Build Coastguard Worker   out_data->resize(length);
252*795d594fSAndroid Build Coastguard Worker   memcpy(out_data->data(), reply_data->GetData() + offset, length);
253*795d594fSAndroid Build Coastguard Worker 
254*795d594fSAndroid Build Coastguard Worker   return true;
255*795d594fSAndroid Build Coastguard Worker }
256*795d594fSAndroid Build Coastguard Worker 
DdmBroadcast(bool connect)257*795d594fSAndroid Build Coastguard Worker void Dbg::DdmBroadcast(bool connect) {
258*795d594fSAndroid Build Coastguard Worker   VLOG(jdwp) << "Broadcasting DDM " << (connect ? "connect" : "disconnect") << "...";
259*795d594fSAndroid Build Coastguard Worker 
260*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
261*795d594fSAndroid Build Coastguard Worker   if (self->GetState() != ThreadState::kRunnable) {
262*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "DDM broadcast in thread state " << self->GetState();
263*795d594fSAndroid Build Coastguard Worker     /* try anyway? */
264*795d594fSAndroid Build Coastguard Worker   }
265*795d594fSAndroid Build Coastguard Worker 
266*795d594fSAndroid Build Coastguard Worker   // TODO: Can we really get here while not `Runnable`? If not, we do not need the `soa`.
267*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccessUnchecked soa(self);
268*795d594fSAndroid Build Coastguard Worker   JNIEnv* env = self->GetJniEnv();
269*795d594fSAndroid Build Coastguard Worker   jint event = connect ? 1 /*DdmServer.CONNECTED*/ : 2 /*DdmServer.DISCONNECTED*/;
270*795d594fSAndroid Build Coastguard Worker   ArtMethod* broadcast = WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_broadcast;
271*795d594fSAndroid Build Coastguard Worker   broadcast->InvokeStatic<'V', 'I'>(self, event);
272*795d594fSAndroid Build Coastguard Worker   if (self->IsExceptionPending()) {
273*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "DdmServer.broadcast " << event << " failed";
274*795d594fSAndroid Build Coastguard Worker     env->ExceptionDescribe();
275*795d594fSAndroid Build Coastguard Worker     env->ExceptionClear();
276*795d594fSAndroid Build Coastguard Worker   }
277*795d594fSAndroid Build Coastguard Worker }
278*795d594fSAndroid Build Coastguard Worker 
DdmConnected()279*795d594fSAndroid Build Coastguard Worker void Dbg::DdmConnected() {
280*795d594fSAndroid Build Coastguard Worker   Dbg::DdmBroadcast(true);
281*795d594fSAndroid Build Coastguard Worker }
282*795d594fSAndroid Build Coastguard Worker 
DdmDisconnected()283*795d594fSAndroid Build Coastguard Worker void Dbg::DdmDisconnected() {
284*795d594fSAndroid Build Coastguard Worker   Dbg::DdmBroadcast(false);
285*795d594fSAndroid Build Coastguard Worker   gDdmThreadNotification = false;
286*795d594fSAndroid Build Coastguard Worker }
287*795d594fSAndroid Build Coastguard Worker 
288*795d594fSAndroid Build Coastguard Worker 
289*795d594fSAndroid Build Coastguard Worker /*
290*795d594fSAndroid Build Coastguard Worker  * Send a notification when a thread starts, stops, or changes its name.
291*795d594fSAndroid Build Coastguard Worker  *
292*795d594fSAndroid Build Coastguard Worker  * Because we broadcast the full set of threads when the notifications are
293*795d594fSAndroid Build Coastguard Worker  * first enabled, it's possible for "thread" to be actively executing.
294*795d594fSAndroid Build Coastguard Worker  */
DdmSendThreadNotification(Thread * t,uint32_t type)295*795d594fSAndroid Build Coastguard Worker void Dbg::DdmSendThreadNotification(Thread* t, uint32_t type) {
296*795d594fSAndroid Build Coastguard Worker   Locks::mutator_lock_->AssertNotExclusiveHeld(Thread::Current());
297*795d594fSAndroid Build Coastguard Worker   if (!gDdmThreadNotification) {
298*795d594fSAndroid Build Coastguard Worker     return;
299*795d594fSAndroid Build Coastguard Worker   }
300*795d594fSAndroid Build Coastguard Worker 
301*795d594fSAndroid Build Coastguard Worker   RuntimeCallbacks* cb = Runtime::Current()->GetRuntimeCallbacks();
302*795d594fSAndroid Build Coastguard Worker   if (type == CHUNK_TYPE("THDE")) {
303*795d594fSAndroid Build Coastguard Worker     uint8_t buf[4];
304*795d594fSAndroid Build Coastguard Worker     Set4BE(&buf[0], t->GetThreadId());
305*795d594fSAndroid Build Coastguard Worker     cb->DdmPublishChunk(CHUNK_TYPE("THDE"), ArrayRef<const uint8_t>(buf));
306*795d594fSAndroid Build Coastguard Worker   } else {
307*795d594fSAndroid Build Coastguard Worker     CHECK(type == CHUNK_TYPE("THCR") || type == CHUNK_TYPE("THNM")) << type;
308*795d594fSAndroid Build Coastguard Worker     StackHandleScope<1> hs(Thread::Current());
309*795d594fSAndroid Build Coastguard Worker     Handle<mirror::String> name(hs.NewHandle(t->GetThreadName()));
310*795d594fSAndroid Build Coastguard Worker     size_t char_count = (name != nullptr) ? name->GetLength() : 0;
311*795d594fSAndroid Build Coastguard Worker     const jchar* chars = (name != nullptr) ? name->GetValue() : nullptr;
312*795d594fSAndroid Build Coastguard Worker     bool is_compressed = (name != nullptr) ? name->IsCompressed() : false;
313*795d594fSAndroid Build Coastguard Worker 
314*795d594fSAndroid Build Coastguard Worker     std::vector<uint8_t> bytes;
315*795d594fSAndroid Build Coastguard Worker     Append4BE(bytes, t->GetThreadId());
316*795d594fSAndroid Build Coastguard Worker     if (is_compressed) {
317*795d594fSAndroid Build Coastguard Worker       const uint8_t* chars_compressed = name->GetValueCompressed();
318*795d594fSAndroid Build Coastguard Worker       AppendUtf16CompressedBE(bytes, chars_compressed, char_count);
319*795d594fSAndroid Build Coastguard Worker     } else {
320*795d594fSAndroid Build Coastguard Worker       AppendUtf16BE(bytes, chars, char_count);
321*795d594fSAndroid Build Coastguard Worker     }
322*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(bytes.size(), char_count*2 + sizeof(uint32_t)*2);
323*795d594fSAndroid Build Coastguard Worker     cb->DdmPublishChunk(type, ArrayRef<const uint8_t>(bytes));
324*795d594fSAndroid Build Coastguard Worker   }
325*795d594fSAndroid Build Coastguard Worker }
326*795d594fSAndroid Build Coastguard Worker 
DdmSetThreadNotification(bool enable)327*795d594fSAndroid Build Coastguard Worker void Dbg::DdmSetThreadNotification(bool enable) {
328*795d594fSAndroid Build Coastguard Worker   // Enable/disable thread notifications.
329*795d594fSAndroid Build Coastguard Worker   gDdmThreadNotification = enable;
330*795d594fSAndroid Build Coastguard Worker   if (enable) {
331*795d594fSAndroid Build Coastguard Worker     // Use a Checkpoint to cause every currently running thread to send their own notification when
332*795d594fSAndroid Build Coastguard Worker     // able. We then wait for every thread thread active at the time to post the creation
333*795d594fSAndroid Build Coastguard Worker     // notification. Threads created later will send this themselves.
334*795d594fSAndroid Build Coastguard Worker     Thread* self = Thread::Current();
335*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(self);
336*795d594fSAndroid Build Coastguard Worker     Barrier finish_barrier(0);
337*795d594fSAndroid Build Coastguard Worker     FunctionClosure fc([&](Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_) {
338*795d594fSAndroid Build Coastguard Worker       Thread* cls_self = Thread::Current();
339*795d594fSAndroid Build Coastguard Worker       Locks::mutator_lock_->AssertSharedHeld(cls_self);
340*795d594fSAndroid Build Coastguard Worker       Dbg::DdmSendThreadNotification(thread, CHUNK_TYPE("THCR"));
341*795d594fSAndroid Build Coastguard Worker       finish_barrier.Pass(cls_self);
342*795d594fSAndroid Build Coastguard Worker     });
343*795d594fSAndroid Build Coastguard Worker     // TODO(b/253671779): The above eventually results in calls to EventHandler::DispatchEvent,
344*795d594fSAndroid Build Coastguard Worker     // which does a ScopedThreadStateChange, which amounts to a thread state change inside the
345*795d594fSAndroid Build Coastguard Worker     // checkpoint run method. Hence the normal check would fail, and thus we specify Unchecked
346*795d594fSAndroid Build Coastguard Worker     // here.
347*795d594fSAndroid Build Coastguard Worker     size_t checkpoints = Runtime::Current()->GetThreadList()->RunCheckpointUnchecked(&fc);
348*795d594fSAndroid Build Coastguard Worker     ScopedThreadSuspension sts(self, ThreadState::kWaitingForCheckPointsToRun);
349*795d594fSAndroid Build Coastguard Worker     finish_barrier.Increment(self, checkpoints);
350*795d594fSAndroid Build Coastguard Worker   }
351*795d594fSAndroid Build Coastguard Worker }
352*795d594fSAndroid Build Coastguard Worker 
PostThreadStartOrStop(Thread * t,uint32_t type)353*795d594fSAndroid Build Coastguard Worker void Dbg::PostThreadStartOrStop(Thread* t, uint32_t type) {
354*795d594fSAndroid Build Coastguard Worker   Dbg::DdmSendThreadNotification(t, type);
355*795d594fSAndroid Build Coastguard Worker }
356*795d594fSAndroid Build Coastguard Worker 
PostThreadStart(Thread * t)357*795d594fSAndroid Build Coastguard Worker void Dbg::PostThreadStart(Thread* t) {
358*795d594fSAndroid Build Coastguard Worker   Dbg::PostThreadStartOrStop(t, CHUNK_TYPE("THCR"));
359*795d594fSAndroid Build Coastguard Worker }
360*795d594fSAndroid Build Coastguard Worker 
PostThreadDeath(Thread * t)361*795d594fSAndroid Build Coastguard Worker void Dbg::PostThreadDeath(Thread* t) {
362*795d594fSAndroid Build Coastguard Worker   Dbg::PostThreadStartOrStop(t, CHUNK_TYPE("THDE"));
363*795d594fSAndroid Build Coastguard Worker }
364*795d594fSAndroid Build Coastguard Worker 
DdmHandleHpifChunk(HpifWhen when)365*795d594fSAndroid Build Coastguard Worker int Dbg::DdmHandleHpifChunk(HpifWhen when) {
366*795d594fSAndroid Build Coastguard Worker   if (when == HPIF_WHEN_NOW) {
367*795d594fSAndroid Build Coastguard Worker     DdmSendHeapInfo(when);
368*795d594fSAndroid Build Coastguard Worker     return 1;
369*795d594fSAndroid Build Coastguard Worker   }
370*795d594fSAndroid Build Coastguard Worker 
371*795d594fSAndroid Build Coastguard Worker   if (when != HPIF_WHEN_NEVER && when != HPIF_WHEN_NEXT_GC && when != HPIF_WHEN_EVERY_GC) {
372*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "invalid HpifWhen value: " << static_cast<int>(when);
373*795d594fSAndroid Build Coastguard Worker     return 0;
374*795d594fSAndroid Build Coastguard Worker   }
375*795d594fSAndroid Build Coastguard Worker 
376*795d594fSAndroid Build Coastguard Worker   gDdmHpifWhen = when;
377*795d594fSAndroid Build Coastguard Worker   return 1;
378*795d594fSAndroid Build Coastguard Worker }
379*795d594fSAndroid Build Coastguard Worker 
DdmHandleHpsgNhsgChunk(Dbg::HpsgWhen when,Dbg::HpsgWhat what,bool native)380*795d594fSAndroid Build Coastguard Worker bool Dbg::DdmHandleHpsgNhsgChunk(Dbg::HpsgWhen when, Dbg::HpsgWhat what, bool native) {
381*795d594fSAndroid Build Coastguard Worker   if (when != HPSG_WHEN_NEVER && when != HPSG_WHEN_EVERY_GC) {
382*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "invalid HpsgWhen value: " << static_cast<int>(when);
383*795d594fSAndroid Build Coastguard Worker     return false;
384*795d594fSAndroid Build Coastguard Worker   }
385*795d594fSAndroid Build Coastguard Worker 
386*795d594fSAndroid Build Coastguard Worker   if (what != HPSG_WHAT_MERGED_OBJECTS && what != HPSG_WHAT_DISTINCT_OBJECTS) {
387*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "invalid HpsgWhat value: " << static_cast<int>(what);
388*795d594fSAndroid Build Coastguard Worker     return false;
389*795d594fSAndroid Build Coastguard Worker   }
390*795d594fSAndroid Build Coastguard Worker 
391*795d594fSAndroid Build Coastguard Worker   if (native) {
392*795d594fSAndroid Build Coastguard Worker     gDdmNhsgWhen = when;
393*795d594fSAndroid Build Coastguard Worker     gDdmNhsgWhat = what;
394*795d594fSAndroid Build Coastguard Worker   } else {
395*795d594fSAndroid Build Coastguard Worker     gDdmHpsgWhen = when;
396*795d594fSAndroid Build Coastguard Worker     gDdmHpsgWhat = what;
397*795d594fSAndroid Build Coastguard Worker   }
398*795d594fSAndroid Build Coastguard Worker   return true;
399*795d594fSAndroid Build Coastguard Worker }
400*795d594fSAndroid Build Coastguard Worker 
DdmSendHeapInfo(HpifWhen reason)401*795d594fSAndroid Build Coastguard Worker void Dbg::DdmSendHeapInfo(HpifWhen reason) {
402*795d594fSAndroid Build Coastguard Worker   // If there's a one-shot 'when', reset it.
403*795d594fSAndroid Build Coastguard Worker   if (reason == gDdmHpifWhen) {
404*795d594fSAndroid Build Coastguard Worker     if (gDdmHpifWhen == HPIF_WHEN_NEXT_GC) {
405*795d594fSAndroid Build Coastguard Worker       gDdmHpifWhen = HPIF_WHEN_NEVER;
406*795d594fSAndroid Build Coastguard Worker     }
407*795d594fSAndroid Build Coastguard Worker   }
408*795d594fSAndroid Build Coastguard Worker 
409*795d594fSAndroid Build Coastguard Worker   /*
410*795d594fSAndroid Build Coastguard Worker    * Chunk HPIF (client --> server)
411*795d594fSAndroid Build Coastguard Worker    *
412*795d594fSAndroid Build Coastguard Worker    * Heap Info. General information about the heap,
413*795d594fSAndroid Build Coastguard Worker    * suitable for a summary display.
414*795d594fSAndroid Build Coastguard Worker    *
415*795d594fSAndroid Build Coastguard Worker    *   [u4]: number of heaps
416*795d594fSAndroid Build Coastguard Worker    *
417*795d594fSAndroid Build Coastguard Worker    *   For each heap:
418*795d594fSAndroid Build Coastguard Worker    *     [u4]: heap ID
419*795d594fSAndroid Build Coastguard Worker    *     [u8]: timestamp in ms since Unix epoch
420*795d594fSAndroid Build Coastguard Worker    *     [u1]: capture reason (same as 'when' value from server)
421*795d594fSAndroid Build Coastguard Worker    *     [u4]: max heap size in bytes (-Xmx)
422*795d594fSAndroid Build Coastguard Worker    *     [u4]: current heap size in bytes
423*795d594fSAndroid Build Coastguard Worker    *     [u4]: current number of bytes allocated
424*795d594fSAndroid Build Coastguard Worker    *     [u4]: current number of objects allocated
425*795d594fSAndroid Build Coastguard Worker    */
426*795d594fSAndroid Build Coastguard Worker   uint8_t heap_count = 1;
427*795d594fSAndroid Build Coastguard Worker   gc::Heap* heap = Runtime::Current()->GetHeap();
428*795d594fSAndroid Build Coastguard Worker   std::vector<uint8_t> bytes;
429*795d594fSAndroid Build Coastguard Worker   Append4BE(bytes, heap_count);
430*795d594fSAndroid Build Coastguard Worker   Append4BE(bytes, 1);  // Heap id (bogus; we only have one heap).
431*795d594fSAndroid Build Coastguard Worker   Append8BE(bytes, MilliTime());
432*795d594fSAndroid Build Coastguard Worker   Append1BE(bytes, reason);
433*795d594fSAndroid Build Coastguard Worker   Append4BE(bytes, heap->GetMaxMemory());  // Max allowed heap size in bytes.
434*795d594fSAndroid Build Coastguard Worker   Append4BE(bytes, heap->GetTotalMemory());  // Current heap size in bytes.
435*795d594fSAndroid Build Coastguard Worker   Append4BE(bytes, heap->GetBytesAllocated());
436*795d594fSAndroid Build Coastguard Worker   Append4BE(bytes, heap->GetObjectsAllocated());
437*795d594fSAndroid Build Coastguard Worker   CHECK_EQ(bytes.size(), 4U + (heap_count * (4 + 8 + 1 + 4 + 4 + 4 + 4)));
438*795d594fSAndroid Build Coastguard Worker   Runtime::Current()->GetRuntimeCallbacks()->DdmPublishChunk(CHUNK_TYPE("HPIF"),
439*795d594fSAndroid Build Coastguard Worker                                                              ArrayRef<const uint8_t>(bytes));
440*795d594fSAndroid Build Coastguard Worker }
441*795d594fSAndroid Build Coastguard Worker 
442*795d594fSAndroid Build Coastguard Worker enum HpsgSolidity {
443*795d594fSAndroid Build Coastguard Worker   SOLIDITY_FREE = 0,
444*795d594fSAndroid Build Coastguard Worker   SOLIDITY_HARD = 1,
445*795d594fSAndroid Build Coastguard Worker   SOLIDITY_SOFT = 2,
446*795d594fSAndroid Build Coastguard Worker   SOLIDITY_WEAK = 3,
447*795d594fSAndroid Build Coastguard Worker   SOLIDITY_PHANTOM = 4,
448*795d594fSAndroid Build Coastguard Worker   SOLIDITY_FINALIZABLE = 5,
449*795d594fSAndroid Build Coastguard Worker   SOLIDITY_SWEEP = 6,
450*795d594fSAndroid Build Coastguard Worker };
451*795d594fSAndroid Build Coastguard Worker 
452*795d594fSAndroid Build Coastguard Worker enum HpsgKind {
453*795d594fSAndroid Build Coastguard Worker   KIND_OBJECT = 0,
454*795d594fSAndroid Build Coastguard Worker   KIND_CLASS_OBJECT = 1,
455*795d594fSAndroid Build Coastguard Worker   KIND_ARRAY_1 = 2,
456*795d594fSAndroid Build Coastguard Worker   KIND_ARRAY_2 = 3,
457*795d594fSAndroid Build Coastguard Worker   KIND_ARRAY_4 = 4,
458*795d594fSAndroid Build Coastguard Worker   KIND_ARRAY_8 = 5,
459*795d594fSAndroid Build Coastguard Worker   KIND_UNKNOWN = 6,
460*795d594fSAndroid Build Coastguard Worker   KIND_NATIVE = 7,
461*795d594fSAndroid Build Coastguard Worker };
462*795d594fSAndroid Build Coastguard Worker 
463*795d594fSAndroid Build Coastguard Worker #define HPSG_PARTIAL (1<<7)
464*795d594fSAndroid Build Coastguard Worker #define HPSG_STATE(solidity, kind) ((uint8_t)((((kind) & 0x7) << 3) | ((solidity) & 0x7)))
465*795d594fSAndroid Build Coastguard Worker 
466*795d594fSAndroid Build Coastguard Worker class HeapChunkContext {
467*795d594fSAndroid Build Coastguard Worker  public:
468*795d594fSAndroid Build Coastguard Worker   // Maximum chunk size.  Obtain this from the formula:
469*795d594fSAndroid Build Coastguard Worker   // (((maximum_heap_size / ALLOCATION_UNIT_SIZE) + 255) / 256) * 2
HeapChunkContext(bool merge,bool native)470*795d594fSAndroid Build Coastguard Worker   HeapChunkContext(bool merge, bool native)
471*795d594fSAndroid Build Coastguard Worker       : buf_(16384 - 16),
472*795d594fSAndroid Build Coastguard Worker         type_(0),
473*795d594fSAndroid Build Coastguard Worker         chunk_overhead_(0) {
474*795d594fSAndroid Build Coastguard Worker     Reset();
475*795d594fSAndroid Build Coastguard Worker     if (native) {
476*795d594fSAndroid Build Coastguard Worker       type_ = CHUNK_TYPE("NHSG");
477*795d594fSAndroid Build Coastguard Worker     } else {
478*795d594fSAndroid Build Coastguard Worker       type_ = merge ? CHUNK_TYPE("HPSG") : CHUNK_TYPE("HPSO");
479*795d594fSAndroid Build Coastguard Worker     }
480*795d594fSAndroid Build Coastguard Worker   }
481*795d594fSAndroid Build Coastguard Worker 
~HeapChunkContext()482*795d594fSAndroid Build Coastguard Worker   ~HeapChunkContext() {
483*795d594fSAndroid Build Coastguard Worker     if (p_ > &buf_[0]) {
484*795d594fSAndroid Build Coastguard Worker       Flush();
485*795d594fSAndroid Build Coastguard Worker     }
486*795d594fSAndroid Build Coastguard Worker   }
487*795d594fSAndroid Build Coastguard Worker 
SetChunkOverhead(size_t chunk_overhead)488*795d594fSAndroid Build Coastguard Worker   void SetChunkOverhead(size_t chunk_overhead) {
489*795d594fSAndroid Build Coastguard Worker     chunk_overhead_ = chunk_overhead;
490*795d594fSAndroid Build Coastguard Worker   }
491*795d594fSAndroid Build Coastguard Worker 
ResetStartOfNextChunk()492*795d594fSAndroid Build Coastguard Worker   void ResetStartOfNextChunk() {
493*795d594fSAndroid Build Coastguard Worker     startOfNextMemoryChunk_ = nullptr;
494*795d594fSAndroid Build Coastguard Worker   }
495*795d594fSAndroid Build Coastguard Worker 
EnsureHeader(const void * chunk_ptr)496*795d594fSAndroid Build Coastguard Worker   void EnsureHeader(const void* chunk_ptr) {
497*795d594fSAndroid Build Coastguard Worker     if (!needHeader_) {
498*795d594fSAndroid Build Coastguard Worker       return;
499*795d594fSAndroid Build Coastguard Worker     }
500*795d594fSAndroid Build Coastguard Worker 
501*795d594fSAndroid Build Coastguard Worker     // Start a new HPSx chunk.
502*795d594fSAndroid Build Coastguard Worker     Write4BE(&p_, 1);  // Heap id (bogus; we only have one heap).
503*795d594fSAndroid Build Coastguard Worker     Write1BE(&p_, 8);  // Size of allocation unit, in bytes.
504*795d594fSAndroid Build Coastguard Worker 
505*795d594fSAndroid Build Coastguard Worker     Write4BE(&p_, reinterpret_cast<uintptr_t>(chunk_ptr));  // virtual address of segment start.
506*795d594fSAndroid Build Coastguard Worker     Write4BE(&p_, 0);  // offset of this piece (relative to the virtual address).
507*795d594fSAndroid Build Coastguard Worker     // [u4]: length of piece, in allocation units
508*795d594fSAndroid Build Coastguard Worker     // We won't know this until we're done, so save the offset and stuff in a fake value.
509*795d594fSAndroid Build Coastguard Worker     pieceLenField_ = p_;
510*795d594fSAndroid Build Coastguard Worker     Write4BE(&p_, 0x55555555);
511*795d594fSAndroid Build Coastguard Worker     needHeader_ = false;
512*795d594fSAndroid Build Coastguard Worker   }
513*795d594fSAndroid Build Coastguard Worker 
Flush()514*795d594fSAndroid Build Coastguard Worker   void Flush() REQUIRES_SHARED(Locks::mutator_lock_) {
515*795d594fSAndroid Build Coastguard Worker     if (pieceLenField_ == nullptr) {
516*795d594fSAndroid Build Coastguard Worker       // Flush immediately post Reset (maybe back-to-back Flush). Ignore.
517*795d594fSAndroid Build Coastguard Worker       CHECK(needHeader_);
518*795d594fSAndroid Build Coastguard Worker       return;
519*795d594fSAndroid Build Coastguard Worker     }
520*795d594fSAndroid Build Coastguard Worker     // Patch the "length of piece" field.
521*795d594fSAndroid Build Coastguard Worker     CHECK_LE(&buf_[0], pieceLenField_);
522*795d594fSAndroid Build Coastguard Worker     CHECK_LE(pieceLenField_, p_);
523*795d594fSAndroid Build Coastguard Worker     Set4BE(pieceLenField_, totalAllocationUnits_);
524*795d594fSAndroid Build Coastguard Worker 
525*795d594fSAndroid Build Coastguard Worker     ArrayRef<const uint8_t> out(&buf_[0], p_ - &buf_[0]);
526*795d594fSAndroid Build Coastguard Worker     Runtime::Current()->GetRuntimeCallbacks()->DdmPublishChunk(type_, out);
527*795d594fSAndroid Build Coastguard Worker     Reset();
528*795d594fSAndroid Build Coastguard Worker   }
529*795d594fSAndroid Build Coastguard Worker 
HeapChunkJavaCallback(void * start,void * end,size_t used_bytes,void * arg)530*795d594fSAndroid Build Coastguard Worker   static void HeapChunkJavaCallback(void* start, void* end, size_t used_bytes, void* arg)
531*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::heap_bitmap_lock_,
532*795d594fSAndroid Build Coastguard Worker                             Locks::mutator_lock_) {
533*795d594fSAndroid Build Coastguard Worker     reinterpret_cast<HeapChunkContext*>(arg)->HeapChunkJavaCallback(start, end, used_bytes);
534*795d594fSAndroid Build Coastguard Worker   }
535*795d594fSAndroid Build Coastguard Worker 
HeapChunkNativeCallback(void * start,void * end,size_t used_bytes,void * arg)536*795d594fSAndroid Build Coastguard Worker   static void HeapChunkNativeCallback(void* start, void* end, size_t used_bytes, void* arg)
537*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
538*795d594fSAndroid Build Coastguard Worker     reinterpret_cast<HeapChunkContext*>(arg)->HeapChunkNativeCallback(start, end, used_bytes);
539*795d594fSAndroid Build Coastguard Worker   }
540*795d594fSAndroid Build Coastguard Worker 
541*795d594fSAndroid Build Coastguard Worker  private:
542*795d594fSAndroid Build Coastguard Worker   enum { ALLOCATION_UNIT_SIZE = 8 };
543*795d594fSAndroid Build Coastguard Worker 
Reset()544*795d594fSAndroid Build Coastguard Worker   void Reset() {
545*795d594fSAndroid Build Coastguard Worker     p_ = &buf_[0];
546*795d594fSAndroid Build Coastguard Worker     ResetStartOfNextChunk();
547*795d594fSAndroid Build Coastguard Worker     totalAllocationUnits_ = 0;
548*795d594fSAndroid Build Coastguard Worker     needHeader_ = true;
549*795d594fSAndroid Build Coastguard Worker     pieceLenField_ = nullptr;
550*795d594fSAndroid Build Coastguard Worker   }
551*795d594fSAndroid Build Coastguard Worker 
IsNative() const552*795d594fSAndroid Build Coastguard Worker   bool IsNative() const {
553*795d594fSAndroid Build Coastguard Worker     return type_ == CHUNK_TYPE("NHSG");
554*795d594fSAndroid Build Coastguard Worker   }
555*795d594fSAndroid Build Coastguard Worker 
556*795d594fSAndroid Build Coastguard Worker   // Returns true if the object is not an empty chunk.
ProcessRecord(void * start,size_t used_bytes)557*795d594fSAndroid Build Coastguard Worker   bool ProcessRecord(void* start, size_t used_bytes) REQUIRES_SHARED(Locks::mutator_lock_) {
558*795d594fSAndroid Build Coastguard Worker     // Note: heap call backs cannot manipulate the heap upon which they are crawling, care is taken
559*795d594fSAndroid Build Coastguard Worker     // in the following code not to allocate memory, by ensuring buf_ is of the correct size
560*795d594fSAndroid Build Coastguard Worker     if (used_bytes == 0) {
561*795d594fSAndroid Build Coastguard Worker       if (start == nullptr) {
562*795d594fSAndroid Build Coastguard Worker         // Reset for start of new heap.
563*795d594fSAndroid Build Coastguard Worker         startOfNextMemoryChunk_ = nullptr;
564*795d594fSAndroid Build Coastguard Worker         Flush();
565*795d594fSAndroid Build Coastguard Worker       }
566*795d594fSAndroid Build Coastguard Worker       // Only process in use memory so that free region information
567*795d594fSAndroid Build Coastguard Worker       // also includes dlmalloc book keeping.
568*795d594fSAndroid Build Coastguard Worker       return false;
569*795d594fSAndroid Build Coastguard Worker     }
570*795d594fSAndroid Build Coastguard Worker     if (startOfNextMemoryChunk_ != nullptr) {
571*795d594fSAndroid Build Coastguard Worker       // Transmit any pending free memory. Native free memory of over kMaxFreeLen could be because
572*795d594fSAndroid Build Coastguard Worker       // of the use of mmaps, so don't report. If not free memory then start a new segment.
573*795d594fSAndroid Build Coastguard Worker       bool flush = true;
574*795d594fSAndroid Build Coastguard Worker       if (start > startOfNextMemoryChunk_) {
575*795d594fSAndroid Build Coastguard Worker         const size_t kMaxFreeLen = 2 * gPageSize;
576*795d594fSAndroid Build Coastguard Worker         void* free_start = startOfNextMemoryChunk_;
577*795d594fSAndroid Build Coastguard Worker         void* free_end = start;
578*795d594fSAndroid Build Coastguard Worker         const size_t free_len =
579*795d594fSAndroid Build Coastguard Worker             reinterpret_cast<uintptr_t>(free_end) - reinterpret_cast<uintptr_t>(free_start);
580*795d594fSAndroid Build Coastguard Worker         if (!IsNative() || free_len < kMaxFreeLen) {
581*795d594fSAndroid Build Coastguard Worker           AppendChunk(HPSG_STATE(SOLIDITY_FREE, 0), free_start, free_len, IsNative());
582*795d594fSAndroid Build Coastguard Worker           flush = false;
583*795d594fSAndroid Build Coastguard Worker         }
584*795d594fSAndroid Build Coastguard Worker       }
585*795d594fSAndroid Build Coastguard Worker       if (flush) {
586*795d594fSAndroid Build Coastguard Worker         startOfNextMemoryChunk_ = nullptr;
587*795d594fSAndroid Build Coastguard Worker         Flush();
588*795d594fSAndroid Build Coastguard Worker       }
589*795d594fSAndroid Build Coastguard Worker     }
590*795d594fSAndroid Build Coastguard Worker     return true;
591*795d594fSAndroid Build Coastguard Worker   }
592*795d594fSAndroid Build Coastguard Worker 
HeapChunkNativeCallback(void * start,void *,size_t used_bytes)593*795d594fSAndroid Build Coastguard Worker   void HeapChunkNativeCallback(void* start, void* /*end*/, size_t used_bytes)
594*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
595*795d594fSAndroid Build Coastguard Worker     if (ProcessRecord(start, used_bytes)) {
596*795d594fSAndroid Build Coastguard Worker       uint8_t state = ExamineNativeObject(start);
597*795d594fSAndroid Build Coastguard Worker       AppendChunk(state, start, used_bytes + chunk_overhead_, /*is_native=*/ true);
598*795d594fSAndroid Build Coastguard Worker       startOfNextMemoryChunk_ = reinterpret_cast<char*>(start) + used_bytes + chunk_overhead_;
599*795d594fSAndroid Build Coastguard Worker     }
600*795d594fSAndroid Build Coastguard Worker   }
601*795d594fSAndroid Build Coastguard Worker 
HeapChunkJavaCallback(void * start,void *,size_t used_bytes)602*795d594fSAndroid Build Coastguard Worker   void HeapChunkJavaCallback(void* start, void* /*end*/, size_t used_bytes)
603*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
604*795d594fSAndroid Build Coastguard Worker     if (ProcessRecord(start, used_bytes)) {
605*795d594fSAndroid Build Coastguard Worker       // Determine the type of this chunk.
606*795d594fSAndroid Build Coastguard Worker       // OLD-TODO: if context.merge, see if this chunk is different from the last chunk.
607*795d594fSAndroid Build Coastguard Worker       // If it's the same, we should combine them.
608*795d594fSAndroid Build Coastguard Worker       uint8_t state = ExamineJavaObject(reinterpret_cast<mirror::Object*>(start));
609*795d594fSAndroid Build Coastguard Worker       AppendChunk(state, start, used_bytes + chunk_overhead_, /*is_native=*/ false);
610*795d594fSAndroid Build Coastguard Worker       startOfNextMemoryChunk_ = reinterpret_cast<char*>(start) + used_bytes + chunk_overhead_;
611*795d594fSAndroid Build Coastguard Worker     }
612*795d594fSAndroid Build Coastguard Worker   }
613*795d594fSAndroid Build Coastguard Worker 
AppendChunk(uint8_t state,void * ptr,size_t length,bool is_native)614*795d594fSAndroid Build Coastguard Worker   void AppendChunk(uint8_t state, void* ptr, size_t length, bool is_native)
615*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
616*795d594fSAndroid Build Coastguard Worker     // Make sure there's enough room left in the buffer.
617*795d594fSAndroid Build Coastguard Worker     // We need to use two bytes for every fractional 256 allocation units used by the chunk plus
618*795d594fSAndroid Build Coastguard Worker     // 17 bytes for any header.
619*795d594fSAndroid Build Coastguard Worker     const size_t needed = ((RoundUp(length / ALLOCATION_UNIT_SIZE, 256) / 256) * 2) + 17;
620*795d594fSAndroid Build Coastguard Worker     size_t byte_left = &buf_.back() - p_;
621*795d594fSAndroid Build Coastguard Worker     if (byte_left < needed) {
622*795d594fSAndroid Build Coastguard Worker       if (is_native) {
623*795d594fSAndroid Build Coastguard Worker       // Cannot trigger memory allocation while walking native heap.
624*795d594fSAndroid Build Coastguard Worker         return;
625*795d594fSAndroid Build Coastguard Worker       }
626*795d594fSAndroid Build Coastguard Worker       Flush();
627*795d594fSAndroid Build Coastguard Worker     }
628*795d594fSAndroid Build Coastguard Worker 
629*795d594fSAndroid Build Coastguard Worker     byte_left = &buf_.back() - p_;
630*795d594fSAndroid Build Coastguard Worker     if (byte_left < needed) {
631*795d594fSAndroid Build Coastguard Worker       LOG(WARNING) << "Chunk is too big to transmit (chunk_len=" << length << ", "
632*795d594fSAndroid Build Coastguard Worker           << needed << " bytes)";
633*795d594fSAndroid Build Coastguard Worker       return;
634*795d594fSAndroid Build Coastguard Worker     }
635*795d594fSAndroid Build Coastguard Worker     EnsureHeader(ptr);
636*795d594fSAndroid Build Coastguard Worker     // Write out the chunk description.
637*795d594fSAndroid Build Coastguard Worker     length /= ALLOCATION_UNIT_SIZE;   // Convert to allocation units.
638*795d594fSAndroid Build Coastguard Worker     totalAllocationUnits_ += length;
639*795d594fSAndroid Build Coastguard Worker     while (length > 256) {
640*795d594fSAndroid Build Coastguard Worker       *p_++ = state | HPSG_PARTIAL;
641*795d594fSAndroid Build Coastguard Worker       *p_++ = 255;     // length - 1
642*795d594fSAndroid Build Coastguard Worker       length -= 256;
643*795d594fSAndroid Build Coastguard Worker     }
644*795d594fSAndroid Build Coastguard Worker     *p_++ = state;
645*795d594fSAndroid Build Coastguard Worker     *p_++ = length - 1;
646*795d594fSAndroid Build Coastguard Worker   }
647*795d594fSAndroid Build Coastguard Worker 
ExamineNativeObject(const void * p)648*795d594fSAndroid Build Coastguard Worker   uint8_t ExamineNativeObject(const void* p) REQUIRES_SHARED(Locks::mutator_lock_) {
649*795d594fSAndroid Build Coastguard Worker     return p == nullptr ? HPSG_STATE(SOLIDITY_FREE, 0) : HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE);
650*795d594fSAndroid Build Coastguard Worker   }
651*795d594fSAndroid Build Coastguard Worker 
ExamineJavaObject(ObjPtr<mirror::Object> o)652*795d594fSAndroid Build Coastguard Worker   uint8_t ExamineJavaObject(ObjPtr<mirror::Object> o)
653*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
654*795d594fSAndroid Build Coastguard Worker     if (o == nullptr) {
655*795d594fSAndroid Build Coastguard Worker       return HPSG_STATE(SOLIDITY_FREE, 0);
656*795d594fSAndroid Build Coastguard Worker     }
657*795d594fSAndroid Build Coastguard Worker     // It's an allocated chunk. Figure out what it is.
658*795d594fSAndroid Build Coastguard Worker     gc::Heap* heap = Runtime::Current()->GetHeap();
659*795d594fSAndroid Build Coastguard Worker     if (!heap->IsLiveObjectLocked(o)) {
660*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Invalid object in managed heap: " << o;
661*795d594fSAndroid Build Coastguard Worker       return HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE);
662*795d594fSAndroid Build Coastguard Worker     }
663*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Class> c = o->GetClass();
664*795d594fSAndroid Build Coastguard Worker     if (c == nullptr) {
665*795d594fSAndroid Build Coastguard Worker       // The object was probably just created but hasn't been initialized yet.
666*795d594fSAndroid Build Coastguard Worker       return HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
667*795d594fSAndroid Build Coastguard Worker     }
668*795d594fSAndroid Build Coastguard Worker     if (!heap->IsValidObjectAddress(c.Ptr())) {
669*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Invalid class for managed heap object: " << o << " " << c;
670*795d594fSAndroid Build Coastguard Worker       return HPSG_STATE(SOLIDITY_HARD, KIND_UNKNOWN);
671*795d594fSAndroid Build Coastguard Worker     }
672*795d594fSAndroid Build Coastguard Worker     if (c->GetClass() == nullptr) {
673*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Null class of class " << c << " for object " << o;
674*795d594fSAndroid Build Coastguard Worker       return HPSG_STATE(SOLIDITY_HARD, KIND_UNKNOWN);
675*795d594fSAndroid Build Coastguard Worker     }
676*795d594fSAndroid Build Coastguard Worker     if (c->IsClassClass()) {
677*795d594fSAndroid Build Coastguard Worker       return HPSG_STATE(SOLIDITY_HARD, KIND_CLASS_OBJECT);
678*795d594fSAndroid Build Coastguard Worker     }
679*795d594fSAndroid Build Coastguard Worker     if (c->IsArrayClass()) {
680*795d594fSAndroid Build Coastguard Worker       switch (c->GetComponentSize()) {
681*795d594fSAndroid Build Coastguard Worker       case 1: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_1);
682*795d594fSAndroid Build Coastguard Worker       case 2: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_2);
683*795d594fSAndroid Build Coastguard Worker       case 4: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_4);
684*795d594fSAndroid Build Coastguard Worker       case 8: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_8);
685*795d594fSAndroid Build Coastguard Worker       }
686*795d594fSAndroid Build Coastguard Worker     }
687*795d594fSAndroid Build Coastguard Worker     return HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
688*795d594fSAndroid Build Coastguard Worker   }
689*795d594fSAndroid Build Coastguard Worker 
690*795d594fSAndroid Build Coastguard Worker   std::vector<uint8_t> buf_;
691*795d594fSAndroid Build Coastguard Worker   uint8_t* p_;
692*795d594fSAndroid Build Coastguard Worker   uint8_t* pieceLenField_;
693*795d594fSAndroid Build Coastguard Worker   void* startOfNextMemoryChunk_;
694*795d594fSAndroid Build Coastguard Worker   size_t totalAllocationUnits_;
695*795d594fSAndroid Build Coastguard Worker   uint32_t type_;
696*795d594fSAndroid Build Coastguard Worker   bool needHeader_;
697*795d594fSAndroid Build Coastguard Worker   size_t chunk_overhead_;
698*795d594fSAndroid Build Coastguard Worker 
699*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(HeapChunkContext);
700*795d594fSAndroid Build Coastguard Worker };
701*795d594fSAndroid Build Coastguard Worker 
702*795d594fSAndroid Build Coastguard Worker 
DdmSendHeapSegments(bool native)703*795d594fSAndroid Build Coastguard Worker void Dbg::DdmSendHeapSegments(bool native) {
704*795d594fSAndroid Build Coastguard Worker   Dbg::HpsgWhen when = native ? gDdmNhsgWhen : gDdmHpsgWhen;
705*795d594fSAndroid Build Coastguard Worker   Dbg::HpsgWhat what = native ? gDdmNhsgWhat : gDdmHpsgWhat;
706*795d594fSAndroid Build Coastguard Worker   if (when == HPSG_WHEN_NEVER) {
707*795d594fSAndroid Build Coastguard Worker     return;
708*795d594fSAndroid Build Coastguard Worker   }
709*795d594fSAndroid Build Coastguard Worker   RuntimeCallbacks* cb = Runtime::Current()->GetRuntimeCallbacks();
710*795d594fSAndroid Build Coastguard Worker   // Figure out what kind of chunks we'll be sending.
711*795d594fSAndroid Build Coastguard Worker   CHECK(what == HPSG_WHAT_MERGED_OBJECTS || what == HPSG_WHAT_DISTINCT_OBJECTS)
712*795d594fSAndroid Build Coastguard Worker       << static_cast<int>(what);
713*795d594fSAndroid Build Coastguard Worker 
714*795d594fSAndroid Build Coastguard Worker   // First, send a heap start chunk.
715*795d594fSAndroid Build Coastguard Worker   uint8_t heap_id[4];
716*795d594fSAndroid Build Coastguard Worker   Set4BE(&heap_id[0], 1);  // Heap id (bogus; we only have one heap).
717*795d594fSAndroid Build Coastguard Worker   cb->DdmPublishChunk(native ? CHUNK_TYPE("NHST") : CHUNK_TYPE("HPST"),
718*795d594fSAndroid Build Coastguard Worker                       ArrayRef<const uint8_t>(heap_id));
719*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
720*795d594fSAndroid Build Coastguard Worker   Locks::mutator_lock_->AssertSharedHeld(self);
721*795d594fSAndroid Build Coastguard Worker 
722*795d594fSAndroid Build Coastguard Worker   // Send a series of heap segment chunks.
723*795d594fSAndroid Build Coastguard Worker   HeapChunkContext context(what == HPSG_WHAT_MERGED_OBJECTS, native);
724*795d594fSAndroid Build Coastguard Worker   auto bump_pointer_space_visitor = [&](mirror::Object* obj)
725*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
726*795d594fSAndroid Build Coastguard Worker     const size_t size = RoundUp(obj->SizeOf(), kObjectAlignment);
727*795d594fSAndroid Build Coastguard Worker     HeapChunkContext::HeapChunkJavaCallback(
728*795d594fSAndroid Build Coastguard Worker         obj, reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(obj) + size), size, &context);
729*795d594fSAndroid Build Coastguard Worker   };
730*795d594fSAndroid Build Coastguard Worker   if (native) {
731*795d594fSAndroid Build Coastguard Worker     UNIMPLEMENTED(WARNING) << "Native heap inspection is not supported";
732*795d594fSAndroid Build Coastguard Worker   } else {
733*795d594fSAndroid Build Coastguard Worker     gc::Heap* heap = Runtime::Current()->GetHeap();
734*795d594fSAndroid Build Coastguard Worker     for (const auto& space : heap->GetContinuousSpaces()) {
735*795d594fSAndroid Build Coastguard Worker       if (space->IsDlMallocSpace()) {
736*795d594fSAndroid Build Coastguard Worker         ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
737*795d594fSAndroid Build Coastguard Worker         // dlmalloc's chunk header is 2 * sizeof(size_t), but if the previous chunk is in use for an
738*795d594fSAndroid Build Coastguard Worker         // allocation then the first sizeof(size_t) may belong to it.
739*795d594fSAndroid Build Coastguard Worker         context.SetChunkOverhead(sizeof(size_t));
740*795d594fSAndroid Build Coastguard Worker         space->AsDlMallocSpace()->Walk(HeapChunkContext::HeapChunkJavaCallback, &context);
741*795d594fSAndroid Build Coastguard Worker       } else if (space->IsRosAllocSpace()) {
742*795d594fSAndroid Build Coastguard Worker         context.SetChunkOverhead(0);
743*795d594fSAndroid Build Coastguard Worker         // Need to acquire the mutator lock before the heap bitmap lock with exclusive access since
744*795d594fSAndroid Build Coastguard Worker         // RosAlloc's internal logic doesn't know to release and reacquire the heap bitmap lock.
745*795d594fSAndroid Build Coastguard Worker         ScopedThreadSuspension sts(self, ThreadState::kSuspended);
746*795d594fSAndroid Build Coastguard Worker         ScopedSuspendAll ssa(__FUNCTION__);
747*795d594fSAndroid Build Coastguard Worker         ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
748*795d594fSAndroid Build Coastguard Worker         space->AsRosAllocSpace()->Walk(HeapChunkContext::HeapChunkJavaCallback, &context);
749*795d594fSAndroid Build Coastguard Worker       } else if (space->IsBumpPointerSpace()) {
750*795d594fSAndroid Build Coastguard Worker         ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
751*795d594fSAndroid Build Coastguard Worker         context.SetChunkOverhead(0);
752*795d594fSAndroid Build Coastguard Worker         space->AsBumpPointerSpace()->Walk(bump_pointer_space_visitor);
753*795d594fSAndroid Build Coastguard Worker         HeapChunkContext::HeapChunkJavaCallback(nullptr, nullptr, 0, &context);
754*795d594fSAndroid Build Coastguard Worker       } else if (space->IsRegionSpace()) {
755*795d594fSAndroid Build Coastguard Worker         heap->IncrementDisableMovingGC(self);
756*795d594fSAndroid Build Coastguard Worker         {
757*795d594fSAndroid Build Coastguard Worker           ScopedThreadSuspension sts(self, ThreadState::kSuspended);
758*795d594fSAndroid Build Coastguard Worker           ScopedSuspendAll ssa(__FUNCTION__);
759*795d594fSAndroid Build Coastguard Worker           ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
760*795d594fSAndroid Build Coastguard Worker           context.SetChunkOverhead(0);
761*795d594fSAndroid Build Coastguard Worker           space->AsRegionSpace()->Walk(bump_pointer_space_visitor);
762*795d594fSAndroid Build Coastguard Worker           HeapChunkContext::HeapChunkJavaCallback(nullptr, nullptr, 0, &context);
763*795d594fSAndroid Build Coastguard Worker         }
764*795d594fSAndroid Build Coastguard Worker         heap->DecrementDisableMovingGC(self);
765*795d594fSAndroid Build Coastguard Worker       } else {
766*795d594fSAndroid Build Coastguard Worker         UNIMPLEMENTED(WARNING) << "Not counting objects in space " << *space;
767*795d594fSAndroid Build Coastguard Worker       }
768*795d594fSAndroid Build Coastguard Worker       context.ResetStartOfNextChunk();
769*795d594fSAndroid Build Coastguard Worker     }
770*795d594fSAndroid Build Coastguard Worker     ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
771*795d594fSAndroid Build Coastguard Worker     // Walk the large objects, these are not in the AllocSpace.
772*795d594fSAndroid Build Coastguard Worker     context.SetChunkOverhead(0);
773*795d594fSAndroid Build Coastguard Worker     heap->GetLargeObjectsSpace()->Walk(HeapChunkContext::HeapChunkJavaCallback, &context);
774*795d594fSAndroid Build Coastguard Worker   }
775*795d594fSAndroid Build Coastguard Worker 
776*795d594fSAndroid Build Coastguard Worker   // Finally, send a heap end chunk.
777*795d594fSAndroid Build Coastguard Worker   cb->DdmPublishChunk(native ? CHUNK_TYPE("NHEN") : CHUNK_TYPE("HPEN"),
778*795d594fSAndroid Build Coastguard Worker                       ArrayRef<const uint8_t>(heap_id));
779*795d594fSAndroid Build Coastguard Worker }
780*795d594fSAndroid Build Coastguard Worker 
SetAllocTrackingEnabled(bool enable)781*795d594fSAndroid Build Coastguard Worker void Dbg::SetAllocTrackingEnabled(bool enable) {
782*795d594fSAndroid Build Coastguard Worker   gc::AllocRecordObjectMap::SetAllocTrackingEnabled(enable);
783*795d594fSAndroid Build Coastguard Worker }
784*795d594fSAndroid Build Coastguard Worker 
785*795d594fSAndroid Build Coastguard Worker class StringTable {
786*795d594fSAndroid Build Coastguard Worker  private:
787*795d594fSAndroid Build Coastguard Worker   struct Entry {
Entryart::StringTable::Entry788*795d594fSAndroid Build Coastguard Worker     explicit Entry(const char* data_in)
789*795d594fSAndroid Build Coastguard Worker         : data(data_in), hash(ComputeModifiedUtf8Hash(data_in)), index(0) {
790*795d594fSAndroid Build Coastguard Worker     }
791*795d594fSAndroid Build Coastguard Worker     Entry(const Entry& entry) = default;
792*795d594fSAndroid Build Coastguard Worker     Entry(Entry&& entry) = default;
793*795d594fSAndroid Build Coastguard Worker 
794*795d594fSAndroid Build Coastguard Worker     // Pointer to the actual string data.
795*795d594fSAndroid Build Coastguard Worker     const char* data;
796*795d594fSAndroid Build Coastguard Worker 
797*795d594fSAndroid Build Coastguard Worker     // The hash of the data.
798*795d594fSAndroid Build Coastguard Worker     const uint32_t hash;
799*795d594fSAndroid Build Coastguard Worker 
800*795d594fSAndroid Build Coastguard Worker     // The index. This will be filled in on Finish and is not part of the ordering, so mark it
801*795d594fSAndroid Build Coastguard Worker     // mutable.
802*795d594fSAndroid Build Coastguard Worker     mutable uint32_t index;
803*795d594fSAndroid Build Coastguard Worker 
operator ==art::StringTable::Entry804*795d594fSAndroid Build Coastguard Worker     bool operator==(const Entry& other) const {
805*795d594fSAndroid Build Coastguard Worker       return strcmp(data, other.data) == 0;
806*795d594fSAndroid Build Coastguard Worker     }
807*795d594fSAndroid Build Coastguard Worker   };
808*795d594fSAndroid Build Coastguard Worker   struct EntryHash {
operator ()art::StringTable::EntryHash809*795d594fSAndroid Build Coastguard Worker     size_t operator()(const Entry& entry) const {
810*795d594fSAndroid Build Coastguard Worker       return entry.hash;
811*795d594fSAndroid Build Coastguard Worker     }
812*795d594fSAndroid Build Coastguard Worker   };
813*795d594fSAndroid Build Coastguard Worker 
814*795d594fSAndroid Build Coastguard Worker  public:
StringTable()815*795d594fSAndroid Build Coastguard Worker   StringTable() : finished_(false) {
816*795d594fSAndroid Build Coastguard Worker   }
817*795d594fSAndroid Build Coastguard Worker 
Add(const char * str,bool copy_string)818*795d594fSAndroid Build Coastguard Worker   void Add(const char* str, bool copy_string) {
819*795d594fSAndroid Build Coastguard Worker     DCHECK(!finished_);
820*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(copy_string)) {
821*795d594fSAndroid Build Coastguard Worker       // Check whether it's already there.
822*795d594fSAndroid Build Coastguard Worker       Entry entry(str);
823*795d594fSAndroid Build Coastguard Worker       if (table_.find(entry) != table_.end()) {
824*795d594fSAndroid Build Coastguard Worker         return;
825*795d594fSAndroid Build Coastguard Worker       }
826*795d594fSAndroid Build Coastguard Worker 
827*795d594fSAndroid Build Coastguard Worker       // Make a copy.
828*795d594fSAndroid Build Coastguard Worker       size_t str_len = strlen(str);
829*795d594fSAndroid Build Coastguard Worker       char* copy = new char[str_len + 1];
830*795d594fSAndroid Build Coastguard Worker       strlcpy(copy, str, str_len + 1);
831*795d594fSAndroid Build Coastguard Worker       string_backup_.emplace_back(copy);
832*795d594fSAndroid Build Coastguard Worker       str = copy;
833*795d594fSAndroid Build Coastguard Worker     }
834*795d594fSAndroid Build Coastguard Worker     Entry entry(str);
835*795d594fSAndroid Build Coastguard Worker     table_.insert(entry);
836*795d594fSAndroid Build Coastguard Worker   }
837*795d594fSAndroid Build Coastguard Worker 
838*795d594fSAndroid Build Coastguard Worker   // Update all entries and give them an index. Note that this is likely not the insertion order,
839*795d594fSAndroid Build Coastguard Worker   // as the set will with high likelihood reorder elements. Thus, Add must not be called after
840*795d594fSAndroid Build Coastguard Worker   // Finish, and Finish must be called before IndexOf. In that case, WriteTo will walk in
841*795d594fSAndroid Build Coastguard Worker   // the same order as Finish, and indices will agree. The order invariant, as well as indices,
842*795d594fSAndroid Build Coastguard Worker   // are enforced through debug checks.
Finish()843*795d594fSAndroid Build Coastguard Worker   void Finish() {
844*795d594fSAndroid Build Coastguard Worker     DCHECK(!finished_);
845*795d594fSAndroid Build Coastguard Worker     finished_ = true;
846*795d594fSAndroid Build Coastguard Worker     uint32_t index = 0;
847*795d594fSAndroid Build Coastguard Worker     for (auto& entry : table_) {
848*795d594fSAndroid Build Coastguard Worker       entry.index = index;
849*795d594fSAndroid Build Coastguard Worker       ++index;
850*795d594fSAndroid Build Coastguard Worker     }
851*795d594fSAndroid Build Coastguard Worker   }
852*795d594fSAndroid Build Coastguard Worker 
IndexOf(const char * s) const853*795d594fSAndroid Build Coastguard Worker   size_t IndexOf(const char* s) const {
854*795d594fSAndroid Build Coastguard Worker     DCHECK(finished_);
855*795d594fSAndroid Build Coastguard Worker     Entry entry(s);
856*795d594fSAndroid Build Coastguard Worker     auto it = table_.find(entry);
857*795d594fSAndroid Build Coastguard Worker     if (it == table_.end()) {
858*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "IndexOf(\"" << s << "\") failed";
859*795d594fSAndroid Build Coastguard Worker     }
860*795d594fSAndroid Build Coastguard Worker     return it->index;
861*795d594fSAndroid Build Coastguard Worker   }
862*795d594fSAndroid Build Coastguard Worker 
Size() const863*795d594fSAndroid Build Coastguard Worker   size_t Size() const {
864*795d594fSAndroid Build Coastguard Worker     return table_.size();
865*795d594fSAndroid Build Coastguard Worker   }
866*795d594fSAndroid Build Coastguard Worker 
WriteTo(std::vector<uint8_t> & bytes) const867*795d594fSAndroid Build Coastguard Worker   void WriteTo(std::vector<uint8_t>& bytes) const {
868*795d594fSAndroid Build Coastguard Worker     DCHECK(finished_);
869*795d594fSAndroid Build Coastguard Worker     uint32_t cur_index = 0;
870*795d594fSAndroid Build Coastguard Worker     for (const auto& entry : table_) {
871*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(cur_index++, entry.index);
872*795d594fSAndroid Build Coastguard Worker 
873*795d594fSAndroid Build Coastguard Worker       size_t s_len = CountModifiedUtf8Chars(entry.data);
874*795d594fSAndroid Build Coastguard Worker       std::unique_ptr<uint16_t[]> s_utf16(new uint16_t[s_len]);
875*795d594fSAndroid Build Coastguard Worker       ConvertModifiedUtf8ToUtf16(s_utf16.get(), entry.data);
876*795d594fSAndroid Build Coastguard Worker       AppendUtf16BE(bytes, s_utf16.get(), s_len);
877*795d594fSAndroid Build Coastguard Worker     }
878*795d594fSAndroid Build Coastguard Worker   }
879*795d594fSAndroid Build Coastguard Worker 
880*795d594fSAndroid Build Coastguard Worker  private:
881*795d594fSAndroid Build Coastguard Worker   std::unordered_set<Entry, EntryHash> table_;
882*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<char[]>> string_backup_;
883*795d594fSAndroid Build Coastguard Worker 
884*795d594fSAndroid Build Coastguard Worker   bool finished_;
885*795d594fSAndroid Build Coastguard Worker 
886*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(StringTable);
887*795d594fSAndroid Build Coastguard Worker };
888*795d594fSAndroid Build Coastguard Worker 
889*795d594fSAndroid Build Coastguard Worker 
GetMethodSourceFile(ArtMethod * method)890*795d594fSAndroid Build Coastguard Worker static const char* GetMethodSourceFile(ArtMethod* method)
891*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
892*795d594fSAndroid Build Coastguard Worker   DCHECK(method != nullptr);
893*795d594fSAndroid Build Coastguard Worker   const char* source_file = method->GetDeclaringClassSourceFile();
894*795d594fSAndroid Build Coastguard Worker   return (source_file != nullptr) ? source_file : "";
895*795d594fSAndroid Build Coastguard Worker }
896*795d594fSAndroid Build Coastguard Worker 
897*795d594fSAndroid Build Coastguard Worker /*
898*795d594fSAndroid Build Coastguard Worker  * The data we send to DDMS contains everything we have recorded.
899*795d594fSAndroid Build Coastguard Worker  *
900*795d594fSAndroid Build Coastguard Worker  * Message header (all values big-endian):
901*795d594fSAndroid Build Coastguard Worker  * (1b) message header len (to allow future expansion); includes itself
902*795d594fSAndroid Build Coastguard Worker  * (1b) entry header len
903*795d594fSAndroid Build Coastguard Worker  * (1b) stack frame len
904*795d594fSAndroid Build Coastguard Worker  * (2b) number of entries
905*795d594fSAndroid Build Coastguard Worker  * (4b) offset to string table from start of message
906*795d594fSAndroid Build Coastguard Worker  * (2b) number of class name strings
907*795d594fSAndroid Build Coastguard Worker  * (2b) number of method name strings
908*795d594fSAndroid Build Coastguard Worker  * (2b) number of source file name strings
909*795d594fSAndroid Build Coastguard Worker  * For each entry:
910*795d594fSAndroid Build Coastguard Worker  *   (4b) total allocation size
911*795d594fSAndroid Build Coastguard Worker  *   (2b) thread id
912*795d594fSAndroid Build Coastguard Worker  *   (2b) allocated object's class name index
913*795d594fSAndroid Build Coastguard Worker  *   (1b) stack depth
914*795d594fSAndroid Build Coastguard Worker  *   For each stack frame:
915*795d594fSAndroid Build Coastguard Worker  *     (2b) method's class name
916*795d594fSAndroid Build Coastguard Worker  *     (2b) method name
917*795d594fSAndroid Build Coastguard Worker  *     (2b) method source file
918*795d594fSAndroid Build Coastguard Worker  *     (2b) line number, clipped to 32767; -2 if native; -1 if no source
919*795d594fSAndroid Build Coastguard Worker  * (xb) class name strings
920*795d594fSAndroid Build Coastguard Worker  * (xb) method name strings
921*795d594fSAndroid Build Coastguard Worker  * (xb) source file strings
922*795d594fSAndroid Build Coastguard Worker  *
923*795d594fSAndroid Build Coastguard Worker  * As with other DDM traffic, strings are sent as a 4-byte length
924*795d594fSAndroid Build Coastguard Worker  * followed by UTF-16 data.
925*795d594fSAndroid Build Coastguard Worker  *
926*795d594fSAndroid Build Coastguard Worker  * We send up 16-bit unsigned indexes into string tables.  In theory there
927*795d594fSAndroid Build Coastguard Worker  * can be (kMaxAllocRecordStackDepth * alloc_record_max_) unique strings in
928*795d594fSAndroid Build Coastguard Worker  * each table, but in practice there should be far fewer.
929*795d594fSAndroid Build Coastguard Worker  *
930*795d594fSAndroid Build Coastguard Worker  * The chief reason for using a string table here is to keep the size of
931*795d594fSAndroid Build Coastguard Worker  * the DDMS message to a minimum.  This is partly to make the protocol
932*795d594fSAndroid Build Coastguard Worker  * efficient, but also because we have to form the whole thing up all at
933*795d594fSAndroid Build Coastguard Worker  * once in a memory buffer.
934*795d594fSAndroid Build Coastguard Worker  *
935*795d594fSAndroid Build Coastguard Worker  * We use separate string tables for class names, method names, and source
936*795d594fSAndroid Build Coastguard Worker  * files to keep the indexes small.  There will generally be no overlap
937*795d594fSAndroid Build Coastguard Worker  * between the contents of these tables.
938*795d594fSAndroid Build Coastguard Worker  */
GetRecentAllocations()939*795d594fSAndroid Build Coastguard Worker jbyteArray Dbg::GetRecentAllocations() {
940*795d594fSAndroid Build Coastguard Worker   if ((false)) {
941*795d594fSAndroid Build Coastguard Worker     DumpRecentAllocations();
942*795d594fSAndroid Build Coastguard Worker   }
943*795d594fSAndroid Build Coastguard Worker 
944*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
945*795d594fSAndroid Build Coastguard Worker   std::vector<uint8_t> bytes;
946*795d594fSAndroid Build Coastguard Worker   {
947*795d594fSAndroid Build Coastguard Worker     MutexLock mu(self, *Locks::alloc_tracker_lock_);
948*795d594fSAndroid Build Coastguard Worker     gc::AllocRecordObjectMap* records = Runtime::Current()->GetHeap()->GetAllocationRecords();
949*795d594fSAndroid Build Coastguard Worker     // In case this method is called when allocation tracker is not enabled,
950*795d594fSAndroid Build Coastguard Worker     // we should still send some data back.
951*795d594fSAndroid Build Coastguard Worker     gc::AllocRecordObjectMap fallback_record_map;
952*795d594fSAndroid Build Coastguard Worker     if (records == nullptr) {
953*795d594fSAndroid Build Coastguard Worker       CHECK(!Runtime::Current()->GetHeap()->IsAllocTrackingEnabled());
954*795d594fSAndroid Build Coastguard Worker       records = &fallback_record_map;
955*795d594fSAndroid Build Coastguard Worker     }
956*795d594fSAndroid Build Coastguard Worker     // We don't need to wait on the condition variable records->new_record_condition_, because this
957*795d594fSAndroid Build Coastguard Worker     // function only reads the class objects, which are already marked so it doesn't change their
958*795d594fSAndroid Build Coastguard Worker     // reachability.
959*795d594fSAndroid Build Coastguard Worker 
960*795d594fSAndroid Build Coastguard Worker     //
961*795d594fSAndroid Build Coastguard Worker     // Part 1: generate string tables.
962*795d594fSAndroid Build Coastguard Worker     //
963*795d594fSAndroid Build Coastguard Worker     StringTable class_names;
964*795d594fSAndroid Build Coastguard Worker     StringTable method_names;
965*795d594fSAndroid Build Coastguard Worker     StringTable filenames;
966*795d594fSAndroid Build Coastguard Worker 
967*795d594fSAndroid Build Coastguard Worker     VLOG(jdwp) << "Collecting StringTables.";
968*795d594fSAndroid Build Coastguard Worker 
969*795d594fSAndroid Build Coastguard Worker     const uint16_t capped_count = CappedAllocRecordCount(records->GetRecentAllocationSize());
970*795d594fSAndroid Build Coastguard Worker     uint16_t count = capped_count;
971*795d594fSAndroid Build Coastguard Worker     size_t alloc_byte_count = 0;
972*795d594fSAndroid Build Coastguard Worker     for (auto it = records->RBegin(), end = records->REnd();
973*795d594fSAndroid Build Coastguard Worker          count > 0 && it != end; count--, it++) {
974*795d594fSAndroid Build Coastguard Worker       const gc::AllocRecord* record = &it->second;
975*795d594fSAndroid Build Coastguard Worker       std::string temp;
976*795d594fSAndroid Build Coastguard Worker       const char* class_descr = record->GetClassDescriptor(&temp);
977*795d594fSAndroid Build Coastguard Worker       class_names.Add(class_descr, !temp.empty());
978*795d594fSAndroid Build Coastguard Worker 
979*795d594fSAndroid Build Coastguard Worker       // Size + tid + class name index + stack depth.
980*795d594fSAndroid Build Coastguard Worker       alloc_byte_count += 4u + 2u + 2u + 1u;
981*795d594fSAndroid Build Coastguard Worker 
982*795d594fSAndroid Build Coastguard Worker       for (size_t i = 0, depth = record->GetDepth(); i < depth; i++) {
983*795d594fSAndroid Build Coastguard Worker         ArtMethod* m = record->StackElement(i).GetMethod();
984*795d594fSAndroid Build Coastguard Worker         class_names.Add(m->GetDeclaringClassDescriptor(), false);
985*795d594fSAndroid Build Coastguard Worker         method_names.Add(m->GetName(), false);
986*795d594fSAndroid Build Coastguard Worker         filenames.Add(GetMethodSourceFile(m), false);
987*795d594fSAndroid Build Coastguard Worker       }
988*795d594fSAndroid Build Coastguard Worker 
989*795d594fSAndroid Build Coastguard Worker       // Depth * (class index + method name index + file name index + line number).
990*795d594fSAndroid Build Coastguard Worker       alloc_byte_count += record->GetDepth() * (2u + 2u + 2u + 2u);
991*795d594fSAndroid Build Coastguard Worker     }
992*795d594fSAndroid Build Coastguard Worker 
993*795d594fSAndroid Build Coastguard Worker     class_names.Finish();
994*795d594fSAndroid Build Coastguard Worker     method_names.Finish();
995*795d594fSAndroid Build Coastguard Worker     filenames.Finish();
996*795d594fSAndroid Build Coastguard Worker     VLOG(jdwp) << "Done collecting StringTables:" << std::endl
997*795d594fSAndroid Build Coastguard Worker                << "  ClassNames: " << class_names.Size() << std::endl
998*795d594fSAndroid Build Coastguard Worker                << "  MethodNames: " << method_names.Size() << std::endl
999*795d594fSAndroid Build Coastguard Worker                << "  Filenames: " << filenames.Size();
1000*795d594fSAndroid Build Coastguard Worker 
1001*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << "recent allocation records: " << capped_count;
1002*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << "allocation records all objects: " << records->Size();
1003*795d594fSAndroid Build Coastguard Worker 
1004*795d594fSAndroid Build Coastguard Worker     //
1005*795d594fSAndroid Build Coastguard Worker     // Part 2: Generate the output and store it in the buffer.
1006*795d594fSAndroid Build Coastguard Worker     //
1007*795d594fSAndroid Build Coastguard Worker 
1008*795d594fSAndroid Build Coastguard Worker     // (1b) message header len (to allow future expansion); includes itself
1009*795d594fSAndroid Build Coastguard Worker     // (1b) entry header len
1010*795d594fSAndroid Build Coastguard Worker     // (1b) stack frame len
1011*795d594fSAndroid Build Coastguard Worker     const int kMessageHeaderLen = 15;
1012*795d594fSAndroid Build Coastguard Worker     const int kEntryHeaderLen = 9;
1013*795d594fSAndroid Build Coastguard Worker     const int kStackFrameLen = 8;
1014*795d594fSAndroid Build Coastguard Worker     Append1BE(bytes, kMessageHeaderLen);
1015*795d594fSAndroid Build Coastguard Worker     Append1BE(bytes, kEntryHeaderLen);
1016*795d594fSAndroid Build Coastguard Worker     Append1BE(bytes, kStackFrameLen);
1017*795d594fSAndroid Build Coastguard Worker 
1018*795d594fSAndroid Build Coastguard Worker     // (2b) number of entries
1019*795d594fSAndroid Build Coastguard Worker     // (4b) offset to string table from start of message
1020*795d594fSAndroid Build Coastguard Worker     // (2b) number of class name strings
1021*795d594fSAndroid Build Coastguard Worker     // (2b) number of method name strings
1022*795d594fSAndroid Build Coastguard Worker     // (2b) number of source file name strings
1023*795d594fSAndroid Build Coastguard Worker     Append2BE(bytes, capped_count);
1024*795d594fSAndroid Build Coastguard Worker     size_t string_table_offset = bytes.size();
1025*795d594fSAndroid Build Coastguard Worker     Append4BE(bytes, 0);  // We'll patch this later...
1026*795d594fSAndroid Build Coastguard Worker     Append2BE(bytes, class_names.Size());
1027*795d594fSAndroid Build Coastguard Worker     Append2BE(bytes, method_names.Size());
1028*795d594fSAndroid Build Coastguard Worker     Append2BE(bytes, filenames.Size());
1029*795d594fSAndroid Build Coastguard Worker 
1030*795d594fSAndroid Build Coastguard Worker     VLOG(jdwp) << "Dumping allocations with stacks";
1031*795d594fSAndroid Build Coastguard Worker 
1032*795d594fSAndroid Build Coastguard Worker     // Enlarge the vector for the allocation data.
1033*795d594fSAndroid Build Coastguard Worker     size_t reserve_size = bytes.size() + alloc_byte_count;
1034*795d594fSAndroid Build Coastguard Worker     bytes.reserve(reserve_size);
1035*795d594fSAndroid Build Coastguard Worker 
1036*795d594fSAndroid Build Coastguard Worker     std::string temp;
1037*795d594fSAndroid Build Coastguard Worker     count = capped_count;
1038*795d594fSAndroid Build Coastguard Worker     // The last "count" number of allocation records in "records" are the most recent "count" number
1039*795d594fSAndroid Build Coastguard Worker     // of allocations. Reverse iterate to get them. The most recent allocation is sent first.
1040*795d594fSAndroid Build Coastguard Worker     for (auto it = records->RBegin(), end = records->REnd();
1041*795d594fSAndroid Build Coastguard Worker          count > 0 && it != end; count--, it++) {
1042*795d594fSAndroid Build Coastguard Worker       // For each entry:
1043*795d594fSAndroid Build Coastguard Worker       // (4b) total allocation size
1044*795d594fSAndroid Build Coastguard Worker       // (2b) thread id
1045*795d594fSAndroid Build Coastguard Worker       // (2b) allocated object's class name index
1046*795d594fSAndroid Build Coastguard Worker       // (1b) stack depth
1047*795d594fSAndroid Build Coastguard Worker       const gc::AllocRecord* record = &it->second;
1048*795d594fSAndroid Build Coastguard Worker       size_t stack_depth = record->GetDepth();
1049*795d594fSAndroid Build Coastguard Worker       size_t allocated_object_class_name_index =
1050*795d594fSAndroid Build Coastguard Worker           class_names.IndexOf(record->GetClassDescriptor(&temp));
1051*795d594fSAndroid Build Coastguard Worker       Append4BE(bytes, record->ByteCount());
1052*795d594fSAndroid Build Coastguard Worker       Append2BE(bytes, static_cast<uint16_t>(record->GetTid()));
1053*795d594fSAndroid Build Coastguard Worker       Append2BE(bytes, allocated_object_class_name_index);
1054*795d594fSAndroid Build Coastguard Worker       Append1BE(bytes, stack_depth);
1055*795d594fSAndroid Build Coastguard Worker 
1056*795d594fSAndroid Build Coastguard Worker       for (size_t stack_frame = 0; stack_frame < stack_depth; ++stack_frame) {
1057*795d594fSAndroid Build Coastguard Worker         // For each stack frame:
1058*795d594fSAndroid Build Coastguard Worker         // (2b) method's class name
1059*795d594fSAndroid Build Coastguard Worker         // (2b) method name
1060*795d594fSAndroid Build Coastguard Worker         // (2b) method source file
1061*795d594fSAndroid Build Coastguard Worker         // (2b) line number, clipped to 32767; -2 if native; -1 if no source
1062*795d594fSAndroid Build Coastguard Worker         ArtMethod* m = record->StackElement(stack_frame).GetMethod();
1063*795d594fSAndroid Build Coastguard Worker         size_t class_name_index = class_names.IndexOf(m->GetDeclaringClassDescriptor());
1064*795d594fSAndroid Build Coastguard Worker         size_t method_name_index = method_names.IndexOf(m->GetName());
1065*795d594fSAndroid Build Coastguard Worker         size_t file_name_index = filenames.IndexOf(GetMethodSourceFile(m));
1066*795d594fSAndroid Build Coastguard Worker         Append2BE(bytes, class_name_index);
1067*795d594fSAndroid Build Coastguard Worker         Append2BE(bytes, method_name_index);
1068*795d594fSAndroid Build Coastguard Worker         Append2BE(bytes, file_name_index);
1069*795d594fSAndroid Build Coastguard Worker         Append2BE(bytes, record->StackElement(stack_frame).ComputeLineNumber());
1070*795d594fSAndroid Build Coastguard Worker       }
1071*795d594fSAndroid Build Coastguard Worker     }
1072*795d594fSAndroid Build Coastguard Worker 
1073*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(bytes.size(), reserve_size);
1074*795d594fSAndroid Build Coastguard Worker     VLOG(jdwp) << "Dumping tables.";
1075*795d594fSAndroid Build Coastguard Worker 
1076*795d594fSAndroid Build Coastguard Worker     // (xb) class name strings
1077*795d594fSAndroid Build Coastguard Worker     // (xb) method name strings
1078*795d594fSAndroid Build Coastguard Worker     // (xb) source file strings
1079*795d594fSAndroid Build Coastguard Worker     Set4BE(&bytes[string_table_offset], bytes.size());
1080*795d594fSAndroid Build Coastguard Worker     class_names.WriteTo(bytes);
1081*795d594fSAndroid Build Coastguard Worker     method_names.WriteTo(bytes);
1082*795d594fSAndroid Build Coastguard Worker     filenames.WriteTo(bytes);
1083*795d594fSAndroid Build Coastguard Worker 
1084*795d594fSAndroid Build Coastguard Worker     VLOG(jdwp) << "GetRecentAllocations: data created. " << bytes.size();
1085*795d594fSAndroid Build Coastguard Worker   }
1086*795d594fSAndroid Build Coastguard Worker   JNIEnv* env = self->GetJniEnv();
1087*795d594fSAndroid Build Coastguard Worker   jbyteArray result = env->NewByteArray(bytes.size());
1088*795d594fSAndroid Build Coastguard Worker   if (result != nullptr) {
1089*795d594fSAndroid Build Coastguard Worker     env->SetByteArrayRegion(result, 0, bytes.size(), reinterpret_cast<const jbyte*>(&bytes[0]));
1090*795d594fSAndroid Build Coastguard Worker   }
1091*795d594fSAndroid Build Coastguard Worker   return result;
1092*795d594fSAndroid Build Coastguard Worker }
1093*795d594fSAndroid Build Coastguard Worker 
ThreadStart(Thread * self)1094*795d594fSAndroid Build Coastguard Worker void Dbg::DbgThreadLifecycleCallback::ThreadStart(Thread* self) {
1095*795d594fSAndroid Build Coastguard Worker   Dbg::PostThreadStart(self);
1096*795d594fSAndroid Build Coastguard Worker }
1097*795d594fSAndroid Build Coastguard Worker 
ThreadDeath(Thread * self)1098*795d594fSAndroid Build Coastguard Worker void Dbg::DbgThreadLifecycleCallback::ThreadDeath(Thread* self) {
1099*795d594fSAndroid Build Coastguard Worker   Dbg::PostThreadDeath(self);
1100*795d594fSAndroid Build Coastguard Worker }
1101*795d594fSAndroid Build Coastguard Worker 
1102*795d594fSAndroid Build Coastguard Worker }  // namespace art
1103