1872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
2872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Copyright (C) 2008 The Android Open Source Project
3872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
4872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * you may not use this file except in compliance with the License.
6872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * You may obtain a copy of the License at
7872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
8872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
10872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Unless required by applicable law or agreed to in writing, software
11872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * See the License for the specific language governing permissions and
14872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * limitations under the License.
15872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
16872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
17872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "debugger.h"
18872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
193bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes#include <sys/uio.h>
203bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes
21545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes#include <set>
22545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
2346ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe#include "android-base/stringprintf.h"
2446ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
25166db04e259ca51838c311891598664deeed85adIan Rogers#include "arch/context.h"
26c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier#include "art_field-inl.h"
27e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "art_method-inl.h"
28542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe#include "base/enums.h"
2980afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "base/time_utils.h"
30545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes#include "class_linker.h"
312dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "class_linker-inl.h"
324f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h"
339323e6e44060545d6c4f925139572868f65b7fe3David Sehr#include "dex_file_annotations.h"
34776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#include "dex_instruction.h"
356ea1a0e2168c8d9b6d97c075c73a72d84080f45bMingyao Yang#include "entrypoints/runtime_asm_entrypoints.h"
361d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/card_table-inl.h"
378c2ff641294715864013737fdec57cdfd410270cMan Cao#include "gc/allocation_record.h"
38aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier#include "gc/scoped_gc_critical_section.h"
391d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/large_object_space.h"
401d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space-inl.h"
41eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier#include "handle_scope.h"
42cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz#include "jdwp/jdwp_priv.h"
4364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes#include "jdwp/object_registry.h"
4413b27842e88ccf1a42807c92daeb108e867dc4cdAndreas Gampe#include "jni_internal.h"
4528bd2e4f151267b34b8e1eb19c489d8d547bbf5cMathieu Chartier#include "jvalue-inl.h"
462dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class.h"
472dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h"
482dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h"
492dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h"
502dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h"
51b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers#include "mirror/string-inl.h"
522dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/throwable.h"
533398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier#include "obj_ptr-inl.h"
5453b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers#include "reflection.h"
55a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes#include "safe_map.h"
560795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "scoped_thread_state_change-inl.h"
576a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes#include "ScopedLocalRef.h"
58f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes#include "ScopedPrimitiveArray.h"
59eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier#include "handle_scope-inl.h"
60475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes#include "thread_list.h"
612dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "utf.h"
62eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "well_known_classes.h"
63475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes
64872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace art {
65872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
6646ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampeusing android::base::StringPrintf;
6746ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
680462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertz// The key identifying the debugger to update instrumentation.
690462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertzstatic constexpr const char* kDbgInstrumentationKey = "Debugger";
700462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertz
718c2ff641294715864013737fdec57cdfd410270cMan Cao// Limit alloc_record_count to the 2BE value (64k-1) that is the limit of the current protocol.
72306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstromstatic uint16_t CappedAllocRecordCount(size_t alloc_record_count) {
731ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  const size_t cap = 0xffff;
748c2ff641294715864013737fdec57cdfd410270cMan Cao  if (alloc_record_count > cap) {
758c2ff641294715864013737fdec57cdfd410270cMan Cao    return cap;
764345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier  }
778c2ff641294715864013737fdec57cdfd410270cMan Cao  return alloc_record_count;
784345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier}
794345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier
806c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light// Takes a method and returns a 'canonical' one if the method is default (and therefore potentially
816c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light// copied from some other class). This ensures that the debugger does not get confused as to which
826c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light// method we are in.
836c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Lightstatic ArtMethod* GetCanonicalMethod(ArtMethod* m)
84bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
856c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light  if (LIKELY(!m->IsDefault())) {
866c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light    return m;
876c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light  } else {
886c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light    mirror::Class* declaring_class = m->GetDeclaringClass();
896c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light    return declaring_class->FindDeclaredVirtualMethod(declaring_class->GetDexCache(),
906c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light                                                      m->GetDexMethodIndex(),
91542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe                                                      kRuntimePointerSize);
926c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light  }
936c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light}
946c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light
9541af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartierclass Breakpoint : public ValueObject {
960ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi public:
9741af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier  Breakpoint(ArtMethod* method, uint32_t dex_pc, DeoptimizationRequest::Kind deoptimization_kind)
986c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light    : method_(GetCanonicalMethod(method)),
9941af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier      dex_pc_(dex_pc),
10041af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier      deoptimization_kind_(deoptimization_kind) {
101f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    CHECK(deoptimization_kind_ == DeoptimizationRequest::kNothing ||
102f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz          deoptimization_kind_ == DeoptimizationRequest::kSelectiveDeoptimization ||
103f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz          deoptimization_kind_ == DeoptimizationRequest::kFullDeoptimization);
1040ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi  }
105a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz
106bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe  Breakpoint(const Breakpoint& other) REQUIRES_SHARED(Locks::mutator_lock_)
10741af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier    : method_(other.method_),
10841af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier      dex_pc_(other.dex_pc_),
10941af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier      deoptimization_kind_(other.deoptimization_kind_) {}
11041af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier
11141af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier  // Method() is called from root visiting, do not use ScopedObjectAccess here or it can cause
11241af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier  // GC to deadlock if another thread tries to call SuspendAll while the GC is in a runnable state.
11341af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier  ArtMethod* Method() const {
11441af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier    return method_;
1150ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi  }
1163b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier
1170ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi  uint32_t DexPc() const {
1180ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi    return dex_pc_;
1190ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi  }
1200ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi
121f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  DeoptimizationRequest::Kind GetDeoptimizationKind() const {
122f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    return deoptimization_kind_;
1233b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier  }
1240ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi
1256c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light  // Returns true if the method of this breakpoint and the passed in method should be considered the
1266c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light  // same. That is, they are either the same method or they are copied from the same method.
127bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe  bool IsInMethod(ArtMethod* m) const REQUIRES_SHARED(Locks::mutator_lock_) {
1286c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light    return method_ == GetCanonicalMethod(m);
1296c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light  }
1306c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light
1310ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi private:
1320ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi  // The location of this breakpoint.
13341af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier  ArtMethod* method_;
1340ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi  uint32_t dex_pc_;
1350ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi
1360ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi  // Indicates whether breakpoint needs full deoptimization or selective deoptimization.
137f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  DeoptimizationRequest::Kind deoptimization_kind_;
1388696433d1b3d8ba15288483b777edd888de69135Elliott Hughes};
1398696433d1b3d8ba15288483b777edd888de69135Elliott Hughes
140ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertzstatic std::ostream& operator<<(std::ostream& os, const Breakpoint& rhs)
141bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
142709b070044354d9f47641f273edacaeeb0240ab7David Sehr  os << StringPrintf("Breakpoint[%s @%#x]", ArtMethod::PrettyMethod(rhs.Method()).c_str(),
143709b070044354d9f47641f273edacaeeb0240ab7David Sehr                     rhs.DexPc());
1448696433d1b3d8ba15288483b777edd888de69135Elliott Hughes  return os;
1458696433d1b3d8ba15288483b777edd888de69135Elliott Hughes}
1468696433d1b3d8ba15288483b777edd888de69135Elliott Hughes
1473f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertzclass DebugInstrumentationListener FINAL : public instrumentation::InstrumentationListener {
14862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers public:
14962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  DebugInstrumentationListener() {}
15062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  virtual ~DebugInstrumentationListener() {}
15162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
152e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  void MethodEntered(Thread* thread, mirror::Object* this_object, ArtMethod* method,
1539d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz                     uint32_t dex_pc)
154bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
15562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    if (method->IsNative()) {
15662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      // TODO: post location events is a suspension point and native method entry stubs aren't.
15762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      return;
15862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
1599d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    if (IsListeningToDexPcMoved()) {
1609d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // We also listen to kDexPcMoved instrumentation event so we know the DexPcMoved method is
1619d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // going to be called right after us. To avoid sending JDWP events twice for this location,
1629d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // we report the event in DexPcMoved. However, we must remind this is method entry so we
1639d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // send the METHOD_ENTRY event. And we can also group it with other events for this location
1649d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // like BREAKPOINT or SINGLE_STEP (or even METHOD_EXIT if this is a RETURN instruction).
1659d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      thread->SetDebugMethodEntry();
1669d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    } else if (IsListeningToMethodExit() && IsReturn(method, dex_pc)) {
1679d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // We also listen to kMethodExited instrumentation event and the current instruction is a
1689d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // RETURN so we know the MethodExited method is going to be called right after us. To avoid
1699d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // sending JDWP events twice for this location, we report the event(s) in MethodExited.
1709d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // However, we must remind this is method entry so we send the METHOD_ENTRY event. And we can
1719d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // also group it with other events for this location like BREAKPOINT or SINGLE_STEP.
1729d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      thread->SetDebugMethodEntry();
1739d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    } else {
1749d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      Dbg::UpdateDebugger(thread, this_object, method, 0, Dbg::kMethodEntry, nullptr);
1759d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    }
17662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
17762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
178e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  void MethodExited(Thread* thread, mirror::Object* this_object, ArtMethod* method,
1793f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                    uint32_t dex_pc, const JValue& return_value)
180bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
18162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    if (method->IsNative()) {
18262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      // TODO: post location events is a suspension point and native method entry stubs aren't.
18362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      return;
18462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
1859d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    uint32_t events = Dbg::kMethodExit;
1869d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    if (thread->IsDebugMethodEntry()) {
1879d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // It is also the method entry.
1889d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      DCHECK(IsReturn(method, dex_pc));
1899d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      events |= Dbg::kMethodEntry;
1909d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      thread->ClearDebugMethodEntry();
1919d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    }
1929d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    Dbg::UpdateDebugger(thread, this_object, method, dex_pc, events, &return_value);
19362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
19462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
1959d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz  void MethodUnwind(Thread* thread ATTRIBUTE_UNUSED, mirror::Object* this_object ATTRIBUTE_UNUSED,
196e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                    ArtMethod* method, uint32_t dex_pc)
197bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
19862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    // We're not recorded to listen to this kind of event, so complain.
199709b070044354d9f47641f273edacaeeb0240ab7David Sehr    LOG(ERROR) << "Unexpected method unwind event in debugger " << ArtMethod::PrettyMethod(method)
20051db44a194bafc3810a41164a8b39614f10e79dfSebastien Hertz               << " " << dex_pc;
20162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
20262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
203e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  void DexPcMoved(Thread* thread, mirror::Object* this_object, ArtMethod* method,
2043f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                  uint32_t new_dex_pc)
205bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
2069d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    if (IsListeningToMethodExit() && IsReturn(method, new_dex_pc)) {
2079d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // We also listen to kMethodExited instrumentation event and the current instruction is a
2089d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // RETURN so we know the MethodExited method is going to be called right after us. Like in
2099d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // MethodEntered, we delegate event reporting to MethodExited.
2109d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // Besides, if this RETURN instruction is the only one in the method, we can send multiple
2119d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // JDWP events in the same packet: METHOD_ENTRY, METHOD_EXIT, BREAKPOINT and/or SINGLE_STEP.
2129d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      // Therefore, we must not clear the debug method entry flag here.
2139d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    } else {
2149d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      uint32_t events = 0;
2159d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      if (thread->IsDebugMethodEntry()) {
2169d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz        // It is also the method entry.
2179d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz        events = Dbg::kMethodEntry;
2189d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz        thread->ClearDebugMethodEntry();
2199d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      }
2209d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz      Dbg::UpdateDebugger(thread, this_object, method, new_dex_pc, events, nullptr);
2219d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    }
22262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
22362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
2249d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz  void FieldRead(Thread* thread ATTRIBUTE_UNUSED, mirror::Object* this_object,
225e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                 ArtMethod* method, uint32_t dex_pc, ArtField* field)
226bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
2273f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    Dbg::PostFieldAccessEvent(method, dex_pc, this_object, field);
22862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
2293f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
2306a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  void FieldWritten(Thread* thread ATTRIBUTE_UNUSED, mirror::Object* this_object,
231e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                    ArtMethod* method, uint32_t dex_pc, ArtField* field,
2326a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                    const JValue& field_value)
233bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
2343f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    Dbg::PostFieldModificationEvent(method, dex_pc, this_object, field, &field_value);
2353f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  }
2363f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
23714691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  void ExceptionCaught(Thread* thread ATTRIBUTE_UNUSED, mirror::Throwable* exception_object)
238bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
23914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray    Dbg::PostException(exception_object);
2403f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  }
2413f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
24281f0f953c4bb159997046c962d44cb1898b1778dNicolas Geoffray  // We only care about branches in the Jit.
24381f0f953c4bb159997046c962d44cb1898b1778dNicolas Geoffray  void Branch(Thread* /*thread*/, ArtMethod* method, uint32_t dex_pc, int32_t dex_pc_offset)
244bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
245709b070044354d9f47641f273edacaeeb0240ab7David Sehr    LOG(ERROR) << "Unexpected branch event in debugger " << ArtMethod::PrettyMethod(method)
24681f0f953c4bb159997046c962d44cb1898b1778dNicolas Geoffray               << " " << dex_pc << ", " << dex_pc_offset;
247e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  }
248e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
2495550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray  // We only care about invokes in the Jit.
2505550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray  void InvokeVirtualOrInterface(Thread* thread ATTRIBUTE_UNUSED,
2515550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray                                mirror::Object*,
2525550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray                                ArtMethod* method,
2535550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray                                uint32_t dex_pc,
2545550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray                                ArtMethod*)
255bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
256709b070044354d9f47641f273edacaeeb0240ab7David Sehr    LOG(ERROR) << "Unexpected invoke event in debugger " << ArtMethod::PrettyMethod(method)
2575550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray               << " " << dex_pc;
2585550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray  }
2595550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray
2603f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz private:
261e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  static bool IsReturn(ArtMethod* method, uint32_t dex_pc)
262bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      REQUIRES_SHARED(Locks::mutator_lock_) {
2639d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    const DexFile::CodeItem* code_item = method->GetCodeItem();
2649d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    const Instruction* instruction = Instruction::At(&code_item->insns_[dex_pc]);
2659d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    return instruction->IsReturn();
2669d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz  }
2679d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz
268bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe  static bool IsListeningToDexPcMoved() REQUIRES_SHARED(Locks::mutator_lock_) {
2699d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    return IsListeningTo(instrumentation::Instrumentation::kDexPcMoved);
2709d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz  }
2719d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz
272bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe  static bool IsListeningToMethodExit() REQUIRES_SHARED(Locks::mutator_lock_) {
2739d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    return IsListeningTo(instrumentation::Instrumentation::kMethodExited);
2749d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz  }
2759d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz
2769d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz  static bool IsListeningTo(instrumentation::Instrumentation::InstrumentationEvent event)
277bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      REQUIRES_SHARED(Locks::mutator_lock_) {
2789d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz    return (Dbg::GetInstrumentationEvents() & event) != 0;
2799d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz  }
2809d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz
2813f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  DISALLOW_COPY_AND_ASSIGN(DebugInstrumentationListener);
28262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} gDebugInstrumentationListener;
28362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
2844ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes// JDWP is allowed unless the Zygote forbids it.
2854ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughesstatic bool gJdwpAllowed = true;
2864ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes
287c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes// Was there a -Xrunjdwp or -agentlib:jdwp= argument on the command line?
2883bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughesstatic bool gJdwpConfigured = false;
2893bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes
290b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertz// JDWP options for debugging. Only valid if IsJdwpConfigured() is true.
291b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertzstatic JDWP::JdwpOptions gJdwpOptions;
292b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertz
2933bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes// Runtime JDWP state.
294c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JDWP::JdwpState* gJdwpState = nullptr;
2953bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughesstatic bool gDebuggerConnected;  // debugger or DDMS is connected.
2963bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes
29747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughesstatic bool gDdmThreadNotification = false;
29847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes
299767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes// DDMS GC-related settings.
300767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesstatic Dbg::HpifWhen gDdmHpifWhen = Dbg::HPIF_WHEN_NEVER;
301767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesstatic Dbg::HpsgWhen gDdmHpsgWhen = Dbg::HPSG_WHEN_NEVER;
302767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesstatic Dbg::HpsgWhat gDdmHpsgWhat;
303767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesstatic Dbg::HpsgWhen gDdmNhsgWhen = Dbg::HPSG_WHEN_NEVER;
304767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesstatic Dbg::HpsgWhat gDdmNhsgWhat;
305767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes
306eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyibool Dbg::gDebuggerActive = false;
3074e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertzbool Dbg::gDisposed = false;
3086995c60cd6657c10811055c42661a55b10b47cefSebastien HertzObjectRegistry* Dbg::gRegistry = nullptr;
309475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes
310138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz// Deoptimization support.
3114d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertzstd::vector<DeoptimizationRequest> Dbg::deoptimization_requests_;
3124d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertzsize_t Dbg::full_deoptimization_event_count_ = 0;
313138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
31442cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz// Instrumentation event reference counters.
31542cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertzsize_t Dbg::dex_pc_change_event_ref_count_ = 0;
31642cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertzsize_t Dbg::method_enter_event_ref_count_ = 0;
31742cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertzsize_t Dbg::method_exit_event_ref_count_ = 0;
31842cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertzsize_t Dbg::field_read_event_ref_count_ = 0;
31942cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertzsize_t Dbg::field_write_event_ref_count_ = 0;
32042cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertzsize_t Dbg::exception_catch_event_ref_count_ = 0;
32142cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertzuint32_t Dbg::instrumentation_events_ = 0;
32242cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz
32304bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas GampeDbg::DbgThreadLifecycleCallback Dbg::thread_lifecycle_callback_;
3240f01b583c3952d0219696480654a0db8fac4b661Andreas GampeDbg::DbgClassLoadCallback Dbg::class_load_callback_;
32504bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampe
326138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz// Breakpoints.
32709bfc6a50bdc9366b13ac3ab479d9278c853d90ajeffhaostatic std::vector<Breakpoint> gBreakpoints GUARDED_BY(Locks::breakpoint_lock_);
3288696433d1b3d8ba15288483b777edd888de69135Elliott Hughes
329bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartiervoid DebugInvokeReq::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) {
330bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  receiver.VisitRootIfNonNull(visitor, root_info);  // null for static method call.
331bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  klass.VisitRoot(visitor, root_info);
3323b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier}
3333b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier
334597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertzvoid SingleStepControl::AddDexPc(uint32_t dex_pc) {
335597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz  dex_pcs_.insert(dex_pc);
336bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz}
337bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz
338597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertzbool SingleStepControl::ContainsDexPc(uint32_t dex_pc) const {
339597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz  return dex_pcs_.find(dex_pc) == dex_pcs_.end();
340bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz}
341bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz
3426c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Lightstatic bool IsBreakpoint(ArtMethod* m, uint32_t dex_pc)
34390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    REQUIRES(!Locks::breakpoint_lock_)
344bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
345ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  ReaderMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
346138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  for (size_t i = 0, e = gBreakpoints.size(); i < e; ++i) {
3476c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light    if (gBreakpoints[i].DexPc() == dex_pc && gBreakpoints[i].IsInMethod(m)) {
3488696433d1b3d8ba15288483b777edd888de69135Elliott Hughes      VLOG(jdwp) << "Hit breakpoint #" << i << ": " << gBreakpoints[i];
3498696433d1b3d8ba15288483b777edd888de69135Elliott Hughes      return true;
3508696433d1b3d8ba15288483b777edd888de69135Elliott Hughes    }
3518696433d1b3d8ba15288483b777edd888de69135Elliott Hughes  }
3528696433d1b3d8ba15288483b777edd888de69135Elliott Hughes  return false;
3538696433d1b3d8ba15288483b777edd888de69135Elliott Hughes}
3548696433d1b3d8ba15288483b777edd888de69135Elliott Hughes
35552d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertzstatic bool IsSuspendedForDebugger(ScopedObjectAccessUnchecked& soa, Thread* thread)
35690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    REQUIRES(!Locks::thread_suspend_count_lock_) {
3579e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes  MutexLock mu(soa.Self(), *Locks::thread_suspend_count_lock_);
3589e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes  // A thread may be suspended for GC; in this code, we really want to know whether
3599e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes  // there's a debugger suspension active.
3609e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes  return thread->IsSuspended() && thread->GetDebugSuspendCount() > 0;
3619e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes}
3629e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes
363c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic mirror::Array* DecodeNonNullArray(JDWP::RefTypeId id, JDWP::JdwpError* error)
364bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
3656995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  mirror::Object* o = Dbg::GetObjectRegistry()->Get<mirror::Object*>(id, error);
366c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (o == nullptr) {
367c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    *error = JDWP::ERR_INVALID_OBJECT;
368c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return nullptr;
369436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  }
370436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  if (!o->IsArrayInstance()) {
371c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    *error = JDWP::ERR_INVALID_ARRAY;
372c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return nullptr;
373436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  }
374c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  *error = JDWP::ERR_NONE;
375436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return o->AsArray();
376436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes}
377436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes
378c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic mirror::Class* DecodeClass(JDWP::RefTypeId id, JDWP::JdwpError* error)
379bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
3806995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  mirror::Object* o = Dbg::GetObjectRegistry()->Get<mirror::Object*>(id, error);
381c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (o == nullptr) {
382c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    *error = JDWP::ERR_INVALID_OBJECT;
383c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return nullptr;
384436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  }
385436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  if (!o->IsClass()) {
386c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    *error = JDWP::ERR_INVALID_CLASS;
387c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return nullptr;
388436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  }
389c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  *error = JDWP::ERR_NONE;
390436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return o->AsClass();
391436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes}
392436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes
393c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic Thread* DecodeThread(ScopedObjectAccessUnchecked& soa, JDWP::ObjectId thread_id,
394c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers                            JDWP::JdwpError* error)
395bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_)
39690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_) {
3976995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  mirror::Object* thread_peer = Dbg::GetObjectRegistry()->Get<mirror::Object*>(thread_id, error);
398c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (thread_peer == nullptr) {
399221229cb523f849f165fdafbf9785010963715daElliott Hughes    // This isn't even an object.
400c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    *error = JDWP::ERR_INVALID_OBJECT;
401c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return nullptr;
402221229cb523f849f165fdafbf9785010963715daElliott Hughes  }
403221229cb523f849f165fdafbf9785010963715daElliott Hughes
4040795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier  ObjPtr<mirror::Class> java_lang_Thread =
4050795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier      soa.Decode<mirror::Class>(WellKnownClasses::java_lang_Thread);
406221229cb523f849f165fdafbf9785010963715daElliott Hughes  if (!java_lang_Thread->IsAssignableFrom(thread_peer->GetClass())) {
407221229cb523f849f165fdafbf9785010963715daElliott Hughes    // This isn't a thread.
408c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    *error = JDWP::ERR_INVALID_THREAD;
409c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return nullptr;
410221229cb523f849f165fdafbf9785010963715daElliott Hughes  }
411221229cb523f849f165fdafbf9785010963715daElliott Hughes
412692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
413c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  Thread* thread = Thread::FromManagedThread(soa, thread_peer);
414c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  // If thread is null then this a java.lang.Thread without a Thread*. Must be a un-started or a
415c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  // zombie.
416c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  *error = (thread == nullptr) ? JDWP::ERR_THREAD_NOT_ALIVE : JDWP::ERR_NONE;
417c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  return thread;
418436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes}
419436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes
42024437995cdac88b42e42b16d9aa121e833330999Elliott Hughesstatic JDWP::JdwpTag BasicTagFromDescriptor(const char* descriptor) {
42124437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  // JDWP deliberately uses the descriptor characters' ASCII values for its enum.
42224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  // Note that by "basic" we mean that we don't get more specific than JT_OBJECT.
42324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  return static_cast<JDWP::JdwpTag>(descriptor[0]);
42424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes}
42524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes
4261ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogersstatic JDWP::JdwpTag BasicTagFromClass(mirror::Class* klass)
427bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
4281ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers  std::string temp;
4291ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers  const char* descriptor = klass->GetDescriptor(&temp);
4301ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers  return BasicTagFromDescriptor(descriptor);
4311ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers}
4321ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers
4339837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogersstatic JDWP::JdwpTag TagFromClass(const ScopedObjectAccessUnchecked& soa, mirror::Class* c)
434bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
435c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  CHECK(c != nullptr);
43624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  if (c->IsArrayClass()) {
43724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes    return JDWP::JT_ARRAY;
43824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  }
43924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  if (c->IsStringClass()) {
44024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes    return JDWP::JT_STRING;
4419837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers  }
4429837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers  if (c->IsClassClass()) {
44324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes    return JDWP::JT_CLASS_OBJECT;
44424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  }
4459837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers  {
4460795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier    ObjPtr<mirror::Class> thread_class =
4470795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier        soa.Decode<mirror::Class>(WellKnownClasses::java_lang_Thread);
4489837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers    if (thread_class->IsAssignableFrom(c)) {
4499837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers      return JDWP::JT_THREAD;
4509837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers    }
4519837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers  }
4529837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers  {
4530795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier    ObjPtr<mirror::Class> thread_group_class =
4540795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier        soa.Decode<mirror::Class>(WellKnownClasses::java_lang_ThreadGroup);
4559837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers    if (thread_group_class->IsAssignableFrom(c)) {
4569837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers      return JDWP::JT_THREAD_GROUP;
4579837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers    }
4589837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers  }
4599837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers  {
4600795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier    ObjPtr<mirror::Class> class_loader_class =
4610795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier        soa.Decode<mirror::Class>(WellKnownClasses::java_lang_ClassLoader);
4629837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers    if (class_loader_class->IsAssignableFrom(c)) {
4639837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers      return JDWP::JT_CLASS_LOADER;
4649837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers    }
4659837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers  }
4669837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers  return JDWP::JT_OBJECT;
46724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes}
46824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes
46924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes/*
47024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * Objects declared to hold Object might actually hold a more specific
47124437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * type.  The debugger may take a special interest in these (e.g. it
47224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * wants to display the contents of Strings), so we want to return an
47324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * appropriate tag.
47424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes *
47524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * Null objects are tagged JT_OBJECT.
47624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes */
4776995c60cd6657c10811055c42661a55b10b47cefSebastien HertzJDWP::JdwpTag Dbg::TagFromObject(const ScopedObjectAccessUnchecked& soa, mirror::Object* o) {
478c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  return (o == nullptr) ? JDWP::JT_OBJECT : TagFromClass(soa, o->GetClass());
47924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes}
48024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes
48124437995cdac88b42e42b16d9aa121e833330999Elliott Hughesstatic bool IsPrimitiveTag(JDWP::JdwpTag tag) {
48224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  switch (tag) {
48324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  case JDWP::JT_BOOLEAN:
48424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  case JDWP::JT_BYTE:
48524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  case JDWP::JT_CHAR:
48624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  case JDWP::JT_FLOAT:
48724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  case JDWP::JT_DOUBLE:
48824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  case JDWP::JT_INT:
48924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  case JDWP::JT_LONG:
49024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  case JDWP::JT_SHORT:
49124437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  case JDWP::JT_VOID:
49224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes    return true;
49324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  default:
49424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes    return false;
49524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  }
49624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes}
49724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes
498b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertzvoid Dbg::StartJdwp() {
499c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes  if (!gJdwpAllowed || !IsJdwpConfigured()) {
500376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes    // No JDWP for you!
501376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes    return;
502376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  }
503376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes
504719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers  CHECK(gRegistry == nullptr);
505475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes  gRegistry = new ObjectRegistry;
506475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes
507d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  // Init JDWP if the debugger is enabled. This may connect out to a
508d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  // debugger, passively listen for a debugger, or block waiting for a
509d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  // debugger.
510b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertz  gJdwpState = JDWP::JdwpState::Create(&gJdwpOptions);
511c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (gJdwpState == nullptr) {
512f8a2df7bbf1021058bc13d1f806a7fec3c89ee62Elliott Hughes    // We probably failed because some other process has the port already, which means that
513f8a2df7bbf1021058bc13d1f806a7fec3c89ee62Elliott Hughes    // if we don't abort the user is likely to think they're talking to us when they're actually
514f8a2df7bbf1021058bc13d1f806a7fec3c89ee62Elliott Hughes    // talking to that other process.
5153d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes    LOG(FATAL) << "Debugger thread failed to initialize";
516d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  }
517d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes
518d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  // If a debugger has already attached, send the "welcome" message.
519d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  // This may cause us to suspend all threads.
520376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  if (gJdwpState->IsActive()) {
52100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    ScopedObjectAccess soa(Thread::Current());
5227d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz    gJdwpState->PostVMStart();
523d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  }
524872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
525872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
526d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughesvoid Dbg::StopJdwp() {
527c6345efb56f9096c4b1a1a90e1d8d847fc01d910Sebastien Hertz  // Post VM_DEATH event before the JDWP connection is closed (either by the JDWP thread or the
528c6345efb56f9096c4b1a1a90e1d8d847fc01d910Sebastien Hertz  // destruction of gJdwpState).
529c6345efb56f9096c4b1a1a90e1d8d847fc01d910Sebastien Hertz  if (gJdwpState != nullptr && gJdwpState->IsActive()) {
530c6345efb56f9096c4b1a1a90e1d8d847fc01d910Sebastien Hertz    gJdwpState->PostVMDeath();
531c6345efb56f9096c4b1a1a90e1d8d847fc01d910Sebastien Hertz  }
5320376e6b62bfb43b515b791f0a7afed2d0d8030bcSebastien Hertz  // Prevent the JDWP thread from processing JDWP incoming packets after we close the connection.
5334e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz  Dispose();
534376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  delete gJdwpState;
535719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers  gJdwpState = nullptr;
536475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes  delete gRegistry;
537719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers  gRegistry = nullptr;
538872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
539872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
540767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesvoid Dbg::GcDidFinish() {
541767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  if (gDdmHpifWhen != HPIF_WHEN_NEVER) {
54200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    ScopedObjectAccess soa(Thread::Current());
5434d466a8e4587422c989705dce3b2a19e7f0137f5Brian Carlstrom    VLOG(jdwp) << "Sending heap info to DDM";
5447162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes    DdmSendHeapInfo(gDdmHpifWhen);
545767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  }
546767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  if (gDdmHpsgWhen != HPSG_WHEN_NEVER) {
54700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    ScopedObjectAccess soa(Thread::Current());
5484d466a8e4587422c989705dce3b2a19e7f0137f5Brian Carlstrom    VLOG(jdwp) << "Dumping heap to DDM";
5496a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes    DdmSendHeapSegments(false);
550767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  }
551767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  if (gDdmNhsgWhen != HPSG_WHEN_NEVER) {
55200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    ScopedObjectAccess soa(Thread::Current());
5534d466a8e4587422c989705dce3b2a19e7f0137f5Brian Carlstrom    VLOG(jdwp) << "Dumping native heap to DDM";
5546a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes    DdmSendHeapSegments(true);
555767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  }
556767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes}
557767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes
5584ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughesvoid Dbg::SetJdwpAllowed(bool allowed) {
5594ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes  gJdwpAllowed = allowed;
5604ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes}
5614ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes
562eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescubool Dbg::IsJdwpAllowed() {
563eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu  return gJdwpAllowed;
564eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu}
565eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu
566872d4ec7225444d9400d30f9027247deb91012fdElliott HughesDebugInvokeReq* Dbg::GetInvokeReq() {
567475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes  return Thread::Current()->GetInvokeReq();
568475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes}
569475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes
570475fc23a4a7f35d1be87ea0b06c80df317a720acElliott HughesThread* Dbg::GetDebugThread() {
571c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  return (gJdwpState != nullptr) ? gJdwpState->GetDebugThread() : nullptr;
572475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes}
573475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes
574475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughesvoid Dbg::ClearWaitForEventThread() {
5752bf93f48bbb417b358c9e3c77911ea6ec7307c15Sebastien Hertz  gJdwpState->ReleaseJdwpTokenForEvent();
576872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
577872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
578872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::Connected() {
5793bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes  CHECK(!gDebuggerConnected);
5804dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(jdwp) << "JDWP has attached";
5813bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes  gDebuggerConnected = true;
5828696433d1b3d8ba15288483b777edd888de69135Elliott Hughes  gDisposed = false;
5838696433d1b3d8ba15288483b777edd888de69135Elliott Hughes}
5848696433d1b3d8ba15288483b777edd888de69135Elliott Hughes
585f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertzbool Dbg::RequiresDeoptimization() {
586f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  // We don't need deoptimization if everything runs with interpreter after
587f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  // enabling -Xint mode.
588f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  return !Runtime::Current()->GetInstrumentation()->IsForcedInterpretOnly();
589f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz}
590f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz
591a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughesvoid Dbg::GoActive() {
592a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  // Enable all debugging features, including scans for breakpoints.
593a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  // This is a no-op if we're already active.
594a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  // Only called from the JDWP handler thread.
595eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  if (IsDebuggerActive()) {
596a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    return;
597a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  }
598a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes
599aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier  Thread* const self = Thread::Current();
600c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes  {
601c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes    // TODO: dalvik only warned if there were breakpoints left over. clear in Dbg::Disconnected?
602aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier    ReaderMutexLock mu(self, *Locks::breakpoint_lock_);
603c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes    CHECK_EQ(gBreakpoints.size(), 0U);
604c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes  }
605a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes
606138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  {
607aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier    MutexLock mu(self, *Locks::deoptimization_lock_);
6084d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    CHECK_EQ(deoptimization_requests_.size(), 0U);
6094d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    CHECK_EQ(full_deoptimization_event_count_, 0U);
61042cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    CHECK_EQ(dex_pc_change_event_ref_count_, 0U);
61142cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    CHECK_EQ(method_enter_event_ref_count_, 0U);
61242cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    CHECK_EQ(method_exit_event_ref_count_, 0U);
61342cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    CHECK_EQ(field_read_event_ref_count_, 0U);
61442cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    CHECK_EQ(field_write_event_ref_count_, 0U);
61542cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    CHECK_EQ(exception_catch_event_ref_count_, 0U);
616138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  }
617138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
61862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Runtime* runtime = Runtime::Current();
619433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray  // Best effort deoptimization if the runtime is non-Java debuggable. This happens when
620433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray  // ro.debuggable is set, but the application is not debuggable, or when a standalone
621433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray  // dalvikvm invocation is not passed the debuggable option (-Xcompiler-option --debuggable).
622433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray  //
623433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray  // The performance cost of this is non-negligible during native-debugging due to the
624f448016e70fa91269d3750384aab1ac98d7896fdDavid Srbecky  // forced JIT, so we keep the AOT code in that case in exchange for limited native debugging.
625433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray  if (!runtime->IsJavaDebuggable() &&
626433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray      !runtime->GetInstrumentation()->IsForcedInterpretOnly() &&
627433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray      !runtime->IsNativeDebuggable()) {
628433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray    runtime->DeoptimizeBootImage();
6296ea1a0e2168c8d9b6d97c075c73a72d84080f45bMingyao Yang  }
6306ea1a0e2168c8d9b6d97c075c73a72d84080f45bMingyao Yang
6314f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier  ScopedSuspendAll ssa(__FUNCTION__);
632f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  if (RequiresDeoptimization()) {
633f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    runtime->GetInstrumentation()->EnableDeoptimization();
634f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  }
63542cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz  instrumentation_events_ = 0;
636a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  gDebuggerActive = true;
63762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  LOG(INFO) << "Debugger is active";
638872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
639872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
640872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::Disconnected() {
641234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes  CHECK(gDebuggerConnected);
642234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes
643c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes  LOG(INFO) << "Debugger is no longer active";
644234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes
64598810e34804e224e5ab302cd353393f72a45202bHiroshi Yamauchi  // Suspend all threads and exclusively acquire the mutator lock. Remove the debugger as a listener
64662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // and clear the object registry.
64762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Runtime* runtime = Runtime::Current();
64862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Thread* self = Thread::Current();
6494f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier  {
650aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier    // Required for DisableDeoptimization.
651aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier    gc::ScopedGCCriticalSection gcs(self,
652aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier                                    gc::kGcCauseInstrumentation,
653aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier                                    gc::kCollectorTypeInstrumentation);
6544f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier    ScopedSuspendAll ssa(__FUNCTION__);
6554f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier    // Debugger may not be active at this point.
6564f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier    if (IsDebuggerActive()) {
6574f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      {
6584f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        // Since we're going to disable deoptimization, we clear the deoptimization requests queue.
6594f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        // This prevents us from having any pending deoptimization request when the debugger attaches
6604f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        // to us again while no event has been requested yet.
661a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartier        MutexLock mu(self, *Locks::deoptimization_lock_);
6624f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        deoptimization_requests_.clear();
6634f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        full_deoptimization_event_count_ = 0U;
6644f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      }
6654f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      if (instrumentation_events_ != 0) {
6664f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        runtime->GetInstrumentation()->RemoveListener(&gDebugInstrumentationListener,
6674f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier                                                      instrumentation_events_);
6684f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        instrumentation_events_ = 0;
6694f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      }
6704f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      if (RequiresDeoptimization()) {
6714f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        runtime->GetInstrumentation()->DisableDeoptimization(kDbgInstrumentationKey);
6724f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      }
6734f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      gDebuggerActive = false;
674f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    }
675aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz  }
67655f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz
67755f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz  {
67855f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz    ScopedObjectAccess soa(self);
67955f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz    gRegistry->Clear();
68055f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz  }
68155f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz
68255f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz  gDebuggerConnected = false;
683872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
684872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
685b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertzvoid Dbg::ConfigureJdwp(const JDWP::JdwpOptions& jdwp_options) {
686b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertz  CHECK_NE(jdwp_options.transport, JDWP::kJdwpTransportUnknown);
687b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertz  gJdwpOptions = jdwp_options;
688b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertz  gJdwpConfigured = true;
689b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertz}
690b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertz
691c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughesbool Dbg::IsJdwpConfigured() {
6923bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes  return gJdwpConfigured;
693872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
694872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
695872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesint64_t Dbg::LastDebuggerActivity() {
696ca9515205010099d006ac2fac244348a1e673dcbElliott Hughes  return gJdwpState->LastDebuggerActivity();
697872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
698872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
699872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::UndoDebuggerSuspensions() {
700234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes  Runtime::Current()->GetThreadList()->UndoDebuggerSuspensions();
701872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
702872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
70388d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughesstd::string Dbg::GetClassName(JDWP::RefTypeId class_id) {
704c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
705c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Object* o = gRegistry->Get<mirror::Object*>(class_id, &error);
706c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (o == nullptr) {
707c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    if (error == JDWP::ERR_NONE) {
7082cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      return "null";
709c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    } else {
710c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      return StringPrintf("invalid object %p", reinterpret_cast<void*>(class_id));
711c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    }
7123d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  }
7133d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  if (!o->IsClass()) {
7147934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    return StringPrintf("non-class %p", o);  // This is only used for debugging output anyway.
7153d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  }
7166995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  return GetClassName(o->AsClass());
7176995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz}
7186995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz
7196995c60cd6657c10811055c42661a55b10b47cefSebastien Hertzstd::string Dbg::GetClassName(mirror::Class* klass) {
720a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz  if (klass == nullptr) {
7212cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    return "null";
722a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz  }
7231ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers  std::string temp;
7246995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  return DescriptorToName(klass->GetDescriptor(&temp));
7253d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes}
7263d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes
727c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId* class_object_id) {
728436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  JDWP::JdwpError status;
729c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Class* c = DecodeClass(id, &status);
730c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (c == nullptr) {
731c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    *class_object_id = 0;
732436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes    return status;
7332435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  }
734c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  *class_object_id = gRegistry->Add(c);
735436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return JDWP::ERR_NONE;
7368696433d1b3d8ba15288483b777edd888de69135Elliott Hughes}
7378696433d1b3d8ba15288483b777edd888de69135Elliott Hughes
738c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId* superclass_id) {
7393d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  JDWP::JdwpError status;
740c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Class* c = DecodeClass(id, &status);
741c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (c == nullptr) {
742c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    *superclass_id = 0;
7433d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes    return status;
7443d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  }
7453d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  if (c->IsInterface()) {
7463d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes    // http://code.google.com/p/android/issues/detail?id=20856
747c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    *superclass_id = 0;
7483d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  } else {
749c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    *superclass_id = gRegistry->Add(c->GetSuperClass());
7503d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  }
7513d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  return JDWP::ERR_NONE;
752872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
753872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
754436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott HughesJDWP::JdwpError Dbg::GetClassLoader(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) {
755c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
7567929a489a9b256020d3add793198ba1e97e426e6Andreas Gampe  mirror::Class* c = DecodeClass(id, &error);
7577929a489a9b256020d3add793198ba1e97e426e6Andreas Gampe  if (c == nullptr) {
7587929a489a9b256020d3add793198ba1e97e426e6Andreas Gampe    return error;
759436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  }
7607929a489a9b256020d3add793198ba1e97e426e6Andreas Gampe  expandBufAddObjectId(pReply, gRegistry->Add(c->GetClassLoader()));
761436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return JDWP::ERR_NONE;
762872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
763872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
764436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott HughesJDWP::JdwpError Dbg::GetModifiers(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) {
765c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
766c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Class* c = DecodeClass(id, &error);
767c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (c == nullptr) {
768c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return error;
7697b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  }
770436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes
771436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  uint32_t access_flags = c->GetAccessFlags() & kAccJavaFlagsMask;
772436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes
773de34eea060edb4eb34d6ecd840e6e1c4c6489642Yevgeny Rouban  // Set ACC_SUPER. Dex files don't contain this flag but only classes are supposed to have it set,
774de34eea060edb4eb34d6ecd840e6e1c4c6489642Yevgeny Rouban  // not interfaces.
775436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  // Class.getModifiers doesn't return it, but JDWP does, so we set it here.
776de34eea060edb4eb34d6ecd840e6e1c4c6489642Yevgeny Rouban  if ((access_flags & kAccInterface) == 0) {
777de34eea060edb4eb34d6ecd840e6e1c4c6489642Yevgeny Rouban    access_flags |= kAccSuper;
778de34eea060edb4eb34d6ecd840e6e1c4c6489642Yevgeny Rouban  }
779436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes
780436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  expandBufAdd4BE(pReply, access_flags);
781436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes
782436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return JDWP::ERR_NONE;
783872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
784872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
785c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetMonitorInfo(JDWP::ObjectId object_id, JDWP::ExpandBuf* reply) {
786c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
787c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error);
788c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (o == nullptr) {
789f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes    return JDWP::ERR_INVALID_OBJECT;
790f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  }
791f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes
792f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  // Ensure all threads are suspended while we read objects' lock words.
793f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  Thread* self = Thread::Current();
7945426324ea7a4c334cde1fdc4b8aae39f8a8e362dSebastien Hertz  CHECK_EQ(self->GetState(), kRunnable);
795f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes
796f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier  MonitorInfo monitor_info;
797f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier  {
798f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier    ScopedThreadSuspension sts(self, kSuspended);
7994f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier    ScopedSuspendAll ssa(__FUNCTION__);
800f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier    monitor_info = MonitorInfo(o);
801f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier  }
802c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (monitor_info.owner_ != nullptr) {
803cafa08146648442ee53348c4918a4fab29e591c1Nicolas Geoffray    expandBufAddObjectId(reply, gRegistry->Add(monitor_info.owner_->GetPeerFromOtherThread()));
804f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  } else {
805c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    expandBufAddObjectId(reply, gRegistry->Add(nullptr));
806f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  }
807d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  expandBufAdd4BE(reply, monitor_info.entry_count_);
808d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  expandBufAdd4BE(reply, monitor_info.waiters_.size());
809d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  for (size_t i = 0; i < monitor_info.waiters_.size(); ++i) {
810cafa08146648442ee53348c4918a4fab29e591c1Nicolas Geoffray    expandBufAddObjectId(reply, gRegistry->Add(monitor_info.waiters_[i]->GetPeerFromOtherThread()));
811f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  }
812f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  return JDWP::ERR_NONE;
813f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes}
814f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes
815734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott HughesJDWP::JdwpError Dbg::GetOwnedMonitors(JDWP::ObjectId thread_id,
816c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers                                      std::vector<JDWP::ObjectId>* monitors,
817c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers                                      std::vector<uint32_t>* stack_depths) {
8184993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  struct OwnedMonitorVisitor : public StackVisitor {
819b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    OwnedMonitorVisitor(Thread* thread, Context* context,
820cc8c5c5433230818cfe31617308198f286cc2ee1Hiroshi Yamauchi                        std::vector<JDWP::ObjectId>* monitor_vector,
821b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi                        std::vector<uint32_t>* stack_depth_vector)
822bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe        REQUIRES_SHARED(Locks::mutator_lock_)
8238e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray      : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
8248e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray        current_stack_depth(0),
8258e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray        monitors(monitor_vector),
8268e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray        stack_depths(stack_depth_vector) {}
8274993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes
8284993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes    // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
8294993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes    // annotalysis.
8304993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes    bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS {
8314993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes      if (!GetMethod()->IsRuntimeMethod()) {
8324993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes        Monitor::VisitLocks(this, AppendOwnedMonitors, this);
833734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes        ++current_stack_depth;
8344993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes      }
8354993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes      return true;
8364993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes    }
8374993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes
838cc8c5c5433230818cfe31617308198f286cc2ee1Hiroshi Yamauchi    static void AppendOwnedMonitors(mirror::Object* owned_monitor, void* arg)
839bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe        REQUIRES_SHARED(Locks::mutator_lock_) {
8407a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers      OwnedMonitorVisitor* visitor = reinterpret_cast<OwnedMonitorVisitor*>(arg);
841cc8c5c5433230818cfe31617308198f286cc2ee1Hiroshi Yamauchi      visitor->monitors->push_back(gRegistry->Add(owned_monitor));
842b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi      visitor->stack_depths->push_back(visitor->current_stack_depth);
8434993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes    }
8444993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes
845734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes    size_t current_stack_depth;
846c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    std::vector<JDWP::ObjectId>* const monitors;
847c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    std::vector<uint32_t>* const stack_depths;
8484993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  };
8494993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes
850b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  ScopedObjectAccessUnchecked soa(Thread::Current());
851692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  JDWP::JdwpError error;
852692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  Thread* thread = DecodeThread(soa, thread_id, &error);
853692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  if (thread == nullptr) {
854692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz    return error;
855692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  }
856692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  if (!IsSuspendedForDebugger(soa, thread)) {
857692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz    return JDWP::ERR_THREAD_NOT_SUSPENDED;
8584993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  }
859cc8c5c5433230818cfe31617308198f286cc2ee1Hiroshi Yamauchi  std::unique_ptr<Context> context(Context::Create());
860c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  OwnedMonitorVisitor visitor(thread, context.get(), monitors, stack_depths);
861cc8c5c5433230818cfe31617308198f286cc2ee1Hiroshi Yamauchi  visitor.WalkStack();
8624993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  return JDWP::ERR_NONE;
8634993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes}
8644993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes
86552d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien HertzJDWP::JdwpError Dbg::GetContendedMonitor(JDWP::ObjectId thread_id,
866c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers                                         JDWP::ObjectId* contended_monitor) {
867f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes  ScopedObjectAccessUnchecked soa(Thread::Current());
868c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  *contended_monitor = 0;
869692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  JDWP::JdwpError error;
870692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  Thread* thread = DecodeThread(soa, thread_id, &error);
871692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  if (thread == nullptr) {
872692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz    return error;
873692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  }
874692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  if (!IsSuspendedForDebugger(soa, thread)) {
875692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz    return JDWP::ERR_THREAD_NOT_SUSPENDED;
876f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes  }
877692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  mirror::Object* contended_monitor_obj = Monitor::GetContendedMonitor(thread);
878b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  // Add() requires the thread_list_lock_ not held to avoid the lock
879b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  // level violation.
880c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  *contended_monitor = gRegistry->Add(contended_monitor_obj);
881f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes  return JDWP::ERR_NONE;
882f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes}
883f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes
884ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott HughesJDWP::JdwpError Dbg::GetInstanceCounts(const std::vector<JDWP::RefTypeId>& class_ids,
885c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers                                       std::vector<uint64_t>* counts) {
886412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  gc::Heap* heap = Runtime::Current()->GetHeap();
887412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  heap->CollectGarbage(false);
888e8a3c576301fd531d5f73a65fc8b84a63619d580Mathieu Chartier  VariableSizedHandleScope hs(Thread::Current());
8899d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier  std::vector<Handle<mirror::Class>> classes;
890c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  counts->clear();
891ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  for (size_t i = 0; i < class_ids.size(); ++i) {
892c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    JDWP::JdwpError error;
8939d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier    ObjPtr<mirror::Class> c = DecodeClass(class_ids[i], &error);
894c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    if (c == nullptr) {
895c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      return error;
896ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes    }
8979d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier    classes.push_back(hs.NewHandle(c));
898c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    counts->push_back(0);
899ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  }
900c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  heap->CountInstances(classes, false, &(*counts)[0]);
901ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  return JDWP::ERR_NONE;
902ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes}
903ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes
904c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetInstances(JDWP::RefTypeId class_id, int32_t max_count,
905c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers                                  std::vector<JDWP::ObjectId>* instances) {
906412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  gc::Heap* heap = Runtime::Current()->GetHeap();
907412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  // We only want reachable instances, so do a GC.
908412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  heap->CollectGarbage(false);
909c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
9109d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier  ObjPtr<mirror::Class> c = DecodeClass(class_id, &error);
911412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  if (c == nullptr) {
912c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return error;
9133b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes  }
9142d8559517759dcfac749a28d6713d36809ec556fMathieu Chartier  VariableSizedHandleScope hs(Thread::Current());
9152d8559517759dcfac749a28d6713d36809ec556fMathieu Chartier  std::vector<Handle<mirror::Object>> raw_instances;
9162d8559517759dcfac749a28d6713d36809ec556fMathieu Chartier  Runtime::Current()->GetHeap()->GetInstances(hs, hs.NewHandle(c), max_count, raw_instances);
9173b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes  for (size_t i = 0; i < raw_instances.size(); ++i) {
9182d8559517759dcfac749a28d6713d36809ec556fMathieu Chartier    instances->push_back(gRegistry->Add(raw_instances[i].Get()));
9193b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes  }
9203b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes  return JDWP::ERR_NONE;
9213b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes}
9223b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes
9230cbaff584244ee767027aff35cd3c625aaee2994Elliott HughesJDWP::JdwpError Dbg::GetReferringObjects(JDWP::ObjectId object_id, int32_t max_count,
924c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers                                         std::vector<JDWP::ObjectId>* referring_objects) {
925412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  gc::Heap* heap = Runtime::Current()->GetHeap();
926412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  heap->CollectGarbage(false);
927c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
9289d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier  ObjPtr<mirror::Object> o = gRegistry->Get<mirror::Object*>(object_id, &error);
929c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (o == nullptr) {
9300cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes    return JDWP::ERR_INVALID_OBJECT;
9310cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes  }
932aea9bfb051bb197fdfb63d56ff0f3d63b36eb499Mathieu Chartier  VariableSizedHandleScope hs(Thread::Current());
933aea9bfb051bb197fdfb63d56ff0f3d63b36eb499Mathieu Chartier  std::vector<Handle<mirror::Object>> raw_instances;
934aea9bfb051bb197fdfb63d56ff0f3d63b36eb499Mathieu Chartier  heap->GetReferringObjects(hs, hs.NewHandle(o), max_count, raw_instances);
9350cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes  for (size_t i = 0; i < raw_instances.size(); ++i) {
936aea9bfb051bb197fdfb63d56ff0f3d63b36eb499Mathieu Chartier    referring_objects->push_back(gRegistry->Add(raw_instances[i].Get()));
9370cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes  }
9380cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes  return JDWP::ERR_NONE;
9390cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes}
9400cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes
941c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::DisableCollection(JDWP::ObjectId object_id) {
942c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
943c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error);
944c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (o == nullptr) {
945e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz    return JDWP::ERR_INVALID_OBJECT;
946e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz  }
94764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  gRegistry->DisableCollection(object_id);
94864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  return JDWP::ERR_NONE;
94964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
95064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
951c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::EnableCollection(JDWP::ObjectId object_id) {
952c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
953c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error);
954e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz  // Unlike DisableCollection, JDWP specs do not state an invalid object causes an error. The RI
955e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz  // also ignores these cases and never return an error. However it's not obvious why this command
956e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz  // should behave differently from DisableCollection and IsCollected commands. So let's be more
957e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz  // strict and return an error if this happens.
958c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (o == nullptr) {
959e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz    return JDWP::ERR_INVALID_OBJECT;
960e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz  }
96164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  gRegistry->EnableCollection(object_id);
96264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  return JDWP::ERR_NONE;
96364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
96464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
965c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::IsCollected(JDWP::ObjectId object_id, bool* is_collected) {
966c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  *is_collected = true;
96765637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz  if (object_id == 0) {
96865637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz    // Null object id is invalid.
96965637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz    return JDWP::ERR_INVALID_OBJECT;
97065637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz  }
971e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz  // JDWP specs state an INVALID_OBJECT error is returned if the object ID is not valid. However
97265637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz  // the RI seems to ignore this and assume object has been collected.
973c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
974c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error);
975c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (o != nullptr) {
976c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    *is_collected = gRegistry->IsCollected(object_id);
977e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz  }
97864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  return JDWP::ERR_NONE;
97964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
98064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
981c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersvoid Dbg::DisposeObject(JDWP::ObjectId object_id, uint32_t reference_count) {
98264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  gRegistry->DisposeObject(object_id, reference_count);
98364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
98464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
9853398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu ChartierJDWP::JdwpTypeTag Dbg::GetTypeTag(ObjPtr<mirror::Class> klass) {
9864d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz  DCHECK(klass != nullptr);
9874d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz  if (klass->IsArrayClass()) {
9884d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz    return JDWP::TT_ARRAY;
9894d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz  } else if (klass->IsInterface()) {
9904d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz    return JDWP::TT_INTERFACE;
9914d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz  } else {
9924d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz    return JDWP::TT_CLASS;
9934d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz  }
9944d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz}
9954d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz
99688d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::GetReflectedType(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) {
997c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
998c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Class* c = DecodeClass(class_id, &error);
999c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (c == nullptr) {
1000c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return error;
10017b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  }
1002436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes
10034d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz  JDWP::JdwpTypeTag type_tag = GetTypeTag(c);
10044d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz  expandBufAdd1(pReply, type_tag);
100588d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes  expandBufAddRefTypeId(pReply, class_id);
1006436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return JDWP::ERR_NONE;
1007872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1008872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1009e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier// Get the complete list of reference classes (i.e. all classes except
1010e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier// the primitive types).
1011e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier// Returns a newly-allocated buffer full of RefTypeId values.
1012e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartierclass ClassListCreator : public ClassVisitor {
1013e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier public:
1014e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier  explicit ClassListCreator(std::vector<JDWP::RefTypeId>* classes) : classes_(classes) {}
10157b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes
101628357fab628bd9b91749988b554977398caf9963Mathieu Chartier  bool operator()(ObjPtr<mirror::Class> c) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
1017e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier    if (!c->IsPrimitive()) {
1018e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier      classes_->push_back(Dbg::GetObjectRegistry()->AddRefType(c));
1019a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    }
1020e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier    return true;
1021e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier  }
1022a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes
1023e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier private:
1024e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier  std::vector<JDWP::RefTypeId>* const classes_;
1025e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier};
1026a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes
1027e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartiervoid Dbg::GetClassList(std::vector<JDWP::RefTypeId>* classes) {
10287b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  ClassListCreator clc(classes);
1029e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier  Runtime::Current()->GetClassLinker()->VisitClassesWithoutClassesLock(&clc);
1030872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1031872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
10321ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian RogersJDWP::JdwpError Dbg::GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* pTypeTag,
10331ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers                                  uint32_t* pStatus, std::string* pDescriptor) {
1034c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
1035c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Class* c = DecodeClass(class_id, &error);
1036c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (c == nullptr) {
1037c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return error;
10387b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  }
10397b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes
1040a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  if (c->IsArrayClass()) {
1041a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    *pStatus = JDWP::CS_VERIFIED | JDWP::CS_PREPARED;
1042a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    *pTypeTag = JDWP::TT_ARRAY;
1043a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  } else {
1044a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    if (c->IsErroneous()) {
1045a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes      *pStatus = JDWP::CS_ERROR;
1046a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    } else {
1047a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes      *pStatus = JDWP::CS_VERIFIED | JDWP::CS_PREPARED | JDWP::CS_INITIALIZED;
1048a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    }
1049a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    *pTypeTag = c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS;
1050a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  }
1051a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes
1052c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (pDescriptor != nullptr) {
10531ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers    std::string temp;
10541ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers    *pDescriptor = c->GetDescriptor(&temp);
1055a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  }
1056436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return JDWP::ERR_NONE;
1057872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1058872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1059c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersvoid Dbg::FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>* ids) {
106028357fab628bd9b91749988b554977398caf9963Mathieu Chartier  std::vector<ObjPtr<mirror::Class>> classes;
1061b1d8c314b55bb2df2b2bb72a3daaf5db65b7ebc7Igor Murashkin  Runtime::Current()->GetClassLinker()->LookupClasses(descriptor, classes);
1062c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ids->clear();
106328357fab628bd9b91749988b554977398caf9963Mathieu Chartier  for (ObjPtr<mirror::Class> c : classes) {
106428357fab628bd9b91749988b554977398caf9963Mathieu Chartier    ids->push_back(gRegistry->Add(c));
10656fa602d614d418f38afebb4d44f42e7dc0b4bd94Elliott Hughes  }
1066872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1067872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1068c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* pReply) {
1069c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
1070c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error);
1071c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (o == nullptr) {
10722435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes    return JDWP::ERR_INVALID_OBJECT;
10732435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  }
10742435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes
10754d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz  JDWP::JdwpTypeTag type_tag = GetTypeTag(o->GetClass());
107664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  JDWP::RefTypeId type_id = gRegistry->AddRefType(o->GetClass());
10772435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes
10782435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  expandBufAdd1(pReply, type_tag);
10792435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  expandBufAddRefTypeId(pReply, type_id);
10802435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes
10812435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  return JDWP::ERR_NONE;
1082872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1083872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1084fc0e94bed3f88ed7e50854fd8dfaf5dcb345250fIan RogersJDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string* signature) {
1085c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
1086c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Class* c = DecodeClass(class_id, &error);
1087c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (c == nullptr) {
1088c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return error;
10897b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  }
10901ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers  std::string temp;
10911ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers  *signature = c->GetDescriptor(&temp);
10921fe7afb88498d48d1f808ee31e986324f2a1c842Elliott Hughes  return JDWP::ERR_NONE;
1093872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1094872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
109524d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion HodsonJDWP::JdwpError Dbg::GetSourceDebugExtension(JDWP::RefTypeId class_id,
109624d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson                                             std::string* extension_data) {
109724d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson  JDWP::JdwpError error;
109824d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson  mirror::Class* c = DecodeClass(class_id, &error);
109924d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson  if (c == nullptr) {
110024d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson    return error;
110124d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson  }
110224d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson  StackHandleScope<1> hs(Thread::Current());
110324d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson  Handle<mirror::Class> klass(hs.NewHandle(c));
110424d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson  const char* data = annotations::GetSourceDebugExtension(klass);
110524d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson  if (data == nullptr) {
110624d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson    return JDWP::ERR_ABSENT_INFORMATION;
110724d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson  }
110824d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson  *extension_data = data;
110924d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson  return JDWP::ERR_NONE;
111024d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson}
111124d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson
1112c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetSourceFile(JDWP::RefTypeId class_id, std::string* result) {
1113c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
1114c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Class* c = DecodeClass(class_id, &error);
11154206eb5d86d3a2406361e59b2018152b2485ccedSebastien Hertz  if (c == nullptr) {
1116c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return error;
11177b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  }
11184206eb5d86d3a2406361e59b2018152b2485ccedSebastien Hertz  const char* source_file = c->GetSourceFile();
11194206eb5d86d3a2406361e59b2018152b2485ccedSebastien Hertz  if (source_file == nullptr) {
1120b7054baf28d4d652fbd98a94b089344a31898d53Sebastien Hertz    return JDWP::ERR_ABSENT_INFORMATION;
1121b7054baf28d4d652fbd98a94b089344a31898d53Sebastien Hertz  }
1122c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  *result = source_file;
1123436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return JDWP::ERR_NONE;
1124872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1125872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1126c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetObjectTag(JDWP::ObjectId object_id, uint8_t* tag) {
11279837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers  ScopedObjectAccessUnchecked soa(Thread::Current());
1128c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
1129c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error);
1130c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (error != JDWP::ERR_NONE) {
1131c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    *tag = JDWP::JT_VOID;
1132c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return error;
1133546b986ecd09c2a498740bd8bf7127e612d94755Elliott Hughes  }
1134c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  *tag = TagFromObject(soa, o);
1135546b986ecd09c2a498740bd8bf7127e612d94755Elliott Hughes  return JDWP::ERR_NONE;
1136872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1137872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1138aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughessize_t Dbg::GetTagWidth(JDWP::JdwpTag tag) {
1139dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  switch (tag) {
1140dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  case JDWP::JT_VOID:
1141dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes    return 0;
1142dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  case JDWP::JT_BYTE:
1143dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  case JDWP::JT_BOOLEAN:
1144dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes    return 1;
1145dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  case JDWP::JT_CHAR:
1146dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  case JDWP::JT_SHORT:
1147dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes    return 2;
1148dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  case JDWP::JT_FLOAT:
1149dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  case JDWP::JT_INT:
1150dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes    return 4;
1151dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  case JDWP::JT_ARRAY:
1152dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  case JDWP::JT_OBJECT:
1153dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  case JDWP::JT_STRING:
1154dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  case JDWP::JT_THREAD:
1155dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  case JDWP::JT_THREAD_GROUP:
1156dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  case JDWP::JT_CLASS_LOADER:
1157dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  case JDWP::JT_CLASS_OBJECT:
1158dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes    return sizeof(JDWP::ObjectId);
1159dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  case JDWP::JT_DOUBLE:
1160dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  case JDWP::JT_LONG:
1161dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes    return 8;
1162dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  default:
11633d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes    LOG(FATAL) << "Unknown tag " << tag;
1164dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes    return -1;
1165dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  }
1166872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1167872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1168c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetArrayLength(JDWP::ObjectId array_id, int32_t* length) {
1169c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
1170c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Array* a = DecodeNonNullArray(array_id, &error);
1171c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (a == nullptr) {
1172c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return error;
117324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  }
1174c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  *length = a->GetLength();
11753d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  return JDWP::ERR_NONE;
1176872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1177872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
117888d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count, JDWP::ExpandBuf* pReply) {
1179c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
1180c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Array* a = DecodeNonNullArray(array_id, &error);
11819837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers  if (a == nullptr) {
1182c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return error;
11833d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  }
118424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes
118524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  if (offset < 0 || count < 0 || offset > a->GetLength() || a->GetLength() - offset < count) {
118624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes    LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count;
11873d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes    return JDWP::ERR_INVALID_LENGTH;
118824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  }
11891ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers  JDWP::JdwpTag element_tag = BasicTagFromClass(a->GetClass()->GetComponentType());
11901ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers  expandBufAdd1(pReply, element_tag);
11913d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  expandBufAdd4BE(pReply, count);
11923d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes
11931ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers  if (IsPrimitiveTag(element_tag)) {
11941ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers    size_t width = GetTagWidth(element_tag);
119524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes    uint8_t* dst = expandBufAddSpace(pReply, count * width);
119624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes    if (width == 8) {
1197ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      const uint64_t* src8 = reinterpret_cast<uint64_t*>(a->GetRawData(sizeof(uint64_t), 0));
119824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes      for (int i = 0; i < count; ++i) JDWP::Write8BE(&dst, src8[offset + i]);
119924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes    } else if (width == 4) {
1200ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      const uint32_t* src4 = reinterpret_cast<uint32_t*>(a->GetRawData(sizeof(uint32_t), 0));
120124437995cdac88b42e42b16d9aa121e833330999Elliott Hughes      for (int i = 0; i < count; ++i) JDWP::Write4BE(&dst, src4[offset + i]);
120224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes    } else if (width == 2) {
1203ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      const uint16_t* src2 = reinterpret_cast<uint16_t*>(a->GetRawData(sizeof(uint16_t), 0));
120424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes      for (int i = 0; i < count; ++i) JDWP::Write2BE(&dst, src2[offset + i]);
120524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes    } else {
1206ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      const uint8_t* src = reinterpret_cast<uint8_t*>(a->GetRawData(sizeof(uint8_t), 0));
120724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes      memcpy(dst, &src[offset * width], count * width);
120824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes    }
120924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  } else {
12109837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers    ScopedObjectAccessUnchecked soa(Thread::Current());
12112dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::ObjectArray<mirror::Object>* oa = a->AsObjectArray<mirror::Object>();
121224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes    for (int i = 0; i < count; ++i) {
12132dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::Object* element = oa->Get(offset + i);
12149837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers      JDWP::JdwpTag specific_tag = (element != nullptr) ? TagFromObject(soa, element)
12151ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers                                                        : element_tag;
121624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes      expandBufAdd1(pReply, specific_tag);
121724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes      expandBufAddObjectId(pReply, gRegistry->Add(element));
121824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes    }
121924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes  }
122024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes
12213d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  return JDWP::ERR_NONE;
1222872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1223872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1224ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogerstemplate <typename T>
1225c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic void CopyArrayData(mirror::Array* a, JDWP::Request* src, int offset, int count)
1226ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    NO_THREAD_SAFETY_ANALYSIS {
1227ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  // TODO: fix when annotalysis correctly handles non-member functions.
12284b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  DCHECK(a->GetClass()->IsPrimitiveArray());
12294b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes
1230ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  T* dst = reinterpret_cast<T*>(a->GetRawData(sizeof(T), offset));
12314b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  for (int i = 0; i < count; ++i) {
1232c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    *dst++ = src->ReadValue(sizeof(T));
12334b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  }
12344b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes}
12354b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes
123688d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::SetArrayElements(JDWP::ObjectId array_id, int offset, int count,
1237c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers                                      JDWP::Request* request) {
1238c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
1239c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Array* dst = DecodeNonNullArray(array_id, &error);
1240c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (dst == nullptr) {
1241c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return error;
12423d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  }
1243f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes
12444b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  if (offset < 0 || count < 0 || offset > dst->GetLength() || dst->GetLength() - offset < count) {
1245f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes    LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count;
12463d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes    return JDWP::ERR_INVALID_LENGTH;
1247f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes  }
12481ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers  JDWP::JdwpTag element_tag = BasicTagFromClass(dst->GetClass()->GetComponentType());
1249f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes
12501ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers  if (IsPrimitiveTag(element_tag)) {
12511ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers    size_t width = GetTagWidth(element_tag);
1252f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes    if (width == 8) {
12534b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes      CopyArrayData<uint64_t>(dst, request, offset, count);
1254f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes    } else if (width == 4) {
12554b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes      CopyArrayData<uint32_t>(dst, request, offset, count);
1256f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes    } else if (width == 2) {
12574b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes      CopyArrayData<uint16_t>(dst, request, offset, count);
1258f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes    } else {
12594b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes      CopyArrayData<uint8_t>(dst, request, offset, count);
1260f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes    }
1261f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes  } else {
12624b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes    mirror::ObjectArray<mirror::Object>* oa = dst->AsObjectArray<mirror::Object>();
1263f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes    for (int i = 0; i < count; ++i) {
1264c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      JDWP::ObjectId id = request->ReadObjectId();
1265c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      mirror::Object* o = gRegistry->Get<mirror::Object*>(id, &error);
1266c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      if (error != JDWP::ERR_NONE) {
1267c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        return error;
1268436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes      }
12692e1c16d9a4695e4b5cab3ed3ec95f7a88e69c79fSebastien Hertz      // Check if the object's type is compatible with the array's type.
12702e1c16d9a4695e4b5cab3ed3ec95f7a88e69c79fSebastien Hertz      if (o != nullptr && !o->InstanceOf(oa->GetClass()->GetComponentType())) {
12712e1c16d9a4695e4b5cab3ed3ec95f7a88e69c79fSebastien Hertz        return JDWP::ERR_TYPE_MISMATCH;
12722e1c16d9a4695e4b5cab3ed3ec95f7a88e69c79fSebastien Hertz      }
1273d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      oa->Set<false>(offset + i, o);
1274f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes    }
1275f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes  }
1276f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes
12773d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  return JDWP::ERR_NONE;
1278872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1279872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
12802c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien HertzJDWP::JdwpError Dbg::CreateString(const std::string& str, JDWP::ObjectId* new_string_id) {
12812c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  Thread* self = Thread::Current();
12822c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  mirror::String* new_string = mirror::String::AllocFromModifiedUtf8(self, str.c_str());
12832c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  if (new_string == nullptr) {
12842c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz    DCHECK(self->IsExceptionPending());
12852c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz    self->ClearException();
12862c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz    LOG(ERROR) << "Could not allocate string";
12872c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz    *new_string_id = 0;
12882c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz    return JDWP::ERR_OUT_OF_MEMORY;
12892c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  }
12902c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  *new_string_id = gRegistry->Add(new_string);
12912c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  return JDWP::ERR_NONE;
1292872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1293872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
12942c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien HertzJDWP::JdwpError Dbg::CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId* new_object_id) {
1295c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
1296c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Class* c = DecodeClass(class_id, &error);
1297c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (c == nullptr) {
12982c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz    *new_object_id = 0;
1299c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return error;
13007b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  }
13012c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  Thread* self = Thread::Current();
130228bd2e4f151267b34b8e1eb19c489d8d547bbf5cMathieu Chartier  ObjPtr<mirror::Object> new_object;
130356d5e50a7519495777f3223e21b9d73d8ceaa6adSebastien Hertz  if (c->IsStringClass()) {
130456d5e50a7519495777f3223e21b9d73d8ceaa6adSebastien Hertz    // Special case for java.lang.String.
130556d5e50a7519495777f3223e21b9d73d8ceaa6adSebastien Hertz    gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
13063aaa37bba53d6df0265793de48b4b0b57327e57ajessicahandojo    new_object = mirror::String::AllocEmptyString<true>(self, allocator_type);
130756d5e50a7519495777f3223e21b9d73d8ceaa6adSebastien Hertz  } else {
130856d5e50a7519495777f3223e21b9d73d8ceaa6adSebastien Hertz    new_object = c->AllocObject(self);
130956d5e50a7519495777f3223e21b9d73d8ceaa6adSebastien Hertz  }
13102c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  if (new_object == nullptr) {
13112c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz    DCHECK(self->IsExceptionPending());
13122c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz    self->ClearException();
1313709b070044354d9f47641f273edacaeeb0240ab7David Sehr    LOG(ERROR) << "Could not allocate object of type " << mirror::Class::PrettyDescriptor(c);
13142c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz    *new_object_id = 0;
13152c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz    return JDWP::ERR_OUT_OF_MEMORY;
13162c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  }
131728bd2e4f151267b34b8e1eb19c489d8d547bbf5cMathieu Chartier  *new_object_id = gRegistry->Add(new_object.Ptr());
1318436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return JDWP::ERR_NONE;
1319872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1320872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1321bf13d36a25ec0a217fc4440c38b03d10f6c7f642Elliott Hughes/*
1322bf13d36a25ec0a217fc4440c38b03d10f6c7f642Elliott Hughes * Used by Eclipse's "Display" view to evaluate "new byte[5]" to get "(byte[]) [0, 0, 0, 0, 0]".
1323bf13d36a25ec0a217fc4440c38b03d10f6c7f642Elliott Hughes */
132488d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::CreateArrayObject(JDWP::RefTypeId array_class_id, uint32_t length,
13252c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz                                       JDWP::ObjectId* new_array_id) {
1326c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
1327c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Class* c = DecodeClass(array_class_id, &error);
1328c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (c == nullptr) {
13292c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz    *new_array_id = 0;
1330c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return error;
13317b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  }
13322c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  Thread* self = Thread::Current();
13332c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  gc::Heap* heap = Runtime::Current()->GetHeap();
13342c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  mirror::Array* new_array = mirror::Array::Alloc<true>(self, c, length,
13352c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz                                                        c->GetComponentSizeShift(),
13362c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz                                                        heap->GetCurrentAllocator());
13372c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  if (new_array == nullptr) {
13382c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz    DCHECK(self->IsExceptionPending());
13392c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz    self->ClearException();
1340709b070044354d9f47641f273edacaeeb0240ab7David Sehr    LOG(ERROR) << "Could not allocate array of type " << mirror::Class::PrettyDescriptor(c);
13412c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz    *new_array_id = 0;
13422c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz    return JDWP::ERR_OUT_OF_MEMORY;
13432c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  }
13442c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  *new_array_id = gRegistry->Add(new_array);
1345436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return JDWP::ERR_NONE;
1346872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1347872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1348c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu ChartierJDWP::FieldId Dbg::ToFieldId(const ArtField* f) {
134903181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  return static_cast<JDWP::FieldId>(reinterpret_cast<uintptr_t>(f));
135003181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes}
135103181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes
13526c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Lightstatic JDWP::MethodId ToMethodId(ArtMethod* m)
1353bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
13546c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light  return static_cast<JDWP::MethodId>(reinterpret_cast<uintptr_t>(GetCanonicalMethod(m)));
135503181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes}
135603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes
1357c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartierstatic ArtField* FromFieldId(JDWP::FieldId fid)
1358bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
1359c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  return reinterpret_cast<ArtField*>(static_cast<uintptr_t>(fid));
1360aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes}
1361aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes
1362e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic ArtMethod* FromMethodId(JDWP::MethodId mid)
1363bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
1364e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  return reinterpret_cast<ArtMethod*>(static_cast<uintptr_t>(mid));
136503181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes}
136603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes
13676995c60cd6657c10811055c42661a55b10b47cefSebastien Hertzbool Dbg::MatchThread(JDWP::ObjectId expected_thread_id, Thread* event_thread) {
13686995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  CHECK(event_thread != nullptr);
13696995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  JDWP::JdwpError error;
1370e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  mirror::Object* expected_thread_peer = gRegistry->Get<mirror::Object*>(
1371e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier      expected_thread_id, &error);
1372cafa08146648442ee53348c4918a4fab29e591c1Nicolas Geoffray  return expected_thread_peer == event_thread->GetPeerFromOtherThread();
13736995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz}
13746995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz
13756995c60cd6657c10811055c42661a55b10b47cefSebastien Hertzbool Dbg::MatchLocation(const JDWP::JdwpLocation& expected_location,
13766995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz                        const JDWP::EventLocation& event_location) {
13776995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  if (expected_location.dex_pc != event_location.dex_pc) {
13786995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz    return false;
13796995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  }
1380e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  ArtMethod* m = FromMethodId(expected_location.method_id);
13816995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  return m == event_location.method;
13826995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz}
13836995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz
13843398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartierbool Dbg::MatchType(ObjPtr<mirror::Class> event_class, JDWP::RefTypeId class_id) {
1385a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz  if (event_class == nullptr) {
1386a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz    return false;
1387a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz  }
13886995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  JDWP::JdwpError error;
13893398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier  ObjPtr<mirror::Class> expected_class = DecodeClass(class_id, &error);
13906995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  CHECK(expected_class != nullptr);
13916995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  return expected_class->IsAssignableFrom(event_class);
13926995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz}
13936995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz
13946995c60cd6657c10811055c42661a55b10b47cefSebastien Hertzbool Dbg::MatchField(JDWP::RefTypeId expected_type_id, JDWP::FieldId expected_field_id,
1395c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier                     ArtField* event_field) {
1396c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  ArtField* expected_field = FromFieldId(expected_field_id);
13976995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  if (expected_field != event_field) {
13986995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz    return false;
13996995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  }
14006995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  return Dbg::MatchType(event_field->GetDeclaringClass(), expected_type_id);
14016995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz}
14026995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz
14036995c60cd6657c10811055c42661a55b10b47cefSebastien Hertzbool Dbg::MatchInstance(JDWP::ObjectId expected_instance_id, mirror::Object* event_instance) {
14046995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  JDWP::JdwpError error;
14056995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  mirror::Object* modifier_instance = gRegistry->Get<mirror::Object*>(expected_instance_id, &error);
14066995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  return modifier_instance == event_instance;
14076995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz}
14086995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz
140990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartiervoid Dbg::SetJdwpLocation(JDWP::JdwpLocation* location, ArtMethod* m, uint32_t dex_pc) {
1410c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (m == nullptr) {
1411a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz    memset(location, 0, sizeof(*location));
141291bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes  } else {
14132dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Class* c = m->GetDeclaringClass();
1414c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    location->type_tag = GetTypeTag(c);
1415c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    location->class_id = gRegistry->AddRefType(c);
14167337631929812fb8a60b5182eba076a32d1cb851Alex Light    // The RI Seems to return 0 for all obsolete methods. For compatibility we shall do the same.
14177337631929812fb8a60b5182eba076a32d1cb851Alex Light    location->method_id = m->IsObsolete() ? 0 : ToMethodId(m);
1418c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    location->dex_pc = (m->IsNative() || m->IsProxyMethod()) ? static_cast<uint64_t>(-1) : dex_pc;
141991bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes  }
1420d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes}
1421d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes
1422c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstd::string Dbg::GetMethodName(JDWP::MethodId method_id) {
1423e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  ArtMethod* m = FromMethodId(method_id);
1424a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz  if (m == nullptr) {
14252cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    return "null";
1426a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz  }
1427542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe  return m->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetName();
1428872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1429872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
14307337631929812fb8a60b5182eba076a32d1cb851Alex Lightbool Dbg::IsMethodObsolete(JDWP::MethodId method_id) {
14317337631929812fb8a60b5182eba076a32d1cb851Alex Light  ArtMethod* m = FromMethodId(method_id);
14327337631929812fb8a60b5182eba076a32d1cb851Alex Light  if (m == nullptr) {
14337337631929812fb8a60b5182eba076a32d1cb851Alex Light    // NB Since we return 0 as MID for obsolete methods we want to default to true here.
14347337631929812fb8a60b5182eba076a32d1cb851Alex Light    return true;
14357337631929812fb8a60b5182eba076a32d1cb851Alex Light  }
14367337631929812fb8a60b5182eba076a32d1cb851Alex Light  return m->IsObsolete();
14377337631929812fb8a60b5182eba076a32d1cb851Alex Light}
14387337631929812fb8a60b5182eba076a32d1cb851Alex Light
1439c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstd::string Dbg::GetFieldName(JDWP::FieldId field_id) {
1440c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  ArtField* f = FromFieldId(field_id);
1441a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz  if (f == nullptr) {
14422cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    return "null";
1443a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz  }
1444a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz  return f->GetName();
1445a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes}
1446a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes
1447a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes/*
1448a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes * Augment the access flags for synthetic methods and fields by setting
1449a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes * the (as described by the spec) "0xf0000000 bit".  Also, strip out any
1450a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes * flags not specified by the Java programming language.
1451a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes */
1452a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughesstatic uint32_t MangleAccessFlags(uint32_t accessFlags) {
1453a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  accessFlags &= kAccJavaFlagsMask;
1454a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  if ((accessFlags & kAccSynthetic) != 0) {
1455a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes    accessFlags |= 0xf0000000;
1456a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  }
1457a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  return accessFlags;
1458872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1459872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1460dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes/*
1461b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao * Circularly shifts registers so that arguments come first. Debuggers
1462b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao * expect slots to begin with arguments, but dex code places them at
1463b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao * the end.
1464dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes */
1465e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic uint16_t MangleSlot(uint16_t slot, ArtMethod* m)
1466bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
1467bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier  const DexFile::CodeItem* code_item = m->GetCodeItem();
1468cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz  if (code_item == nullptr) {
1469cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz    // We should not get here for a method without code (native, proxy or abstract). Log it and
1470cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz    // return the slot as is since all registers are arguments.
1471709b070044354d9f47641f273edacaeeb0240ab7David Sehr    LOG(WARNING) << "Trying to mangle slot for method without code " << m->PrettyMethod();
1472cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz    return slot;
1473cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz  }
1474b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao  uint16_t ins_size = code_item->ins_size_;
1475b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao  uint16_t locals_size = code_item->registers_size_ - ins_size;
1476b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao  if (slot >= locals_size) {
1477b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao    return slot - locals_size;
1478b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao  } else {
1479b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao    return slot + ins_size;
1480dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  }
1481dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes}
1482dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes
1483aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertzstatic size_t GetMethodNumArgRegistersIncludingThis(ArtMethod* method)
1484bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
1485aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz  uint32_t num_registers = ArtMethod::NumArgRegisters(method->GetShorty());
1486aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz  if (!method->IsStatic()) {
1487aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz    ++num_registers;
1488aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz  }
1489aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz  return num_registers;
1490aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz}
1491aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz
1492b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao/*
1493b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao * Circularly shifts registers so that arguments come last. Reverts
1494b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao * slots to dex style argument placement.
1495b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao */
1496e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic uint16_t DemangleSlot(uint16_t slot, ArtMethod* m, JDWP::JdwpError* error)
1497bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
1498bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier  const DexFile::CodeItem* code_item = m->GetCodeItem();
1499cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz  if (code_item == nullptr) {
1500cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz    // We should not get here for a method without code (native, proxy or abstract). Log it and
1501cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz    // return the slot as is since all registers are arguments.
1502709b070044354d9f47641f273edacaeeb0240ab7David Sehr    LOG(WARNING) << "Trying to demangle slot for method without code "
1503709b070044354d9f47641f273edacaeeb0240ab7David Sehr                 << m->PrettyMethod();
1504aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz    uint16_t vreg_count = GetMethodNumArgRegistersIncludingThis(m);
1505abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz    if (slot < vreg_count) {
1506abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      *error = JDWP::ERR_NONE;
1507abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      return slot;
1508abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz    }
1509b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao  } else {
1510abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz    if (slot < code_item->registers_size_) {
1511abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      uint16_t ins_size = code_item->ins_size_;
1512abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      uint16_t locals_size = code_item->registers_size_ - ins_size;
1513abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      *error = JDWP::ERR_NONE;
1514abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      return (slot < ins_size) ? slot + locals_size : slot - ins_size;
1515abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz    }
1516dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  }
1517abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz
1518abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz  // Slot is invalid in the method.
1519709b070044354d9f47641f273edacaeeb0240ab7David Sehr  LOG(ERROR) << "Invalid local slot " << slot << " for method " << m->PrettyMethod();
1520abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz  *error = JDWP::ERR_INVALID_SLOT;
1521abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz  return DexFile::kDexNoIndex16;
1522dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes}
1523dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes
152490443477f9a0061581c420775ce3b7eeae7468bcMathieu ChartierJDWP::JdwpError Dbg::OutputDeclaredFields(JDWP::RefTypeId class_id, bool with_generic,
152590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier                                          JDWP::ExpandBuf* pReply) {
1526c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
1527c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Class* c = DecodeClass(class_id, &error);
1528c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (c == nullptr) {
1529c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return error;
15307b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  }
1531a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes
1532a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  size_t instance_field_count = c->NumInstanceFields();
1533a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  size_t static_field_count = c->NumStaticFields();
1534a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes
1535a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  expandBufAdd4BE(pReply, instance_field_count + static_field_count);
1536a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes
1537a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  for (size_t i = 0; i < instance_field_count + static_field_count; ++i) {
153890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    ArtField* f = (i < instance_field_count) ? c->GetInstanceField(i) :
153990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier        c->GetStaticField(i - instance_field_count);
1540a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes    expandBufAddFieldId(pReply, ToFieldId(f));
154161c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier    expandBufAddUtf8String(pReply, f->GetName());
154261c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier    expandBufAddUtf8String(pReply, f->GetTypeDescriptor());
1543c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes    if (with_generic) {
1544a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes      static const char genericSignature[1] = "";
1545a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes      expandBufAddUtf8String(pReply, genericSignature);
1546a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes    }
1547a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes    expandBufAdd4BE(pReply, MangleAccessFlags(f->GetAccessFlags()));
1548a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  }
1549436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return JDWP::ERR_NONE;
1550a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes}
1551a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes
155288d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::OutputDeclaredMethods(JDWP::RefTypeId class_id, bool with_generic,
155300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                           JDWP::ExpandBuf* pReply) {
1554c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
1555c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Class* c = DecodeClass(class_id, &error);
1556c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (c == nullptr) {
1557c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return error;
15587b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  }
1559a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes
156051a64d5d4fe91842cc2a5f2a412441147c145683Alex Light  expandBufAdd4BE(pReply, c->NumMethods());
1561a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes
1562e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  auto* cl = Runtime::Current()->GetClassLinker();
1563e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  auto ptr_size = cl->GetImagePointerSize();
156451a64d5d4fe91842cc2a5f2a412441147c145683Alex Light  for (ArtMethod& m : c->GetMethods(ptr_size)) {
156551a64d5d4fe91842cc2a5f2a412441147c145683Alex Light    expandBufAddMethodId(pReply, ToMethodId(&m));
1566542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe    expandBufAddUtf8String(pReply, m.GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetName());
1567542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe    expandBufAddUtf8String(
1568542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe        pReply, m.GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetSignature().ToString());
1569c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes    if (with_generic) {
1570e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier      const char* generic_signature = "";
1571e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier      expandBufAddUtf8String(pReply, generic_signature);
1572a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes    }
157351a64d5d4fe91842cc2a5f2a412441147c145683Alex Light    expandBufAdd4BE(pReply, MangleAccessFlags(m.GetAccessFlags()));
1574a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  }
1575436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return JDWP::ERR_NONE;
1576a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes}
1577a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes
157888d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::OutputDeclaredInterfaces(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) {
1579c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
1580f832284dd847ff077577bb5712225430bbbb3b67Mathieu Chartier  Thread* self = Thread::Current();
158119a4d374738da4dc668a078f92dbe887ff9f00d9Vladimir Marko  ObjPtr<mirror::Class> c = DecodeClass(class_id, &error);
158219a4d374738da4dc668a078f92dbe887ff9f00d9Vladimir Marko  if (c == nullptr) {
1583c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return error;
15847b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  }
1585f832284dd847ff077577bb5712225430bbbb3b67Mathieu Chartier  size_t interface_count = c->NumDirectInterfaces();
1586a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  expandBufAdd4BE(pReply, interface_count);
1587a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  for (size_t i = 0; i < interface_count; ++i) {
158819a4d374738da4dc668a078f92dbe887ff9f00d9Vladimir Marko    ObjPtr<mirror::Class> interface = mirror::Class::GetDirectInterface(self, c, i);
158919a4d374738da4dc668a078f92dbe887ff9f00d9Vladimir Marko    DCHECK(interface != nullptr);
159019a4d374738da4dc668a078f92dbe887ff9f00d9Vladimir Marko    expandBufAddRefTypeId(pReply, gRegistry->AddRefType(interface));
1591a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  }
1592436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return JDWP::ERR_NONE;
1593872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1594872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1595c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersvoid Dbg::OutputLineTable(JDWP::RefTypeId, JDWP::MethodId method_id, JDWP::ExpandBuf* pReply) {
159603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  struct DebugCallbackContext {
159703181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes    int numItems;
159803181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes    JDWP::ExpandBuf* pReply;
159903181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes
1600b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky    static bool Callback(void* context, const DexFile::PositionInfo& entry) {
160103181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes      DebugCallbackContext* pContext = reinterpret_cast<DebugCallbackContext*>(context);
1602b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky      expandBufAdd8BE(pContext->pReply, entry.address_);
1603b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky      expandBufAdd4BE(pContext->pReply, entry.line_);
160403181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes      pContext->numItems++;
1605f2910eef247b45ce1d489e323b36b5de6b6157aaSebastien Hertz      return false;
160603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes    }
160703181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  };
1608e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  ArtMethod* m = FromMethodId(method_id);
1609bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier  const DexFile::CodeItem* code_item = m->GetCodeItem();
161003181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  uint64_t start, end;
1611cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz  if (code_item == nullptr) {
1612cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz    DCHECK(m->IsNative() || m->IsProxyMethod());
161303181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes    start = -1;
161403181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes    end = -1;
161503181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  } else {
161603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes    start = 0;
161714f0db92225d34622fa5cb1a6dc9287334aaf6c7jeffhao    // Return the index of the last instruction
1618cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz    end = code_item->insns_size_in_code_units_ - 1;
161903181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  }
162003181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes
162103181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  expandBufAdd8BE(pReply, start);
162203181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  expandBufAdd8BE(pReply, end);
162303181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes
162403181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  // Add numLines later
162503181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  size_t numLinesOffset = expandBufGetLength(pReply);
162603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  expandBufAdd4BE(pReply, 0);
162703181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes
162803181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  DebugCallbackContext context;
162903181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  context.numItems = 0;
163003181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  context.pReply = pReply;
163103181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes
1632cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz  if (code_item != nullptr) {
1633b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky    m->GetDexFile()->DecodeDebugPositionInfo(code_item, DebugCallbackContext::Callback, &context);
1634cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz  }
163503181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes
163603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  JDWP::Set4BE(expandBufGetBuffer(pReply) + numLinesOffset, context.numItems);
1637872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1638872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1639bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartiervoid Dbg::OutputVariableTable(JDWP::RefTypeId, JDWP::MethodId method_id, bool with_generic,
1640bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier                              JDWP::ExpandBuf* pReply) {
1641dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  struct DebugCallbackContext {
1642e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ArtMethod* method;
1643dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes    JDWP::ExpandBuf* pReply;
1644c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes    size_t variable_count;
1645c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes    bool with_generic;
1646dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes
1647b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky    static void Callback(void* context, const DexFile::LocalInfo& entry)
1648bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe        REQUIRES_SHARED(Locks::mutator_lock_) {
1649dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes      DebugCallbackContext* pContext = reinterpret_cast<DebugCallbackContext*>(context);
1650dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes
1651b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky      uint16_t slot = entry.reg_;
1652bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier      VLOG(jdwp) << StringPrintf("    %2zd: %d(%d) '%s' '%s' '%s' actual slot=%d mangled slot=%d",
1653b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky                                 pContext->variable_count, entry.start_address_,
1654b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky                                 entry.end_address_ - entry.start_address_,
1655b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky                                 entry.name_, entry.descriptor_, entry.signature_, slot,
1656bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier                                 MangleSlot(slot, pContext->method));
1657dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes
1658b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao      slot = MangleSlot(slot, pContext->method);
165968fdbd07fc2b8856905e06f3cc945b046c3bfcd3Elliott Hughes
1660b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky      expandBufAdd8BE(pContext->pReply, entry.start_address_);
1661b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky      expandBufAddUtf8String(pContext->pReply, entry.name_);
1662b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky      expandBufAddUtf8String(pContext->pReply, entry.descriptor_);
1663c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes      if (pContext->with_generic) {
1664b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky        expandBufAddUtf8String(pContext->pReply, entry.signature_);
1665dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes      }
1666b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky      expandBufAdd4BE(pContext->pReply, entry.end_address_- entry.start_address_);
1667dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes      expandBufAdd4BE(pContext->pReply, slot);
1668dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes
1669c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes      ++pContext->variable_count;
1670dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes    }
1671dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  };
1672e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  ArtMethod* m = FromMethodId(method_id);
1673dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes
1674c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes  // arg_count considers doubles and longs to take 2 units.
1675c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes  // variable_count considers everything to take 1 unit.
1676aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz  expandBufAdd4BE(pReply, GetMethodNumArgRegistersIncludingThis(m));
1677dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes
1678c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes  // We don't know the total number of variables yet, so leave a blank and update it later.
1679c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes  size_t variable_count_offset = expandBufGetLength(pReply);
1680dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  expandBufAdd4BE(pReply, 0);
1681dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes
1682dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  DebugCallbackContext context;
1683b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao  context.method = m;
1684dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  context.pReply = pReply;
1685c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes  context.variable_count = 0;
1686c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes  context.with_generic = with_generic;
1687dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes
1688bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier  const DexFile::CodeItem* code_item = m->GetCodeItem();
1689cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz  if (code_item != nullptr) {
1690b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky    m->GetDexFile()->DecodeDebugLocalInfo(
1691b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky        code_item, m->IsStatic(), m->GetDexMethodIndex(), DebugCallbackContext::Callback,
1692bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier        &context);
1693cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz  }
1694dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes
1695c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes  JDWP::Set4BE(expandBufGetBuffer(pReply) + variable_count_offset, context.variable_count);
1696872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1697872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1698579b02416e05e32e535126e1ed61613a2cdb030eJeff Haovoid Dbg::OutputMethodReturnValue(JDWP::MethodId method_id, const JValue* return_value,
1699579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao                                  JDWP::ExpandBuf* pReply) {
1700e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  ArtMethod* m = FromMethodId(method_id);
1701bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier  JDWP::JdwpTag tag = BasicTagFromDescriptor(m->GetShorty());
1702579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao  OutputJValue(tag, return_value, pReply);
1703579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao}
1704579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao
17053f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertzvoid Dbg::OutputFieldValue(JDWP::FieldId field_id, const JValue* field_value,
17063f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                           JDWP::ExpandBuf* pReply) {
1707c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  ArtField* f = FromFieldId(field_id);
170861c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier  JDWP::JdwpTag tag = BasicTagFromDescriptor(f->GetTypeDescriptor());
17093f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  OutputJValue(tag, field_value, pReply);
17103f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz}
17113f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
17129777ba230c83a0edcbda2cf7b208339e77bf171bElliott HughesJDWP::JdwpError Dbg::GetBytecodes(JDWP::RefTypeId, JDWP::MethodId method_id,
1713c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers                                  std::vector<uint8_t>* bytecodes) {
1714e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  ArtMethod* m = FromMethodId(method_id);
1715c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (m == nullptr) {
17169777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes    return JDWP::ERR_INVALID_METHODID;
17179777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes  }
1718bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier  const DexFile::CodeItem* code_item = m->GetCodeItem();
17199777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes  size_t byte_count = code_item->insns_size_in_code_units_ * 2;
17209777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes  const uint8_t* begin = reinterpret_cast<const uint8_t*>(code_item->insns_);
17219777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes  const uint8_t* end = begin + byte_count;
17229777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes  for (const uint8_t* p = begin; p != end; ++p) {
1723c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    bytecodes->push_back(*p);
17249777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes  }
17259777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes  return JDWP::ERR_NONE;
17269777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes}
17279777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes
172888d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpTag Dbg::GetFieldBasicTag(JDWP::FieldId field_id) {
172961c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier  return BasicTagFromDescriptor(FromFieldId(field_id)->GetTypeDescriptor());
1730872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1731872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
173288d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpTag Dbg::GetStaticFieldBasicTag(JDWP::FieldId field_id) {
173361c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier  return BasicTagFromDescriptor(FromFieldId(field_id)->GetTypeDescriptor());
1734872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1735872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
173605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertzstatic JValue GetArtFieldValue(ArtField* f, mirror::Object* o)
1737bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
173805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz  Primitive::Type fieldType = f->GetTypeAsPrimitiveType();
173905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz  JValue field_value;
174005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz  switch (fieldType) {
174105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimBoolean:
174205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      field_value.SetZ(f->GetBoolean(o));
174305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      return field_value;
174405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz
174505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimByte:
174605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      field_value.SetB(f->GetByte(o));
174705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      return field_value;
174805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz
174905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimChar:
175005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      field_value.SetC(f->GetChar(o));
175105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      return field_value;
175205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz
175305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimShort:
175405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      field_value.SetS(f->GetShort(o));
175505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      return field_value;
175605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz
175705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimInt:
175805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimFloat:
175905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      // Int and Float must be treated as 32-bit values in JDWP.
176005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      field_value.SetI(f->GetInt(o));
176105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      return field_value;
176205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz
176305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimLong:
176405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimDouble:
176505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      // Long and Double must be treated as 64-bit values in JDWP.
176605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      field_value.SetJ(f->GetLong(o));
176705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      return field_value;
176805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz
176905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimNot:
17701cc62e4ea24828fdb3f3da0b8603f0b107d09a04Mathieu Chartier      field_value.SetL(f->GetObject(o).Ptr());
177105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      return field_value;
177205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz
177305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimVoid:
177405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      LOG(FATAL) << "Attempt to read from field of type 'void'";
177505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      UNREACHABLE();
177605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz  }
177705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz  LOG(FATAL) << "Attempt to read from field of unknown type";
177805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz  UNREACHABLE();
177905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz}
178005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz
178188d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughesstatic JDWP::JdwpError GetFieldValueImpl(JDWP::RefTypeId ref_type_id, JDWP::ObjectId object_id,
178288d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes                                         JDWP::FieldId field_id, JDWP::ExpandBuf* pReply,
178300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                         bool is_static)
1784bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
1785c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
1786c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Class* c = DecodeClass(ref_type_id, &error);
1787c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (ref_type_id != 0 && c == nullptr) {
1788c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return error;
17890cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes  }
17900cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes
1791de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao  Thread* self = Thread::Current();
1792de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao  StackHandleScope<2> hs(self);
1793de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao  MutableHandle<mirror::Object>
1794de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao      o(hs.NewHandle(Dbg::GetObjectRegistry()->Get<mirror::Object*>(object_id, &error)));
1795fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  if ((!is_static && o == nullptr) || error != JDWP::ERR_NONE) {
17963f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes    return JDWP::ERR_INVALID_OBJECT;
17973f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes  }
1798c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  ArtField* f = FromFieldId(field_id);
17990cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes
18002dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Class* receiver_class = c;
1801fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  if (receiver_class == nullptr && o != nullptr) {
18020cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes    receiver_class = o->GetClass();
18030cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes  }
1804de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao
18052cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  // TODO: should we give up now if receiver_class is null?
1806c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (receiver_class != nullptr && !f->GetDeclaringClass()->IsAssignableFrom(receiver_class)) {
1807709b070044354d9f47641f273edacaeeb0240ab7David Sehr    LOG(INFO) << "ERR_INVALID_FIELDID: " << f->PrettyField() << " "
1808709b070044354d9f47641f273edacaeeb0240ab7David Sehr              << receiver_class->PrettyClass();
18093f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes    return JDWP::ERR_INVALID_FIELDID;
18103f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes  }
1811aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes
1812de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao  // Ensure the field's class is initialized.
1813de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao  Handle<mirror::Class> klass(hs.NewHandle(f->GetDeclaringClass()));
1814de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao  if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(self, klass, true, false)) {
1815709b070044354d9f47641f273edacaeeb0240ab7David Sehr    LOG(WARNING) << "Not able to initialize class for SetValues: "
1816709b070044354d9f47641f273edacaeeb0240ab7David Sehr                 << mirror::Class::PrettyClass(klass.Get());
1817de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao  }
1818de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao
18190cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes  // The RI only enforces the static/non-static mismatch in one direction.
18200cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes  // TODO: should we change the tests and check both?
18210cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes  if (is_static) {
18220cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes    if (!f->IsStatic()) {
18230cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes      return JDWP::ERR_INVALID_FIELDID;
18240cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes    }
18250cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes  } else {
18260cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes    if (f->IsStatic()) {
182705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      LOG(WARNING) << "Ignoring non-nullptr receiver for ObjectReference.GetValues"
1828709b070044354d9f47641f273edacaeeb0240ab7David Sehr                   << " on static field " << f->PrettyField();
18290cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes    }
18300cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes  }
18310dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao  if (f->IsStatic()) {
1832de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao    o.Assign(f->GetDeclaringClass());
18330dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao  }
18340cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes
1835de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao  JValue field_value(GetArtFieldValue(f, o.Get()));
183661c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier  JDWP::JdwpTag tag = BasicTagFromDescriptor(f->GetTypeDescriptor());
1837579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao  Dbg::OutputJValue(tag, &field_value, pReply);
18383f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes  return JDWP::ERR_NONE;
1839872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1840872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
184188d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::GetFieldValue(JDWP::ObjectId object_id, JDWP::FieldId field_id,
184200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                   JDWP::ExpandBuf* pReply) {
184388d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes  return GetFieldValueImpl(0, object_id, field_id, pReply, false);
18443f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes}
18453f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes
1846c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetStaticFieldValue(JDWP::RefTypeId ref_type_id, JDWP::FieldId field_id,
1847c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers                                         JDWP::ExpandBuf* pReply) {
184888d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes  return GetFieldValueImpl(ref_type_id, 0, field_id, pReply, true);
18493f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes}
18503f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes
185105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertzstatic JDWP::JdwpError SetArtFieldValue(ArtField* f, mirror::Object* o, uint64_t value, int width)
1852bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
185305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz  Primitive::Type fieldType = f->GetTypeAsPrimitiveType();
185405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz  // Debugging only happens at runtime so we know we are not running in a transaction.
185505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz  static constexpr bool kNoTransactionMode = false;
185605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz  switch (fieldType) {
185705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimBoolean:
185805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      CHECK_EQ(width, 1);
185905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      f->SetBoolean<kNoTransactionMode>(o, static_cast<uint8_t>(value));
186005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      return JDWP::ERR_NONE;
186105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz
186205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimByte:
186305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      CHECK_EQ(width, 1);
186405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      f->SetByte<kNoTransactionMode>(o, static_cast<uint8_t>(value));
186505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      return JDWP::ERR_NONE;
186605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz
186705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimChar:
186805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      CHECK_EQ(width, 2);
186905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      f->SetChar<kNoTransactionMode>(o, static_cast<uint16_t>(value));
187005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      return JDWP::ERR_NONE;
187105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz
187205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimShort:
187305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      CHECK_EQ(width, 2);
187405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      f->SetShort<kNoTransactionMode>(o, static_cast<int16_t>(value));
187505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      return JDWP::ERR_NONE;
187605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz
187705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimInt:
187805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimFloat:
187905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      CHECK_EQ(width, 4);
188005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      // Int and Float must be treated as 32-bit values in JDWP.
188105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      f->SetInt<kNoTransactionMode>(o, static_cast<int32_t>(value));
188205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      return JDWP::ERR_NONE;
188305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz
188405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimLong:
188505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimDouble:
188605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      CHECK_EQ(width, 8);
188705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      // Long and Double must be treated as 64-bit values in JDWP.
188805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      f->SetLong<kNoTransactionMode>(o, value);
188905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      return JDWP::ERR_NONE;
189005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz
189105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimNot: {
189205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      JDWP::JdwpError error;
189305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      mirror::Object* v = Dbg::GetObjectRegistry()->Get<mirror::Object*>(value, &error);
189405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      if (error != JDWP::ERR_NONE) {
189505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz        return JDWP::ERR_INVALID_OBJECT;
189605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      }
189705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      if (v != nullptr) {
18983398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier        ObjPtr<mirror::Class> field_type;
189905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz        {
190005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz          StackHandleScope<2> hs(Thread::Current());
190105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz          HandleWrapper<mirror::Object> h_v(hs.NewHandleWrapper(&v));
190205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz          HandleWrapper<mirror::Object> h_o(hs.NewHandleWrapper(&o));
190305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz          field_type = f->GetType<true>();
190405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz        }
190505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz        if (!field_type->IsAssignableFrom(v->GetClass())) {
190605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz          return JDWP::ERR_INVALID_OBJECT;
190705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz        }
190805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      }
190905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      f->SetObject<kNoTransactionMode>(o, v);
191005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      return JDWP::ERR_NONE;
191105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    }
191205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz
191305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz    case Primitive::kPrimVoid:
191405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      LOG(FATAL) << "Attempt to write to field of type 'void'";
191505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      UNREACHABLE();
191605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz  }
191705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz  LOG(FATAL) << "Attempt to write to field of unknown type";
191805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz  UNREACHABLE();
191905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz}
192005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz
192188d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughesstatic JDWP::JdwpError SetFieldValueImpl(JDWP::ObjectId object_id, JDWP::FieldId field_id,
192200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                         uint64_t value, int width, bool is_static)
1923bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
1924c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
1925de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao  Thread* self = Thread::Current();
1926de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao  StackHandleScope<2> hs(self);
1927de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao  MutableHandle<mirror::Object>
1928de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao      o(hs.NewHandle(Dbg::GetObjectRegistry()->Get<mirror::Object*>(object_id, &error)));
1929fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  if ((!is_static && o == nullptr) || error != JDWP::ERR_NONE) {
19303f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes    return JDWP::ERR_INVALID_OBJECT;
19313f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes  }
1932c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  ArtField* f = FromFieldId(field_id);
19330cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes
1934de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao  // Ensure the field's class is initialized.
1935de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao  Handle<mirror::Class> klass(hs.NewHandle(f->GetDeclaringClass()));
1936de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao  if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(self, klass, true, false)) {
1937709b070044354d9f47641f273edacaeeb0240ab7David Sehr    LOG(WARNING) << "Not able to initialize class for SetValues: "
1938709b070044354d9f47641f273edacaeeb0240ab7David Sehr                 << mirror::Class::PrettyClass(klass.Get());
1939de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao  }
1940de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao
19410cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes  // The RI only enforces the static/non-static mismatch in one direction.
19420cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes  // TODO: should we change the tests and check both?
19430cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes  if (is_static) {
19440cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes    if (!f->IsStatic()) {
19450cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes      return JDWP::ERR_INVALID_FIELDID;
19460cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes    }
19470cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes  } else {
19480cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes    if (f->IsStatic()) {
194905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz      LOG(WARNING) << "Ignoring non-nullptr receiver for ObjectReference.SetValues"
1950709b070044354d9f47641f273edacaeeb0240ab7David Sehr                   << " on static field " << f->PrettyField();
19510cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes    }
19523f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes  }
19530dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao  if (f->IsStatic()) {
1954de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao    o.Assign(f->GetDeclaringClass());
19550dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao  }
1956de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao  return SetArtFieldValue(f, o.Get(), value, width);
1957872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1958872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
195988d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::SetFieldValue(JDWP::ObjectId object_id, JDWP::FieldId field_id, uint64_t value,
196000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                   int width) {
196188d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes  return SetFieldValueImpl(object_id, field_id, value, width, false);
1962872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1963872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
196488d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::SetStaticFieldValue(JDWP::FieldId field_id, uint64_t value, int width) {
196588d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes  return SetFieldValueImpl(0, field_id, value, width, true);
1966872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1967872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1968b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien HertzJDWP::JdwpError Dbg::StringToUtf8(JDWP::ObjectId string_id, std::string* str) {
1969c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
1970b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz  mirror::Object* obj = gRegistry->Get<mirror::Object*>(string_id, &error);
1971b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz  if (error != JDWP::ERR_NONE) {
1972b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz    return error;
1973b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz  }
1974b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz  if (obj == nullptr) {
1975b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz    return JDWP::ERR_INVALID_OBJECT;
1976b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz  }
1977b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz  {
1978b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz    ScopedObjectAccessUnchecked soa(Thread::Current());
19790795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier    ObjPtr<mirror::Class> java_lang_String =
19800795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier        soa.Decode<mirror::Class>(WellKnownClasses::java_lang_String);
1981b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz    if (!java_lang_String->IsAssignableFrom(obj->GetClass())) {
1982b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz      // This isn't a string.
1983b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz      return JDWP::ERR_INVALID_STRING;
1984b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz    }
1985b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz  }
1986b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz  *str = obj->AsString()->ToModifiedUtf8();
1987b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz  return JDWP::ERR_NONE;
1988872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1989872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1990579b02416e05e32e535126e1ed61613a2cdb030eJeff Haovoid Dbg::OutputJValue(JDWP::JdwpTag tag, const JValue* return_value, JDWP::ExpandBuf* pReply) {
1991579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao  if (IsPrimitiveTag(tag)) {
1992579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao    expandBufAdd1(pReply, tag);
1993579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao    if (tag == JDWP::JT_BOOLEAN || tag == JDWP::JT_BYTE) {
1994579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao      expandBufAdd1(pReply, return_value->GetI());
1995579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao    } else if (tag == JDWP::JT_CHAR || tag == JDWP::JT_SHORT) {
1996579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao      expandBufAdd2BE(pReply, return_value->GetI());
1997579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao    } else if (tag == JDWP::JT_FLOAT || tag == JDWP::JT_INT) {
1998579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao      expandBufAdd4BE(pReply, return_value->GetI());
1999579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao    } else if (tag == JDWP::JT_DOUBLE || tag == JDWP::JT_LONG) {
2000579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao      expandBufAdd8BE(pReply, return_value->GetJ());
2001579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao    } else {
2002579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao      CHECK_EQ(tag, JDWP::JT_VOID);
2003579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao    }
2004579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao  } else {
20059837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers    ScopedObjectAccessUnchecked soa(Thread::Current());
2006579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao    mirror::Object* value = return_value->GetL();
20079837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers    expandBufAdd1(pReply, TagFromObject(soa, value));
2008579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao    expandBufAddObjectId(pReply, gRegistry->Add(value));
2009579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao  }
2010579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao}
2011579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao
2012c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetThreadName(JDWP::ObjectId thread_id, std::string* name) {
2013a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao  ScopedObjectAccessUnchecked soa(Thread::Current());
2014c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
20154b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain  DecodeThread(soa, thread_id, &error);
2016221229cb523f849f165fdafbf9785010963715daElliott Hughes  if (error != JDWP::ERR_NONE && error != JDWP::ERR_THREAD_NOT_ALIVE) {
2017221229cb523f849f165fdafbf9785010963715daElliott Hughes    return error;
2018a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  }
2019221229cb523f849f165fdafbf9785010963715daElliott Hughes
2020221229cb523f849f165fdafbf9785010963715daElliott Hughes  // We still need to report the zombie threads' names, so we can't just call Thread::GetThreadName.
2021c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id, &error);
2022c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  CHECK(thread_object != nullptr) << error;
2023c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  ArtField* java_lang_Thread_name_field =
202408883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe      jni::DecodeArtField(WellKnownClasses::java_lang_Thread_name);
2025f8ac97f94aad9ce2d324c2c7c21dde3abf13315bMathieu Chartier  ObjPtr<mirror::String> s(java_lang_Thread_name_field->GetObject(thread_object)->AsString());
2026c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (s != nullptr) {
2027c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    *name = s->ToModifiedUtf8();
2028221229cb523f849f165fdafbf9785010963715daElliott Hughes  }
2029221229cb523f849f165fdafbf9785010963715daElliott Hughes  return JDWP::ERR_NONE;
2030872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2031872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2032221229cb523f849f165fdafbf9785010963715daElliott HughesJDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply) {
2033a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  ScopedObjectAccessUnchecked soa(Thread::Current());
2034c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
2035c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id, &error);
2036c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (error != JDWP::ERR_NONE) {
20372435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes    return JDWP::ERR_INVALID_OBJECT;
20382435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  }
2039268764da8022cafa5661c5b514eaa343c5257e57Mathieu Chartier  ScopedAssertNoThreadSuspension ants("Debugger: GetThreadGroup");
20402435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  // Okay, so it's an object, but is it actually a thread?
20414b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain  DecodeThread(soa, thread_id, &error);
2042221229cb523f849f165fdafbf9785010963715daElliott Hughes  if (error == JDWP::ERR_THREAD_NOT_ALIVE) {
2043221229cb523f849f165fdafbf9785010963715daElliott Hughes    // Zombie threads are in the null group.
2044221229cb523f849f165fdafbf9785010963715daElliott Hughes    expandBufAddObjectId(pReply, JDWP::ObjectId(0));
204552d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz    error = JDWP::ERR_NONE;
204652d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz  } else if (error == JDWP::ERR_NONE) {
20470795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier    ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(WellKnownClasses::java_lang_Thread);
204852d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz    CHECK(c != nullptr);
204908883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe    ArtField* f = jni::DecodeArtField(WellKnownClasses::java_lang_Thread_group);
2050b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    CHECK(f != nullptr);
20513398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier    ObjPtr<mirror::Object> group = f->GetObject(thread_object);
2052b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    CHECK(group != nullptr);
205352d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz    JDWP::ObjectId thread_group_id = gRegistry->Add(group);
205452d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz    expandBufAddObjectId(pReply, thread_group_id);
20552435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  }
205652d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz  return error;
2057872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2058872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2059a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertzstatic mirror::Object* DecodeThreadGroup(ScopedObjectAccessUnchecked& soa,
2060a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz                                         JDWP::ObjectId thread_group_id, JDWP::JdwpError* error)
2061bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
20626995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  mirror::Object* thread_group = Dbg::GetObjectRegistry()->Get<mirror::Object*>(thread_group_id,
20636995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz                                                                                error);
2064a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  if (*error != JDWP::ERR_NONE) {
2065a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    return nullptr;
2066a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  }
2067a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  if (thread_group == nullptr) {
2068a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    *error = JDWP::ERR_INVALID_OBJECT;
2069a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    return nullptr;
2070a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  }
20710795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier  ObjPtr<mirror::Class> c =
20720795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier      soa.Decode<mirror::Class>(WellKnownClasses::java_lang_ThreadGroup);
2073a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  CHECK(c != nullptr);
2074a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  if (!c->IsAssignableFrom(thread_group->GetClass())) {
2075a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    // This is not a java.lang.ThreadGroup.
2076a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    *error = JDWP::ERR_INVALID_THREAD_GROUP;
2077a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    return nullptr;
2078a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  }
2079a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  *error = JDWP::ERR_NONE;
2080a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  return thread_group;
2081a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz}
2082a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz
2083a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien HertzJDWP::JdwpError Dbg::GetThreadGroupName(JDWP::ObjectId thread_group_id, JDWP::ExpandBuf* pReply) {
2084a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  ScopedObjectAccessUnchecked soa(Thread::Current());
2085c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
2086a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  mirror::Object* thread_group = DecodeThreadGroup(soa, thread_group_id, &error);
2087a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  if (error != JDWP::ERR_NONE) {
2088a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    return error;
2089a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  }
2090268764da8022cafa5661c5b514eaa343c5257e57Mathieu Chartier  ScopedAssertNoThreadSuspension ants("Debugger: GetThreadGroupName");
209108883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe  ArtField* f = jni::DecodeArtField(WellKnownClasses::java_lang_ThreadGroup_name);
2092c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  CHECK(f != nullptr);
20933398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier  ObjPtr<mirror::String> s = f->GetObject(thread_group)->AsString();
2094a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz
2095a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  std::string thread_group_name(s->ToModifiedUtf8());
2096a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  expandBufAddUtf8String(pReply, thread_group_name);
2097a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  return JDWP::ERR_NONE;
2098872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2099872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2100a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien HertzJDWP::JdwpError Dbg::GetThreadGroupParent(JDWP::ObjectId thread_group_id, JDWP::ExpandBuf* pReply) {
21019837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers  ScopedObjectAccessUnchecked soa(Thread::Current());
2102c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
2103a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  mirror::Object* thread_group = DecodeThreadGroup(soa, thread_group_id, &error);
2104a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  if (error != JDWP::ERR_NONE) {
2105a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    return error;
2106a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  }
21073398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier  ObjPtr<mirror::Object> parent;
21082d5f39ed5aeaeb7ca22b07b4c6e8c56348ef8893Mathieu Chartier  {
2109268764da8022cafa5661c5b514eaa343c5257e57Mathieu Chartier    ScopedAssertNoThreadSuspension ants("Debugger: GetThreadGroupParent");
211008883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe    ArtField* f = jni::DecodeArtField(WellKnownClasses::java_lang_ThreadGroup_parent);
21112d5f39ed5aeaeb7ca22b07b4c6e8c56348ef8893Mathieu Chartier    CHECK(f != nullptr);
21122d5f39ed5aeaeb7ca22b07b4c6e8c56348ef8893Mathieu Chartier    parent = f->GetObject(thread_group);
21132d5f39ed5aeaeb7ca22b07b4c6e8c56348ef8893Mathieu Chartier  }
2114a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  JDWP::ObjectId parent_group_id = gRegistry->Add(parent);
2115a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  expandBufAddObjectId(pReply, parent_group_id);
2116a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  return JDWP::ERR_NONE;
2117872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2118872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
211908883debd927d18c9ecf66683a2a11aa98165656Andreas Gampestatic void GetChildThreadGroups(mirror::Object* thread_group,
2120a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz                                 std::vector<JDWP::ObjectId>* child_thread_group_ids)
2121bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
2122a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  CHECK(thread_group != nullptr);
2123a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz
2124464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak  // Get the int "ngroups" count of this thread group...
212508883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe  ArtField* ngroups_field = jni::DecodeArtField(WellKnownClasses::java_lang_ThreadGroup_ngroups);
2126464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak  CHECK(ngroups_field != nullptr);
2127464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak  const int32_t size = ngroups_field->GetInt(thread_group);
2128464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak  if (size == 0) {
2129464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak    return;
2130e49e195c4bc2f20df0289c0bbb46f56839308ddeSebastien Hertz  }
2131a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz
2132464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak  // Get the ThreadGroup[] "groups" out of this thread group...
213308883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe  ArtField* groups_field = jni::DecodeArtField(WellKnownClasses::java_lang_ThreadGroup_groups);
21343398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier  ObjPtr<mirror::Object> groups_array = groups_field->GetObject(thread_group);
2135464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak
2136464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak  CHECK(groups_array != nullptr);
2137464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak  CHECK(groups_array->IsObjectArray());
2138464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak
21393398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier  ObjPtr<mirror::ObjectArray<mirror::Object>> groups_array_as_array =
2140464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak      groups_array->AsObjectArray<mirror::Object>();
2141a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz
2142a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  // Copy the first 'size' elements out of the array into the result.
21436995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  ObjectRegistry* registry = Dbg::GetObjectRegistry();
2144a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  for (int32_t i = 0; i < size; ++i) {
2145464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak    child_thread_group_ids->push_back(registry->Add(groups_array_as_array->Get(i)));
2146a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  }
2147a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz}
2148a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz
2149a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien HertzJDWP::JdwpError Dbg::GetThreadGroupChildren(JDWP::ObjectId thread_group_id,
2150a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz                                            JDWP::ExpandBuf* pReply) {
215100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccessUnchecked soa(Thread::Current());
2152a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  JDWP::JdwpError error;
2153a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  mirror::Object* thread_group = DecodeThreadGroup(soa, thread_group_id, &error);
2154a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  if (error != JDWP::ERR_NONE) {
2155a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    return error;
2156a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  }
2157a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz
2158a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  // Add child threads.
2159a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  {
2160a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    std::vector<JDWP::ObjectId> child_thread_ids;
2161a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    GetThreads(thread_group, &child_thread_ids);
2162a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    expandBufAdd4BE(pReply, child_thread_ids.size());
2163a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    for (JDWP::ObjectId child_thread_id : child_thread_ids) {
2164a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz      expandBufAddObjectId(pReply, child_thread_id);
2165a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    }
2166a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  }
2167a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz
2168a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  // Add child thread groups.
2169a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  {
2170a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    std::vector<JDWP::ObjectId> child_thread_groups_ids;
217108883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe    GetChildThreadGroups(thread_group, &child_thread_groups_ids);
2172a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    expandBufAdd4BE(pReply, child_thread_groups_ids.size());
2173a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    for (JDWP::ObjectId child_thread_group_id : child_thread_groups_ids) {
2174a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz      expandBufAddObjectId(pReply, child_thread_group_id);
2175a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz    }
2176a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  }
2177a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz
2178a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  return JDWP::ERR_NONE;
2179872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2180872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2181a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien HertzJDWP::ObjectId Dbg::GetSystemThreadGroupId() {
2182a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  ScopedObjectAccessUnchecked soa(Thread::Current());
218308883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe  ArtField* f = jni::DecodeArtField(WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup);
21843398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier  ObjPtr<mirror::Object> group = f->GetObject(f->GetDeclaringClass());
2185365c10235438607541fa2259a5fec48061b90bd8Ian Rogers  return gRegistry->Add(group);
2186872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2187872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2188920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff HaoJDWP::JdwpThreadStatus Dbg::ToJdwpThreadStatus(ThreadState state) {
2189920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao  switch (state) {
2190920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kBlocked:
2191920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao      return JDWP::TS_MONITOR;
2192920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kNative:
2193920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kRunnable:
2194920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kSuspended:
2195920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao      return JDWP::TS_RUNNING;
2196920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kSleeping:
2197920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao      return JDWP::TS_SLEEPING;
2198920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kStarting:
2199920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kTerminated:
2200920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao      return JDWP::TS_ZOMBIE;
2201920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kTimedWaiting:
2202bae182cbc6adc8796154162a87fc54ae804e0469Sebastien Hertz    case kWaitingForCheckPointsToRun:
2203920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kWaitingForDebuggerSend:
2204920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kWaitingForDebuggerSuspension:
2205920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kWaitingForDebuggerToAttach:
2206138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    case kWaitingForDeoptimization:
2207920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kWaitingForGcToComplete:
2208b43390cb87eace4a017f672d66cfb20fb9e76aa1Mathieu Chartier    case kWaitingForGetObjectsAllocated:
2209920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kWaitingForJniOnLoad:
2210bae182cbc6adc8796154162a87fc54ae804e0469Sebastien Hertz    case kWaitingForMethodTracingStart:
2211920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kWaitingForSignalCatcherOutput:
22120c8c303c20cdaaf54d26e45cc17dc5afb820d8efHiroshi Yamauchi    case kWaitingForVisitObjects:
2213920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kWaitingInMainDebuggerLoop:
2214920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kWaitingInMainSignalCatcherLoop:
2215920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kWaitingPerformingGc:
221690ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier    case kWaitingWeakGcRootRead:
221776f55b030d2517d434f227bee2363c3fb760e5c6Hiroshi Yamauchi    case kWaitingForGcThreadFlip:
2218920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao    case kWaiting:
2219920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao      return JDWP::TS_WAIT;
2220920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao      // Don't add a 'default' here so the compiler can spot incompatible enum changes.
2221920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao  }
2222920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao  LOG(FATAL) << "Unknown thread state: " << state;
2223920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao  return JDWP::TS_ZOMBIE;
2224920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao}
2225920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao
222652d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien HertzJDWP::JdwpError Dbg::GetThreadStatus(JDWP::ObjectId thread_id, JDWP::JdwpThreadStatus* pThreadStatus,
222752d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz                                     JDWP::JdwpSuspendStatus* pSuspendStatus) {
222800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(Thread::Current());
2229499c5133d361e7c659fc38e5ccfeb1280a7996f5Elliott Hughes
22309e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes  *pSuspendStatus = JDWP::SUSPEND_STATUS_NOT_SUSPENDED;
22319e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes
2232c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
2233c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  Thread* thread = DecodeThread(soa, thread_id, &error);
2234221229cb523f849f165fdafbf9785010963715daElliott Hughes  if (error != JDWP::ERR_NONE) {
2235221229cb523f849f165fdafbf9785010963715daElliott Hughes    if (error == JDWP::ERR_THREAD_NOT_ALIVE) {
2236221229cb523f849f165fdafbf9785010963715daElliott Hughes      *pThreadStatus = JDWP::TS_ZOMBIE;
2237221229cb523f849f165fdafbf9785010963715daElliott Hughes      return JDWP::ERR_NONE;
2238221229cb523f849f165fdafbf9785010963715daElliott Hughes    }
2239221229cb523f849f165fdafbf9785010963715daElliott Hughes    return error;
2240499c5133d361e7c659fc38e5ccfeb1280a7996f5Elliott Hughes  }
2241499c5133d361e7c659fc38e5ccfeb1280a7996f5Elliott Hughes
22429e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes  if (IsSuspendedForDebugger(soa, thread)) {
22439e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes    *pSuspendStatus = JDWP::SUSPEND_STATUS_SUSPENDED;
22449e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes  }
224500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
2246920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao  *pThreadStatus = ToJdwpThreadStatus(thread->GetState());
2247221229cb523f849f165fdafbf9785010963715daElliott Hughes  return JDWP::ERR_NONE;
2248872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2249872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2250221229cb523f849f165fdafbf9785010963715daElliott HughesJDWP::JdwpError Dbg::GetThreadDebugSuspendCount(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply) {
225100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(Thread::Current());
2252c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
2253c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  Thread* thread = DecodeThread(soa, thread_id, &error);
2254221229cb523f849f165fdafbf9785010963715daElliott Hughes  if (error != JDWP::ERR_NONE) {
2255221229cb523f849f165fdafbf9785010963715daElliott Hughes    return error;
22562435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  }
225750b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_);
225800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  expandBufAdd4BE(pReply, thread->GetDebugSuspendCount());
22592435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  return JDWP::ERR_NONE;
2260872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2261872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2262f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott HughesJDWP::JdwpError Dbg::Interrupt(JDWP::ObjectId thread_id) {
2263f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes  ScopedObjectAccess soa(Thread::Current());
2264c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
2265c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  Thread* thread = DecodeThread(soa, thread_id, &error);
2266f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes  if (error != JDWP::ERR_NONE) {
2267f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes    return error;
2268f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes  }
2269dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  thread->Interrupt(soa.Self());
2270f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes  return JDWP::ERR_NONE;
2271f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes}
2272f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes
227308883debd927d18c9ecf66683a2a11aa98165656Andreas Gampestatic bool IsInDesiredThreadGroup(mirror::Object* desired_thread_group, mirror::Object* peer)
2274bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
2275070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz  // Do we want threads from all thread groups?
2276070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz  if (desired_thread_group == nullptr) {
2277070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz    return true;
2278070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz  }
227908883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe  ArtField* thread_group_field = jni::DecodeArtField(WellKnownClasses::java_lang_Thread_group);
2280070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz  DCHECK(thread_group_field != nullptr);
22813398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier  ObjPtr<mirror::Object> group = thread_group_field->GetObject(peer);
2282070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz  return (group == desired_thread_group);
2283070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz}
2284a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes
2285a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertzvoid Dbg::GetThreads(mirror::Object* thread_group, std::vector<JDWP::ObjectId>* thread_ids) {
228600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccessUnchecked soa(Thread::Current());
2287070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz  std::list<Thread*> all_threads_list;
2288070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz  {
2289070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz    MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
2290070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz    all_threads_list = Runtime::Current()->GetThreadList()->GetList();
2291070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz  }
2292070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz  for (Thread* t : all_threads_list) {
2293070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz    if (t == Dbg::GetDebugThread()) {
2294070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz      // Skip the JDWP thread. Some debuggers get bent out of shape when they can't suspend and
2295070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz      // query all threads, so it's easier if we just don't tell them about this thread.
2296070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz      continue;
2297070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz    }
2298070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz    if (t->IsStillStarting()) {
2299070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz      // This thread is being started (and has been registered in the thread list). However, it is
2300070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz      // not completely started yet so we must ignore it.
2301070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz      continue;
2302070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz    }
2303cafa08146648442ee53348c4918a4fab29e591c1Nicolas Geoffray    mirror::Object* peer = t->GetPeerFromOtherThread();
2304070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz    if (peer == nullptr) {
23052cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      // peer might be null if the thread is still starting up. We can't tell the debugger about
2306070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz      // this thread yet.
2307070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz      // TODO: if we identified threads to the debugger by their Thread*
2308070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz      // rather than their peer's mirror::Object*, we could fix this.
2309070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz      // Doing so might help us report ZOMBIE threads too.
2310070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz      continue;
2311070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz    }
231208883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe    if (IsInDesiredThreadGroup(thread_group, peer)) {
2313070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz      thread_ids->push_back(gRegistry->Add(peer));
2314070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz    }
2315070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz  }
2316a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes}
2317a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes
2318bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampestatic int GetStackDepth(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_) {
23190399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  struct CountStackDepthVisitor : public StackVisitor {
2320277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe    explicit CountStackDepthVisitor(Thread* thread_in)
23218e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray        : StackVisitor(thread_in, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
23228e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray          depth(0) {}
23230399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers
232464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
232564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    // annotalysis.
232664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS {
23270399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      if (!GetMethod()->IsRuntimeMethod()) {
2328f8a2df7bbf1021058bc13d1f806a7fec3c89ee62Elliott Hughes        ++depth;
2329f8a2df7bbf1021058bc13d1f806a7fec3c89ee62Elliott Hughes      }
2330530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes      return true;
2331a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes    }
2332a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes    size_t depth;
2333a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  };
233408fc03ae5dded4adc9b45b7014a4b9dfedbe95a6Elliott Hughes
23357a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers  CountStackDepthVisitor visitor(thread);
23360399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  visitor.WalkStack();
2337a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  return visitor.depth;
2338872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2339872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2340c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetThreadFrameCount(JDWP::ObjectId thread_id, size_t* result) {
234100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(Thread::Current());
2342c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
2343c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  *result = 0;
2344c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  Thread* thread = DecodeThread(soa, thread_id, &error);
2345221229cb523f849f165fdafbf9785010963715daElliott Hughes  if (error != JDWP::ERR_NONE) {
2346221229cb523f849f165fdafbf9785010963715daElliott Hughes    return error;
2347221229cb523f849f165fdafbf9785010963715daElliott Hughes  }
2348f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes  if (!IsSuspendedForDebugger(soa, thread)) {
2349f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes    return JDWP::ERR_THREAD_NOT_SUSPENDED;
2350f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes  }
2351c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  *result = GetStackDepth(thread);
2352221229cb523f849f165fdafbf9785010963715daElliott Hughes  return JDWP::ERR_NONE;
23538696433d1b3d8ba15288483b777edd888de69135Elliott Hughes}
23548696433d1b3d8ba15288483b777edd888de69135Elliott Hughes
2355306057fd278d75bf3794bd5243a3b6652c487d18Ian RogersJDWP::JdwpError Dbg::GetThreadFrames(JDWP::ObjectId thread_id, size_t start_frame,
2356306057fd278d75bf3794bd5243a3b6652c487d18Ian Rogers                                     size_t frame_count, JDWP::ExpandBuf* buf) {
23576e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  class GetFrameVisitor : public StackVisitor {
23586e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes   public:
2359277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe    GetFrameVisitor(Thread* thread, size_t start_frame_in, size_t frame_count_in,
2360277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe                    JDWP::ExpandBuf* buf_in)
2361bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe        REQUIRES_SHARED(Locks::mutator_lock_)
23628e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray        : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
23638e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray          depth_(0),
23648e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray          start_frame_(start_frame_in),
23658e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray          frame_count_(frame_count_in),
23668e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray          buf_(buf_in) {
23676e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes      expandBufAdd4BE(buf_, frame_count_);
236803181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes    }
23690399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers
2370bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
23710399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      if (GetMethod()->IsRuntimeMethod()) {
23727934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        return true;  // The debugger can't do anything useful with a frame that has no Method*.
237303181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes      }
23746e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes      if (depth_ >= start_frame_ + frame_count_) {
2375530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes        return false;
237603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes      }
23776e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes      if (depth_ >= start_frame_) {
23786e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes        JDWP::FrameId frame_id(GetFrameId());
23796e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes        JDWP::JdwpLocation location;
23806995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz        SetJdwpLocation(&location, GetMethod(), GetDexPc());
2381ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        VLOG(jdwp) << StringPrintf("    Frame %3zd: id=%3" PRIu64 " ", depth_, frame_id) << location;
23826e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes        expandBufAdd8BE(buf_, frame_id);
23836e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes        expandBufAddLocation(buf_, location);
23846e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes      }
23856e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes      ++depth_;
2386530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes      return true;
238703181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes    }
23886e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes
23896e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes   private:
23906e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes    size_t depth_;
23916e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes    const size_t start_frame_;
23926e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes    const size_t frame_count_;
23936e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes    JDWP::ExpandBuf* buf_;
239403181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  };
239500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
239600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccessUnchecked soa(Thread::Current());
2397c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
2398c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  Thread* thread = DecodeThread(soa, thread_id, &error);
2399221229cb523f849f165fdafbf9785010963715daElliott Hughes  if (error != JDWP::ERR_NONE) {
2400221229cb523f849f165fdafbf9785010963715daElliott Hughes    return error;
2401221229cb523f849f165fdafbf9785010963715daElliott Hughes  }
2402f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes  if (!IsSuspendedForDebugger(soa, thread)) {
2403f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes    return JDWP::ERR_THREAD_NOT_SUSPENDED;
2404f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes  }
24057a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers  GetFrameVisitor visitor(thread, start_frame, frame_count, buf);
24060399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  visitor.WalkStack();
24076e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  return JDWP::ERR_NONE;
2408872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2409872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2410872d4ec7225444d9400d30f9027247deb91012fdElliott HughesJDWP::ObjectId Dbg::GetThreadSelfId() {
24116995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  return GetThreadId(Thread::Current());
24126995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz}
24136995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz
24146995c60cd6657c10811055c42661a55b10b47cefSebastien HertzJDWP::ObjectId Dbg::GetThreadId(Thread* thread) {
2415dbe6f4613ae0161b169f4fca8a616b0b393370abMathieu Chartier  ScopedObjectAccessUnchecked soa(Thread::Current());
2416cafa08146648442ee53348c4918a4fab29e591c1Nicolas Geoffray  return gRegistry->Add(thread->GetPeerFromOtherThread());
2417872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2418872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2419475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughesvoid Dbg::SuspendVM() {
24208f95cf3cb5f715b1277de9cd7fade07ce4b230beHiroshi Yamauchi  // Avoid a deadlock between GC and debugger where GC gets suspended during GC. b/25800335.
24218f95cf3cb5f715b1277de9cd7fade07ce4b230beHiroshi Yamauchi  gc::ScopedGCCriticalSection gcs(Thread::Current(),
24228f95cf3cb5f715b1277de9cd7fade07ce4b230beHiroshi Yamauchi                                  gc::kGcCauseDebugger,
24238f95cf3cb5f715b1277de9cd7fade07ce4b230beHiroshi Yamauchi                                  gc::kCollectorTypeDebugger);
242400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Runtime::Current()->GetThreadList()->SuspendAllForDebugger();
2425872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2426872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2427872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::ResumeVM() {
2428253fa555d9424a56c52879449eabe73d5c96cf61Sebastien Hertz  Runtime::Current()->GetThreadList()->ResumeAllForDebugger();
2429872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2430872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2431221229cb523f849f165fdafbf9785010963715daElliott HughesJDWP::JdwpError Dbg::SuspendThread(JDWP::ObjectId thread_id, bool request_suspension) {
2432f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers  Thread* self = Thread::Current();
2433c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ScopedLocalRef<jobject> peer(self->GetJniEnv(), nullptr);
243400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  {
2435f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers    ScopedObjectAccess soa(self);
2436c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    JDWP::JdwpError error;
2437c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    peer.reset(soa.AddLocalReference<jobject>(gRegistry->Get<mirror::Object*>(thread_id, &error)));
243800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
2439c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (peer.get() == nullptr) {
244000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return JDWP::ERR_THREAD_NOT_ALIVE;
244100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
24424ad5cd3e7d519484559ef778d96fb3f0be8919faIan Rogers  // Suspend thread to build stack trace.
2443f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  bool timed_out;
2444ba32de47e32f436d7c11cb4a2e78bdd4ad4dc5d2Brian Carlstrom  ThreadList* thread_list = Runtime::Current()->GetThreadList();
2445cdd798de1b2e7807f1cab8ebbfbb165069beae6bSebastien Hertz  Thread* thread = thread_list->SuspendThreadByPeer(peer.get(),
2446cdd798de1b2e7807f1cab8ebbfbb165069beae6bSebastien Hertz                                                    request_suspension,
2447cdd798de1b2e7807f1cab8ebbfbb165069beae6bSebastien Hertz                                                    /* debug_suspension */ true,
2448ba32de47e32f436d7c11cb4a2e78bdd4ad4dc5d2Brian Carlstrom                                                    &timed_out);
2449c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (thread != nullptr) {
245000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return JDWP::ERR_NONE;
2451f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  } else if (timed_out) {
245200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return JDWP::ERR_INTERNAL;
245300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  } else {
245400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return JDWP::ERR_THREAD_NOT_ALIVE;
24554e235316b4ada4d865c544d9b4ba397139333fa6Elliott Hughes  }
2456872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2457872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2458221229cb523f849f165fdafbf9785010963715daElliott Hughesvoid Dbg::ResumeThread(JDWP::ObjectId thread_id) {
245900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccessUnchecked soa(Thread::Current());
2460c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
2461c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  mirror::Object* peer = gRegistry->Get<mirror::Object*>(thread_id, &error);
2462c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  CHECK(peer != nullptr) << error;
2463a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao  Thread* thread;
2464a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao  {
2465a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao    MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
2466a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao    thread = Thread::FromManagedThread(soa, peer);
2467a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao  }
2468c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (thread == nullptr) {
24694e235316b4ada4d865c544d9b4ba397139333fa6Elliott Hughes    LOG(WARNING) << "No such thread for resume: " << peer;
24704e235316b4ada4d865c544d9b4ba397139333fa6Elliott Hughes    return;
24714e235316b4ada4d865c544d9b4ba397139333fa6Elliott Hughes  }
247200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool needs_resume;
247300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  {
247450b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_);
247570d60275cc2860bde50e5f9c5b151e94f745ae14Sebastien Hertz    needs_resume = thread->GetDebugSuspendCount() > 0;
247600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
247700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if (needs_resume) {
2478546b986ecd09c2a498740bd8bf7127e612d94755Elliott Hughes    Runtime::Current()->GetThreadList()->Resume(thread, true);
2479546b986ecd09c2a498740bd8bf7127e612d94755Elliott Hughes  }
2480872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2481872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2482872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::SuspendSelf() {
2483475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes  Runtime::Current()->GetThreadList()->SuspendSelfForDebugger();
2484872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2485872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
24860399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersstruct GetThisVisitor : public StackVisitor {
2487277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe  GetThisVisitor(Thread* thread, Context* context, JDWP::FrameId frame_id_in)
2488bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      REQUIRES_SHARED(Locks::mutator_lock_)
24898e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray      : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
24908e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray        this_object(nullptr),
24918e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray        frame_id(frame_id_in) {}
249268fdbd07fc2b8856905e06f3cc945b046c3bfcd3Elliott Hughes
249300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
249400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // annotalysis.
249500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS {
24966e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes    if (frame_id != GetFrameId()) {
24970399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      return true;  // continue
24980399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    } else {
249962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      this_object = GetThisObject();
250062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      return false;
25010399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    }
250268fdbd07fc2b8856905e06f3cc945b046c3bfcd3Elliott Hughes  }
2503dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes
25042dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Object* this_object;
25056e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  JDWP::FrameId frame_id;
25060399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers};
2507ad3da694bbba88662d1d1bd2cc574d6e3ab6cd42Elliott Hughes
250800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan RogersJDWP::JdwpError Dbg::GetThisObject(JDWP::ObjectId thread_id, JDWP::FrameId frame_id,
250900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                   JDWP::ObjectId* result) {
251000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccessUnchecked soa(Thread::Current());
2511692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  JDWP::JdwpError error;
2512692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  Thread* thread = DecodeThread(soa, thread_id, &error);
2513692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  if (error != JDWP::ERR_NONE) {
2514692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz    return error;
2515692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  }
2516692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  if (!IsSuspendedForDebugger(soa, thread)) {
2517692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz    return JDWP::ERR_THREAD_NOT_SUSPENDED;
25186e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  }
2519700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<Context> context(Context::Create());
25207a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers  GetThisVisitor visitor(thread, context.get(), frame_id);
25210399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  visitor.WalkStack();
25226e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  *result = gRegistry->Add(visitor.this_object);
25236e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  return JDWP::ERR_NONE;
25240399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers}
25250399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers
25268009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz// Walks the stack until we find the frame with the given FrameId.
25278009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertzclass FindFrameVisitor FINAL : public StackVisitor {
25288009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz public:
25298009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  FindFrameVisitor(Thread* thread, Context* context, JDWP::FrameId frame_id)
2530bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      REQUIRES_SHARED(Locks::mutator_lock_)
25318e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray      : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
25328e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray        frame_id_(frame_id),
25338e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray        error_(JDWP::ERR_INVALID_FRAMEID) {}
2534ad3da694bbba88662d1d1bd2cc574d6e3ab6cd42Elliott Hughes
25358009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
25368009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  // annotalysis.
25378009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS {
25388009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    if (GetFrameId() != frame_id_) {
25398009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      return true;  // Not our frame, carry on.
25400399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    }
2541e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ArtMethod* m = GetMethod();
25428009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    if (m->IsNative()) {
25438009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      // We can't read/write local value from/into native method.
25448009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      error_ = JDWP::ERR_OPAQUE_FRAME;
25458009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    } else {
25468009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      // We found our frame.
25478009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      error_ = JDWP::ERR_NONE;
25488009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    }
25498009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    return false;
25508009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  }
25518009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz
25528009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  JDWP::JdwpError GetError() const {
25538009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    return error_;
25548009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  }
25558009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz
25568009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz private:
25578009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  const JDWP::FrameId frame_id_;
25588009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  JDWP::JdwpError error_;
255926f728661a08062a373a3203b72dc2555c2aed2dSebastien Hertz
256026f728661a08062a373a3203b72dc2555c2aed2dSebastien Hertz  DISALLOW_COPY_AND_ASSIGN(FindFrameVisitor);
25618009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz};
25628009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz
25638009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien HertzJDWP::JdwpError Dbg::GetLocalValues(JDWP::Request* request, JDWP::ExpandBuf* pReply) {
25648009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  JDWP::ObjectId thread_id = request->ReadThreadId();
25658009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  JDWP::FrameId frame_id = request->ReadFrameId();
256600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
256700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccessUnchecked soa(Thread::Current());
2568692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  JDWP::JdwpError error;
2569692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  Thread* thread = DecodeThread(soa, thread_id, &error);
2570692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  if (error != JDWP::ERR_NONE) {
2571692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz    return error;
2572692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  }
2573692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  if (!IsSuspendedForDebugger(soa, thread)) {
2574692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz    return JDWP::ERR_THREAD_NOT_SUSPENDED;
2575221229cb523f849f165fdafbf9785010963715daElliott Hughes  }
25768009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  // Find the frame with the given frame_id.
2577700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<Context> context(Context::Create());
25788009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  FindFrameVisitor visitor(thread, context.get(), frame_id);
25790399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  visitor.WalkStack();
25808009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  if (visitor.GetError() != JDWP::ERR_NONE) {
25818009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    return visitor.GetError();
25828009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  }
25830399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers
25848009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  // Read the values from visitor's context.
25858009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  int32_t slot_count = request->ReadSigned32("slot count");
25868009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  expandBufAdd4BE(pReply, slot_count);     /* "int values" */
25878009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  for (int32_t i = 0; i < slot_count; ++i) {
25888009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    uint32_t slot = request->ReadUnsigned32("slot");
25898009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    JDWP::JdwpTag reqSigByte = request->ReadTag();
2590ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers
25918009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    VLOG(jdwp) << "    --> slot " << slot << " " << reqSigByte;
25928009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz
25938009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    size_t width = Dbg::GetTagWidth(reqSigByte);
25947d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz    uint8_t* ptr = expandBufAddSpace(pReply, width + 1);
2595692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz    error = Dbg::GetLocalValue(visitor, soa, slot, reqSigByte, ptr, width);
25968009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    if (error != JDWP::ERR_NONE) {
25978009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      return error;
25988009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    }
25998009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  }
26008009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  return JDWP::ERR_NONE;
26018009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz}
26028009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz
2603abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertzconstexpr JDWP::JdwpError kStackFrameLocalAccessError = JDWP::ERR_ABSENT_INFORMATION;
2604abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz
2605abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertzstatic std::string GetStackContextAsString(const StackVisitor& visitor)
2606bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
2607abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz  return StringPrintf(" at DEX pc 0x%08x in method %s", visitor.GetDexPc(false),
2608709b070044354d9f47641f273edacaeeb0240ab7David Sehr                      ArtMethod::PrettyMethod(visitor.GetMethod()).c_str());
2609abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz}
2610abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz
2611abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertzstatic JDWP::JdwpError FailGetLocalValue(const StackVisitor& visitor, uint16_t vreg,
2612abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz                                         JDWP::JdwpTag tag)
2613bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
2614abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz  LOG(ERROR) << "Failed to read " << tag << " local from register v" << vreg
2615abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz             << GetStackContextAsString(visitor);
2616abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz  return kStackFrameLocalAccessError;
2617abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz}
2618abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz
26198009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien HertzJDWP::JdwpError Dbg::GetLocalValue(const StackVisitor& visitor, ScopedObjectAccessUnchecked& soa,
26208009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz                                   int slot, JDWP::JdwpTag tag, uint8_t* buf, size_t width) {
2621e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  ArtMethod* m = visitor.GetMethod();
2622abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz  JDWP::JdwpError error = JDWP::ERR_NONE;
2623abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz  uint16_t vreg = DemangleSlot(slot, m, &error);
2624abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz  if (error != JDWP::ERR_NONE) {
2625abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz    return error;
2626abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz  }
26278009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  // TODO: check that the tag is compatible with the actual type of the slot!
26288009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  switch (tag) {
26298009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_BOOLEAN: {
26308009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      CHECK_EQ(width, 1U);
26318009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      uint32_t intVal;
2632abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      if (!visitor.GetVReg(m, vreg, kIntVReg, &intVal)) {
2633abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        return FailGetLocalValue(visitor, vreg, tag);
2634ad3da694bbba88662d1d1bd2cc574d6e3ab6cd42Elliott Hughes      }
2635abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      VLOG(jdwp) << "get boolean local " << vreg << " = " << intVal;
2636abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      JDWP::Set1(buf + 1, intVal != 0);
26378009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      break;
26388009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    }
26398009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_BYTE: {
26408009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      CHECK_EQ(width, 1U);
26418009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      uint32_t intVal;
2642abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      if (!visitor.GetVReg(m, vreg, kIntVReg, &intVal)) {
2643abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        return FailGetLocalValue(visitor, vreg, tag);
2644cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz      }
2645abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      VLOG(jdwp) << "get byte local " << vreg << " = " << intVal;
2646abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      JDWP::Set1(buf + 1, intVal);
26478009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      break;
26488009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    }
26498009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_SHORT:
26508009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_CHAR: {
26518009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      CHECK_EQ(width, 2U);
26528009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      uint32_t intVal;
2653abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      if (!visitor.GetVReg(m, vreg, kIntVReg, &intVal)) {
2654abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        return FailGetLocalValue(visitor, vreg, tag);
26558009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      }
2656abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      VLOG(jdwp) << "get short/char local " << vreg << " = " << intVal;
2657abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      JDWP::Set2BE(buf + 1, intVal);
26588009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      break;
26598009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    }
26608009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_INT: {
26618009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      CHECK_EQ(width, 4U);
26628009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      uint32_t intVal;
2663abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      if (!visitor.GetVReg(m, vreg, kIntVReg, &intVal)) {
2664abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        return FailGetLocalValue(visitor, vreg, tag);
26658009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      }
2666abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      VLOG(jdwp) << "get int local " << vreg << " = " << intVal;
2667abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      JDWP::Set4BE(buf + 1, intVal);
26688009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      break;
26698009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    }
26708009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_FLOAT: {
26718009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      CHECK_EQ(width, 4U);
26728009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      uint32_t intVal;
2673abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      if (!visitor.GetVReg(m, vreg, kFloatVReg, &intVal)) {
2674abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        return FailGetLocalValue(visitor, vreg, tag);
26758009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      }
2676abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      VLOG(jdwp) << "get float local " << vreg << " = " << intVal;
2677abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      JDWP::Set4BE(buf + 1, intVal);
26788009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      break;
26798009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    }
26808009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_ARRAY:
26818009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_CLASS_LOADER:
26828009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_CLASS_OBJECT:
26838009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_OBJECT:
26848009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_STRING:
26858009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_THREAD:
26868009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_THREAD_GROUP: {
26878009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      CHECK_EQ(width, sizeof(JDWP::ObjectId));
26888009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      uint32_t intVal;
2689abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      if (!visitor.GetVReg(m, vreg, kReferenceVReg, &intVal)) {
2690abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        return FailGetLocalValue(visitor, vreg, tag);
2691abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      }
2692abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      mirror::Object* o = reinterpret_cast<mirror::Object*>(intVal);
2693abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      VLOG(jdwp) << "get " << tag << " object local " << vreg << " = " << o;
2694abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
2695abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        LOG(FATAL) << StringPrintf("Found invalid object %#" PRIxPTR " in register v%u",
2696abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz                                   reinterpret_cast<uintptr_t>(o), vreg)
2697abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz                                   << GetStackContextAsString(visitor);
2698abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        UNREACHABLE();
26990399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      }
2700abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      tag = TagFromObject(soa, o);
2701abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      JDWP::SetObjectId(buf + 1, gRegistry->Add(o));
27028009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      break;
27038009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    }
27048009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_DOUBLE: {
27058009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      CHECK_EQ(width, 8U);
27068009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      uint64_t longVal;
2707abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      if (!visitor.GetVRegPair(m, vreg, kDoubleLoVReg, kDoubleHiVReg, &longVal)) {
2708abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        return FailGetLocalValue(visitor, vreg, tag);
27098009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      }
2710abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      VLOG(jdwp) << "get double local " << vreg << " = " << longVal;
2711abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      JDWP::Set8BE(buf + 1, longVal);
27128009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      break;
27138009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    }
27148009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_LONG: {
27158009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      CHECK_EQ(width, 8U);
27168009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      uint64_t longVal;
2717abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      if (!visitor.GetVRegPair(m, vreg, kLongLoVReg, kLongHiVReg, &longVal)) {
2718abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        return FailGetLocalValue(visitor, vreg, tag);
27198009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      }
2720abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      VLOG(jdwp) << "get long local " << vreg << " = " << longVal;
2721abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      JDWP::Set8BE(buf + 1, longVal);
27228009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      break;
2723cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes    }
27248009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    default:
27258009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      LOG(FATAL) << "Unknown tag " << tag;
2726abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      UNREACHABLE();
27278009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  }
27280399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers
27298009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  // Prepend tag, which may have been updated.
27308009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  JDWP::Set1(buf, tag);
27318009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  return JDWP::ERR_NONE;
27328009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz}
27338009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz
27348009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien HertzJDWP::JdwpError Dbg::SetLocalValues(JDWP::Request* request) {
27358009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  JDWP::ObjectId thread_id = request->ReadThreadId();
27368009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  JDWP::FrameId frame_id = request->ReadFrameId();
273700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
273800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccessUnchecked soa(Thread::Current());
2739692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  JDWP::JdwpError error;
2740692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  Thread* thread = DecodeThread(soa, thread_id, &error);
2741692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  if (error != JDWP::ERR_NONE) {
2742692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz    return error;
2743692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  }
2744692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  if (!IsSuspendedForDebugger(soa, thread)) {
2745692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz    return JDWP::ERR_THREAD_NOT_SUSPENDED;
2746221229cb523f849f165fdafbf9785010963715daElliott Hughes  }
27478009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  // Find the frame with the given frame_id.
2748700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<Context> context(Context::Create());
27498009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  FindFrameVisitor visitor(thread, context.get(), frame_id);
27500399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  visitor.WalkStack();
27518009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  if (visitor.GetError() != JDWP::ERR_NONE) {
27528009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    return visitor.GetError();
27538009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  }
27548009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz
27558009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  // Writes the values into visitor's context.
27568009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  int32_t slot_count = request->ReadSigned32("slot count");
27578009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  for (int32_t i = 0; i < slot_count; ++i) {
27588009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    uint32_t slot = request->ReadUnsigned32("slot");
27598009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    JDWP::JdwpTag sigByte = request->ReadTag();
27608009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    size_t width = Dbg::GetTagWidth(sigByte);
27618009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    uint64_t value = request->ReadValue(width);
27628009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz
27638009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    VLOG(jdwp) << "    --> slot " << slot << " " << sigByte << " " << value;
276499170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang    error = Dbg::SetLocalValue(thread, visitor, slot, sigByte, value, width);
27658009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    if (error != JDWP::ERR_NONE) {
27668009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      return error;
27678009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    }
27688009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  }
27698009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  return JDWP::ERR_NONE;
27708009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz}
27718009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz
2772abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertztemplate<typename T>
2773abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertzstatic JDWP::JdwpError FailSetLocalValue(const StackVisitor& visitor, uint16_t vreg,
2774abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz                                         JDWP::JdwpTag tag, T value)
2775bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
2776abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz  LOG(ERROR) << "Failed to write " << tag << " local " << value
2777abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz             << " (0x" << std::hex << value << ") into register v" << vreg
2778abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz             << GetStackContextAsString(visitor);
2779abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz  return kStackFrameLocalAccessError;
2780abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz}
2781abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz
278299170c636dfae4908b102347cfe9f92bad1881ccMingyao YangJDWP::JdwpError Dbg::SetLocalValue(Thread* thread, StackVisitor& visitor, int slot,
278399170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang                                   JDWP::JdwpTag tag, uint64_t value, size_t width) {
2784e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  ArtMethod* m = visitor.GetMethod();
2785abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz  JDWP::JdwpError error = JDWP::ERR_NONE;
2786abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz  uint16_t vreg = DemangleSlot(slot, m, &error);
2787abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz  if (error != JDWP::ERR_NONE) {
2788abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz    return error;
2789abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz  }
27908009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  // TODO: check that the tag is compatible with the actual type of the slot!
27918009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  switch (tag) {
27928009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_BOOLEAN:
27938009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_BYTE:
27948009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      CHECK_EQ(width, 1U);
2795636b9252af8d8848dbf8f30b7e9638867b62c791Mingyao Yang      if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(value), kIntVReg)) {
2796abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        return FailSetLocalValue(visitor, vreg, tag, static_cast<uint32_t>(value));
27978009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      }
27988009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      break;
27998009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_SHORT:
28008009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_CHAR:
28018009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      CHECK_EQ(width, 2U);
2802636b9252af8d8848dbf8f30b7e9638867b62c791Mingyao Yang      if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(value), kIntVReg)) {
2803abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        return FailSetLocalValue(visitor, vreg, tag, static_cast<uint32_t>(value));
28048009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      }
28058009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      break;
28068009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_INT:
28078009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      CHECK_EQ(width, 4U);
2808636b9252af8d8848dbf8f30b7e9638867b62c791Mingyao Yang      if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(value), kIntVReg)) {
2809abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        return FailSetLocalValue(visitor, vreg, tag, static_cast<uint32_t>(value));
28108009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      }
28118009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      break;
28128009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_FLOAT:
28138009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      CHECK_EQ(width, 4U);
2814636b9252af8d8848dbf8f30b7e9638867b62c791Mingyao Yang      if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(value), kFloatVReg)) {
2815abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        return FailSetLocalValue(visitor, vreg, tag, static_cast<uint32_t>(value));
28168009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      }
28178009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      break;
28188009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_ARRAY:
28198009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_CLASS_LOADER:
28208009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_CLASS_OBJECT:
28218009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_OBJECT:
28228009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_STRING:
28238009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_THREAD:
28248009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_THREAD_GROUP: {
28258009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      CHECK_EQ(width, sizeof(JDWP::ObjectId));
28268009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      mirror::Object* o = gRegistry->Get<mirror::Object*>(static_cast<JDWP::ObjectId>(value),
28278009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz                                                          &error);
28288009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      if (error != JDWP::ERR_NONE) {
28298009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz        VLOG(jdwp) << tag << " object " << o << " is an invalid object";
28308009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz        return JDWP::ERR_INVALID_OBJECT;
2831abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      }
2832636b9252af8d8848dbf8f30b7e9638867b62c791Mingyao Yang      if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(o)),
2833abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz                                 kReferenceVReg)) {
2834abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        return FailSetLocalValue(visitor, vreg, tag, reinterpret_cast<uintptr_t>(o));
28358009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      }
28368009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      break;
28378009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    }
28388009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_DOUBLE: {
28398009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      CHECK_EQ(width, 8U);
2840636b9252af8d8848dbf8f30b7e9638867b62c791Mingyao Yang      if (!visitor.SetVRegPair(m, vreg, value, kDoubleLoVReg, kDoubleHiVReg)) {
2841abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        return FailSetLocalValue(visitor, vreg, tag, value);
28428009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      }
28438009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      break;
28448009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    }
28458009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    case JDWP::JT_LONG: {
28468009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      CHECK_EQ(width, 8U);
2847636b9252af8d8848dbf8f30b7e9638867b62c791Mingyao Yang      if (!visitor.SetVRegPair(m, vreg, value, kLongLoVReg, kLongHiVReg)) {
2848abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz        return FailSetLocalValue(visitor, vreg, tag, value);
28498009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      }
28508009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      break;
28518009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    }
28528009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz    default:
28538009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz      LOG(FATAL) << "Unknown tag " << tag;
2854abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz      UNREACHABLE();
28558009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  }
285699170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang
285799170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang  // If we set the local variable in a compiled frame, we need to trigger a deoptimization of
285899170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang  // the stack so we continue execution with the interpreter using the new value(s) of the updated
285999170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang  // local variable(s). To achieve this, we install instrumentation exit stub on each method of the
286099170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang  // thread's stack. The stub will cause the deoptimization to happen.
286199170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang  if (!visitor.IsShadowFrame() && thread->HasDebuggerShadowFrames()) {
286299170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang    Runtime::Current()->GetInstrumentation()->InstrumentThreadStack(thread);
286399170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang  }
286499170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang
28658009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  return JDWP::ERR_NONE;
2866872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2867872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2868e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic void SetEventLocation(JDWP::EventLocation* location, ArtMethod* m, uint32_t dex_pc)
2869bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
28706995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  DCHECK(location != nullptr);
28716995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  if (m == nullptr) {
28726995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz    memset(location, 0, sizeof(*location));
28736995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  } else {
28746c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light    location->method = GetCanonicalMethod(m);
28756995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz    location->dex_pc = (m->IsNative() || m->IsProxyMethod()) ? static_cast<uint32_t>(-1) : dex_pc;
28763f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  }
28773f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz}
28783f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
2879e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid Dbg::PostLocationEvent(ArtMethod* m, int dex_pc, mirror::Object* this_object,
2880579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao                            int event_flags, const JValue* return_value) {
28813f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  if (!IsDebuggerActive()) {
28823f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    return;
28833f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  }
28843f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  DCHECK(m != nullptr);
28853f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  DCHECK_EQ(m->IsStatic(), this_object == nullptr);
28866995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  JDWP::EventLocation location;
28876995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  SetEventLocation(&location, m, dex_pc);
288891bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes
2889de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz  // We need to be sure no exception is pending when calling JdwpState::PostLocationEvent.
2890de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz  // This is required to be able to call JNI functions to create JDWP ids. To achieve this,
2891de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz  // we temporarily clear the current thread's exception (if any) and will restore it after
2892de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz  // the call.
2893de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz  // Note: the only way to get a pending exception here is to suspend on a move-exception
2894de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz  // instruction.
2895de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz  Thread* const self = Thread::Current();
2896de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz  StackHandleScope<1> hs(self);
2897de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz  Handle<mirror::Throwable> pending_exception(hs.NewHandle(self->GetException()));
2898de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz  self->ClearException();
2899fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  if (kIsDebugBuild && pending_exception != nullptr) {
2900de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz    const DexFile::CodeItem* code_item = location.method->GetCodeItem();
2901de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz    const Instruction* instr = Instruction::At(&code_item->insns_[location.dex_pc]);
2902de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz    CHECK_EQ(Instruction::MOVE_EXCEPTION, instr->Opcode());
2903de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz  }
2904de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz
29056995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  gJdwpState->PostLocationEvent(&location, this_object, event_flags, return_value);
2906de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz
2907fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  if (pending_exception != nullptr) {
2908de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz    self->SetException(pending_exception.Get());
2909de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz  }
2910872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
2911872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2912e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid Dbg::PostFieldAccessEvent(ArtMethod* m, int dex_pc,
2913c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier                               mirror::Object* this_object, ArtField* f) {
29143f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  if (!IsDebuggerActive()) {
29153f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    return;
29163f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  }
29173f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  DCHECK(m != nullptr);
29183f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  DCHECK(f != nullptr);
29196995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  JDWP::EventLocation location;
29206995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  SetEventLocation(&location, m, dex_pc);
29213f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
29226995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  gJdwpState->PostFieldEvent(&location, f, this_object, nullptr, false);
29233f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz}
29243f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
2925e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid Dbg::PostFieldModificationEvent(ArtMethod* m, int dex_pc,
2926c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier                                     mirror::Object* this_object, ArtField* f,
29273f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                                     const JValue* field_value) {
29283f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  if (!IsDebuggerActive()) {
29293f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    return;
29303f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  }
29313f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  DCHECK(m != nullptr);
29323f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  DCHECK(f != nullptr);
29333f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  DCHECK(field_value != nullptr);
29346995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  JDWP::EventLocation location;
29356995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  SetEventLocation(&location, m, dex_pc);
29363f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
29376995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  gJdwpState->PostFieldEvent(&location, f, this_object, field_value, true);
29383f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz}
29393f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
294014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray/**
294114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray * Finds the location where this exception will be caught. We search until we reach the top
294214691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray * frame, in which case this exception is considered uncaught.
294314691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray */
294414691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffrayclass CatchLocationFinder : public StackVisitor {
294514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray public:
294614691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  CatchLocationFinder(Thread* self, const Handle<mirror::Throwable>& exception, Context* context)
2947bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      REQUIRES_SHARED(Locks::mutator_lock_)
29488e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray    : StackVisitor(self, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
294914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      exception_(exception),
295014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      handle_scope_(self),
295114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      this_at_throw_(handle_scope_.NewHandle<mirror::Object>(nullptr)),
2952e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier      catch_method_(nullptr),
2953e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier      throw_method_(nullptr),
295414691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      catch_dex_pc_(DexFile::kDexNoIndex),
295514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      throw_dex_pc_(DexFile::kDexNoIndex) {
295614691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  }
295714691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray
2958bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe  bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
2959e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ArtMethod* method = GetMethod();
296014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray    DCHECK(method != nullptr);
296114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray    if (method->IsRuntimeMethod()) {
296214691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      // Ignore callee save method.
296314691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      DCHECK(method->IsCalleeSaveMethod());
296414691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      return true;
296514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray    }
296614691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray
296714691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray    uint32_t dex_pc = GetDexPc();
2968e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    if (throw_method_ == nullptr) {
296914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      // First Java method found. It is either the method that threw the exception,
297014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      // or the Java native method that is reporting an exception thrown by
297114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      // native code.
297214691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      this_at_throw_.Assign(GetThisObject());
2973e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier      throw_method_ = method;
297414691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      throw_dex_pc_ = dex_pc;
297514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray    }
297614691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray
297714691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray    if (dex_pc != DexFile::kDexNoIndex) {
297826f728661a08062a373a3203b72dc2555c2aed2dSebastien Hertz      StackHandleScope<1> hs(GetThread());
297914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      uint32_t found_dex_pc;
298014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      Handle<mirror::Class> exception_class(hs.NewHandle(exception_->GetClass()));
298114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      bool unused_clear_exception;
2982e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier      found_dex_pc = method->FindCatchBlock(exception_class, dex_pc, &unused_clear_exception);
298314691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      if (found_dex_pc != DexFile::kDexNoIndex) {
2984e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier        catch_method_ = method;
298514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray        catch_dex_pc_ = found_dex_pc;
298614691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray        return false;  // End stack walk.
298714691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      }
298814691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray    }
298914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray    return true;  // Continue stack walk.
299014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  }
299114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray
2992bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe  ArtMethod* GetCatchMethod() REQUIRES_SHARED(Locks::mutator_lock_) {
2993e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    return catch_method_;
299414691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  }
299514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray
2996bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe  ArtMethod* GetThrowMethod() REQUIRES_SHARED(Locks::mutator_lock_) {
2997e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    return throw_method_;
299814691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  }
299914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray
3000bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe  mirror::Object* GetThisAtThrow() REQUIRES_SHARED(Locks::mutator_lock_) {
300114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray    return this_at_throw_.Get();
300214691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  }
300314691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray
300414691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  uint32_t GetCatchDexPc() const {
300514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray    return catch_dex_pc_;
300614691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  }
300714691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray
300814691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  uint32_t GetThrowDexPc() const {
300914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray    return throw_dex_pc_;
301014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  }
301114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray
301214691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray private:
301314691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  const Handle<mirror::Throwable>& exception_;
3014e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  StackHandleScope<1> handle_scope_;
301514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  MutableHandle<mirror::Object> this_at_throw_;
3016e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  ArtMethod* catch_method_;
3017e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  ArtMethod* throw_method_;
301814691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  uint32_t catch_dex_pc_;
301914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  uint32_t throw_dex_pc_;
302014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray
302114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(CatchLocationFinder);
302214691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray};
302314691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray
302414691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffrayvoid Dbg::PostException(mirror::Throwable* exception_object) {
3025c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes  if (!IsDebuggerActive()) {
30260ad5bb8ea378a223eb6eaf89e0be2823c6f87c0eIan Rogers    return;
30270ad5bb8ea378a223eb6eaf89e0be2823c6f87c0eIan Rogers  }
3028261bc044a3575512869586593e99e97cd8b1c321Sebastien Hertz  Thread* const self = Thread::Current();
3029261bc044a3575512869586593e99e97cd8b1c321Sebastien Hertz  StackHandleScope<1> handle_scope(self);
303014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  Handle<mirror::Throwable> h_exception(handle_scope.NewHandle(exception_object));
303114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  std::unique_ptr<Context> context(Context::Create());
3032261bc044a3575512869586593e99e97cd8b1c321Sebastien Hertz  CatchLocationFinder clf(self, h_exception, context.get());
303314691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  clf.WalkStack(/* include_transitions */ false);
30346995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  JDWP::EventLocation exception_throw_location;
303514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  SetEventLocation(&exception_throw_location, clf.GetThrowMethod(), clf.GetThrowDexPc());
30366995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  JDWP::EventLocation exception_catch_location;
303714691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  SetEventLocation(&exception_catch_location, clf.GetCatchMethod(), clf.GetCatchDexPc());
30384740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes
303914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray  gJdwpState->PostException(&exception_throw_location, h_exception.Get(), &exception_catch_location,
304014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray                            clf.GetThisAtThrow());
3041872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
3042872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
30432dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersvoid Dbg::PostClassPrepare(mirror::Class* c) {
3044c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes  if (!IsDebuggerActive()) {
30454740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes    return;
30464740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes  }
30476995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz  gJdwpState->PostClassPrepare(c);
3048872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
3049872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
305062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object,
3051e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                         ArtMethod* m, uint32_t dex_pc,
30528379b2256be5d2be4ad083a76e9f8ec403c4d405Sebastien Hertz                         int event_flags, const JValue* return_value) {
305362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (!IsDebuggerActive() || dex_pc == static_cast<uint32_t>(-2) /* fake method exit */) {
30542aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes    return;
305591bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes  }
305691bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes
30578696433d1b3d8ba15288483b777edd888de69135Elliott Hughes  if (IsBreakpoint(m, dex_pc)) {
30588696433d1b3d8ba15288483b777edd888de69135Elliott Hughes    event_flags |= kBreakpoint;
305991bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes  }
306091bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes
306161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz  // If the debugger is single-stepping one of our threads, check to
306261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz  // see if we're that thread and we've reached a step point.
306361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz  const SingleStepControl* single_step_control = thread->GetSingleStepControl();
3064597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz  if (single_step_control != nullptr) {
306561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz    CHECK(!m->IsNative());
3066597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz    if (single_step_control->GetStepDepth() == JDWP::SD_INTO) {
306761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      // Step into method calls.  We break when the line number
306861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      // or method pointer changes.  If we're in SS_MIN mode, we
306961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      // always stop.
3070597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz      if (single_step_control->GetMethod() != m) {
307161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz        event_flags |= kSingleStep;
307261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz        VLOG(jdwp) << "SS new method";
3073597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz      } else if (single_step_control->GetStepSize() == JDWP::SS_MIN) {
307461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz        event_flags |= kSingleStep;
307561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz        VLOG(jdwp) << "SS new instruction";
3076bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz      } else if (single_step_control->ContainsDexPc(dex_pc)) {
307761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz        event_flags |= kSingleStep;
307861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz        VLOG(jdwp) << "SS new line";
307961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      }
3080597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz    } else if (single_step_control->GetStepDepth() == JDWP::SD_OVER) {
308161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      // Step over method calls.  We break when the line number is
308261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      // different and the frame depth is <= the original frame
308361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      // depth.  (We can't just compare on the method, because we
308461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      // might get unrolled past it by an exception, and it's tricky
308561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      // to identify recursion.)
308661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz
308761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      int stack_depth = GetStackDepth(thread);
308861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz
3089597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz      if (stack_depth < single_step_control->GetStackDepth()) {
309061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz        // Popped up one or more frames, always trigger.
309161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz        event_flags |= kSingleStep;
309261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz        VLOG(jdwp) << "SS method pop";
3093597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz      } else if (stack_depth == single_step_control->GetStackDepth()) {
309461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz        // Same depth, see if we moved.
3095597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz        if (single_step_control->GetStepSize() == JDWP::SS_MIN) {
30968696433d1b3d8ba15288483b777edd888de69135Elliott Hughes          event_flags |= kSingleStep;
30978696433d1b3d8ba15288483b777edd888de69135Elliott Hughes          VLOG(jdwp) << "SS new instruction";
3098bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz        } else if (single_step_control->ContainsDexPc(dex_pc)) {
30992435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes          event_flags |= kSingleStep;
31002435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes          VLOG(jdwp) << "SS new line";
310191bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes        }
310261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      }
310361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz    } else {
3104597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz      CHECK_EQ(single_step_control->GetStepDepth(), JDWP::SD_OUT);
310561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      // Return from the current method.  We break when the frame
310661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      // depth pops up.
310761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz
310861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      // This differs from the "method exit" break in that it stops
310961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      // with the PC at the next instruction in the returned-to
311061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      // function, rather than the end of the returning function.
311161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz
311261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz      int stack_depth = GetStackDepth(thread);
3113597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz      if (stack_depth < single_step_control->GetStackDepth()) {
311461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz        event_flags |= kSingleStep;
311561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz        VLOG(jdwp) << "SS method pop";
31168696433d1b3d8ba15288483b777edd888de69135Elliott Hughes      }
311791bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes    }
311891bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes  }
311991bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes
312091bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes  // If there's something interesting going on, see if it matches one
312191bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes  // of the debugger filters.
312291bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes  if (event_flags != 0) {
31238379b2256be5d2be4ad083a76e9f8ec403c4d405Sebastien Hertz    Dbg::PostLocationEvent(m, dex_pc, this_object, event_flags, return_value);
312491bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes  }
312591bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes}
312691bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes
312742cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertzsize_t* Dbg::GetReferenceCounterForEvent(uint32_t instrumentation_event) {
312842cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz  switch (instrumentation_event) {
312942cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    case instrumentation::Instrumentation::kMethodEntered:
313042cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      return &method_enter_event_ref_count_;
313142cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    case instrumentation::Instrumentation::kMethodExited:
313242cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      return &method_exit_event_ref_count_;
313342cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    case instrumentation::Instrumentation::kDexPcMoved:
313442cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      return &dex_pc_change_event_ref_count_;
313542cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    case instrumentation::Instrumentation::kFieldRead:
313642cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      return &field_read_event_ref_count_;
313742cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    case instrumentation::Instrumentation::kFieldWritten:
313842cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      return &field_write_event_ref_count_;
313942cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    case instrumentation::Instrumentation::kExceptionCaught:
314042cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      return &exception_catch_event_ref_count_;
314142cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    default:
314242cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      return nullptr;
314342cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz  }
314442cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz}
314542cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz
31464d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz// Process request while all mutator threads are suspended.
31474d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertzvoid Dbg::ProcessDeoptimizationRequest(const DeoptimizationRequest& request) {
3148138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
31490ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi  switch (request.GetKind()) {
31504d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    case DeoptimizationRequest::kNothing:
31514d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      LOG(WARNING) << "Ignoring empty deoptimization request.";
31524d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      break;
315342cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    case DeoptimizationRequest::kRegisterForEvent:
315442cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      VLOG(jdwp) << StringPrintf("Add debugger as listener for instrumentation event 0x%x",
31550ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi                                 request.InstrumentationEvent());
31560ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      instrumentation->AddListener(&gDebugInstrumentationListener, request.InstrumentationEvent());
31570ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      instrumentation_events_ |= request.InstrumentationEvent();
315842cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      break;
315942cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    case DeoptimizationRequest::kUnregisterForEvent:
316042cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      VLOG(jdwp) << StringPrintf("Remove debugger as listener for instrumentation event 0x%x",
31610ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi                                 request.InstrumentationEvent());
316242cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      instrumentation->RemoveListener(&gDebugInstrumentationListener,
31630ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi                                      request.InstrumentationEvent());
31640ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      instrumentation_events_ &= ~request.InstrumentationEvent();
316542cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      break;
31664d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    case DeoptimizationRequest::kFullDeoptimization:
31677ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz      VLOG(jdwp) << "Deoptimize the world ...";
31680462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertz      instrumentation->DeoptimizeEverything(kDbgInstrumentationKey);
31697ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz      VLOG(jdwp) << "Deoptimize the world DONE";
31704d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      break;
31714d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    case DeoptimizationRequest::kFullUndeoptimization:
31727ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz      VLOG(jdwp) << "Undeoptimize the world ...";
31730462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertz      instrumentation->UndeoptimizeEverything(kDbgInstrumentationKey);
31747ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz      VLOG(jdwp) << "Undeoptimize the world DONE";
31754d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      break;
31764d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    case DeoptimizationRequest::kSelectiveDeoptimization:
3177709b070044354d9f47641f273edacaeeb0240ab7David Sehr      VLOG(jdwp) << "Deoptimize method " << ArtMethod::PrettyMethod(request.Method()) << " ...";
31780ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      instrumentation->Deoptimize(request.Method());
3179709b070044354d9f47641f273edacaeeb0240ab7David Sehr      VLOG(jdwp) << "Deoptimize method " << ArtMethod::PrettyMethod(request.Method()) << " DONE";
31804d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      break;
31814d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    case DeoptimizationRequest::kSelectiveUndeoptimization:
3182709b070044354d9f47641f273edacaeeb0240ab7David Sehr      VLOG(jdwp) << "Undeoptimize method " << ArtMethod::PrettyMethod(request.Method()) << " ...";
31830ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      instrumentation->Undeoptimize(request.Method());
3184709b070044354d9f47641f273edacaeeb0240ab7David Sehr      VLOG(jdwp) << "Undeoptimize method " << ArtMethod::PrettyMethod(request.Method()) << " DONE";
31854d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      break;
31864d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    default:
31870ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      LOG(FATAL) << "Unsupported deoptimization request kind " << request.GetKind();
31884d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      break;
31894d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz  }
31904d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz}
31914d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz
31924d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertzvoid Dbg::RequestDeoptimization(const DeoptimizationRequest& req) {
31930ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi  if (req.GetKind() == DeoptimizationRequest::kNothing) {
31944d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    // Nothing to do.
31954d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    return;
31964d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz  }
3197306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom  MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_);
31987ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz  RequestDeoptimizationLocked(req);
31997ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz}
32007ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz
32017ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertzvoid Dbg::RequestDeoptimizationLocked(const DeoptimizationRequest& req) {
32020ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi  switch (req.GetKind()) {
320342cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    case DeoptimizationRequest::kRegisterForEvent: {
32040ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      DCHECK_NE(req.InstrumentationEvent(), 0u);
32050ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      size_t* counter = GetReferenceCounterForEvent(req.InstrumentationEvent());
320642cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      CHECK(counter != nullptr) << StringPrintf("No counter for instrumentation event 0x%x",
32070ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi                                                req.InstrumentationEvent());
320842cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      if (*counter == 0) {
32097d2ae437a87ceb2bdda098ab11f4da588c6a75f5Sebastien Hertz        VLOG(jdwp) << StringPrintf("Queue request #%zd to start listening to instrumentation event 0x%x",
32100ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi                                   deoptimization_requests_.size(), req.InstrumentationEvent());
321142cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz        deoptimization_requests_.push_back(req);
321242cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      }
321342cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      *counter = *counter + 1;
321442cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      break;
321542cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    }
321642cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    case DeoptimizationRequest::kUnregisterForEvent: {
32170ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      DCHECK_NE(req.InstrumentationEvent(), 0u);
32180ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      size_t* counter = GetReferenceCounterForEvent(req.InstrumentationEvent());
321942cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      CHECK(counter != nullptr) << StringPrintf("No counter for instrumentation event 0x%x",
32200ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi                                                req.InstrumentationEvent());
322142cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      *counter = *counter - 1;
322242cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      if (*counter == 0) {
32237d2ae437a87ceb2bdda098ab11f4da588c6a75f5Sebastien Hertz        VLOG(jdwp) << StringPrintf("Queue request #%zd to stop listening to instrumentation event 0x%x",
32240ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi                                   deoptimization_requests_.size(), req.InstrumentationEvent());
322542cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz        deoptimization_requests_.push_back(req);
322642cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      }
322742cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz      break;
322842cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz    }
32294d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    case DeoptimizationRequest::kFullDeoptimization: {
32300ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      DCHECK(req.Method() == nullptr);
32314d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      if (full_deoptimization_event_count_ == 0) {
32327ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz        VLOG(jdwp) << "Queue request #" << deoptimization_requests_.size()
32337ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz                   << " for full deoptimization";
32344d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz        deoptimization_requests_.push_back(req);
3235138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      }
32364d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      ++full_deoptimization_event_count_;
32374d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      break;
32384d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    }
32394d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    case DeoptimizationRequest::kFullUndeoptimization: {
32400ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      DCHECK(req.Method() == nullptr);
3241e713d9338ad122d6b8c7997387d0c9fc464eea3eSebastien Hertz      DCHECK_GT(full_deoptimization_event_count_, 0U);
32424d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      --full_deoptimization_event_count_;
32434d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      if (full_deoptimization_event_count_ == 0) {
32447ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz        VLOG(jdwp) << "Queue request #" << deoptimization_requests_.size()
32457ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz                   << " for full undeoptimization";
32464d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz        deoptimization_requests_.push_back(req);
3247138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      }
32484d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      break;
32494d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    }
32504d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    case DeoptimizationRequest::kSelectiveDeoptimization: {
32510ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      DCHECK(req.Method() != nullptr);
32527ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz      VLOG(jdwp) << "Queue request #" << deoptimization_requests_.size()
3253709b070044354d9f47641f273edacaeeb0240ab7David Sehr                 << " for deoptimization of " << req.Method()->PrettyMethod();
32544d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      deoptimization_requests_.push_back(req);
32554d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      break;
32564d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    }
32574d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    case DeoptimizationRequest::kSelectiveUndeoptimization: {
32580ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      DCHECK(req.Method() != nullptr);
32597ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz      VLOG(jdwp) << "Queue request #" << deoptimization_requests_.size()
3260709b070044354d9f47641f273edacaeeb0240ab7David Sehr                 << " for undeoptimization of " << req.Method()->PrettyMethod();
32614d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      deoptimization_requests_.push_back(req);
32624d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      break;
32634d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    }
32644d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    default: {
32650ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      LOG(FATAL) << "Unknown deoptimization request kind " << req.GetKind();
32664d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      break;
3267138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    }
3268138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  }
3269138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz}
3270138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
3271138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertzvoid Dbg::ManageDeoptimization() {
3272138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  Thread* const self = Thread::Current();
3273138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  {
3274138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    // Avoid suspend/resume if there is no pending request.
3275306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom    MutexLock mu(self, *Locks::deoptimization_lock_);
32764d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    if (deoptimization_requests_.empty()) {
3277138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      return;
3278138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    }
3279138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  }
3280138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  CHECK_EQ(self->GetState(), kRunnable);
3281f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier  ScopedThreadSuspension sts(self, kWaitingForDeoptimization);
3282aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier  // Required for ProcessDeoptimizationRequest.
3283aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier  gc::ScopedGCCriticalSection gcs(self,
3284aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier                                  gc::kGcCauseInstrumentation,
3285aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier                                  gc::kCollectorTypeInstrumentation);
3286138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // We need to suspend mutator threads first.
32874f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier  ScopedSuspendAll ssa(__FUNCTION__);
3288138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  const ThreadState old_state = self->SetStateUnsafe(kRunnable);
32894d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz  {
3290306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom    MutexLock mu(self, *Locks::deoptimization_lock_);
32917ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz    size_t req_index = 0;
32920ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi    for (DeoptimizationRequest& request : deoptimization_requests_) {
32937ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz      VLOG(jdwp) << "Process deoptimization request #" << req_index++;
32944d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      ProcessDeoptimizationRequest(request);
32954d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    }
32964d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    deoptimization_requests_.clear();
32974d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz  }
3298138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  CHECK_EQ(self->SetStateUnsafe(old_state), kRunnable);
3299138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz}
3300138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
3301e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic const Breakpoint* FindFirstBreakpointForMethod(ArtMethod* m)
3302bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_, Locks::breakpoint_lock_) {
33030ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi  for (Breakpoint& breakpoint : gBreakpoints) {
33046c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light    if (breakpoint.IsInMethod(m)) {
3305a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz      return &breakpoint;
3306138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    }
3307a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz  }
3308a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz  return nullptr;
3309a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz}
3310138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
3311e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierbool Dbg::MethodHasAnyBreakpoints(ArtMethod* method) {
3312d8565456d29f4ad05f11cf84d2d2dac488508e06Mathieu Chartier  ReaderMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
3313d8565456d29f4ad05f11cf84d2d2dac488508e06Mathieu Chartier  return FindFirstBreakpointForMethod(method) != nullptr;
3314d8565456d29f4ad05f11cf84d2d2dac488508e06Mathieu Chartier}
3315d8565456d29f4ad05f11cf84d2d2dac488508e06Mathieu Chartier
3316a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz// Sanity checks all existing breakpoints on the same method.
3317e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic void SanityCheckExistingBreakpoints(ArtMethod* m,
3318f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz                                           DeoptimizationRequest::Kind deoptimization_kind)
3319bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_, Locks::breakpoint_lock_) {
33204d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz  for (const Breakpoint& breakpoint : gBreakpoints) {
33216c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light    if (breakpoint.IsInMethod(m)) {
3322f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz      CHECK_EQ(deoptimization_kind, breakpoint.GetDeoptimizationKind());
3323f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    }
33244d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz  }
3325f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
3326f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  if (deoptimization_kind == DeoptimizationRequest::kFullDeoptimization) {
33274d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz    // We should have deoptimized everything but not "selectively" deoptimized this method.
3328f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    CHECK(instrumentation->AreAllMethodsDeoptimized());
3329f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    CHECK(!instrumentation->IsDeoptimized(m));
3330f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  } else if (deoptimization_kind == DeoptimizationRequest::kSelectiveDeoptimization) {
33314d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz    // We should have "selectively" deoptimized this method.
33324d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz    // Note: while we have not deoptimized everything for this method, we may have done it for
33334d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz    // another event.
3334f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    CHECK(instrumentation->IsDeoptimized(m));
3335f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  } else {
3336f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    // This method does not require deoptimization.
3337f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    CHECK_EQ(deoptimization_kind, DeoptimizationRequest::kNothing);
3338f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    CHECK(!instrumentation->IsDeoptimized(m));
3339138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  }
3340a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz}
3341138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
3342abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz// Returns the deoptimization kind required to set a breakpoint in a method.
3343abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz// If a breakpoint has already been set, we also return the first breakpoint
3344abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz// through the given 'existing_brkpt' pointer.
3345f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertzstatic DeoptimizationRequest::Kind GetRequiredDeoptimizationKind(Thread* self,
3346e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                                                                 ArtMethod* m,
3347abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz                                                                 const Breakpoint** existing_brkpt)
3348bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
3349f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  if (!Dbg::RequiresDeoptimization()) {
3350f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    // We already run in interpreter-only mode so we don't need to deoptimize anything.
3351f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    VLOG(jdwp) << "No need for deoptimization when fully running with interpreter for method "
3352709b070044354d9f47641f273edacaeeb0240ab7David Sehr               << ArtMethod::PrettyMethod(m);
3353f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    return DeoptimizationRequest::kNothing;
3354f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  }
3355abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz  const Breakpoint* first_breakpoint;
33564d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz  {
33574d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz    ReaderMutexLock mu(self, *Locks::breakpoint_lock_);
3358abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz    first_breakpoint = FindFirstBreakpointForMethod(m);
3359abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz    *existing_brkpt = first_breakpoint;
33604d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz  }
3361abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz
3362abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz  if (first_breakpoint == nullptr) {
33636300fd77033817664aee3056c4ff5fab85698d2bNicolas Geoffray    // There is no breakpoint on this method yet: we need to deoptimize. If this method is default,
33646300fd77033817664aee3056c4ff5fab85698d2bNicolas Geoffray    // we deoptimize everything; otherwise we deoptimize only this method. We
33656c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light    // deoptimize with defaults because we do not know everywhere they are used. It is possible some
33666300fd77033817664aee3056c4ff5fab85698d2bNicolas Geoffray    // of the copies could be missed.
33676c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light    // TODO Deoptimizing on default methods might not be necessary in all cases.
33686300fd77033817664aee3056c4ff5fab85698d2bNicolas Geoffray    bool need_full_deoptimization = m->IsDefault();
3369a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz    if (need_full_deoptimization) {
33706300fd77033817664aee3056c4ff5fab85698d2bNicolas Geoffray      VLOG(jdwp) << "Need full deoptimization because of copying of method "
3371709b070044354d9f47641f273edacaeeb0240ab7David Sehr                 << ArtMethod::PrettyMethod(m);
3372f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz      return DeoptimizationRequest::kFullDeoptimization;
3373a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz    } else {
3374f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz      // We don't need to deoptimize if the method has not been compiled.
3375a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray      const bool is_compiled = m->HasAnyCompiledCode();
3376f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz      if (is_compiled) {
3377709b070044354d9f47641f273edacaeeb0240ab7David Sehr        VLOG(jdwp) << "Need selective deoptimization for compiled method "
3378709b070044354d9f47641f273edacaeeb0240ab7David Sehr                   << ArtMethod::PrettyMethod(m);
33796300fd77033817664aee3056c4ff5fab85698d2bNicolas Geoffray        return DeoptimizationRequest::kSelectiveDeoptimization;
3380f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz      } else {
3381f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz        // Method is not compiled: we don't need to deoptimize.
3382709b070044354d9f47641f273edacaeeb0240ab7David Sehr        VLOG(jdwp) << "No need for deoptimization for non-compiled method "
3383709b070044354d9f47641f273edacaeeb0240ab7David Sehr                   << ArtMethod::PrettyMethod(m);
3384f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz        return DeoptimizationRequest::kNothing;
3385f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz      }
3386a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz    }
3387a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz  } else {
3388a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz    // There is at least one breakpoint for this method: we don't need to deoptimize.
3389f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    // Let's check that all breakpoints are configured the same way for deoptimization.
3390f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    VLOG(jdwp) << "Breakpoint already set: no deoptimization is required";
3391abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz    DeoptimizationRequest::Kind deoptimization_kind = first_breakpoint->GetDeoptimizationKind();
33924d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz    if (kIsDebugBuild) {
33934d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz      ReaderMutexLock mu(self, *Locks::breakpoint_lock_);
3394f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz      SanityCheckExistingBreakpoints(m, deoptimization_kind);
33954d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz    }
3396f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    return DeoptimizationRequest::kNothing;
3397f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  }
3398f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz}
3399f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz
3400f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz// Installs a breakpoint at the specified location. Also indicates through the deoptimization
3401f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz// request if we need to deoptimize.
3402f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertzvoid Dbg::WatchLocation(const JDWP::JdwpLocation* location, DeoptimizationRequest* req) {
3403f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  Thread* const self = Thread::Current();
3404e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  ArtMethod* m = FromMethodId(location->method_id);
3405f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  DCHECK(m != nullptr) << "No method for method id " << location->method_id;
3406f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz
3407abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz  const Breakpoint* existing_breakpoint = nullptr;
3408abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz  const DeoptimizationRequest::Kind deoptimization_kind =
3409abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz      GetRequiredDeoptimizationKind(self, m, &existing_breakpoint);
3410f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  req->SetKind(deoptimization_kind);
3411f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  if (deoptimization_kind == DeoptimizationRequest::kSelectiveDeoptimization) {
3412f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    req->SetMethod(m);
3413f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  } else {
3414f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    CHECK(deoptimization_kind == DeoptimizationRequest::kNothing ||
3415f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz          deoptimization_kind == DeoptimizationRequest::kFullDeoptimization);
3416f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    req->SetMethod(nullptr);
3417138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  }
3418a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz
34194d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz  {
34204d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz    WriterMutexLock mu(self, *Locks::breakpoint_lock_);
3421abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz    // If there is at least one existing breakpoint on the same method, the new breakpoint
3422abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz    // must have the same deoptimization kind than the existing breakpoint(s).
3423abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz    DeoptimizationRequest::Kind breakpoint_deoptimization_kind;
3424abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz    if (existing_breakpoint != nullptr) {
3425abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz      breakpoint_deoptimization_kind = existing_breakpoint->GetDeoptimizationKind();
3426abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz    } else {
3427abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz      breakpoint_deoptimization_kind = deoptimization_kind;
3428abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz    }
3429abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz    gBreakpoints.push_back(Breakpoint(m, location->dex_pc, breakpoint_deoptimization_kind));
34304d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz    VLOG(jdwp) << "Set breakpoint #" << (gBreakpoints.size() - 1) << ": "
34314d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz               << gBreakpoints[gBreakpoints.size() - 1];
34324d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz  }
3433872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
3434872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
3435a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz// Uninstalls a breakpoint at the specified location. Also indicates through the deoptimization
3436a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz// request if we need to undeoptimize.
34374d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertzvoid Dbg::UnwatchLocation(const JDWP::JdwpLocation* location, DeoptimizationRequest* req) {
3438ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  WriterMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
3439e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  ArtMethod* m = FromMethodId(location->method_id);
3440a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz  DCHECK(m != nullptr) << "No method for method id " << location->method_id;
3441f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz  DeoptimizationRequest::Kind deoptimization_kind = DeoptimizationRequest::kNothing;
3442a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz  for (size_t i = 0, e = gBreakpoints.size(); i < e; ++i) {
34436c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light    if (gBreakpoints[i].DexPc() == location->dex_pc && gBreakpoints[i].IsInMethod(m)) {
3444a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz      VLOG(jdwp) << "Removed breakpoint #" << i << ": " << gBreakpoints[i];
3445f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz      deoptimization_kind = gBreakpoints[i].GetDeoptimizationKind();
3446f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz      DCHECK_EQ(deoptimization_kind == DeoptimizationRequest::kSelectiveDeoptimization,
3447f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz                Runtime::Current()->GetInstrumentation()->IsDeoptimized(m));
3448a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz      gBreakpoints.erase(gBreakpoints.begin() + i);
3449a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz      break;
3450138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    }
3451138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  }
3452a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz  const Breakpoint* const existing_breakpoint = FindFirstBreakpointForMethod(m);
3453a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz  if (existing_breakpoint == nullptr) {
3454a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz    // There is no more breakpoint on this method: we need to undeoptimize.
3455f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    if (deoptimization_kind == DeoptimizationRequest::kFullDeoptimization) {
3456a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz      // This method required full deoptimization: we need to undeoptimize everything.
34570ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      req->SetKind(DeoptimizationRequest::kFullUndeoptimization);
34580ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      req->SetMethod(nullptr);
3459f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    } else if (deoptimization_kind == DeoptimizationRequest::kSelectiveDeoptimization) {
3460a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz      // This method required selective deoptimization: we need to undeoptimize only that method.
34610ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      req->SetKind(DeoptimizationRequest::kSelectiveUndeoptimization);
34620ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi      req->SetMethod(m);
3463f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz    } else {
3464f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz      // This method had no need for deoptimization: do nothing.
3465f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz      CHECK_EQ(deoptimization_kind, DeoptimizationRequest::kNothing);
3466f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz      req->SetKind(DeoptimizationRequest::kNothing);
3467f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz      req->SetMethod(nullptr);
3468a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz    }
3469a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz  } else {
3470a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz    // There is at least one breakpoint for this method: we don't need to undeoptimize.
34710ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi    req->SetKind(DeoptimizationRequest::kNothing);
34720ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi    req->SetMethod(nullptr);
34734d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz    if (kIsDebugBuild) {
3474f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz      SanityCheckExistingBreakpoints(m, deoptimization_kind);
34754d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz    }
34768696433d1b3d8ba15288483b777edd888de69135Elliott Hughes  }
3477872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
3478872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
3479e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierbool Dbg::IsForcedInterpreterNeededForCallingImpl(Thread* thread, ArtMethod* m) {
3480eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  const SingleStepControl* const ssc = thread->GetSingleStepControl();
3481eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  if (ssc == nullptr) {
3482eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // If we are not single-stepping, then we don't have to force interpreter.
3483eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    return false;
3484eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  }
3485eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  if (Runtime::Current()->GetInstrumentation()->InterpretOnly()) {
3486eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // If we are in interpreter only mode, then we don't have to force interpreter.
3487eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    return false;
3488eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  }
3489eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi
3490eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  if (!m->IsNative() && !m->IsProxyMethod()) {
3491eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // If we want to step into a method, then we have to force interpreter on that call.
3492eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    if (ssc->GetStepDepth() == JDWP::SD_INTO) {
3493eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi      return true;
3494eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    }
3495eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  }
3496eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  return false;
3497eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi}
3498eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi
3499e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierbool Dbg::IsForcedInterpreterNeededForResolutionImpl(Thread* thread, ArtMethod* m) {
3500eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  instrumentation::Instrumentation* const instrumentation =
3501eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi      Runtime::Current()->GetInstrumentation();
3502eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // If we are in interpreter only mode, then we don't have to force interpreter.
3503eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  if (instrumentation->InterpretOnly()) {
3504eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    return false;
3505eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  }
3506eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // We can only interpret pure Java method.
3507eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  if (m->IsNative() || m->IsProxyMethod()) {
3508eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    return false;
3509eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  }
3510eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  const SingleStepControl* const ssc = thread->GetSingleStepControl();
3511eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  if (ssc != nullptr) {
3512eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // If we want to step into a method, then we have to force interpreter on that call.
3513eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    if (ssc->GetStepDepth() == JDWP::SD_INTO) {
3514eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi      return true;
3515eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    }
3516eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // If we are stepping out from a static initializer, by issuing a step
3517eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // in or step over, that was implicitly invoked by calling a static method,
3518eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // then we need to step into that method. Having a lower stack depth than
3519eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // the one the single step control has indicates that the step originates
3520eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // from the static initializer.
3521eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    if (ssc->GetStepDepth() != JDWP::SD_OUT &&
3522eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi        ssc->GetStackDepth() > GetStackDepth(thread)) {
3523eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi      return true;
3524eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    }
3525eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  }
3526eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // There are cases where we have to force interpreter on deoptimized methods,
3527eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // because in some cases the call will not be performed by invoking an entry
3528eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // point that has been replaced by the deoptimization, but instead by directly
3529eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // invoking the compiled code of the method, for example.
3530eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  return instrumentation->IsDeoptimized(m);
3531eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi}
3532eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi
3533e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierbool Dbg::IsForcedInstrumentationNeededForResolutionImpl(Thread* thread, ArtMethod* m) {
35342cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  // The upcall can be null and in that case we don't need to do anything.
3535eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  if (m == nullptr) {
3536eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    return false;
3537eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  }
3538eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  instrumentation::Instrumentation* const instrumentation =
3539eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi      Runtime::Current()->GetInstrumentation();
3540eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // If we are in interpreter only mode, then we don't have to force interpreter.
3541eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  if (instrumentation->InterpretOnly()) {
3542eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    return false;
3543eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  }
3544eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // We can only interpret pure Java method.
3545eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  if (m->IsNative() || m->IsProxyMethod()) {
3546eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    return false;
3547eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  }
3548eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  const SingleStepControl* const ssc = thread->GetSingleStepControl();
3549eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  if (ssc != nullptr) {
3550eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // If we are stepping out from a static initializer, by issuing a step
3551eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // out, that was implicitly invoked by calling a static method, then we
3552eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // need to step into the caller of that method. Having a lower stack
3553eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // depth than the one the single step control has indicates that the
3554eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // step originates from the static initializer.
3555eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    if (ssc->GetStepDepth() == JDWP::SD_OUT &&
3556eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi        ssc->GetStackDepth() > GetStackDepth(thread)) {
3557eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi      return true;
3558eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    }
3559eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  }
3560eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // If we are returning from a static intializer, that was implicitly
3561eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // invoked by calling a static method and the caller is deoptimized,
3562eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // then we have to deoptimize the stack without forcing interpreter
3563eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // on the static method that was called originally. This problem can
3564eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // be solved easily by forcing instrumentation on the called method,
3565eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // because the instrumentation exit hook will recognise the need of
3566eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // stack deoptimization by calling IsForcedInterpreterNeededForUpcall.
3567eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  return instrumentation->IsDeoptimized(m);
3568eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi}
3569eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi
3570e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierbool Dbg::IsForcedInterpreterNeededForUpcallImpl(Thread* thread, ArtMethod* m) {
35712cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  // The upcall can be null and in that case we don't need to do anything.
3572eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  if (m == nullptr) {
3573eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    return false;
3574eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  }
3575eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  instrumentation::Instrumentation* const instrumentation =
3576eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi      Runtime::Current()->GetInstrumentation();
3577eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // If we are in interpreter only mode, then we don't have to force interpreter.
3578eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  if (instrumentation->InterpretOnly()) {
3579eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    return false;
3580eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  }
3581eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // We can only interpret pure Java method.
3582eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  if (m->IsNative() || m->IsProxyMethod()) {
3583eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    return false;
3584eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  }
3585eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  const SingleStepControl* const ssc = thread->GetSingleStepControl();
3586eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  if (ssc != nullptr) {
3587eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // The debugger is not interested in what is happening under the level
3588eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // of the step, thus we only force interpreter when we are not below of
3589eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    // the step.
3590eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    if (ssc->GetStackDepth() >= GetStackDepth(thread)) {
3591eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi      return true;
3592eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi    }
3593eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  }
359499170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang  if (thread->HasDebuggerShadowFrames()) {
359599170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang    // We need to deoptimize the stack for the exception handling flow so that
359699170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang    // we don't miss any deoptimization that should be done when there are
359799170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang    // debugger shadow frames.
359899170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang    return true;
359999170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang  }
3600eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  // We have to require stack deoptimization if the upcall is deoptimized.
3601eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi  return instrumentation->IsDeoptimized(m);
3602eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi}
3603eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi
360499170c636dfae4908b102347cfe9f92bad1881ccMingyao Yangclass NeedsDeoptimizationVisitor : public StackVisitor {
3605520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz public:
3606520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  explicit NeedsDeoptimizationVisitor(Thread* self)
3607bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      REQUIRES_SHARED(Locks::mutator_lock_)
3608520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz    : StackVisitor(self, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
3609520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz      needs_deoptimization_(false) {}
3610520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz
3611bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe  bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
3612520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz    // The visitor is meant to be used when handling exception from compiled code only.
3613709b070044354d9f47641f273edacaeeb0240ab7David Sehr    CHECK(!IsShadowFrame()) << "We only expect to visit compiled frame: "
3614709b070044354d9f47641f273edacaeeb0240ab7David Sehr                            << ArtMethod::PrettyMethod(GetMethod());
3615520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz    ArtMethod* method = GetMethod();
3616520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz    if (method == nullptr) {
3617520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz      // We reach an upcall and don't need to deoptimize this part of the stack (ManagedFragment)
3618520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz      // so we can stop the visit.
3619520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz      DCHECK(!needs_deoptimization_);
3620520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz      return false;
3621520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz    }
3622520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz    if (Runtime::Current()->GetInstrumentation()->InterpretOnly()) {
3623520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz      // We found a compiled frame in the stack but instrumentation is set to interpret
3624520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz      // everything: we need to deoptimize.
3625520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz      needs_deoptimization_ = true;
3626520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz      return false;
3627520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz    }
3628520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz    if (Runtime::Current()->GetInstrumentation()->IsDeoptimized(method)) {
3629520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz      // We found a deoptimized method in the stack.
3630520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz      needs_deoptimization_ = true;
3631520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz      return false;
3632520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz    }
363399170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang    ShadowFrame* frame = GetThread()->FindDebuggerShadowFrame(GetFrameId());
363499170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang    if (frame != nullptr) {
363599170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang      // The debugger allocated a ShadowFrame to update a variable in the stack: we need to
363699170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang      // deoptimize the stack to execute (and deallocate) this frame.
363799170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang      needs_deoptimization_ = true;
363899170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang      return false;
363999170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang    }
3640520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz    return true;
3641520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  }
3642520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz
3643520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  bool NeedsDeoptimization() const {
3644520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz    return needs_deoptimization_;
3645520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  }
3646520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz
3647520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz private:
3648520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  // Do we need to deoptimize the stack?
3649520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  bool needs_deoptimization_;
3650520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz
3651520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  DISALLOW_COPY_AND_ASSIGN(NeedsDeoptimizationVisitor);
3652520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz};
3653520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz
3654520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz// Do we need to deoptimize the stack to handle an exception?
3655520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertzbool Dbg::IsForcedInterpreterNeededForExceptionImpl(Thread* thread) {
3656520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  const SingleStepControl* const ssc = thread->GetSingleStepControl();
3657520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  if (ssc != nullptr) {
3658520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz    // We deopt to step into the catch handler.
3659520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz    return true;
3660520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  }
3661520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  // Deoptimization is required if at least one method in the stack needs it. However we
3662520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  // skip frames that will be unwound (thus not executed).
3663520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  NeedsDeoptimizationVisitor visitor(thread);
3664520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  visitor.WalkStack(true);  // includes upcall.
3665520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  return visitor.NeedsDeoptimization();
3666520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz}
3667520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz
3668449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao// Scoped utility class to suspend a thread so that we may do tasks such as walk its stack. Doesn't
3669449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao// cause suspension if the thread is the current thread.
3670f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartierclass ScopedDebuggerThreadSuspension {
3671449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao public:
3672f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier  ScopedDebuggerThreadSuspension(Thread* self, JDWP::ObjectId thread_id)
367390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      REQUIRES(!Locks::thread_list_lock_)
3674bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      REQUIRES_SHARED(Locks::mutator_lock_) :
3675f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers      thread_(nullptr),
3676449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao      error_(JDWP::ERR_NONE),
3677449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao      self_suspend_(false),
367833e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers      other_suspend_(false) {
3679449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao    ScopedObjectAccessUnchecked soa(self);
3680692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz    thread_ = DecodeThread(soa, thread_id, &error_);
3681449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao    if (error_ == JDWP::ERR_NONE) {
3682449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao      if (thread_ == soa.Self()) {
3683449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao        self_suspend_ = true;
3684449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao      } else {
3685f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier        Thread* suspended_thread;
3686f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier        {
3687f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier          ScopedThreadSuspension sts(self, kWaitingForDebuggerSuspension);
3688f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier          jobject thread_peer = Dbg::GetObjectRegistry()->GetJObject(thread_id);
3689f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier          bool timed_out;
3690f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier          ThreadList* const thread_list = Runtime::Current()->GetThreadList();
3691cdd798de1b2e7807f1cab8ebbfbb165069beae6bSebastien Hertz          suspended_thread = thread_list->SuspendThreadByPeer(thread_peer,
3692cdd798de1b2e7807f1cab8ebbfbb165069beae6bSebastien Hertz                                                              /* request_suspension */ true,
3693cdd798de1b2e7807f1cab8ebbfbb165069beae6bSebastien Hertz                                                              /* debug_suspension */ true,
3694cdd798de1b2e7807f1cab8ebbfbb165069beae6bSebastien Hertz                                                              &timed_out);
3695f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier        }
3696f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers        if (suspended_thread == nullptr) {
3697449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao          // Thread terminated from under us while suspending.
3698449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao          error_ = JDWP::ERR_INVALID_THREAD;
3699449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao        } else {
3700449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao          CHECK_EQ(suspended_thread, thread_);
3701449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao          other_suspend_ = true;
3702449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao        }
3703449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao      }
3704449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao    }
3705449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  }
3706449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao
3707449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  Thread* GetThread() const {
3708449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao    return thread_;
3709449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  }
3710449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao
3711449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  JDWP::JdwpError GetError() const {
3712449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao    return error_;
3713449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  }
3714449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao
3715f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier  ~ScopedDebuggerThreadSuspension() {
3716449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao    if (other_suspend_) {
3717449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao      Runtime::Current()->GetThreadList()->Resume(thread_, true);
3718449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao    }
3719449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  }
3720449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao
3721449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao private:
3722449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  Thread* thread_;
3723449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  JDWP::JdwpError error_;
3724449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  bool self_suspend_;
3725449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  bool other_suspend_;
3726449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao};
3727449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao
3728221229cb523f849f165fdafbf9785010963715daElliott HughesJDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize step_size,
372900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                   JDWP::JdwpStepDepth step_depth) {
3730449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  Thread* self = Thread::Current();
3731f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier  ScopedDebuggerThreadSuspension sts(self, thread_id);
3732449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  if (sts.GetError() != JDWP::ERR_NONE) {
3733449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao    return sts.GetError();
37342435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  }
37358696433d1b3d8ba15288483b777edd888de69135Elliott Hughes
3736597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz  // Work out what ArtMethod* we're in, the current line number, and how deep the stack currently
37372435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  // is for step-out.
37380399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  struct SingleStepStackVisitor : public StackVisitor {
3739bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    explicit SingleStepStackVisitor(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_)
37408e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray        : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
37418e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray          stack_depth(0),
37428e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray          method(nullptr),
37438e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray          line_number(-1) {}
3744ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers
374500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
374600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    // annotalysis.
374700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS {
3748e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier      ArtMethod* m = GetMethod();
37490399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      if (!m->IsRuntimeMethod()) {
3750597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz        ++stack_depth;
3751597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz        if (method == nullptr) {
37527337631929812fb8a60b5182eba076a32d1cb851Alex Light          const DexFile* dex_file = m->GetDexFile();
3753597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz          method = m;
37547337631929812fb8a60b5182eba076a32d1cb851Alex Light          if (dex_file != nullptr) {
37559323e6e44060545d6c4f925139572868f65b7fe3David Sehr            line_number = annotations::GetLineNumFromPC(dex_file, m, GetDexPc());
37562435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes          }
37578696433d1b3d8ba15288483b777edd888de69135Elliott Hughes        }
37588696433d1b3d8ba15288483b777edd888de69135Elliott Hughes      }
3759530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes      return true;
37608696433d1b3d8ba15288483b777edd888de69135Elliott Hughes    }
376161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz
3762597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz    int stack_depth;
3763e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ArtMethod* method;
3764597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz    int32_t line_number;
37658696433d1b3d8ba15288483b777edd888de69135Elliott Hughes  };
3766449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao
376761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz  Thread* const thread = sts.GetThread();
3768597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz  SingleStepStackVisitor visitor(thread);
37690399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  visitor.WalkStack();
37708696433d1b3d8ba15288483b777edd888de69135Elliott Hughes
37712435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  // Find the dex_pc values that correspond to the current line, for line-based single-stepping.
37722435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  struct DebugCallbackContext {
37733887c468d731420e929e6ad3acf190d5431e94fcRoland Levillain    DebugCallbackContext(SingleStepControl* single_step_control_cb,
37743887c468d731420e929e6ad3acf190d5431e94fcRoland Levillain                         int32_t line_number_cb, const DexFile::CodeItem* code_item)
37753887c468d731420e929e6ad3acf190d5431e94fcRoland Levillain        : single_step_control_(single_step_control_cb), line_number_(line_number_cb),
37763887c468d731420e929e6ad3acf190d5431e94fcRoland Levillain          code_item_(code_item), last_pc_valid(false), last_pc(0) {
37772435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes    }
37782435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes
3779b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky    static bool Callback(void* raw_context, const DexFile::PositionInfo& entry) {
37802435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes      DebugCallbackContext* context = reinterpret_cast<DebugCallbackContext*>(raw_context);
3781b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky      if (static_cast<int32_t>(entry.line_) == context->line_number_) {
37822435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes        if (!context->last_pc_valid) {
37832435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes          // Everything from this address until the next line change is ours.
3784b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky          context->last_pc = entry.address_;
37852435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes          context->last_pc_valid = true;
37862435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes        }
37872435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes        // Otherwise, if we're already in a valid range for this line,
37882435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes        // just keep going (shouldn't really happen)...
37897934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom      } else if (context->last_pc_valid) {  // and the line number is new
37902435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes        // Add everything from the last entry up until here to the set
3791b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky        for (uint32_t dex_pc = context->last_pc; dex_pc < entry.address_; ++dex_pc) {
3792597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz          context->single_step_control_->AddDexPc(dex_pc);
37932435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes        }
37942435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes        context->last_pc_valid = false;
37952435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes      }
37967934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom      return false;  // There may be multiple entries for any given line.
37972435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes    }
37982435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes
379961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz    ~DebugCallbackContext() {
38002435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes      // If the line number was the last in the position table...
38012435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes      if (last_pc_valid) {
3802bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz        size_t end = code_item_->insns_size_in_code_units_;
38032435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes        for (uint32_t dex_pc = last_pc; dex_pc < end; ++dex_pc) {
3804597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz          single_step_control_->AddDexPc(dex_pc);
38052435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes        }
38062435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes      }
38072435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes    }
38082435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes
380961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz    SingleStepControl* const single_step_control_;
381061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz    const int32_t line_number_;
3811bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz    const DexFile::CodeItem* const code_item_;
38122435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes    bool last_pc_valid;
38132435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes    uint32_t last_pc;
38142435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  };
3815597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz
3816597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz  // Allocate single step.
38171558b577907b613864e98f05862543557263e864Sebastien Hertz  SingleStepControl* single_step_control =
38181558b577907b613864e98f05862543557263e864Sebastien Hertz      new (std::nothrow) SingleStepControl(step_size, step_depth,
38191558b577907b613864e98f05862543557263e864Sebastien Hertz                                           visitor.stack_depth, visitor.method);
38201558b577907b613864e98f05862543557263e864Sebastien Hertz  if (single_step_control == nullptr) {
38211558b577907b613864e98f05862543557263e864Sebastien Hertz    LOG(ERROR) << "Failed to allocate SingleStepControl";
38221558b577907b613864e98f05862543557263e864Sebastien Hertz    return JDWP::ERR_OUT_OF_MEMORY;
38231558b577907b613864e98f05862543557263e864Sebastien Hertz  }
38241558b577907b613864e98f05862543557263e864Sebastien Hertz
3825e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  ArtMethod* m = single_step_control->GetMethod();
3826597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz  const int32_t line_number = visitor.line_number;
382752f5f93873ec244320e05b033243c5c7a3ae40e2Sebastien Hertz  // Note: if the thread is not running Java code (pure native thread), there is no "current"
382852f5f93873ec244320e05b033243c5c7a3ae40e2Sebastien Hertz  // method on the stack (and no line number either).
382952f5f93873ec244320e05b033243c5c7a3ae40e2Sebastien Hertz  if (m != nullptr && !m->IsNative()) {
3830bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier    const DexFile::CodeItem* const code_item = m->GetCodeItem();
3831bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz    DebugCallbackContext context(single_step_control, line_number, code_item);
3832b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky    m->GetDexFile()->DecodeDebugPositionInfo(code_item, DebugCallbackContext::Callback, &context);
38333e2e1a2380e7b2ce402640ea4f6a177c06bd19a2Elliott Hughes  }
38342435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes
3835597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz  // Activate single-step in the thread.
3836597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz  thread->ActivateSingleStepControl(single_step_control);
38378696433d1b3d8ba15288483b777edd888de69135Elliott Hughes
38382435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  if (VLOG_IS_ON(jdwp)) {
383961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz    VLOG(jdwp) << "Single-step thread: " << *thread;
3840597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz    VLOG(jdwp) << "Single-step step size: " << single_step_control->GetStepSize();
3841597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz    VLOG(jdwp) << "Single-step step depth: " << single_step_control->GetStepDepth();
3842709b070044354d9f47641f273edacaeeb0240ab7David Sehr    VLOG(jdwp) << "Single-step current method: "
3843709b070044354d9f47641f273edacaeeb0240ab7David Sehr               << ArtMethod::PrettyMethod(single_step_control->GetMethod());
384461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz    VLOG(jdwp) << "Single-step current line: " << line_number;
3845597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz    VLOG(jdwp) << "Single-step current stack depth: " << single_step_control->GetStackDepth();
38462435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes    VLOG(jdwp) << "Single-step dex_pc values:";
3847597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz    for (uint32_t dex_pc : single_step_control->GetDexPcs()) {
3848bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz      VLOG(jdwp) << StringPrintf(" %#x", dex_pc);
38492435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes    }
38502435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  }
38512435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes
38522435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  return JDWP::ERR_NONE;
3853872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
3854872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
385561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertzvoid Dbg::UnconfigureStep(JDWP::ObjectId thread_id) {
385661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz  ScopedObjectAccessUnchecked soa(Thread::Current());
3857c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JDWP::JdwpError error;
3858c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  Thread* thread = DecodeThread(soa, thread_id, &error);
385987118ed6f3f99e7df33214c277cf200a7b9a7499Sebastien Hertz  if (error == JDWP::ERR_NONE) {
3860597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz    thread->DeactivateSingleStepControl();
386161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz  }
3862872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
3863872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
386445651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughesstatic char JdwpTagToShortyChar(JDWP::JdwpTag tag) {
386545651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes  switch (tag) {
386645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    default:
386745651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes      LOG(FATAL) << "unknown JDWP tag: " << PrintableChar(tag);
3868fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers      UNREACHABLE();
386945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes
387045651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    // Primitives.
387145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    case JDWP::JT_BYTE:    return 'B';
387245651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    case JDWP::JT_CHAR:    return 'C';
387345651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    case JDWP::JT_FLOAT:   return 'F';
387445651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    case JDWP::JT_DOUBLE:  return 'D';
387545651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    case JDWP::JT_INT:     return 'I';
387645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    case JDWP::JT_LONG:    return 'J';
387745651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    case JDWP::JT_SHORT:   return 'S';
387845651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    case JDWP::JT_VOID:    return 'V';
387945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    case JDWP::JT_BOOLEAN: return 'Z';
388045651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes
388145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    // Reference types.
388245651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    case JDWP::JT_ARRAY:
388345651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    case JDWP::JT_OBJECT:
388445651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    case JDWP::JT_STRING:
388545651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    case JDWP::JT_THREAD:
388645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    case JDWP::JT_THREAD_GROUP:
388745651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    case JDWP::JT_CLASS_LOADER:
388845651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    case JDWP::JT_CLASS_OBJECT:
388945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes      return 'L';
389045651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes  }
389145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes}
389245651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes
3893cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien HertzJDWP::JdwpError Dbg::PrepareInvokeMethod(uint32_t request_id, JDWP::ObjectId thread_id,
3894cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz                                         JDWP::ObjectId object_id, JDWP::RefTypeId class_id,
3895cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz                                         JDWP::MethodId method_id, uint32_t arg_count,
3896cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz                                         uint64_t arg_values[], JDWP::JdwpTag* arg_types,
3897cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz                                         uint32_t options) {
3898cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  Thread* const self = Thread::Current();
3899cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  CHECK_EQ(self, GetDebugThread()) << "This must be called by the JDWP thread";
3900d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz  const bool resume_all_threads = ((options & JDWP::INVOKE_SINGLE_THREADED) == 0);
3901d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes
3902cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  ThreadList* thread_list = Runtime::Current()->GetThreadList();
3903c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  Thread* targetThread = nullptr;
3904d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes  {
390500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    ScopedObjectAccessUnchecked soa(self);
3906c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    JDWP::JdwpError error;
3907c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    targetThread = DecodeThread(soa, thread_id, &error);
3908221229cb523f849f165fdafbf9785010963715daElliott Hughes    if (error != JDWP::ERR_NONE) {
3909221229cb523f849f165fdafbf9785010963715daElliott Hughes      LOG(ERROR) << "InvokeMethod request for invalid thread id " << thread_id;
3910221229cb523f849f165fdafbf9785010963715daElliott Hughes      return error;
3911d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes    }
39121558b577907b613864e98f05862543557263e864Sebastien Hertz    if (targetThread->GetInvokeReq() != nullptr) {
39131558b577907b613864e98f05862543557263e864Sebastien Hertz      // Thread is already invoking a method on behalf of the debugger.
39141558b577907b613864e98f05862543557263e864Sebastien Hertz      LOG(ERROR) << "InvokeMethod request for thread already invoking a method: " << *targetThread;
39151558b577907b613864e98f05862543557263e864Sebastien Hertz      return JDWP::ERR_ALREADY_INVOKING;
39161558b577907b613864e98f05862543557263e864Sebastien Hertz    }
39171558b577907b613864e98f05862543557263e864Sebastien Hertz    if (!targetThread->IsReadyForDebugInvoke()) {
39181558b577907b613864e98f05862543557263e864Sebastien Hertz      // Thread is not suspended by an event so it cannot invoke a method.
3919d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes      LOG(ERROR) << "InvokeMethod request for thread not stopped by event: " << *targetThread;
3920d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes      return JDWP::ERR_INVALID_THREAD;
3921d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes    }
3922d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes
3923d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes    /*
3924d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz     * According to the JDWP specs, we are expected to resume all threads (or only the
3925d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz     * target thread) once. So if a thread has been suspended more than once (either by
3926d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz     * the debugger for an event or by the runtime for GC), it will remain suspended before
3927d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz     * the invoke is executed. This means the debugger is responsible to properly resume all
3928d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz     * the threads it has suspended so the target thread can execute the method.
3929d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes     *
3930d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz     * However, for compatibility reason with older versions of debuggers (like Eclipse), we
3931d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz     * fully resume all threads (by canceling *all* debugger suspensions) when the debugger
3932d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz     * wants us to resume all threads. This is to avoid ending up in deadlock situation.
3933d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz     *
3934d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz     * On the other hand, if we are asked to only resume the target thread, then we follow the
3935d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz     * JDWP specs by resuming that thread only once. This means the thread will remain suspended
3936d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz     * if it has been suspended more than once before the invoke (and again, this is the
3937d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz     * responsibility of the debugger to properly resume that thread before invoking a method).
3938d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes     */
393900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    int suspend_count;
394000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    {
394150b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers      MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_);
394200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      suspend_count = targetThread->GetSuspendCount();
394300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
3944d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz    if (suspend_count > 1 && resume_all_threads) {
3945d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz      // The target thread will remain suspended even after we resume it. Let's emit a warning
3946d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz      // to indicate the invoke won't be executed until the thread is resumed.
3947d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz      LOG(WARNING) << *targetThread << " suspended more than once (suspend count == "
3948d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz                   << suspend_count << "). This thread will invoke the method only once "
3949d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz                   << "it is fully resumed.";
3950d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes    }
3951d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes
3952c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    mirror::Object* receiver = gRegistry->Get<mirror::Object*>(object_id, &error);
3953c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    if (error != JDWP::ERR_NONE) {
39543f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes      return JDWP::ERR_INVALID_OBJECT;
39553f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes    }
395645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes
39571558b577907b613864e98f05862543557263e864Sebastien Hertz    gRegistry->Get<mirror::Object*>(thread_id, &error);
3958c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    if (error != JDWP::ERR_NONE) {
39593f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes      return JDWP::ERR_INVALID_OBJECT;
39603f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes    }
396145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes
3962c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    mirror::Class* c = DecodeClass(class_id, &error);
3963c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    if (c == nullptr) {
3964c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      return error;
39653f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes    }
396645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes
3967e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ArtMethod* m = FromMethodId(method_id);
3968c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    if (m->IsStatic() != (receiver == nullptr)) {
396945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes      return JDWP::ERR_INVALID_METHODID;
397045651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    }
397145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    if (m->IsStatic()) {
397245651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes      if (m->GetDeclaringClass() != c) {
397345651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes        return JDWP::ERR_INVALID_METHODID;
397445651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes      }
397545651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    } else {
397645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes      if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
397745651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes        return JDWP::ERR_INVALID_METHODID;
397845651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes      }
397945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    }
398045651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes
398145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    // Check the argument list matches the method.
3982bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier    uint32_t shorty_len = 0;
3983bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier    const char* shorty = m->GetShorty(&shorty_len);
3984bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier    if (shorty_len - 1 != arg_count) {
398545651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes      return JDWP::ERR_ILLEGAL_ARGUMENT;
398645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    }
39870920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes
3988bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier    {
3989e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier      StackHandleScope<2> hs(soa.Self());
3990bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier      HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&receiver));
3991bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier      HandleWrapper<mirror::Class> h_klass(hs.NewHandleWrapper(&c));
3992bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier      const DexFile::TypeList* types = m->GetParameterTypeList();
3993bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier      for (size_t i = 0; i < arg_count; ++i) {
3994bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier        if (shorty[i + 1] != JdwpTagToShortyChar(arg_types[i])) {
39950920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes          return JDWP::ERR_ILLEGAL_ARGUMENT;
39960920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes        }
39970920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes
3998bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier        if (shorty[i + 1] == 'L') {
3999bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier          // Did we really get an argument of an appropriate reference type?
4000a0485607a4a4d8c683a9849f6f20902c4e1da7a4Ian Rogers          mirror::Class* parameter_type =
4001942fd3130254d8276cbfe8e6201825e9c49e9b2cVladimir Marko              m->GetClassFromTypeIndex(types->GetTypeItem(i).type_idx_, true /* resolve */);
4002c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers          mirror::Object* argument = gRegistry->Get<mirror::Object*>(arg_values[i], &error);
4003c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers          if (error != JDWP::ERR_NONE) {
4004bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier            return JDWP::ERR_INVALID_OBJECT;
4005bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier          }
4006c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers          if (argument != nullptr && !argument->InstanceOf(parameter_type)) {
4007bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier            return JDWP::ERR_ILLEGAL_ARGUMENT;
4008bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier          }
4009bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier
4010bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier          // Turn the on-the-wire ObjectId into a jobject.
4011bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier          jvalue& v = reinterpret_cast<jvalue&>(arg_values[i]);
4012bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier          v.l = gRegistry->GetJObject(arg_values[i]);
4013bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier        }
40140920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes      }
401545651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    }
401645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes
40171558b577907b613864e98f05862543557263e864Sebastien Hertz    // Allocates a DebugInvokeReq.
4018cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    DebugInvokeReq* req = new (std::nothrow) DebugInvokeReq(request_id, thread_id, receiver, c, m,
4019cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz                                                            options, arg_values, arg_count);
4020cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    if (req == nullptr) {
40211558b577907b613864e98f05862543557263e864Sebastien Hertz      LOG(ERROR) << "Failed to allocate DebugInvokeReq";
40221558b577907b613864e98f05862543557263e864Sebastien Hertz      return JDWP::ERR_OUT_OF_MEMORY;
40231558b577907b613864e98f05862543557263e864Sebastien Hertz    }
40241558b577907b613864e98f05862543557263e864Sebastien Hertz
4025cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    // Attaches the DebugInvokeReq to the target thread so it executes the method when
4026cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    // it is resumed. Once the invocation completes, the target thread will delete it before
4027cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    // suspending itself (see ThreadList::SuspendSelfForDebugger).
4028cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    targetThread->SetDebugInvokeReq(req);
4029d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes  }
4030d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes
4031d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes  // The fact that we've released the thread list lock is a bit risky --- if the thread goes
4032cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  // away we're sitting high and dry -- but we must release this before the UndoDebuggerSuspensions
4033cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  // call.
4034d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz  if (resume_all_threads) {
4035cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    VLOG(jdwp) << "      Resuming all threads";
4036cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    thread_list->UndoDebuggerSuspensions();
4037cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  } else {
4038cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    VLOG(jdwp) << "      Resuming event thread only";
4039d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes    thread_list->Resume(targetThread, true);
4040d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes  }
4041d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes
4042cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  return JDWP::ERR_NONE;
4043872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
4044872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
4045872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::ExecuteMethod(DebugInvokeReq* pReq) {
4046cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  Thread* const self = Thread::Current();
4047cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  CHECK_NE(self, GetDebugThread()) << "This must be called by the event thread";
4048cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4049cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  ScopedObjectAccess soa(self);
4050d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes
405181ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // We can be called while an exception is pending. We need
4052d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes  // to preserve that across the method invocation.
4053cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  StackHandleScope<1> hs(soa.Self());
4054cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  Handle<mirror::Throwable> old_exception = hs.NewHandle(soa.Self()->GetException());
40551558b577907b613864e98f05862543557263e864Sebastien Hertz  soa.Self()->ClearException();
4056d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes
4057cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  // Execute the method then sends reply to the debugger.
4058cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  ExecuteMethodWithoutPendingException(soa, pReq);
4059cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4060cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  // If an exception was pending before the invoke, restore it now.
4061fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  if (old_exception != nullptr) {
4062cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    soa.Self()->SetException(old_exception.Get());
4063cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  }
4064cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz}
4065cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4066cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz// Helper function: write a variable-width value into the output input buffer.
4067cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertzstatic void WriteValue(JDWP::ExpandBuf* pReply, int width, uint64_t value) {
4068cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  switch (width) {
4069cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    case 1:
4070cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      expandBufAdd1(pReply, value);
4071cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      break;
4072cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    case 2:
4073cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      expandBufAdd2BE(pReply, value);
4074cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      break;
4075cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    case 4:
4076cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      expandBufAdd4BE(pReply, value);
4077cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      break;
4078cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    case 8:
4079cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      expandBufAdd8BE(pReply, value);
4080cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      break;
4081cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    default:
4082cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      LOG(FATAL) << width;
4083cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      UNREACHABLE();
4084cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  }
4085cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz}
4086cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4087cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertzvoid Dbg::ExecuteMethodWithoutPendingException(ScopedObjectAccess& soa, DebugInvokeReq* pReq) {
4088cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  soa.Self()->AssertNoPendingException();
4089cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4090d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes  // Translate the method through the vtable, unless the debugger wants to suppress it.
4091cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  ArtMethod* m = pReq->method;
4092542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe  PointerSize image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
40931558b577907b613864e98f05862543557263e864Sebastien Hertz  if ((pReq->options & JDWP::INVOKE_NONVIRTUAL) == 0 && pReq->receiver.Read() != nullptr) {
4094e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ArtMethod* actual_method =
4095e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier        pReq->klass.Read()->FindVirtualMethodForVirtualOrInterface(m, image_pointer_size);
4096e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    if (actual_method != m) {
4097709b070044354d9f47641f273edacaeeb0240ab7David Sehr      VLOG(jdwp) << "ExecuteMethod translated " << ArtMethod::PrettyMethod(m)
4098709b070044354d9f47641f273edacaeeb0240ab7David Sehr                 << " to " << ArtMethod::PrettyMethod(actual_method);
4099e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier      m = actual_method;
410045651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    }
4101d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes  }
4102709b070044354d9f47641f273edacaeeb0240ab7David Sehr  VLOG(jdwp) << "ExecuteMethod " << ArtMethod::PrettyMethod(m)
41031558b577907b613864e98f05862543557263e864Sebastien Hertz             << " receiver=" << pReq->receiver.Read()
4104d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz             << " arg_count=" << pReq->arg_count;
4105e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  CHECK(m != nullptr);
4106d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes
410733d6903e570daf8f3cf7c1f6ebd9a6dd22c7c23cRoland Levillain  static_assert(sizeof(jvalue) == sizeof(uint64_t), "jvalue and uint64_t have different sizes.");
4108d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes
4109cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  // Invoke the method.
411039b6c24ce68cf05db0f82f454b4401cfb03d675fJeff Hao  ScopedLocalRef<jobject> ref(soa.Env(), soa.AddLocalReference<jobject>(pReq->receiver.Read()));
411113b27842e88ccf1a42807c92daeb108e867dc4cdAndreas Gampe  JValue result = InvokeWithJValues(soa, ref.get(), jni::EncodeArtMethod(m),
4112cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz                                    reinterpret_cast<jvalue*>(pReq->arg_values.get()));
4113d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes
4114cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  // Prepare JDWP ids for the reply.
4115cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  JDWP::JdwpTag result_tag = BasicTagFromDescriptor(m->GetShorty());
4116cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  const bool is_object_result = (result_tag == JDWP::JT_OBJECT);
4117064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao  StackHandleScope<3> hs(soa.Self());
41181558b577907b613864e98f05862543557263e864Sebastien Hertz  Handle<mirror::Object> object_result = hs.NewHandle(is_object_result ? result.GetL() : nullptr);
41191558b577907b613864e98f05862543557263e864Sebastien Hertz  Handle<mirror::Throwable> exception = hs.NewHandle(soa.Self()->GetException());
41201558b577907b613864e98f05862543557263e864Sebastien Hertz  soa.Self()->ClearException();
4121cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4122cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  if (!IsDebuggerActive()) {
4123cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    // The debugger detached: we must not re-suspend threads. We also don't need to fill the reply
4124cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    // because it won't be sent either.
4125cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    return;
4126cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  }
4127cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4128cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  JDWP::ObjectId exceptionObjectId = gRegistry->Add(exception);
4129cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  uint64_t result_value = 0;
4130cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  if (exceptionObjectId != 0) {
41311558b577907b613864e98f05862543557263e864Sebastien Hertz    VLOG(jdwp) << "  JDWP invocation returning with exception=" << exception.Get()
41321558b577907b613864e98f05862543557263e864Sebastien Hertz               << " " << exception->Dump();
4133cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    result_value = 0;
41341558b577907b613864e98f05862543557263e864Sebastien Hertz  } else if (is_object_result) {
4135cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    /* if no exception was thrown, examine object result more closely */
41361558b577907b613864e98f05862543557263e864Sebastien Hertz    JDWP::JdwpTag new_tag = TagFromObject(soa, object_result.Get());
4137cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    if (new_tag != result_tag) {
4138cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      VLOG(jdwp) << "  JDWP promoted result from " << result_tag << " to " << new_tag;
4139cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      result_tag = new_tag;
4140d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes    }
4141d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes
41421558b577907b613864e98f05862543557263e864Sebastien Hertz    // Register the object in the registry and reference its ObjectId. This ensures
41431558b577907b613864e98f05862543557263e864Sebastien Hertz    // GC safety and prevents from accessing stale reference if the object is moved.
4144cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    result_value = gRegistry->Add(object_result.Get());
41451558b577907b613864e98f05862543557263e864Sebastien Hertz  } else {
41461558b577907b613864e98f05862543557263e864Sebastien Hertz    // Primitive result.
4147cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    DCHECK(IsPrimitiveTag(result_tag));
4148cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    result_value = result.GetJ();
4149cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  }
4150cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  const bool is_constructor = m->IsConstructor() && !m->IsStatic();
4151cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  if (is_constructor) {
4152cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    // If we invoked a constructor (which actually returns void), return the receiver,
4153cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    // unless we threw, in which case we return null.
4154a3e1377f3f389a33f6a283796ea5cea1583911f3Sebastien Hertz    DCHECK_EQ(JDWP::JT_VOID, result_tag);
4155cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    if (exceptionObjectId == 0) {
4156064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao      if (m->GetDeclaringClass()->IsStringClass()) {
4157064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao        // For string constructors, the new string is remapped to the receiver (stored in ref).
4158064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao        Handle<mirror::Object> decoded_ref = hs.NewHandle(soa.Self()->DecodeJObject(ref.get()));
4159064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao        result_value = gRegistry->Add(decoded_ref);
4160064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao        result_tag = TagFromObject(soa, decoded_ref.Get());
4161064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao      } else {
4162064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao        // TODO we could keep the receiver ObjectId in the DebugInvokeReq to avoid looking into the
4163064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao        // object registry.
4164064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao        result_value = GetObjectRegistry()->Add(pReq->receiver.Read());
4165064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao        result_tag = TagFromObject(soa, pReq->receiver.Read());
4166064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao      }
4167cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    } else {
4168cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      result_value = 0;
4169a3e1377f3f389a33f6a283796ea5cea1583911f3Sebastien Hertz      result_tag = JDWP::JT_OBJECT;
4170cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    }
4171d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes  }
4172d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes
4173cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  // Suspend other threads if the invoke is not single-threaded.
4174cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  if ((pReq->options & JDWP::INVOKE_SINGLE_THREADED) == 0) {
4175f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier    ScopedThreadSuspension sts(soa.Self(), kWaitingForDebuggerSuspension);
41768f95cf3cb5f715b1277de9cd7fade07ce4b230beHiroshi Yamauchi    // Avoid a deadlock between GC and debugger where GC gets suspended during GC. b/25800335.
41778f95cf3cb5f715b1277de9cd7fade07ce4b230beHiroshi Yamauchi    gc::ScopedGCCriticalSection gcs(soa.Self(), gc::kGcCauseDebugger, gc::kCollectorTypeDebugger);
4178cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    VLOG(jdwp) << "      Suspending all threads";
4179cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    Runtime::Current()->GetThreadList()->SuspendAllForDebugger();
4180cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  }
4181cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4182cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  VLOG(jdwp) << "  --> returned " << result_tag
4183cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz             << StringPrintf(" %#" PRIx64 " (except=%#" PRIx64 ")", result_value,
4184cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz                             exceptionObjectId);
4185cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4186cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  // Show detailed debug output.
4187cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  if (result_tag == JDWP::JT_STRING && exceptionObjectId == 0) {
4188cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    if (result_value != 0) {
4189cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      if (VLOG_IS_ON(jdwp)) {
4190cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz        std::string result_string;
4191cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz        JDWP::JdwpError error = Dbg::StringToUtf8(result_value, &result_string);
4192cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz        CHECK_EQ(error, JDWP::ERR_NONE);
4193cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz        VLOG(jdwp) << "      string '" << result_string << "'";
4194cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      }
4195cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    } else {
4196cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      VLOG(jdwp) << "      string (null)";
4197cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    }
4198cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  }
4199cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4200cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  // Attach the reply to DebugInvokeReq so it can be sent to the debugger when the event thread
4201cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  // is ready to suspend.
4202cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  BuildInvokeReply(pReq->reply, pReq->request_id, result_tag, result_value, exceptionObjectId);
4203cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz}
4204cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4205cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertzvoid Dbg::BuildInvokeReply(JDWP::ExpandBuf* pReply, uint32_t request_id, JDWP::JdwpTag result_tag,
4206cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz                           uint64_t result_value, JDWP::ObjectId exception) {
4207cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  // Make room for the JDWP header since we do not know the size of the reply yet.
4208cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  JDWP::expandBufAddSpace(pReply, kJDWPHeaderLen);
4209cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4210cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  size_t width = GetTagWidth(result_tag);
4211cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  JDWP::expandBufAdd1(pReply, result_tag);
4212cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  if (width != 0) {
4213cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    WriteValue(pReply, width, result_value);
4214cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  }
4215cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  JDWP::expandBufAdd1(pReply, JDWP::JT_OBJECT);
4216cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  JDWP::expandBufAddObjectId(pReply, exception);
4217cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4218cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  // Now we know the size, we can complete the JDWP header.
4219cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  uint8_t* buf = expandBufGetBuffer(pReply);
4220cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  JDWP::Set4BE(buf + kJDWPHeaderSizeOffset, expandBufGetLength(pReply));
4221cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  JDWP::Set4BE(buf + kJDWPHeaderIdOffset, request_id);
4222cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  JDWP::Set1(buf + kJDWPHeaderFlagsOffset, kJDWPFlagReply);  // flags
4223cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  JDWP::Set2BE(buf + kJDWPHeaderErrorCodeOffset, JDWP::ERR_NONE);
4224cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz}
4225cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4226cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertzvoid Dbg::FinishInvokeMethod(DebugInvokeReq* pReq) {
4227cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  CHECK_NE(Thread::Current(), GetDebugThread()) << "This must be called by the event thread";
4228cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4229cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  JDWP::ExpandBuf* const pReply = pReq->reply;
4230cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  CHECK(pReply != nullptr) << "No reply attached to DebugInvokeReq";
4231cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4232cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  // We need to prevent other threads (including JDWP thread) from interacting with the debugger
4233cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  // while we send the reply but are not yet suspended. The JDWP token will be released just before
4234cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  // we suspend ourself again (see ThreadList::SuspendSelfForDebugger).
4235cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  gJdwpState->AcquireJdwpTokenForEvent(pReq->thread_id);
4236cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4237cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  // Send the reply unless the debugger detached before the completion of the method.
4238cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  if (IsDebuggerActive()) {
4239cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    const size_t replyDataLength = expandBufGetLength(pReply) - kJDWPHeaderLen;
4240cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    VLOG(jdwp) << StringPrintf("REPLY INVOKE id=0x%06x (length=%zu)",
4241cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz                               pReq->request_id, replyDataLength);
4242cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
4243cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    gJdwpState->SendRequest(pReply);
4244cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  } else {
4245cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    VLOG(jdwp) << "Not sending invoke reply because debugger detached";
4246d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes  }
4247872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
4248872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
4249d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes/*
42504b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes * "request" contains a full JDWP packet, possibly with multiple chunks.  We
4251f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * need to process each, accumulate the replies, and ship the whole thing
4252f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * back.
4253f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes *
4254f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Returns "true" if we have a reply.  The reply buffer is newly allocated,
4255f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * and includes the chunk type/length, followed by the data.
4256f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes *
42573d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes * OLD-TODO: we currently assume that the request and reply include a single
4258f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * chunk.  If this becomes inconvenient we will need to adapt.
4259f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes */
4260c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersbool Dbg::DdmHandlePacket(JDWP::Request* request, uint8_t** pReplyBuf, int* pReplyLen) {
4261f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  Thread* self = Thread::Current();
4262f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  JNIEnv* env = self->GetJniEnv();
4263f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes
4264c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  uint32_t type = request->ReadUnsigned32("type");
4265c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  uint32_t length = request->ReadUnsigned32("length");
42664b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes
42674b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  // Create a byte[] corresponding to 'request'.
4268c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  size_t request_length = request->size();
42694b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  ScopedLocalRef<jbyteArray> dataArray(env, env->NewByteArray(request_length));
4270c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (dataArray.get() == nullptr) {
42714b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes    LOG(WARNING) << "byte[] allocation failed: " << request_length;
4272f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes    env->ExceptionClear();
4273f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes    return false;
4274f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  }
4275c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  env->SetByteArrayRegion(dataArray.get(), 0, request_length,
4276c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers                          reinterpret_cast<const jbyte*>(request->data()));
4277c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  request->Skip(request_length);
4278f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes
4279f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  // Run through and find all chunks.  [Currently just find the first.]
42806a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  ScopedByteArrayRO contents(env, dataArray.get());
42814b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  if (length != request_length) {
4282ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    LOG(WARNING) << StringPrintf("bad chunk found (len=%u pktLen=%zd)", length, request_length);
4283f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes    return false;
4284f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  }
4285f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes
4286f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  // Call "private static Chunk dispatch(int type, byte[] data, int offset, int length)".
4287eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes  ScopedLocalRef<jobject> chunk(env, env->CallStaticObjectMethod(WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer,
4288eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes                                                                 WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_dispatch,
42894b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes                                                                 type, dataArray.get(), 0, length));
4290f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  if (env->ExceptionCheck()) {
4291f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes    LOG(INFO) << StringPrintf("Exception thrown by dispatcher for 0x%08x", type);
4292f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes    env->ExceptionDescribe();
4293f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes    env->ExceptionClear();
4294f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes    return false;
4295f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  }
4296f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes
4297c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (chunk.get() == nullptr) {
4298f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes    return false;
4299f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  }
4300f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes
4301f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  /*
4302f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes   * Pull the pieces out of the chunk.  We copy the results into a
4303f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes   * newly-allocated buffer that the caller can free.  We don't want to
4304f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes   * continue using the Chunk object because nothing has a reference to it.
4305f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes   *
4306f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes   * We could avoid this by returning type/data/offset/length and having
4307f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes   * the caller be aware of the object lifetime issues, but that
430881ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes   * integrates the JDWP code more tightly into the rest of the runtime, and doesn't work
4309f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes   * if we have responses for multiple chunks.
4310f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes   *
4311f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes   * So we're pretty much stuck with copying data around multiple times.
4312f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes   */
4313eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes  ScopedLocalRef<jbyteArray> replyData(env, reinterpret_cast<jbyteArray>(env->GetObjectField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_data)));
43144b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  jint offset = env->GetIntField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_offset);
4315eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes  length = env->GetIntField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_length);
4316eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes  type = env->GetIntField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_type);
4317f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes
43184dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(jdwp) << StringPrintf("DDM reply: type=0x%08x data=%p offset=%d length=%d", type, replyData.get(), offset, length);
4319c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (length == 0 || replyData.get() == nullptr) {
4320f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes    return false;
4321f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  }
4322f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes
43234b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  const int kChunkHdrLen = 8;
4324f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  uint8_t* reply = new uint8_t[length + kChunkHdrLen];
4325c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (reply == nullptr) {
4326f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes    LOG(WARNING) << "malloc failed: " << (length + kChunkHdrLen);
4327f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes    return false;
4328f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  }
4329f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  JDWP::Set4BE(reply + 0, type);
4330f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  JDWP::Set4BE(reply + 4, length);
43316a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  env->GetByteArrayRegion(replyData.get(), offset, length, reinterpret_cast<jbyte*>(reply + kChunkHdrLen));
4332f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes
4333f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  *pReplyBuf = reply;
4334f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  *pReplyLen = length + kChunkHdrLen;
4335f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes
43364b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  VLOG(jdwp) << StringPrintf("dvmHandleDdm returning type=%.4s %p len=%d", reinterpret_cast<char*>(reply), reply, length);
4337f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  return true;
4338872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
4339872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
4340a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughesvoid Dbg::DdmBroadcast(bool connect) {
43414dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(jdwp) << "Broadcasting DDM " << (connect ? "connect" : "disconnect") << "...";
434247fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes
434347fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes  Thread* self = Thread::Current();
434450b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  if (self->GetState() != kRunnable) {
434550b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    LOG(ERROR) << "DDM broadcast in thread state " << self->GetState();
434650b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    /* try anyway? */
434747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes  }
434847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes
434947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes  JNIEnv* env = self->GetJniEnv();
435047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes  jint event = connect ? 1 /*DdmServer.CONNECTED*/ : 2 /*DdmServer.DISCONNECTED*/;
4351eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes  env->CallStaticVoidMethod(WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer,
4352eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes                            WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_broadcast,
4353eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes                            event);
435447fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes  if (env->ExceptionCheck()) {
435547fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes    LOG(ERROR) << "DdmServer.broadcast " << event << " failed";
435647fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes    env->ExceptionDescribe();
435747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes    env->ExceptionClear();
435847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes  }
435947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes}
436047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes
4361872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::DdmConnected() {
4362a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  Dbg::DdmBroadcast(true);
4363872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
4364872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
4365872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::DdmDisconnected() {
4366a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  Dbg::DdmBroadcast(false);
436747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes  gDdmThreadNotification = false;
436847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes}
436947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes
437047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes/*
43718218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes * Send a notification when a thread starts, stops, or changes its name.
437247fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes *
437347fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes * Because we broadcast the full set of threads when the notifications are
437447fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes * first enabled, it's possible for "thread" to be actively executing.
437547fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes */
43768218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughesvoid Dbg::DdmSendThreadNotification(Thread* t, uint32_t type) {
437747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes  if (!gDdmThreadNotification) {
437847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes    return;
437947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes  }
438047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes
43818218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes  if (type == CHUNK_TYPE("THDE")) {
43828218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes    uint8_t buf[4];
4383d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    JDWP::Set4BE(&buf[0], t->GetThreadId());
43848218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes    Dbg::DdmSendChunk(CHUNK_TYPE("THDE"), 4, buf);
43858218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes  } else {
43868218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes    CHECK(type == CHUNK_TYPE("THCR") || type == CHUNK_TYPE("THNM")) << type;
438700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    ScopedObjectAccessUnchecked soa(Thread::Current());
4388eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    StackHandleScope<1> hs(soa.Self());
438908883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe    Handle<mirror::String> name(hs.NewHandle(t->GetThreadName()));
4390fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe    size_t char_count = (name != nullptr) ? name->GetLength() : 0;
4391fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe    const jchar* chars = (name != nullptr) ? name->GetValue() : nullptr;
4392fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe    bool is_compressed = (name != nullptr) ? name->IsCompressed() : false;
439347fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes
439421f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes    std::vector<uint8_t> bytes;
4395d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    JDWP::Append4BE(bytes, t->GetThreadId());
43963aaa37bba53d6df0265793de48b4b0b57327e57ajessicahandojo    if (is_compressed) {
43973aaa37bba53d6df0265793de48b4b0b57327e57ajessicahandojo      const uint8_t* chars_compressed = name->GetValueCompressed();
43983aaa37bba53d6df0265793de48b4b0b57327e57ajessicahandojo      JDWP::AppendUtf16CompressedBE(bytes, chars_compressed, char_count);
43993aaa37bba53d6df0265793de48b4b0b57327e57ajessicahandojo    } else {
44003aaa37bba53d6df0265793de48b4b0b57327e57ajessicahandojo      JDWP::AppendUtf16BE(bytes, chars, char_count);
44013aaa37bba53d6df0265793de48b4b0b57327e57ajessicahandojo    }
440221f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes    CHECK_EQ(bytes.size(), char_count*2 + sizeof(uint32_t)*2);
440321f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes    Dbg::DdmSendChunk(type, bytes);
440447fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes  }
440547fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes}
440647fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes
440747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughesvoid Dbg::DdmSetThreadNotification(bool enable) {
440800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Enable/disable thread notifications.
440947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes  gDdmThreadNotification = enable;
441047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes  if (enable) {
441100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    // Suspend the VM then post thread start notifications for all threads. Threads attaching will
441200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    // see a suspension in progress and block until that ends. They then post their own start
441300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    // notification.
441400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    SuspendVM();
441500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    std::list<Thread*> threads;
441650b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    Thread* self = Thread::Current();
441700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    {
441850b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers      MutexLock mu(self, *Locks::thread_list_lock_);
441900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      threads = Runtime::Current()->GetThreadList()->GetList();
442000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
442100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    {
442250b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers      ScopedObjectAccess soa(self);
442302e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      for (Thread* thread : threads) {
442402e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier        Dbg::DdmSendThreadNotification(thread, CHUNK_TYPE("THCR"));
442500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      }
442600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
442700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    ResumeVM();
442847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes  }
442947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes}
443047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes
4431a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughesvoid Dbg::PostThreadStartOrStop(Thread* t, uint32_t type) {
4432c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes  if (IsDebuggerActive()) {
44336995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz    gJdwpState->PostThreadChange(t, type == CHUNK_TYPE("THCR"));
443447fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes  }
44358218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes  Dbg::DdmSendThreadNotification(t, type);
443647fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes}
443747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes
443847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughesvoid Dbg::PostThreadStart(Thread* t) {
4439a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  Dbg::PostThreadStartOrStop(t, CHUNK_TYPE("THCR"));
444047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes}
444147fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes
444247fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughesvoid Dbg::PostThreadDeath(Thread* t) {
4443a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  Dbg::PostThreadStartOrStop(t, CHUNK_TYPE("THDE"));
4444872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
4445872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
44468218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughesvoid Dbg::DdmSendChunk(uint32_t type, size_t byte_count, const uint8_t* buf) {
4447c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  CHECK(buf != nullptr);
44483bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes  iovec vec[1];
44493bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes  vec[0].iov_base = reinterpret_cast<void*>(const_cast<uint8_t*>(buf));
44503bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes  vec[0].iov_len = byte_count;
44513bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes  Dbg::DdmSendChunkV(type, vec, 1);
4452872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
4453872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
445421f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughesvoid Dbg::DdmSendChunk(uint32_t type, const std::vector<uint8_t>& bytes) {
445521f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes  DdmSendChunk(type, bytes.size(), &bytes[0]);
445621f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes}
445721f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes
4458f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstromvoid Dbg::DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count) {
4459c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (gJdwpState == nullptr) {
44604dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "Debugger thread not active, ignoring DDM send: " << type;
44613bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes  } else {
4462cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes    gJdwpState->DdmSendChunkV(type, iov, iov_count);
44633bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes  }
4464872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
4465872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
4466ad466adf38db74a9840659626858196091151a64Mathieu ChartierJDWP::JdwpState* Dbg::GetJdwpState() {
4467ad466adf38db74a9840659626858196091151a64Mathieu Chartier  return gJdwpState;
4468ad466adf38db74a9840659626858196091151a64Mathieu Chartier}
4469ad466adf38db74a9840659626858196091151a64Mathieu Chartier
4470767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesint Dbg::DdmHandleHpifChunk(HpifWhen when) {
4471767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  if (when == HPIF_WHEN_NOW) {
44727162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes    DdmSendHeapInfo(when);
4473767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes    return true;
4474767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  }
4475767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes
4476767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  if (when != HPIF_WHEN_NEVER && when != HPIF_WHEN_NEXT_GC && when != HPIF_WHEN_EVERY_GC) {
4477767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes    LOG(ERROR) << "invalid HpifWhen value: " << static_cast<int>(when);
4478767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes    return false;
4479767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  }
4480767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes
4481767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  gDdmHpifWhen = when;
4482767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  return true;
4483767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes}
4484767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes
4485767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesbool Dbg::DdmHandleHpsgNhsgChunk(Dbg::HpsgWhen when, Dbg::HpsgWhat what, bool native) {
4486767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  if (when != HPSG_WHEN_NEVER && when != HPSG_WHEN_EVERY_GC) {
4487767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes    LOG(ERROR) << "invalid HpsgWhen value: " << static_cast<int>(when);
4488767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes    return false;
4489767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  }
4490767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes
4491767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  if (what != HPSG_WHAT_MERGED_OBJECTS && what != HPSG_WHAT_DISTINCT_OBJECTS) {
4492767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes    LOG(ERROR) << "invalid HpsgWhat value: " << static_cast<int>(what);
4493767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes    return false;
4494767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  }
4495767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes
4496767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  if (native) {
4497767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes    gDdmNhsgWhen = when;
4498767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes    gDdmNhsgWhat = what;
4499767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  } else {
4500767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes    gDdmHpsgWhen = when;
4501767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes    gDdmHpsgWhat = what;
4502767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  }
4503767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes  return true;
4504767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes}
4505767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes
45067162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughesvoid Dbg::DdmSendHeapInfo(HpifWhen reason) {
45077162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes  // If there's a one-shot 'when', reset it.
45087162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes  if (reason == gDdmHpifWhen) {
45097162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes    if (gDdmHpifWhen == HPIF_WHEN_NEXT_GC) {
45107162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes      gDdmHpifWhen = HPIF_WHEN_NEVER;
45117162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes    }
45127162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes  }
45137162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes
45147162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes  /*
45157162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes   * Chunk HPIF (client --> server)
45167162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes   *
45177162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes   * Heap Info. General information about the heap,
45187162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes   * suitable for a summary display.
45197162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes   *
45207162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes   *   [u4]: number of heaps
45217162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes   *
45227162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes   *   For each heap:
45237162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes   *     [u4]: heap ID
45247162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes   *     [u8]: timestamp in ms since Unix epoch
45257162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes   *     [u1]: capture reason (same as 'when' value from server)
45267162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes   *     [u4]: max heap size in bytes (-Xmx)
45277162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes   *     [u4]: current heap size in bytes
45287162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes   *     [u4]: current number of bytes allocated
45297162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes   *     [u4]: current number of objects allocated
45307162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes   */
45317162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes  uint8_t heap_count = 1;
45321d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  gc::Heap* heap = Runtime::Current()->GetHeap();
453321f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes  std::vector<uint8_t> bytes;
4534545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  JDWP::Append4BE(bytes, heap_count);
45357934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  JDWP::Append4BE(bytes, 1);  // Heap id (bogus; we only have one heap).
4536545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  JDWP::Append8BE(bytes, MilliTime());
4537545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  JDWP::Append1BE(bytes, reason);
45387934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  JDWP::Append4BE(bytes, heap->GetMaxMemory());  // Max allowed heap size in bytes.
45397934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  JDWP::Append4BE(bytes, heap->GetTotalMemory());  // Current heap size in bytes.
4540b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  JDWP::Append4BE(bytes, heap->GetBytesAllocated());
4541b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  JDWP::Append4BE(bytes, heap->GetObjectsAllocated());
454221f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes  CHECK_EQ(bytes.size(), 4U + (heap_count * (4 + 8 + 1 + 4 + 4 + 4 + 4)));
454321f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes  Dbg::DdmSendChunk(CHUNK_TYPE("HPIF"), bytes);
4544767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes}
4545767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes
45466a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughesenum HpsgSolidity {
45476a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  SOLIDITY_FREE = 0,
45486a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  SOLIDITY_HARD = 1,
45496a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  SOLIDITY_SOFT = 2,
45506a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  SOLIDITY_WEAK = 3,
45516a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  SOLIDITY_PHANTOM = 4,
45526a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  SOLIDITY_FINALIZABLE = 5,
45536a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  SOLIDITY_SWEEP = 6,
45546a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes};
45556a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes
45566a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughesenum HpsgKind {
45576a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  KIND_OBJECT = 0,
45586a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  KIND_CLASS_OBJECT = 1,
45596a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  KIND_ARRAY_1 = 2,
45606a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  KIND_ARRAY_2 = 3,
45616a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  KIND_ARRAY_4 = 4,
45626a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  KIND_ARRAY_8 = 5,
45636a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  KIND_UNKNOWN = 6,
45646a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  KIND_NATIVE = 7,
45656a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes};
45666a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes
45676a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes#define HPSG_PARTIAL (1<<7)
45686a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes#define HPSG_STATE(solidity, kind) ((uint8_t)((((kind) & 0x7) << 3) | ((solidity) & 0x7)))
45696a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes
457030fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogersclass HeapChunkContext {
457130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers public:
45726a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  // Maximum chunk size.  Obtain this from the formula:
45736a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  // (((maximum_heap_size / ALLOCATION_UNIT_SIZE) + 255) / 256) * 2
45746a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  HeapChunkContext(bool merge, bool native)
457530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers      : buf_(16384 - 16),
457630fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers        type_(0),
457736dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier        chunk_overhead_(0) {
45786a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes    Reset();
45796a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes    if (native) {
458030fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers      type_ = CHUNK_TYPE("NHSG");
45816a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes    } else {
458230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers      type_ = merge ? CHUNK_TYPE("HPSG") : CHUNK_TYPE("HPSO");
45836a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes    }
45846a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  }
45856a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes
45866a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  ~HeapChunkContext() {
458730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    if (p_ > &buf_[0]) {
45886a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes      Flush();
45896a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes    }
45906a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  }
45916a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes
459236dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier  void SetChunkOverhead(size_t chunk_overhead) {
459336dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier    chunk_overhead_ = chunk_overhead;
459436dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier  }
459536dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier
459636dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier  void ResetStartOfNextChunk() {
459736dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier    startOfNextMemoryChunk_ = nullptr;
459836dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier  }
459936dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier
46006a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  void EnsureHeader(const void* chunk_ptr) {
460130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    if (!needHeader_) {
46026a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes      return;
46036a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes    }
46046a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes
46056a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes    // Start a new HPSx chunk.
46067934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    JDWP::Write4BE(&p_, 1);  // Heap id (bogus; we only have one heap).
46077934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    JDWP::Write1BE(&p_, 8);  // Size of allocation unit, in bytes.
46086a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes
46097934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    JDWP::Write4BE(&p_, reinterpret_cast<uintptr_t>(chunk_ptr));  // virtual address of segment start.
46107934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    JDWP::Write4BE(&p_, 0);  // offset of this piece (relative to the virtual address).
46116a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes    // [u4]: length of piece, in allocation units
46126a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes    // We won't know this until we're done, so save the offset and stuff in a dummy value.
461330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    pieceLenField_ = p_;
461430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    JDWP::Write4BE(&p_, 0x55555555);
461530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    needHeader_ = false;
46166a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  }
46176a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes
4618bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe  void Flush() REQUIRES_SHARED(Locks::mutator_lock_) {
4619c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    if (pieceLenField_ == nullptr) {
4620d636b0623307a379e255a9aaa682c12a2acc3a92Ian Rogers      // Flush immediately post Reset (maybe back-to-back Flush). Ignore.
4621d636b0623307a379e255a9aaa682c12a2acc3a92Ian Rogers      CHECK(needHeader_);
4622d636b0623307a379e255a9aaa682c12a2acc3a92Ian Rogers      return;
4623d636b0623307a379e255a9aaa682c12a2acc3a92Ian Rogers    }
46246a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes    // Patch the "length of piece" field.
462530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    CHECK_LE(&buf_[0], pieceLenField_);
462630fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    CHECK_LE(pieceLenField_, p_);
462730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    JDWP::Set4BE(pieceLenField_, totalAllocationUnits_);
46286a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes
462930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    Dbg::DdmSendChunk(type_, p_ - &buf_[0], &buf_[0]);
46306a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes    Reset();
46316a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  }
46326a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes
4633bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  static void HeapChunkJavaCallback(void* start, void* end, size_t used_bytes, void* arg)
4634bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      REQUIRES_SHARED(Locks::heap_bitmap_lock_,
4635b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers                            Locks::mutator_lock_) {
4636bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    reinterpret_cast<HeapChunkContext*>(arg)->HeapChunkJavaCallback(start, end, used_bytes);
4637bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  }
4638bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier
4639bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  static void HeapChunkNativeCallback(void* start, void* end, size_t used_bytes, void* arg)
4640bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      REQUIRES_SHARED(Locks::mutator_lock_) {
4641bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    reinterpret_cast<HeapChunkContext*>(arg)->HeapChunkNativeCallback(start, end, used_bytes);
4642a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  }
4643a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes
46446a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes private:
4645a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  enum { ALLOCATION_UNIT_SIZE = 8 };
4646a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes
46476a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  void Reset() {
464830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    p_ = &buf_[0];
464936dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier    ResetStartOfNextChunk();
465030fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    totalAllocationUnits_ = 0;
465130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    needHeader_ = true;
4652c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    pieceLenField_ = nullptr;
46536a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  }
46546a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes
4655bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  bool IsNative() const {
4656bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    return type_ == CHUNK_TYPE("NHSG");
4657bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  }
4658bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier
4659bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  // Returns true if the object is not an empty chunk.
4660bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe  bool ProcessRecord(void* start, size_t used_bytes) REQUIRES_SHARED(Locks::mutator_lock_) {
466130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    // Note: heap call backs cannot manipulate the heap upon which they are crawling, care is taken
466230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    // in the following code not to allocate memory, by ensuring buf_ is of the correct size
466315bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    if (used_bytes == 0) {
4664bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      if (start == nullptr) {
4665bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier        // Reset for start of new heap.
4666bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier        startOfNextMemoryChunk_ = nullptr;
4667bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier        Flush();
4668bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      }
4669bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      // Only process in use memory so that free region information
4670bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      // also includes dlmalloc book keeping.
4671bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      return false;
4672a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    }
4673c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    if (startOfNextMemoryChunk_ != nullptr) {
4674bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      // Transmit any pending free memory. Native free memory of over kMaxFreeLen could be because
4675bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      // of the use of mmaps, so don't report. If not free memory then start a new segment.
4676bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      bool flush = true;
4677bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      if (start > startOfNextMemoryChunk_) {
4678bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier        const size_t kMaxFreeLen = 2 * kPageSize;
4679bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier        void* free_start = startOfNextMemoryChunk_;
4680bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier        void* free_end = start;
4681bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier        const size_t free_len =
4682bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier            reinterpret_cast<uintptr_t>(free_end) - reinterpret_cast<uintptr_t>(free_start);
4683bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier        if (!IsNative() || free_len < kMaxFreeLen) {
4684bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier          AppendChunk(HPSG_STATE(SOLIDITY_FREE, 0), free_start, free_len, IsNative());
4685bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier          flush = false;
468615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers        }
4687bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      }
4688bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      if (flush) {
4689bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier        startOfNextMemoryChunk_ = nullptr;
4690bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier        Flush();
4691bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      }
469215bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    }
4693bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    return true;
4694bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  }
4695bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier
4696bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  void HeapChunkNativeCallback(void* start, void* /*end*/, size_t used_bytes)
4697bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      REQUIRES_SHARED(Locks::mutator_lock_) {
4698bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    if (ProcessRecord(start, used_bytes)) {
4699bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      uint8_t state = ExamineNativeObject(start);
4700bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      AppendChunk(state, start, used_bytes + chunk_overhead_, true /*is_native*/);
4701bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      startOfNextMemoryChunk_ = reinterpret_cast<char*>(start) + used_bytes + chunk_overhead_;
4702bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    }
4703bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  }
4704a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes
4705bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  void HeapChunkJavaCallback(void* start, void* /*end*/, size_t used_bytes)
4706bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      REQUIRES_SHARED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
4707bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    if (ProcessRecord(start, used_bytes)) {
4708bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      // Determine the type of this chunk.
4709bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      // OLD-TODO: if context.merge, see if this chunk is different from the last chunk.
4710bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      // If it's the same, we should combine them.
4711bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      uint8_t state = ExamineJavaObject(reinterpret_cast<mirror::Object*>(start));
4712bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      AppendChunk(state, start, used_bytes + chunk_overhead_, false /*is_native*/);
4713bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      startOfNextMemoryChunk_ = reinterpret_cast<char*>(start) + used_bytes + chunk_overhead_;
4714bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    }
471515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  }
471615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers
4717bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  void AppendChunk(uint8_t state, void* ptr, size_t length, bool is_native)
4718bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      REQUIRES_SHARED(Locks::mutator_lock_) {
471915bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    // Make sure there's enough room left in the buffer.
472015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    // We need to use two bytes for every fractional 256 allocation units used by the chunk plus
472115bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    // 17 bytes for any header.
4722bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    const size_t needed = ((RoundUp(length / ALLOCATION_UNIT_SIZE, 256) / 256) * 2) + 17;
4723bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    size_t byte_left = &buf_.back() - p_;
4724bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    if (byte_left < needed) {
4725bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      if (is_native) {
47267522c741d9660a56da2dd6a8e20b8cdf01a6c333Pavel Vyssotski      // Cannot trigger memory allocation while walking native heap.
47277522c741d9660a56da2dd6a8e20b8cdf01a6c333Pavel Vyssotski        return;
47287522c741d9660a56da2dd6a8e20b8cdf01a6c333Pavel Vyssotski      }
472915bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers      Flush();
473015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    }
4731a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes
4732bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    byte_left = &buf_.back() - p_;
4733bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    if (byte_left < needed) {
473415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers      LOG(WARNING) << "Chunk is too big to transmit (chunk_len=" << length << ", "
473515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers          << needed << " bytes)";
473615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers      return;
473715bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    }
473815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    EnsureHeader(ptr);
4739a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    // Write out the chunk description.
474015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    length /= ALLOCATION_UNIT_SIZE;   // Convert to allocation units.
474115bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    totalAllocationUnits_ += length;
474215bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    while (length > 256) {
474330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers      *p_++ = state | HPSG_PARTIAL;
474430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers      *p_++ = 255;     // length - 1
474515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers      length -= 256;
4746a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    }
474730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    *p_++ = state;
474815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    *p_++ = length - 1;
47496a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  }
47506a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes
4751bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe  uint8_t ExamineNativeObject(const void* p) REQUIRES_SHARED(Locks::mutator_lock_) {
4752bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    return p == nullptr ? HPSG_STATE(SOLIDITY_FREE, 0) : HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE);
4753bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  }
4754bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier
4755bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  uint8_t ExamineJavaObject(mirror::Object* o)
4756bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      REQUIRES_SHARED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
4757c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    if (o == nullptr) {
4758a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes      return HPSG_STATE(SOLIDITY_FREE, 0);
4759a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    }
4760a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    // It's an allocated chunk. Figure out what it is.
4761bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    gc::Heap* heap = Runtime::Current()->GetHeap();
4762bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    if (!heap->IsLiveObjectLocked(o)) {
4763bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      LOG(ERROR) << "Invalid object in managed heap: " << o;
476415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers      return HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE);
476500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
47662dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Class* c = o->GetClass();
4767c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    if (c == nullptr) {
4768a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes      // The object was probably just created but hasn't been initialized yet.
4769a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes      return HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
4770a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    }
4771bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    if (!heap->IsValidObjectAddress(c)) {
477215bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers      LOG(ERROR) << "Invalid class for managed heap object: " << o << " " << c;
4773a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes      return HPSG_STATE(SOLIDITY_HARD, KIND_UNKNOWN);
4774a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    }
4775f26e1b355333cbb5b064da3b4bbf2dc450a5eb40Mathieu Chartier    if (c->GetClass() == nullptr) {
4776f26e1b355333cbb5b064da3b4bbf2dc450a5eb40Mathieu Chartier      LOG(ERROR) << "Null class of class " << c << " for object " << o;
4777f26e1b355333cbb5b064da3b4bbf2dc450a5eb40Mathieu Chartier      return HPSG_STATE(SOLIDITY_HARD, KIND_UNKNOWN);
4778f26e1b355333cbb5b064da3b4bbf2dc450a5eb40Mathieu Chartier    }
4779a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    if (c->IsClassClass()) {
4780a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes      return HPSG_STATE(SOLIDITY_HARD, KIND_CLASS_OBJECT);
47816a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes    }
4782a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    if (c->IsArrayClass()) {
4783a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes      switch (c->GetComponentSize()) {
4784a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes      case 1: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_1);
4785a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes      case 2: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_2);
4786a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes      case 4: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_4);
4787a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes      case 8: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_8);
4788a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes      }
47896a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes    }
4790a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    return HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
47916a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  }
47926a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes
479330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  std::vector<uint8_t> buf_;
479430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  uint8_t* p_;
479530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  uint8_t* pieceLenField_;
479615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  void* startOfNextMemoryChunk_;
479730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  size_t totalAllocationUnits_;
479830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  uint32_t type_;
479930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  bool needHeader_;
480036dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier  size_t chunk_overhead_;
480130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers
4802a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  DISALLOW_COPY_AND_ASSIGN(HeapChunkContext);
4803a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes};
48046a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes
480536dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartierstatic void BumpPointerSpaceCallback(mirror::Object* obj, void* arg)
4806bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
480736dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier  const size_t size = RoundUp(obj->SizeOf(), kObjectAlignment);
4808bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  HeapChunkContext::HeapChunkJavaCallback(
480936dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier      obj, reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(obj) + size), size, arg);
481036dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier}
481136dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier
48126a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughesvoid Dbg::DdmSendHeapSegments(bool native) {
4813bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  Dbg::HpsgWhen when = native ? gDdmNhsgWhen : gDdmHpsgWhen;
4814bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  Dbg::HpsgWhat what = native ? gDdmNhsgWhat : gDdmHpsgWhat;
48156a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  if (when == HPSG_WHEN_NEVER) {
48166a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes    return;
48176a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  }
48186a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  // Figure out what kind of chunks we'll be sending.
4819bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  CHECK(what == HPSG_WHAT_MERGED_OBJECTS || what == HPSG_WHAT_DISTINCT_OBJECTS)
4820bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier      << static_cast<int>(what);
48216a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes
48226a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  // First, send a heap start chunk.
48236a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  uint8_t heap_id[4];
48247934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  JDWP::Set4BE(&heap_id[0], 1);  // Heap id (bogus; we only have one heap).
48256a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  Dbg::DdmSendChunk(native ? CHUNK_TYPE("NHST") : CHUNK_TYPE("HPST"), sizeof(heap_id), heap_id);
4826cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi  Thread* self = Thread::Current();
4827cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi  Locks::mutator_lock_->AssertSharedHeld(self);
4828cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi
48296a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  // Send a series of heap segment chunks.
4830bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier  HeapChunkContext context(what == HPSG_WHAT_MERGED_OBJECTS, native);
4831a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  if (native) {
4832e6465bc8a52cfa3995b4072810cdb7ab397a7793Dimitry Ivanov    UNIMPLEMENTED(WARNING) << "Native heap inspection is not supported";
4833a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  } else {
48341d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    gc::Heap* heap = Runtime::Current()->GetHeap();
483536dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier    for (const auto& space : heap->GetContinuousSpaces()) {
483636dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier      if (space->IsDlMallocSpace()) {
48374c69d7f4df78d20c631abc5f70b811a9944854d3Mathieu Chartier        ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
483836dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier        // dlmalloc's chunk header is 2 * sizeof(size_t), but if the previous chunk is in use for an
483936dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier        // allocation then the first sizeof(size_t) may belong to it.
484036dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier        context.SetChunkOverhead(sizeof(size_t));
4841bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier        space->AsDlMallocSpace()->Walk(HeapChunkContext::HeapChunkJavaCallback, &context);
484236dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier      } else if (space->IsRosAllocSpace()) {
484336dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier        context.SetChunkOverhead(0);
48444c69d7f4df78d20c631abc5f70b811a9944854d3Mathieu Chartier        // Need to acquire the mutator lock before the heap bitmap lock with exclusive access since
48454c69d7f4df78d20c631abc5f70b811a9944854d3Mathieu Chartier        // RosAlloc's internal logic doesn't know to release and reacquire the heap bitmap lock.
4846f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier        ScopedThreadSuspension sts(self, kSuspended);
48474f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        ScopedSuspendAll ssa(__FUNCTION__);
48484f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
48494f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        space->AsRosAllocSpace()->Walk(HeapChunkContext::HeapChunkJavaCallback, &context);
485036dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier      } else if (space->IsBumpPointerSpace()) {
48514c69d7f4df78d20c631abc5f70b811a9944854d3Mathieu Chartier        ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
485236dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier        context.SetChunkOverhead(0);
485336dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier        space->AsBumpPointerSpace()->Walk(BumpPointerSpaceCallback, &context);
4854bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier        HeapChunkContext::HeapChunkJavaCallback(nullptr, nullptr, 0, &context);
48552cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi      } else if (space->IsRegionSpace()) {
48562cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi        heap->IncrementDisableMovingGC(self);
4857f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier        {
4858f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier          ScopedThreadSuspension sts(self, kSuspended);
48594f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier          ScopedSuspendAll ssa(__FUNCTION__);
4860f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier          ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
4861f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier          context.SetChunkOverhead(0);
4862f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier          space->AsRegionSpace()->Walk(BumpPointerSpaceCallback, &context);
4863f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier          HeapChunkContext::HeapChunkJavaCallback(nullptr, nullptr, 0, &context);
4864f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier        }
48652cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi        heap->DecrementDisableMovingGC(self);
486636dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier      } else {
486736dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier        UNIMPLEMENTED(WARNING) << "Not counting objects in space " << *space;
4868b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier      }
486936dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier      context.ResetStartOfNextChunk();
4870b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier    }
48714c69d7f4df78d20c631abc5f70b811a9944854d3Mathieu Chartier    ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
4872e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier    // Walk the large objects, these are not in the AllocSpace.
487336dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier    context.SetChunkOverhead(0);
4874bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier    heap->GetLargeObjectsSpace()->Walk(HeapChunkContext::HeapChunkJavaCallback, &context);
4875a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  }
48766a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes
48776a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  // Finally, send a heap end chunk.
48786a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes  Dbg::DdmSendChunk(native ? CHUNK_TYPE("NHEN") : CHUNK_TYPE("HPEN"), sizeof(heap_id), heap_id);
4879767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes}
4880767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes
4881306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstromvoid Dbg::SetAllocTrackingEnabled(bool enable) {
48828c2ff641294715864013737fdec57cdfd410270cMan Cao  gc::AllocRecordObjectMap::SetAllocTrackingEnabled(enable);
4883545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes}
4884545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
4885545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughesvoid Dbg::DumpRecentAllocations() {
488600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(Thread::Current());
4887306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom  MutexLock mu(soa.Self(), *Locks::alloc_tracker_lock_);
48888c2ff641294715864013737fdec57cdfd410270cMan Cao  if (!Runtime::Current()->GetHeap()->IsAllocTrackingEnabled()) {
4889545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes    LOG(INFO) << "Not recording tracked allocations";
4890545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes    return;
4891545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  }
48928c2ff641294715864013737fdec57cdfd410270cMan Cao  gc::AllocRecordObjectMap* records = Runtime::Current()->GetHeap()->GetAllocationRecords();
48938c2ff641294715864013737fdec57cdfd410270cMan Cao  CHECK(records != nullptr);
4894545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
48951ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  const uint16_t capped_count = CappedAllocRecordCount(records->GetRecentAllocationSize());
4896306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom  uint16_t count = capped_count;
4897545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
48988c2ff641294715864013737fdec57cdfd410270cMan Cao  LOG(INFO) << "Tracked allocations, (count=" << count << ")";
48998c2ff641294715864013737fdec57cdfd410270cMan Cao  for (auto it = records->RBegin(), end = records->REnd();
49008c2ff641294715864013737fdec57cdfd410270cMan Cao      count > 0 && it != end; count--, it++) {
4901458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier    const gc::AllocRecord* record = &it->second;
4902545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
49038c2ff641294715864013737fdec57cdfd410270cMan Cao    LOG(INFO) << StringPrintf(" Thread %-2d %6zd bytes ", record->GetTid(), record->ByteCount())
4904709b070044354d9f47641f273edacaeeb0240ab7David Sehr              << mirror::Class::PrettyClass(record->GetClass());
4905545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
49068c2ff641294715864013737fdec57cdfd410270cMan Cao    for (size_t stack_frame = 0, depth = record->GetDepth(); stack_frame < depth; ++stack_frame) {
49078c2ff641294715864013737fdec57cdfd410270cMan Cao      const gc::AllocRecordStackTraceElement& stack_element = record->StackElement(stack_frame);
49088c2ff641294715864013737fdec57cdfd410270cMan Cao      ArtMethod* m = stack_element.GetMethod();
4909709b070044354d9f47641f273edacaeeb0240ab7David Sehr      LOG(INFO) << "    " << ArtMethod::PrettyMethod(m) << " line "
4910709b070044354d9f47641f273edacaeeb0240ab7David Sehr                << stack_element.ComputeLineNumber();
4911545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes    }
4912545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
4913545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes    // pause periodically to help logcat catch up
4914545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes    if ((count % 5) == 0) {
4915545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes      usleep(40000);
4916545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes    }
4917545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  }
4918545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes}
4919545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
4920545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughesclass StringTable {
4921545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes public:
4922545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  StringTable() {
4923545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  }
4924545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
49254345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier  void Add(const std::string& str) {
49264345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier    table_.insert(str);
49274345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier  }
49284345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier
49294345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier  void Add(const char* str) {
49304345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier    table_.insert(str);
4931545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  }
4932545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
4933a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes  size_t IndexOf(const char* s) const {
493402e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier    auto it = table_.find(s);
4935a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes    if (it == table_.end()) {
4936a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes      LOG(FATAL) << "IndexOf(\"" << s << "\") failed";
4937a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes    }
4938a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes    return std::distance(table_.begin(), it);
4939545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  }
4940545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
4941a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes  size_t Size() const {
4942545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes    return table_.size();
4943545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  }
4944545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
4945a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes  void WriteTo(std::vector<uint8_t>& bytes) const {
494602e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier    for (const std::string& str : table_) {
494702e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      const char* s = str.c_str();
49486d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers      size_t s_len = CountModifiedUtf8Chars(s);
49498a35405e00ad3a722750e37c8eae1c3e1cc0afb0Christopher Ferris      std::unique_ptr<uint16_t[]> s_utf16(new uint16_t[s_len]);
49506d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers      ConvertModifiedUtf8ToUtf16(s_utf16.get(), s);
49516d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers      JDWP::AppendUtf16BE(bytes, s_utf16.get(), s_len);
4952545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes    }
4953545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  }
4954545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
4955545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes private:
4956a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes  std::set<std::string> table_;
4957545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(StringTable);
4958545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes};
4959545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
4960e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic const char* GetMethodSourceFile(ArtMethod* method)
4961bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
4962bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier  DCHECK(method != nullptr);
4963bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier  const char* source_file = method->GetDeclaringClassSourceFile();
4964280286ac8a0e3a30c68be511c8b7a0a4d62936d7Sebastien Hertz  return (source_file != nullptr) ? source_file : "";
4965280286ac8a0e3a30c68be511c8b7a0a4d62936d7Sebastien Hertz}
4966280286ac8a0e3a30c68be511c8b7a0a4d62936d7Sebastien Hertz
4967545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes/*
4968545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * The data we send to DDMS contains everything we have recorded.
4969545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes *
4970545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * Message header (all values big-endian):
4971545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (1b) message header len (to allow future expansion); includes itself
4972545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (1b) entry header len
4973545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (1b) stack frame len
4974545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) number of entries
4975545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (4b) offset to string table from start of message
4976545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) number of class name strings
4977545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) number of method name strings
4978545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) number of source file name strings
4979545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * For each entry:
4980545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes *   (4b) total allocation size
4981221229cb523f849f165fdafbf9785010963715daElliott Hughes *   (2b) thread id
4982545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes *   (2b) allocated object's class name index
4983545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes *   (1b) stack depth
4984545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes *   For each stack frame:
4985545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes *     (2b) method's class name
4986545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes *     (2b) method name
4987545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes *     (2b) method source file
4988545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes *     (2b) line number, clipped to 32767; -2 if native; -1 if no source
4989545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (xb) class name strings
4990545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (xb) method name strings
4991545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (xb) source file strings
4992545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes *
4993545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * As with other DDM traffic, strings are sent as a 4-byte length
4994545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * followed by UTF-16 data.
4995545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes *
4996545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * We send up 16-bit unsigned indexes into string tables.  In theory there
4997306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom * can be (kMaxAllocRecordStackDepth * alloc_record_max_) unique strings in
4998545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * each table, but in practice there should be far fewer.
4999545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes *
5000545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * The chief reason for using a string table here is to keep the size of
5001545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * the DDMS message to a minimum.  This is partly to make the protocol
5002545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * efficient, but also because we have to form the whole thing up all at
5003545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * once in a memory buffer.
5004545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes *
5005545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * We use separate string tables for class names, method names, and source
5006545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * files to keep the indexes small.  There will generally be no overlap
5007545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * between the contents of these tables.
5008545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes */
5009545a064aca775ba801790fced3d713d8a87bfc61Elliott HughesjbyteArray Dbg::GetRecentAllocations() {
5010cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers  if ((false)) {
5011545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes    DumpRecentAllocations();
5012545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  }
5013545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
501450b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  Thread* self = Thread::Current();
501546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier  std::vector<uint8_t> bytes;
501646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier  {
5017306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom    MutexLock mu(self, *Locks::alloc_tracker_lock_);
50188c2ff641294715864013737fdec57cdfd410270cMan Cao    gc::AllocRecordObjectMap* records = Runtime::Current()->GetHeap()->GetAllocationRecords();
50198c2ff641294715864013737fdec57cdfd410270cMan Cao    // In case this method is called when allocation tracker is disabled,
50208c2ff641294715864013737fdec57cdfd410270cMan Cao    // we should still send some data back.
50218c2ff641294715864013737fdec57cdfd410270cMan Cao    gc::AllocRecordObjectMap dummy;
50228c2ff641294715864013737fdec57cdfd410270cMan Cao    if (records == nullptr) {
50238c2ff641294715864013737fdec57cdfd410270cMan Cao      CHECK(!Runtime::Current()->GetHeap()->IsAllocTrackingEnabled());
50248c2ff641294715864013737fdec57cdfd410270cMan Cao      records = &dummy;
50258c2ff641294715864013737fdec57cdfd410270cMan Cao    }
502641656de4b6440bcd1bea5fb785f0710153b2bc68Man Cao    // We don't need to wait on the condition variable records->new_record_condition_, because this
502741656de4b6440bcd1bea5fb785f0710153b2bc68Man Cao    // function only reads the class objects, which are already marked so it doesn't change their
502841656de4b6440bcd1bea5fb785f0710153b2bc68Man Cao    // reachability.
50298c2ff641294715864013737fdec57cdfd410270cMan Cao
503046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    //
503146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    // Part 1: generate string tables.
503246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    //
503346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    StringTable class_names;
503446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    StringTable method_names;
503546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    StringTable filenames;
503646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier
50371ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    const uint16_t capped_count = CappedAllocRecordCount(records->GetRecentAllocationSize());
5038306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom    uint16_t count = capped_count;
50398c2ff641294715864013737fdec57cdfd410270cMan Cao    for (auto it = records->RBegin(), end = records->REnd();
50408c2ff641294715864013737fdec57cdfd410270cMan Cao         count > 0 && it != end; count--, it++) {
5041458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier      const gc::AllocRecord* record = &it->second;
50421ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers      std::string temp;
504341656de4b6440bcd1bea5fb785f0710153b2bc68Man Cao      class_names.Add(record->GetClassDescriptor(&temp));
50448c2ff641294715864013737fdec57cdfd410270cMan Cao      for (size_t i = 0, depth = record->GetDepth(); i < depth; i++) {
50458c2ff641294715864013737fdec57cdfd410270cMan Cao        ArtMethod* m = record->StackElement(i).GetMethod();
50468c2ff641294715864013737fdec57cdfd410270cMan Cao        class_names.Add(m->GetDeclaringClassDescriptor());
50478c2ff641294715864013737fdec57cdfd410270cMan Cao        method_names.Add(m->GetName());
50488c2ff641294715864013737fdec57cdfd410270cMan Cao        filenames.Add(GetMethodSourceFile(m));
504946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier      }
505046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    }
505146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier
50528c2ff641294715864013737fdec57cdfd410270cMan Cao    LOG(INFO) << "recent allocation records: " << capped_count;
50538c2ff641294715864013737fdec57cdfd410270cMan Cao    LOG(INFO) << "allocation records all objects: " << records->Size();
505446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier
505546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    //
505646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    // Part 2: Generate the output and store it in the buffer.
505746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    //
505846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier
505946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    // (1b) message header len (to allow future expansion); includes itself
506046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    // (1b) entry header len
506146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    // (1b) stack frame len
506246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    const int kMessageHeaderLen = 15;
506346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    const int kEntryHeaderLen = 9;
506446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    const int kStackFrameLen = 8;
506546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    JDWP::Append1BE(bytes, kMessageHeaderLen);
506646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    JDWP::Append1BE(bytes, kEntryHeaderLen);
506746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    JDWP::Append1BE(bytes, kStackFrameLen);
506846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier
506946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    // (2b) number of entries
507046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    // (4b) offset to string table from start of message
507146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    // (2b) number of class name strings
507246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    // (2b) number of method name strings
507346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    // (2b) number of source file name strings
5074306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom    JDWP::Append2BE(bytes, capped_count);
507546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    size_t string_table_offset = bytes.size();
50767934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    JDWP::Append4BE(bytes, 0);  // We'll patch this later...
507746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    JDWP::Append2BE(bytes, class_names.Size());
507846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    JDWP::Append2BE(bytes, method_names.Size());
507946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    JDWP::Append2BE(bytes, filenames.Size());
508046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier
50811ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers    std::string temp;
50828c2ff641294715864013737fdec57cdfd410270cMan Cao    count = capped_count;
50838c2ff641294715864013737fdec57cdfd410270cMan Cao    // The last "count" number of allocation records in "records" are the most recent "count" number
50848c2ff641294715864013737fdec57cdfd410270cMan Cao    // of allocations. Reverse iterate to get them. The most recent allocation is sent first.
50858c2ff641294715864013737fdec57cdfd410270cMan Cao    for (auto it = records->RBegin(), end = records->REnd();
50868c2ff641294715864013737fdec57cdfd410270cMan Cao         count > 0 && it != end; count--, it++) {
508746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier      // For each entry:
508846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier      // (4b) total allocation size
508946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier      // (2b) thread id
509046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier      // (2b) allocated object's class name index
509146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier      // (1b) stack depth
5092458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier      const gc::AllocRecord* record = &it->second;
509346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier      size_t stack_depth = record->GetDepth();
5094f832284dd847ff077577bb5712225430bbbb3b67Mathieu Chartier      size_t allocated_object_class_name_index =
509541656de4b6440bcd1bea5fb785f0710153b2bc68Man Cao          class_names.IndexOf(record->GetClassDescriptor(&temp));
5096b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi      JDWP::Append4BE(bytes, record->ByteCount());
50978c2ff641294715864013737fdec57cdfd410270cMan Cao      JDWP::Append2BE(bytes, static_cast<uint16_t>(record->GetTid()));
509846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier      JDWP::Append2BE(bytes, allocated_object_class_name_index);
509946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier      JDWP::Append1BE(bytes, stack_depth);
510046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier
510146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier      for (size_t stack_frame = 0; stack_frame < stack_depth; ++stack_frame) {
510246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier        // For each stack frame:
510346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier        // (2b) method's class name
510446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier        // (2b) method name
510546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier        // (2b) method source file
510646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier        // (2b) line number, clipped to 32767; -2 if native; -1 if no source
51078c2ff641294715864013737fdec57cdfd410270cMan Cao        ArtMethod* m = record->StackElement(stack_frame).GetMethod();
5108bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier        size_t class_name_index = class_names.IndexOf(m->GetDeclaringClassDescriptor());
5109bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier        size_t method_name_index = method_names.IndexOf(m->GetName());
5110bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier        size_t file_name_index = filenames.IndexOf(GetMethodSourceFile(m));
511146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier        JDWP::Append2BE(bytes, class_name_index);
511246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier        JDWP::Append2BE(bytes, method_name_index);
511346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier        JDWP::Append2BE(bytes, file_name_index);
51148c2ff641294715864013737fdec57cdfd410270cMan Cao        JDWP::Append2BE(bytes, record->StackElement(stack_frame).ComputeLineNumber());
5115545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes      }
5116545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes    }
5117545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
511846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    // (xb) class name strings
511946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    // (xb) method name strings
512046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    // (xb) source file strings
512146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    JDWP::Set4BE(&bytes[string_table_offset], bytes.size());
512246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    class_names.WriteTo(bytes);
512346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    method_names.WriteTo(bytes);
512446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier    filenames.WriteTo(bytes);
5125545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  }
512650b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  JNIEnv* env = self->GetJniEnv();
5127545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  jbyteArray result = env->NewByteArray(bytes.size());
5128c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (result != nullptr) {
5129545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes    env->SetByteArrayRegion(result, 0, bytes.size(), reinterpret_cast<const jbyte*>(&bytes[0]));
5130545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  }
5131545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes  return result;
5132545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes}
5133545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
5134e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu ChartierArtMethod* DeoptimizationRequest::Method() const {
513513b27842e88ccf1a42807c92daeb108e867dc4cdAndreas Gampe  return jni::DecodeArtMethod(method_);
51360ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi}
51370ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi
5138e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid DeoptimizationRequest::SetMethod(ArtMethod* m) {
513913b27842e88ccf1a42807c92daeb108e867dc4cdAndreas Gampe  method_ = jni::EncodeArtMethod(m);
51400ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi}
51410ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi
5142a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartiervoid Dbg::VisitRoots(RootVisitor* visitor) {
5143a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartier  // Visit breakpoint roots, used to prevent unloading of methods with breakpoints.
5144a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartier  ReaderMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
5145a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartier  BufferedRootVisitor<128> root_visitor(visitor, RootInfo(kRootVMInternal));
5146a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartier  for (Breakpoint& breakpoint : gBreakpoints) {
5147542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe    breakpoint.Method()->VisitRoots(root_visitor, kRuntimePointerSize);
5148a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartier  }
5149a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartier}
5150a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartier
515104bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampevoid Dbg::DbgThreadLifecycleCallback::ThreadStart(Thread* self) {
515204bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampe  Dbg::PostThreadStart(self);
515304bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampe}
515404bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampe
515504bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampevoid Dbg::DbgThreadLifecycleCallback::ThreadDeath(Thread* self) {
515604bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampe  Dbg::PostThreadDeath(self);
515704bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampe}
515804bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampe
51590f01b583c3952d0219696480654a0db8fac4b661Andreas Gampevoid Dbg::DbgClassLoadCallback::ClassLoad(Handle<mirror::Class> klass ATTRIBUTE_UNUSED) {
51600f01b583c3952d0219696480654a0db8fac4b661Andreas Gampe  // Ignore ClassLoad;
51610f01b583c3952d0219696480654a0db8fac4b661Andreas Gampe}
51620f01b583c3952d0219696480654a0db8fac4b661Andreas Gampevoid Dbg::DbgClassLoadCallback::ClassPrepare(Handle<mirror::Class> temp_klass ATTRIBUTE_UNUSED,
51630f01b583c3952d0219696480654a0db8fac4b661Andreas Gampe                                             Handle<mirror::Class> klass) {
51640f01b583c3952d0219696480654a0db8fac4b661Andreas Gampe  Dbg::PostClassPrepare(klass.Get());
51650f01b583c3952d0219696480654a0db8fac4b661Andreas Gampe}
51660f01b583c3952d0219696480654a0db8fac4b661Andreas Gampe
5167872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}  // namespace art
5168