• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * Dalvik-specific side of debugger support.  (The JDWP code is intended to
19  * be relatively generic.)
20  */
21 #ifndef ART_RUNTIME_DEBUGGER_H_
22 #define ART_RUNTIME_DEBUGGER_H_
23 
24 #include <pthread.h>
25 
26 #include <string>
27 
28 #include "jdwp/jdwp.h"
29 #include "jni.h"
30 #include "jvalue.h"
31 #include "root_visitor.h"
32 #include "thread_state.h"
33 
34 namespace art {
35 namespace mirror {
36 class ArtMethod;
37 class Class;
38 class Object;
39 class Throwable;
40 }  // namespace mirror
41 struct AllocRecord;
42 class Thread;
43 class ThrowLocation;
44 
45 /*
46  * Invoke-during-breakpoint support.
47  */
48 struct DebugInvokeReq {
DebugInvokeReqDebugInvokeReq49   DebugInvokeReq()
50       : ready(false), invoke_needed_(false),
51         receiver_(NULL), thread_(NULL), class_(NULL), method_(NULL),
52         arg_count_(0), arg_values_(NULL), options_(0), error(JDWP::ERR_NONE),
53         result_tag(JDWP::JT_VOID), exception(0),
54         lock_("a DebugInvokeReq lock", kBreakpointInvokeLock),
55         cond_("a DebugInvokeReq condition variable", lock_) {
56   }
57 
58   /* boolean; only set when we're in the tail end of an event handler */
59   bool ready;
60 
61   /* boolean; set if the JDWP thread wants this thread to do work */
62   bool invoke_needed_;
63 
64   /* request */
65   mirror::Object* receiver_;      /* not used for ClassType.InvokeMethod */
66   mirror::Object* thread_;
67   mirror::Class* class_;
68   mirror::ArtMethod* method_;
69   uint32_t arg_count_;
70   uint64_t* arg_values_;   /* will be NULL if arg_count_ == 0 */
71   uint32_t options_;
72 
73   /* result */
74   JDWP::JdwpError error;
75   JDWP::JdwpTag result_tag;
76   JValue result_value;
77   JDWP::ObjectId exception;
78 
79   /* condition variable to wait on while the method executes */
80   Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
81   ConditionVariable cond_ GUARDED_BY(lock_);
82 };
83 
84 class Dbg {
85  public:
86   static bool ParseJdwpOptions(const std::string& options);
87   static void SetJdwpAllowed(bool allowed);
88 
89   static void StartJdwp();
90   static void StopJdwp();
91 
92   // Invoked by the GC in case we need to keep DDMS informed.
93   static void GcDidFinish() LOCKS_EXCLUDED(Locks::mutator_lock_);
94 
95   // Return the DebugInvokeReq for the current thread.
96   static DebugInvokeReq* GetInvokeReq();
97 
98   static Thread* GetDebugThread();
99   static void ClearWaitForEventThread();
100 
101   /*
102    * Enable/disable breakpoints and step modes.  Used to provide a heads-up
103    * when the debugger attaches.
104    */
105   static void Connected();
106   static void GoActive() LOCKS_EXCLUDED(Locks::breakpoint_lock_, Locks::mutator_lock_);
107   static void Disconnected() LOCKS_EXCLUDED(Locks::mutator_lock_);
108   static void Disposed();
109 
110   // Returns true if we're actually debugging with a real debugger, false if it's
111   // just DDMS (or nothing at all).
112   static bool IsDebuggerActive();
113 
114   // Returns true if we had -Xrunjdwp or -agentlib:jdwp= on the command line.
115   static bool IsJdwpConfigured();
116 
117   static bool IsDisposed();
118 
119   /*
120    * Time, in milliseconds, since the last debugger activity.  Does not
121    * include DDMS activity.  Returns -1 if there has been no activity.
122    * Returns 0 if we're in the middle of handling a debugger request.
123    */
124   static int64_t LastDebuggerActivity();
125 
126   static void UndoDebuggerSuspensions();
127 
128   /*
129    * Class, Object, Array
130    */
131   static std::string GetClassName(JDWP::RefTypeId id)
132       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
133   static JDWP::JdwpError GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId& class_object_id)
134       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
135   static JDWP::JdwpError GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId& superclass_id)
136       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
137   static JDWP::JdwpError GetClassLoader(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply)
138       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
139   static JDWP::JdwpError GetModifiers(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply)
140       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
141   static JDWP::JdwpError GetReflectedType(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply)
142       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
143   static void GetClassList(std::vector<JDWP::RefTypeId>& classes)
144       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
145   static JDWP::JdwpError GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* pTypeTag,
146                                       uint32_t* pStatus, std::string* pDescriptor)
147       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
148   static void FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>& ids)
149       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
150   static JDWP::JdwpError GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* pReply)
151       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
152   static JDWP::JdwpError GetSignature(JDWP::RefTypeId ref_type_id, std::string& signature)
153       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
154   static JDWP::JdwpError GetSourceFile(JDWP::RefTypeId ref_type_id, std::string& source_file)
155       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
156   static JDWP::JdwpError GetObjectTag(JDWP::ObjectId object_id, uint8_t& tag)
157       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
158   static size_t GetTagWidth(JDWP::JdwpTag tag);
159 
160   static JDWP::JdwpError GetArrayLength(JDWP::ObjectId array_id, int& length)
161       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
162   static JDWP::JdwpError OutputArray(JDWP::ObjectId array_id, int offset, int count,
163                                      JDWP::ExpandBuf* pReply)
164       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
165   static JDWP::JdwpError SetArrayElements(JDWP::ObjectId array_id, int offset, int count,
166                                           JDWP::Request& request)
167       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
168 
169   static JDWP::ObjectId CreateString(const std::string& str)
170       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
171   static JDWP::JdwpError CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId& new_object)
172       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
173   static JDWP::JdwpError CreateArrayObject(JDWP::RefTypeId array_class_id, uint32_t length,
174                                            JDWP::ObjectId& new_array)
175       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
176 
177   static bool MatchType(JDWP::RefTypeId instance_class_id, JDWP::RefTypeId class_id)
178       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
179 
180   //
181   // Monitors.
182   //
183   static JDWP::JdwpError GetMonitorInfo(JDWP::ObjectId object_id, JDWP::ExpandBuf* reply)
184       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
185   static JDWP::JdwpError GetOwnedMonitors(JDWP::ObjectId thread_id,
186                                           std::vector<JDWP::ObjectId>& monitors,
187                                           std::vector<uint32_t>& stack_depths)
188       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
189   static JDWP::JdwpError GetContendedMonitor(JDWP::ObjectId thread_id, JDWP::ObjectId& contended_monitor)
190       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
191 
192   //
193   // Heap.
194   //
195   static JDWP::JdwpError GetInstanceCounts(const std::vector<JDWP::RefTypeId>& class_ids,
196                                            std::vector<uint64_t>& counts)
197       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
198   static JDWP::JdwpError GetInstances(JDWP::RefTypeId class_id, int32_t max_count,
199                                       std::vector<JDWP::ObjectId>& instances)
200       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
201   static JDWP::JdwpError GetReferringObjects(JDWP::ObjectId object_id, int32_t max_count,
202                                              std::vector<JDWP::ObjectId>& referring_objects)
203       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
204   static JDWP::JdwpError DisableCollection(JDWP::ObjectId object_id)
205       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
206   static JDWP::JdwpError EnableCollection(JDWP::ObjectId object_id)
207       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
208   static JDWP::JdwpError IsCollected(JDWP::ObjectId object_id, bool& is_collected)
209       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
210   static void DisposeObject(JDWP::ObjectId object_id, uint32_t reference_count)
211       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
212 
213   //
214   // Methods and fields.
215   //
216   static std::string GetMethodName(JDWP::MethodId method_id)
217       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
218   static JDWP::JdwpError OutputDeclaredFields(JDWP::RefTypeId ref_type_id, bool with_generic,
219                                               JDWP::ExpandBuf* pReply)
220       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
221   static JDWP::JdwpError OutputDeclaredMethods(JDWP::RefTypeId ref_type_id, bool with_generic,
222                                                JDWP::ExpandBuf* pReply)
223       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
224   static JDWP::JdwpError OutputDeclaredInterfaces(JDWP::RefTypeId ref_type_id,
225                                                   JDWP::ExpandBuf* pReply)
226       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
227   static void OutputLineTable(JDWP::RefTypeId ref_type_id, JDWP::MethodId method_id,
228                               JDWP::ExpandBuf* pReply)
229       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
230   static void OutputVariableTable(JDWP::RefTypeId ref_type_id, JDWP::MethodId id, bool with_generic,
231                                   JDWP::ExpandBuf* pReply)
232       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
233   static JDWP::JdwpError GetBytecodes(JDWP::RefTypeId class_id, JDWP::MethodId method_id,
234                                       std::vector<uint8_t>& bytecodes)
235       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
236 
237   static std::string GetFieldName(JDWP::FieldId field_id)
238       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
239   static JDWP::JdwpTag GetFieldBasicTag(JDWP::FieldId field_id)
240       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
241   static JDWP::JdwpTag GetStaticFieldBasicTag(JDWP::FieldId field_id)
242       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
243   static JDWP::JdwpError GetFieldValue(JDWP::ObjectId object_id, JDWP::FieldId field_id,
244                                        JDWP::ExpandBuf* pReply)
245       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
246   static JDWP::JdwpError SetFieldValue(JDWP::ObjectId object_id, JDWP::FieldId field_id,
247                                        uint64_t value, int width)
248       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
249   static JDWP::JdwpError GetStaticFieldValue(JDWP::RefTypeId ref_type_id, JDWP::FieldId field_id,
250                                              JDWP::ExpandBuf* pReply)
251       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
252   static JDWP::JdwpError SetStaticFieldValue(JDWP::FieldId field_id, uint64_t value, int width)
253       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
254 
255   static std::string StringToUtf8(JDWP::ObjectId string_id)
256       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
257 
258   /*
259    * Thread, ThreadGroup, Frame
260    */
261   static JDWP::JdwpError GetThreadName(JDWP::ObjectId thread_id, std::string& name)
262       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
263       LOCKS_EXCLUDED(Locks::thread_list_lock_);
264   static JDWP::JdwpError GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply);
265   static std::string GetThreadGroupName(JDWP::ObjectId thread_group_id);
266   static JDWP::ObjectId GetThreadGroupParent(JDWP::ObjectId thread_group_id)
267       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
268   static JDWP::ObjectId GetSystemThreadGroupId()
269       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
270   static JDWP::ObjectId GetMainThreadGroupId();
271 
272   static JDWP::JdwpThreadStatus ToJdwpThreadStatus(ThreadState state);
273   static JDWP::JdwpError GetThreadStatus(JDWP::ObjectId thread_id, JDWP::JdwpThreadStatus* pThreadStatus, JDWP::JdwpSuspendStatus* pSuspendStatus);
274   static JDWP::JdwpError GetThreadDebugSuspendCount(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply);
275   // static void WaitForSuspend(JDWP::ObjectId thread_id);
276 
277   // Fills 'thread_ids' with the threads in the given thread group. If thread_group_id == 0,
278   // returns all threads.
279   static void GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>& thread_ids)
280       LOCKS_EXCLUDED(Locks::thread_list_lock_)
281       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
282   static void GetChildThreadGroups(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>& child_thread_group_ids);
283 
284   static JDWP::JdwpError GetThreadFrameCount(JDWP::ObjectId thread_id, size_t& result);
285   static JDWP::JdwpError GetThreadFrames(JDWP::ObjectId thread_id, size_t start_frame,
286                                          size_t frame_count, JDWP::ExpandBuf* buf)
287       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
288 
289   static JDWP::ObjectId GetThreadSelfId()
290       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
291   static void SuspendVM()
292       LOCKS_EXCLUDED(Locks::thread_list_lock_,
293                      Locks::thread_suspend_count_lock_);
294   static void ResumeVM();
295   static JDWP::JdwpError SuspendThread(JDWP::ObjectId thread_id, bool request_suspension = true)
296       LOCKS_EXCLUDED(Locks::mutator_lock_,
297                      Locks::thread_list_lock_,
298                      Locks::thread_suspend_count_lock_);
299 
300   static void ResumeThread(JDWP::ObjectId thread_id)
301       LOCKS_EXCLUDED(Locks::thread_list_lock_,
302                      Locks::thread_suspend_count_lock_)
303       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
304   static void SuspendSelf();
305 
306   static JDWP::JdwpError GetThisObject(JDWP::ObjectId thread_id, JDWP::FrameId frame_id,
307                                        JDWP::ObjectId* result)
308       LOCKS_EXCLUDED(Locks::thread_list_lock_,
309                      Locks::thread_suspend_count_lock_)
310       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
311   static void GetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int slot,
312                             JDWP::JdwpTag tag, uint8_t* buf, size_t expectedLen)
313       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
314   static void SetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int slot,
315                             JDWP::JdwpTag tag, uint64_t value, size_t width)
316       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
317 
318   static JDWP::JdwpError Interrupt(JDWP::ObjectId thread_id);
319 
320   /*
321    * Debugger notification
322    */
323   enum {
324     kBreakpoint     = 0x01,
325     kSingleStep     = 0x02,
326     kMethodEntry    = 0x04,
327     kMethodExit     = 0x08,
328   };
329   static void PostLocationEvent(const mirror::ArtMethod* method, int pcOffset,
330                                 mirror::Object* thisPtr, int eventFlags)
331       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
332   static void PostException(Thread* thread, const ThrowLocation& throw_location,
333                             mirror::ArtMethod* catch_method,
334                             uint32_t catch_dex_pc, mirror::Throwable* exception)
335       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
336   static void PostThreadStart(Thread* t)
337       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
338   static void PostThreadDeath(Thread* t)
339       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
340   static void PostClassPrepare(mirror::Class* c)
341       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
342 
343   static void UpdateDebugger(Thread* thread, mirror::Object* this_object,
344                              const mirror::ArtMethod* method, uint32_t new_dex_pc)
345       LOCKS_EXCLUDED(Locks::breakpoint_lock_)
346       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
347 
348   static void WatchLocation(const JDWP::JdwpLocation* pLoc)
349       LOCKS_EXCLUDED(Locks::breakpoint_lock_)
350       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
351   static void UnwatchLocation(const JDWP::JdwpLocation* pLoc)
352       LOCKS_EXCLUDED(Locks::breakpoint_lock_)
353       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
354   static JDWP::JdwpError ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize size,
355                                        JDWP::JdwpStepDepth depth)
356       LOCKS_EXCLUDED(Locks::breakpoint_lock_)
357       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
358   static void UnconfigureStep(JDWP::ObjectId thread_id) LOCKS_EXCLUDED(Locks::breakpoint_lock_);
359 
360   static JDWP::JdwpError InvokeMethod(JDWP::ObjectId thread_id, JDWP::ObjectId object_id,
361                                       JDWP::RefTypeId class_id, JDWP::MethodId method_id,
362                                       uint32_t arg_count, uint64_t* arg_values,
363                                       JDWP::JdwpTag* arg_types, uint32_t options,
364                                       JDWP::JdwpTag* pResultTag, uint64_t* pResultValue,
365                                       JDWP::ObjectId* pExceptObj)
366       LOCKS_EXCLUDED(Locks::thread_list_lock_,
367                      Locks::thread_suspend_count_lock_)
368       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
369   static void ExecuteMethod(DebugInvokeReq* pReq);
370 
371   /*
372    * DDM support.
373    */
374   static void DdmSendThreadNotification(Thread* t, uint32_t type)
375       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
376   static void DdmSetThreadNotification(bool enable);
377   static bool DdmHandlePacket(JDWP::Request& request, uint8_t** pReplyBuf, int* pReplyLen);
378   static void DdmConnected() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
379   static void DdmDisconnected() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
380   static void DdmSendChunk(uint32_t type, const std::vector<uint8_t>& bytes)
381       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
382   static void DdmSendChunk(uint32_t type, size_t len, const uint8_t* buf)
383       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
384   static void DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count)
385       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
386 
387   /*
388    * Recent allocation tracking support.
389    */
390   static void RecordAllocation(mirror::Class* type, size_t byte_count)
391       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
392   static void SetAllocTrackingEnabled(bool enabled);
IsAllocTrackingEnabled()393   static inline bool IsAllocTrackingEnabled() { return recent_allocation_records_ != NULL; }
394   static jbyteArray GetRecentAllocations() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
395   static void DumpRecentAllocations();
396 
397   enum HpifWhen {
398     HPIF_WHEN_NEVER = 0,
399     HPIF_WHEN_NOW = 1,
400     HPIF_WHEN_NEXT_GC = 2,
401     HPIF_WHEN_EVERY_GC = 3
402   };
403   static int DdmHandleHpifChunk(HpifWhen when)
404       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
405 
406   enum HpsgWhen {
407     HPSG_WHEN_NEVER = 0,
408     HPSG_WHEN_EVERY_GC = 1,
409   };
410   enum HpsgWhat {
411     HPSG_WHAT_MERGED_OBJECTS = 0,
412     HPSG_WHAT_DISTINCT_OBJECTS = 1,
413   };
414   static bool DdmHandleHpsgNhsgChunk(HpsgWhen when, HpsgWhat what, bool native);
415 
416   static void DdmSendHeapInfo(HpifWhen reason)
417       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
418   static void DdmSendHeapSegments(bool native)
419       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
420 
421  private:
422   static void DdmBroadcast(bool connect) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
423   static void PostThreadStartOrStop(Thread*, uint32_t)
424       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
425 
426   static AllocRecord* recent_allocation_records_;
427 };
428 
429 #define CHUNK_TYPE(_name) \
430     static_cast<uint32_t>((_name)[0] << 24 | (_name)[1] << 16 | (_name)[2] << 8 | (_name)[3])
431 
432 }  // namespace art
433 
434 #endif  // ART_RUNTIME_DEBUGGER_H_
435