diff options
| -rw-r--r-- | src/debugger.cc | 43 | ||||
| -rw-r--r-- | src/debugger.h | 2 | ||||
| -rw-r--r-- | src/heap.cc | 15 | ||||
| -rw-r--r-- | src/heap.h | 3 | ||||
| -rw-r--r-- | src/jdwp/jdwp_bits.h | 20 | ||||
| -rw-r--r-- | src/jdwp/jdwp_handler.cc | 2 | ||||
| -rw-r--r-- | src/jdwp/jdwp_main.cc | 17 | ||||
| -rw-r--r-- | src/jdwp/jdwp_priv.h | 3 | ||||
| -rw-r--r-- | src/utils.cc | 6 | ||||
| -rw-r--r-- | src/utils.h | 3 |
10 files changed, 80 insertions, 34 deletions
diff --git a/src/debugger.cc b/src/debugger.cc index f7e80d374e..3321d68476 100644 --- a/src/debugger.cc +++ b/src/debugger.cc @@ -233,7 +233,7 @@ void Dbg::StopJdwp() { void Dbg::GcDidFinish() { if (gDdmHpifWhen != HPIF_WHEN_NEVER) { LOG(DEBUG) << "Sending VM heap info to DDM"; - DdmSendHeapInfo(gDdmHpifWhen, false); + DdmSendHeapInfo(gDdmHpifWhen); } if (gDdmHpsgWhen != HPSG_WHEN_NEVER) { LOG(DEBUG) << "Dumping VM heap to DDM"; @@ -867,7 +867,7 @@ void Dbg::DdmSendChunkV(int type, const struct iovec* iov, int iovcnt) { int Dbg::DdmHandleHpifChunk(HpifWhen when) { if (when == HPIF_WHEN_NOW) { - DdmSendHeapInfo(when, true); + DdmSendHeapInfo(when); return true; } @@ -901,8 +901,43 @@ bool Dbg::DdmHandleHpsgNhsgChunk(Dbg::HpsgWhen when, Dbg::HpsgWhat what, bool na return true; } -void Dbg::DdmSendHeapInfo(HpifWhen reason, bool shouldLock) { - UNIMPLEMENTED(WARNING) << "reason=" << static_cast<int>(reason) << " shouldLock=" << shouldLock; +void Dbg::DdmSendHeapInfo(HpifWhen reason) { + // If there's a one-shot 'when', reset it. + if (reason == gDdmHpifWhen) { + if (gDdmHpifWhen == HPIF_WHEN_NEXT_GC) { + gDdmHpifWhen = HPIF_WHEN_NEVER; + } + } + + /* + * Chunk HPIF (client --> server) + * + * Heap Info. General information about the heap, + * suitable for a summary display. + * + * [u4]: number of heaps + * + * For each heap: + * [u4]: heap ID + * [u8]: timestamp in ms since Unix epoch + * [u1]: capture reason (same as 'when' value from server) + * [u4]: max heap size in bytes (-Xmx) + * [u4]: current heap size in bytes + * [u4]: current number of bytes allocated + * [u4]: current number of objects allocated + */ + uint8_t heap_count = 1; + std::vector<uint8_t> bytes(4 + (heap_count * (4 + 8 + 1 + 4 + 4 + 4 + 4))); + uint8_t* dst = &bytes[0]; + JDWP::Write4BE(&dst, heap_count); + JDWP::Write4BE(&dst, 1); // Heap id (bogus; we only have one heap). + JDWP::Write8BE(&dst, MilliTime()); + JDWP::Write1BE(&dst, reason); + JDWP::Write4BE(&dst, Heap::GetMaxMemory()); // Max allowed heap size in bytes. + JDWP::Write4BE(&dst, Heap::GetTotalMemory()); // Current heap size in bytes. + JDWP::Write4BE(&dst, Heap::GetBytesAllocated()); + JDWP::Write4BE(&dst, Heap::GetObjectsAllocated()); + Dbg::DdmSendChunk(CHUNK_TYPE("HPIF"), bytes.size(), &bytes[0]); } void Dbg::DdmSendHeapSegments(bool shouldLock, bool native) { diff --git a/src/debugger.h b/src/debugger.h index a818a48d53..85cc1f8fcd 100644 --- a/src/debugger.h +++ b/src/debugger.h @@ -257,7 +257,7 @@ public: }; static bool DdmHandleHpsgNhsgChunk(HpsgWhen when, HpsgWhat what, bool native); - static void DdmSendHeapInfo(HpifWhen reason, bool shouldLock); + static void DdmSendHeapInfo(HpifWhen reason); static void DdmSendHeapSegments(bool shouldLock, bool native); }; diff --git a/src/heap.cc b/src/heap.cc index 555569a7f3..9fe77508e3 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -405,18 +405,15 @@ Object* Heap::AllocateLocked(Space* space, size_t size) { } int64_t Heap::GetMaxMemory() { - UNIMPLEMENTED(WARNING); - return 0; + return maximum_size_; } int64_t Heap::GetTotalMemory() { - UNIMPLEMENTED(WARNING); - return 0; + return alloc_space_->Size(); } int64_t Heap::GetFreeMemory() { - UNIMPLEMENTED(WARNING); - return 0; + return alloc_space_->Size() - num_bytes_allocated_; } class InstanceCounter { @@ -523,14 +520,14 @@ void Heap::CollectGarbageInternal() { bool is_small = (bytes_freed > 0 && bytes_freed < 1024); size_t kib_freed = (bytes_freed > 0 ? std::max(bytes_freed/1024, 1U) : 0); - size_t footprint = alloc_space_->Size(); - size_t percentFree = 100 - static_cast<size_t>(100.0f * float(num_bytes_allocated_) / footprint); + size_t total = GetTotalMemory(); + size_t percentFree = 100 - static_cast<size_t>(100.0f * float(num_bytes_allocated_) / total); uint32_t duration = (t1 - t0)/1000/1000; if (is_verbose_gc_) { LOG(INFO) << "GC freed " << (is_small ? "<" : "") << kib_freed << "KiB, " << percentFree << "% free " - << (num_bytes_allocated_/1024) << "KiB/" << (footprint/1024) << "KiB, " + << (num_bytes_allocated_/1024) << "KiB/" << (total/1024) << "KiB, " << "paused " << duration << "ms"; } Dbg::GcDidFinish(); diff --git a/src/heap.h b/src/heap.h index 9e21272576..2e8057100f 100644 --- a/src/heap.h +++ b/src/heap.h @@ -175,6 +175,9 @@ class Heap { static void AddFinalizerReference(Object* object); + static size_t GetBytesAllocated() { return num_bytes_allocated_; } + static size_t GetObjectsAllocated() { return num_objects_allocated_; } + private: // Allocates uninitialized storage. static Object* AllocateLocked(size_t num_bytes); diff --git a/src/jdwp/jdwp_bits.h b/src/jdwp/jdwp_bits.h index 59ece0358c..3b951f9a8c 100644 --- a/src/jdwp/jdwp_bits.h +++ b/src/jdwp/jdwp_bits.h @@ -107,6 +107,26 @@ static inline void Set8BE(uint8_t* buf, uint64_t val) { *buf = (uint8_t)(val); } +static inline void Write1BE(uint8_t** dst, uint8_t value) { + Set1(*dst, value); + *dst += sizeof(value); +} + +static inline void Write2BE(uint8_t** dst, uint16_t value) { + Set2BE(*dst, value); + *dst += sizeof(value); +} + +static inline void Write4BE(uint8_t** dst, uint32_t value) { + Set4BE(*dst, value); + *dst += sizeof(value); +} + +static inline void Write8BE(uint8_t** dst, uint64_t value) { + Set8BE(*dst, value); + *dst += sizeof(value); +} + /* * Stuff a UTF-8 string into the buffer. */ diff --git a/src/jdwp/jdwp_handler.cc b/src/jdwp/jdwp_handler.cc index f408c5478f..04c4734f45 100644 --- a/src/jdwp/jdwp_handler.cc +++ b/src/jdwp/jdwp_handler.cc @@ -1806,7 +1806,7 @@ void JdwpState::ProcessRequest(const JdwpReqHeader* pHeader, const uint8_t* buf, * the initial setup. Only update if this is a non-DDMS packet. */ if (pHeader->cmdSet != kJDWPDdmCmdSet) { - QuasiAtomicSwap64(GetNowMsec(), &lastActivityWhen); + QuasiAtomicSwap64(MilliTime(), &lastActivityWhen); } /* tell the VM that GC is okay again */ diff --git a/src/jdwp/jdwp_main.cc b/src/jdwp/jdwp_main.cc index 1df0d66601..fa02895bba 100644 --- a/src/jdwp/jdwp_main.cc +++ b/src/jdwp/jdwp_main.cc @@ -412,21 +412,6 @@ Thread* JdwpState::GetDebugThread() { */ /* - * Get a notion of the current time, in milliseconds. - */ -int64_t GetNowMsec() { -#ifdef HAVE_POSIX_CLOCKS - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - return now.tv_sec * 1000LL + now.tv_nsec / 1000000LL; -#else - struct timeval now; - gettimeofday(&now, NULL); - return now.tv_sec * 1000LL + now.tv_usec / 1000LL; -#endif -} - -/* * Return the time, in milliseconds, since the last debugger activity. * * Returns -1 if no debugger is attached, or 0 if we're in the middle of @@ -447,7 +432,7 @@ int64_t JdwpState::LastDebuggerActivity() { } /* now get the current time */ - int64_t now = GetNowMsec(); + int64_t now = MilliTime(); CHECK_GT(now, last); LOG(VERBOSE) << "+++ debugger interval=" << (now - last); diff --git a/src/jdwp/jdwp_priv.h b/src/jdwp/jdwp_priv.h index 46f79b86db..45d70f85f0 100644 --- a/src/jdwp/jdwp_priv.h +++ b/src/jdwp/jdwp_priv.h @@ -83,9 +83,6 @@ private: Mutex socket_lock_; }; -/* get current time, in msec */ -int64_t GetNowMsec(); - } // namespace JDWP } // namespace art diff --git a/src/utils.cc b/src/utils.cc index 639339abf3..4c65036ce4 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -49,6 +49,12 @@ std::string GetIsoDate() { ptm->tm_hour, ptm->tm_min, ptm->tm_sec); } +uint64_t MilliTime() { + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + return static_cast<uint64_t>(now.tv_sec) * 1000LL + now.tv_nsec / 1000000LL; +} + uint64_t NanoTime() { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); diff --git a/src/utils.h b/src/utils.h index bf8191eeaa..bb307d14da 100644 --- a/src/utils.h +++ b/src/utils.h @@ -209,6 +209,9 @@ bool ReadFileToString(const std::string& file_name, std::string* result); // Returns the current date in ISO yyyy-mm-dd hh:mm:ss format. std::string GetIsoDate(); +// Returns the current time in milliseconds (using the POSIX CLOCK_MONOTONIC). +uint64_t MilliTime(); + // Returns the current time in nanoseconds (using the POSIX CLOCK_MONOTONIC). uint64_t NanoTime(); |