Adjust whitespace in hprof.
Change-Id: Ia84f3a13fa240e05fbd701bac64f5a2e95c6a97c
diff --git a/src/hprof/hprof.cc b/src/hprof/hprof.cc
index e285307..d00f6f9 100644
--- a/src/hprof/hprof.cc
+++ b/src/hprof/hprof.cc
@@ -44,168 +44,158 @@
#define kHeadSuffix "-hptemp"
// TODO: use File::WriteFully
-int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg)
-{
- while (count != 0) {
- ssize_t actual = TEMP_FAILURE_RETRY(write(fd, buf, count));
- if (actual < 0) {
- int err = errno;
- LOG(ERROR) << StringPrintf("%s: write failed: %s", logMsg, strerror(err));
- return err;
- } else if (actual != (ssize_t) count) {
- LOG(DEBUG) << StringPrintf("%s: partial write (will retry): (%d of %zd)",
- logMsg, (int) actual, count);
- buf = (const void*) (((const uint8_t*) buf) + actual);
- }
- count -= actual;
+int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg) {
+ while (count != 0) {
+ ssize_t actual = TEMP_FAILURE_RETRY(write(fd, buf, count));
+ if (actual < 0) {
+ int err = errno;
+ LOG(ERROR) << StringPrintf("%s: write failed: %s", logMsg, strerror(err));
+ return err;
+ } else if (actual != (ssize_t) count) {
+ LOG(DEBUG) << StringPrintf("%s: partial write (will retry): (%d of %zd)",
+ logMsg, (int) actual, count);
+ buf = (const void*) (((const uint8_t*) buf) + actual);
}
-
- return 0;
+ count -= actual;
+ }
+ return 0;
}
/*
* Finish up the hprof dump. Returns true on success.
*/
-bool Hprof::Finish()
-{
- /* flush the "tail" portion of the output */
- StartNewRecord(HPROF_TAG_HEAP_DUMP_END, HPROF_TIME);
- FlushCurrentRecord();
+bool Hprof::Finish() {
+ // flush the "tail" portion of the output
+ StartNewRecord(HPROF_TAG_HEAP_DUMP_END, HPROF_TIME);
+ FlushCurrentRecord();
- // Create a new Hprof for the start of the file (as opposed to this, which is the tail).
- Hprof headCtx(file_name_, fd_, true, direct_to_ddms_);
- headCtx.classes_ = classes_;
- headCtx.strings_ = strings_;
+ // create a new Hprof for the start of the file (as opposed to this, which is the tail)
+ Hprof headCtx(file_name_, fd_, true, direct_to_ddms_);
+ headCtx.classes_ = classes_;
+ headCtx.strings_ = strings_;
- LOG(INFO) << StringPrintf("hprof: dumping heap strings to \"%s\".", file_name_);
- headCtx.DumpStrings();
- headCtx.DumpClasses();
+ LOG(INFO) << StringPrintf("hprof: dumping heap strings to \"%s\".", file_name_);
+ headCtx.DumpStrings();
+ headCtx.DumpClasses();
- /* Write a dummy stack trace record so the analysis
- * tools don't freak out.
- */
- headCtx.StartNewRecord(HPROF_TAG_STACK_TRACE, HPROF_TIME);
- headCtx.current_record_.AddU4(HPROF_NULL_STACK_TRACE);
- headCtx.current_record_.AddU4(HPROF_NULL_THREAD);
- headCtx.current_record_.AddU4(0); // no frames
+ // write a dummy stack trace record so the analysis tools don't freak out
+ headCtx.StartNewRecord(HPROF_TAG_STACK_TRACE, HPROF_TIME);
+ headCtx.current_record_.AddU4(HPROF_NULL_STACK_TRACE);
+ headCtx.current_record_.AddU4(HPROF_NULL_THREAD);
+ headCtx.current_record_.AddU4(0); // no frames
- headCtx.FlushCurrentRecord();
+ headCtx.FlushCurrentRecord();
- /* flush to ensure memstream pointer and size are updated */
- fflush(headCtx.mem_fp_);
- fflush(mem_fp_);
+ // flush to ensure memstream pointer and size are updated
+ fflush(headCtx.mem_fp_);
+ fflush(mem_fp_);
- if (direct_to_ddms_) {
- /* send the data off to DDMS */
- struct iovec iov[2];
- iov[0].iov_base = headCtx.file_data_ptr_;
- iov[0].iov_len = headCtx.file_data_size_;
- iov[1].iov_base = file_data_ptr_;
- iov[1].iov_len = file_data_size_;
- Dbg::DdmSendChunkV(CHUNK_TYPE("HPDS"), iov, 2);
+ if (direct_to_ddms_) {
+ // send the data off to DDMS
+ struct iovec iov[2];
+ iov[0].iov_base = headCtx.file_data_ptr_;
+ iov[0].iov_len = headCtx.file_data_size_;
+ iov[1].iov_base = file_data_ptr_;
+ iov[1].iov_len = file_data_size_;
+ Dbg::DdmSendChunkV(CHUNK_TYPE("HPDS"), iov, 2);
+ } else {
+ // open the output file, and copy the head and tail to it.
+ CHECK_EQ(headCtx.fd_, fd_);
+
+ int outFd;
+ if (headCtx.fd_ >= 0) {
+ outFd = dup(headCtx.fd_);
+ if (outFd < 0) {
+ LOG(ERROR) << StringPrintf("dup(%d) failed: %s", headCtx.fd_, strerror(errno));
+ // continue to fail-handler below
+ }
} else {
- /*
- * Open the output file, and copy the head and tail to it.
- */
- CHECK_EQ(headCtx.fd_, fd_);
-
- int outFd;
- if (headCtx.fd_ >= 0) {
- outFd = dup(headCtx.fd_);
- if (outFd < 0) {
- LOG(ERROR) << StringPrintf("dup(%d) failed: %s", headCtx.fd_, strerror(errno));
- /* continue to fail-handler below */
- }
- } else {
- outFd = open(file_name_, O_WRONLY|O_CREAT|O_TRUNC, 0644);
- if (outFd < 0) {
- LOG(ERROR) << StringPrintf("can't open %s: %s", headCtx.file_name_, strerror(errno));
- /* continue to fail-handler below */
- }
- }
- if (outFd < 0) {
- return false;
- }
-
- int result = sysWriteFully(outFd, headCtx.file_data_ptr_,
- headCtx.file_data_size_, "hprof-head");
- result |= sysWriteFully(outFd, file_data_ptr_, file_data_size_, "hprof-tail");
- close(outFd);
- if (result != 0) {
- return false;
- }
+ outFd = open(file_name_, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if (outFd < 0) {
+ LOG(ERROR) << StringPrintf("can't open %s: %s", headCtx.file_name_, strerror(errno));
+ // continue to fail-handler below
+ }
+ }
+ if (outFd < 0) {
+ return false;
}
- /* throw out a log message for the benefit of "runhat" */
- LOG(INFO) << StringPrintf("hprof: heap dump completed (%dKB)",
- (headCtx.file_data_size_ + file_data_size_ + 1023) / 1024);
+ int result = sysWriteFully(outFd, headCtx.file_data_ptr_,
+ headCtx.file_data_size_, "hprof-head");
+ result |= sysWriteFully(outFd, file_data_ptr_, file_data_size_, "hprof-tail");
+ close(outFd);
+ if (result != 0) {
+ return false;
+ }
+ }
- return true;
+ // throw out a log message for the benefit of "runhat"
+ LOG(INFO) << StringPrintf("hprof: heap dump completed (%dKB)",
+ (headCtx.file_data_size_ + file_data_size_ + 1023) / 1024);
+
+ return true;
}
Hprof::~Hprof() {
- /* we don't own ctx->fd_, do not close */
-
- if (mem_fp_ != NULL) {
- fclose(mem_fp_);
- }
- free(current_record_.body_);
- free(file_name_);
- free(file_data_ptr_);
+ // we don't own ctx->fd_, do not close
+ if (mem_fp_ != NULL) {
+ fclose(mem_fp_);
+ }
+ free(current_record_.body_);
+ free(file_name_);
+ free(file_data_ptr_);
}
/*
* Visitor invoked on every root reference.
*/
void HprofRootVisitor(const Object* obj, void* arg) {
- CHECK(arg != NULL);
- Hprof* hprof = (Hprof*)arg;
- hprof->VisitRoot(obj);
+ CHECK(arg != NULL);
+ Hprof* hprof = (Hprof*)arg;
+ hprof->VisitRoot(obj);
}
void Hprof::VisitRoot(const Object* obj) {
- uint32_t threadId = 0; // TODO
- /*RootType */ size_t type = 0; // TODO
+ uint32_t threadId = 0; // TODO
+ /*RootType */ size_t type = 0; // TODO
- static const HprofHeapTag xlate[] = {
- HPROF_ROOT_UNKNOWN,
- HPROF_ROOT_JNI_GLOBAL,
- HPROF_ROOT_JNI_LOCAL,
- HPROF_ROOT_JAVA_FRAME,
- HPROF_ROOT_NATIVE_STACK,
- HPROF_ROOT_STICKY_CLASS,
- HPROF_ROOT_THREAD_BLOCK,
- HPROF_ROOT_MONITOR_USED,
- HPROF_ROOT_THREAD_OBJECT,
- HPROF_ROOT_INTERNED_STRING,
- HPROF_ROOT_FINALIZING,
- HPROF_ROOT_DEBUGGER,
- HPROF_ROOT_REFERENCE_CLEANUP,
- HPROF_ROOT_VM_INTERNAL,
- HPROF_ROOT_JNI_MONITOR,
- };
+ static const HprofHeapTag xlate[] = {
+ HPROF_ROOT_UNKNOWN,
+ HPROF_ROOT_JNI_GLOBAL,
+ HPROF_ROOT_JNI_LOCAL,
+ HPROF_ROOT_JAVA_FRAME,
+ HPROF_ROOT_NATIVE_STACK,
+ HPROF_ROOT_STICKY_CLASS,
+ HPROF_ROOT_THREAD_BLOCK,
+ HPROF_ROOT_MONITOR_USED,
+ HPROF_ROOT_THREAD_OBJECT,
+ HPROF_ROOT_INTERNED_STRING,
+ HPROF_ROOT_FINALIZING,
+ HPROF_ROOT_DEBUGGER,
+ HPROF_ROOT_REFERENCE_CLEANUP,
+ HPROF_ROOT_VM_INTERNAL,
+ HPROF_ROOT_JNI_MONITOR,
+ };
- CHECK_LT(type, sizeof(xlate) / sizeof(HprofHeapTag));
- if (obj == NULL) {
- return;
- }
- gc_scan_state_ = xlate[type];
- gc_thread_serial_number_ = threadId;
- MarkRootObject(obj, 0);
- gc_scan_state_ = 0;
- gc_thread_serial_number_ = 0;
+ CHECK_LT(type, sizeof(xlate) / sizeof(HprofHeapTag));
+ if (obj == NULL) {
+ return;
+ }
+ gc_scan_state_ = xlate[type];
+ gc_thread_serial_number_ = threadId;
+ MarkRootObject(obj, 0);
+ gc_scan_state_ = 0;
+ gc_thread_serial_number_ = 0;
}
/*
* Visitor invoked on every heap object.
*/
-
-static void HprofBitmapCallback(Object *obj, void *arg)
-{
- CHECK(obj != NULL);
- CHECK(arg != NULL);
- Hprof *hprof = (Hprof*)arg;
- hprof->DumpHeapObject(obj);
+static void HprofBitmapCallback(Object *obj, void *arg) {
+ CHECK(obj != NULL);
+ CHECK(arg != NULL);
+ Hprof *hprof = (Hprof*)arg;
+ hprof->DumpHeapObject(obj);
}
/*
@@ -220,22 +210,21 @@
*
* Returns 0 on success, or an error code on failure.
*/
-int DumpHeap(const char* fileName, int fd, bool directToDdms)
-{
- CHECK(fileName != NULL);
- ScopedHeapLock lock;
- ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
+int DumpHeap(const char* fileName, int fd, bool directToDdms) {
+ CHECK(fileName != NULL);
+ ScopedHeapLock lock;
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
- ThreadList* thread_list = Runtime::Current()->GetThreadList();
- thread_list->SuspendAll();
+ ThreadList* thread_list = Runtime::Current()->GetThreadList();
+ thread_list->SuspendAll();
- Hprof hprof(fileName, fd, false, directToDdms);
- Runtime::Current()->VisitRoots(HprofRootVisitor, &hprof);
- Heap::GetLiveBits()->Walk(HprofBitmapCallback, &hprof);
-//TODO: write a HEAP_SUMMARY record
- int success = hprof.Finish() ? 0 : -1;
- thread_list->ResumeAll();
- return success;
+ Hprof hprof(fileName, fd, false, directToDdms);
+ Runtime::Current()->VisitRoots(HprofRootVisitor, &hprof);
+ Heap::GetLiveBits()->Walk(HprofBitmapCallback, &hprof);
+ // TODO: write a HEAP_SUMMARY record
+ int success = hprof.Finish() ? 0 : -1;
+ thread_list->ResumeAll();
+ return success;
}
} // namespace hprof
diff --git a/src/hprof/hprof.h b/src/hprof/hprof.h
index 94852bc..38520cc 100644
--- a/src/hprof/hprof.h
+++ b/src/hprof/hprof.h
@@ -46,153 +46,142 @@
typedef std::tr1::unordered_map<std::string, size_t>::iterator StringMapIterator;
enum HprofBasicType {
- hprof_basic_object = 2,
- hprof_basic_boolean = 4,
- hprof_basic_char = 5,
- hprof_basic_float = 6,
- hprof_basic_double = 7,
- hprof_basic_byte = 8,
- hprof_basic_short = 9,
- hprof_basic_int = 10,
- hprof_basic_long = 11,
+ hprof_basic_object = 2,
+ hprof_basic_boolean = 4,
+ hprof_basic_char = 5,
+ hprof_basic_float = 6,
+ hprof_basic_double = 7,
+ hprof_basic_byte = 8,
+ hprof_basic_short = 9,
+ hprof_basic_int = 10,
+ hprof_basic_long = 11,
};
enum HprofTag {
- HPROF_TAG_STRING = 0x01,
- HPROF_TAG_LOAD_CLASS = 0x02,
- HPROF_TAG_UNLOAD_CLASS = 0x03,
- HPROF_TAG_STACK_FRAME = 0x04,
- HPROF_TAG_STACK_TRACE = 0x05,
- HPROF_TAG_ALLOC_SITES = 0x06,
- HPROF_TAG_HEAP_SUMMARY = 0x07,
- HPROF_TAG_START_THREAD = 0x0A,
- HPROF_TAG_END_THREAD = 0x0B,
- HPROF_TAG_HEAP_DUMP = 0x0C,
- HPROF_TAG_HEAP_DUMP_SEGMENT = 0x1C,
- HPROF_TAG_HEAP_DUMP_END = 0x2C,
- HPROF_TAG_CPU_SAMPLES = 0x0D,
- HPROF_TAG_CONTROL_SETTINGS = 0x0E,
+ HPROF_TAG_STRING = 0x01,
+ HPROF_TAG_LOAD_CLASS = 0x02,
+ HPROF_TAG_UNLOAD_CLASS = 0x03,
+ HPROF_TAG_STACK_FRAME = 0x04,
+ HPROF_TAG_STACK_TRACE = 0x05,
+ HPROF_TAG_ALLOC_SITES = 0x06,
+ HPROF_TAG_HEAP_SUMMARY = 0x07,
+ HPROF_TAG_START_THREAD = 0x0A,
+ HPROF_TAG_END_THREAD = 0x0B,
+ HPROF_TAG_HEAP_DUMP = 0x0C,
+ HPROF_TAG_HEAP_DUMP_SEGMENT = 0x1C,
+ HPROF_TAG_HEAP_DUMP_END = 0x2C,
+ HPROF_TAG_CPU_SAMPLES = 0x0D,
+ HPROF_TAG_CONTROL_SETTINGS = 0x0E,
};
-/* Values for the first byte of
- * HEAP_DUMP and HEAP_DUMP_SEGMENT
- * records:
- */
+// Values for the first byte of HEAP_DUMP and HEAP_DUMP_SEGMENT records:
enum HprofHeapTag {
- /* standard */
- HPROF_ROOT_UNKNOWN = 0xFF,
- HPROF_ROOT_JNI_GLOBAL = 0x01,
- HPROF_ROOT_JNI_LOCAL = 0x02,
- HPROF_ROOT_JAVA_FRAME = 0x03,
- HPROF_ROOT_NATIVE_STACK = 0x04,
- HPROF_ROOT_STICKY_CLASS = 0x05,
- HPROF_ROOT_THREAD_BLOCK = 0x06,
- HPROF_ROOT_MONITOR_USED = 0x07,
- HPROF_ROOT_THREAD_OBJECT = 0x08,
- HPROF_CLASS_DUMP = 0x20,
- HPROF_INSTANCE_DUMP = 0x21,
- HPROF_OBJECT_ARRAY_DUMP = 0x22,
- HPROF_PRIMITIVE_ARRAY_DUMP = 0x23,
+ /* standard */
+ HPROF_ROOT_UNKNOWN = 0xFF,
+ HPROF_ROOT_JNI_GLOBAL = 0x01,
+ HPROF_ROOT_JNI_LOCAL = 0x02,
+ HPROF_ROOT_JAVA_FRAME = 0x03,
+ HPROF_ROOT_NATIVE_STACK = 0x04,
+ HPROF_ROOT_STICKY_CLASS = 0x05,
+ HPROF_ROOT_THREAD_BLOCK = 0x06,
+ HPROF_ROOT_MONITOR_USED = 0x07,
+ HPROF_ROOT_THREAD_OBJECT = 0x08,
+ HPROF_CLASS_DUMP = 0x20,
+ HPROF_INSTANCE_DUMP = 0x21,
+ HPROF_OBJECT_ARRAY_DUMP = 0x22,
+ HPROF_PRIMITIVE_ARRAY_DUMP = 0x23,
- /* Android */
- HPROF_HEAP_DUMP_INFO = 0xfe,
- HPROF_ROOT_INTERNED_STRING = 0x89,
- HPROF_ROOT_FINALIZING = 0x8a, /* obsolete */
- HPROF_ROOT_DEBUGGER = 0x8b,
- HPROF_ROOT_REFERENCE_CLEANUP = 0x8c, /* obsolete */
- HPROF_ROOT_VM_INTERNAL = 0x8d,
- HPROF_ROOT_JNI_MONITOR = 0x8e,
- HPROF_UNREACHABLE = 0x90, /* obsolete */
- HPROF_PRIMITIVE_ARRAY_NODATA_DUMP = 0xc3,
+ /* Android */
+ HPROF_HEAP_DUMP_INFO = 0xfe,
+ HPROF_ROOT_INTERNED_STRING = 0x89,
+ HPROF_ROOT_FINALIZING = 0x8a, /* obsolete */
+ HPROF_ROOT_DEBUGGER = 0x8b,
+ HPROF_ROOT_REFERENCE_CLEANUP = 0x8c, /* obsolete */
+ HPROF_ROOT_VM_INTERNAL = 0x8d,
+ HPROF_ROOT_JNI_MONITOR = 0x8e,
+ HPROF_UNREACHABLE = 0x90, /* obsolete */
+ HPROF_PRIMITIVE_ARRAY_NODATA_DUMP = 0xc3,
};
-/* Represents a top-level hprof record, whose serialized
- * format is:
- *
- * uint8_t TAG: denoting the type of the record
- * uint32_t TIME: number of microseconds since the time stamp in the header
- * uint32_t LENGTH: number of bytes that follow this uint32_t field
- * and belong to this record
- * [uint8_t]* BODY: as many bytes as specified in the above uint32_t field
- */
+// Represents a top-level hprof record, whose serialized format is:
+// U1 TAG: denoting the type of the record
+// U4 TIME: number of microseconds since the time stamp in the header
+// U4 LENGTH: number of bytes that follow this uint32_t field and belong to this record
+// U1* BODY: as many bytes as specified in the above uint32_t field
class HprofRecord {
- public:
- int Flush(FILE *fp);
- int AddU1(uint8_t value);
- int AddU2(uint16_t value);
- int AddU4(uint32_t value);
- int AddU8(uint64_t value);
- int AddId(HprofObjectId value);
- int AddU1List(const uint8_t *values, size_t numValues);
- int AddU2List(const uint16_t *values, size_t numValues);
- int AddU4List(const uint32_t *values, size_t numValues);
- int AddU8List(const uint64_t *values, size_t numValues);
- int AddIdList(const HprofObjectId *values, size_t numValues);
- int AddUtf8String(const char *str);
+ public:
+ int Flush(FILE *fp);
+ int AddU1(uint8_t value);
+ int AddU2(uint16_t value);
+ int AddU4(uint32_t value);
+ int AddU8(uint64_t value);
+ int AddId(HprofObjectId value);
+ int AddU1List(const uint8_t *values, size_t numValues);
+ int AddU2List(const uint16_t *values, size_t numValues);
+ int AddU4List(const uint32_t *values, size_t numValues);
+ int AddU8List(const uint64_t *values, size_t numValues);
+ int AddIdList(const HprofObjectId *values, size_t numValues);
+ int AddUtf8String(const char *str);
- unsigned char *body_;
- uint32_t time_;
- uint32_t length_;
- size_t alloc_length_;
- uint8_t tag_;
- bool dirty_;
+ unsigned char *body_;
+ uint32_t time_;
+ uint32_t length_;
+ size_t alloc_length_;
+ uint8_t tag_;
+ bool dirty_;
};
enum HprofHeapId {
- HPROF_HEAP_DEFAULT = 0,
- HPROF_HEAP_ZYGOTE = 'Z',
- HPROF_HEAP_APP = 'A'
+ HPROF_HEAP_DEFAULT = 0,
+ HPROF_HEAP_ZYGOTE = 'Z',
+ HPROF_HEAP_APP = 'A'
};
class Hprof {
- public:
- Hprof(const char *outputFileName, int fd, bool writeHeader, bool directToDdms);
- ~Hprof();
+ public:
+ Hprof(const char *outputFileName, int fd, bool writeHeader, bool directToDdms);
+ ~Hprof();
- void VisitRoot(const Object* obj);
- int DumpHeapObject(const Object *obj);
- bool Finish();
+ void VisitRoot(const Object* obj);
+ int DumpHeapObject(const Object *obj);
+ bool Finish();
- private:
- int DumpClasses();
- int DumpStrings();
- int StartNewRecord(uint8_t tag, uint32_t time);
- int FlushCurrentRecord();
- int MarkRootObject(const Object *obj, jobject jniObj);
- HprofClassObjectId LookupClassId(Class* clazz);
- HprofStringId LookupStringId(String* string);
- HprofStringId LookupStringId(const char* string);
- HprofStringId LookupStringId(std::string string);
- HprofStringId LookupClassNameId(Class* clazz);
+ private:
+ int DumpClasses();
+ int DumpStrings();
+ int StartNewRecord(uint8_t tag, uint32_t time);
+ int FlushCurrentRecord();
+ int MarkRootObject(const Object *obj, jobject jniObj);
+ HprofClassObjectId LookupClassId(Class* clazz);
+ HprofStringId LookupStringId(String* string);
+ HprofStringId LookupStringId(const char* string);
+ HprofStringId LookupStringId(std::string string);
+ HprofStringId LookupClassNameId(Class* clazz);
- /* current_record_ *must* be first so that we
- * can cast from a context to a record.
- */
- HprofRecord current_record_;
+ // current_record_ *must* be first so that we can cast from a context to a record.
+ HprofRecord current_record_;
- uint32_t gc_thread_serial_number_;
- uint8_t gc_scan_state_;
- HprofHeapId current_heap_; // which heap we're currently emitting
- size_t objects_in_segment_;
+ uint32_t gc_thread_serial_number_;
+ uint8_t gc_scan_state_;
+ HprofHeapId current_heap_; // which heap we're currently emitting
+ size_t objects_in_segment_;
- /*
- * If direct_to_ddms_ is set, "file_name_" and "fd" will be ignored.
- * Otherwise, "file_name_" must be valid, though if "fd" >= 0 it will
- * only be used for debug messages.
- */
- bool direct_to_ddms_;
- char *file_name_;
- char *file_data_ptr_; // for open_memstream
- size_t file_data_size_; // for open_memstream
- FILE *mem_fp_;
- int fd_;
+ // If direct_to_ddms_ is set, "file_name_" and "fd" will be ignored.
+ // Otherwise, "file_name_" must be valid, though if "fd" >= 0 it will
+ // only be used for debug messages.
+ bool direct_to_ddms_;
+ char *file_name_;
+ char *file_data_ptr_; // for open_memstream
+ size_t file_data_size_; // for open_memstream
+ FILE *mem_fp_;
+ int fd_;
- mutable Mutex classes_lock_;
- ClassSet classes_;
+ mutable Mutex classes_lock_;
+ ClassSet classes_;
- size_t next_string_id_;
- mutable Mutex strings_lock_;
- StringMap strings_;
+ size_t next_string_id_;
+ mutable Mutex strings_lock_;
+ StringMap strings_;
};
int DumpHeap(const char* fileName, int fd, bool directToDdms);
diff --git a/src/hprof/hprof_class.cc b/src/hprof/hprof_class.cc
index ebedc2d..4286d29 100644
--- a/src/hprof/hprof_class.cc
+++ b/src/hprof/hprof_class.cc
@@ -27,61 +27,53 @@
namespace hprof {
HprofStringId Hprof::LookupClassNameId(Class* clazz) {
- return LookupStringId(PrettyDescriptor(clazz->GetDescriptor()));
+ return LookupStringId(PrettyDescriptor(clazz->GetDescriptor()));
}
HprofClassObjectId Hprof::LookupClassId(Class* clazz) {
- if (clazz == NULL) {
- /* Someone's probably looking up the superclass
- * of java.lang.Object or of a primitive class.
- */
- return (HprofClassObjectId)0;
- }
+ if (clazz == NULL) {
+ // clazz is the superclass of java.lang.Object or a primitive
+ return (HprofClassObjectId)0;
+ }
- MutexLock mu(classes_lock_);
+ MutexLock mu(classes_lock_);
- std::pair<ClassSetIterator, bool> result = classes_.insert(clazz);
- Class* present = *result.first;
+ std::pair<ClassSetIterator, bool> result = classes_.insert(clazz);
+ Class* present = *result.first;
- // Make sure that we've assigned a string ID for this class' name
- LookupClassNameId(clazz);
+ // Make sure that we've assigned a string ID for this class' name
+ LookupClassNameId(clazz);
- CHECK_EQ(present, clazz);
- return (HprofStringId) present;
+ CHECK_EQ(present, clazz);
+ return (HprofStringId) present;
}
int Hprof::DumpClasses() {
- MutexLock mu(classes_lock_);
+ MutexLock mu(classes_lock_);
+ HprofRecord *rec = ¤t_record_;
+ uint32_t nextSerialNumber = 1;
- HprofRecord *rec = ¤t_record_;
+ for (ClassSetIterator it = classes_.begin(); it != classes_.end(); ++it) {
+ Class* clazz = *it;
+ CHECK(clazz != NULL);
- uint32_t nextSerialNumber = 1;
-
- for (ClassSetIterator it = classes_.begin(); it != classes_.end(); ++it) {
- Class* clazz = *it;
- CHECK(clazz != NULL);
-
- int err = StartNewRecord(HPROF_TAG_LOAD_CLASS, HPROF_TIME);
- if (err != 0) {
- return err;
- }
-
- /* LOAD CLASS format:
- *
- * uint32_t: class serial number (always > 0)
- * ID: class object ID
- * uint32_t: stack trace serial number
- * ID: class name string ID
- *
- * We use the address of the class object structure as its ID.
- */
- rec->AddU4(nextSerialNumber++);
- rec->AddId((HprofClassObjectId) clazz);
- rec->AddU4(HPROF_NULL_STACK_TRACE);
- rec->AddId(LookupClassNameId(clazz));
+ int err = StartNewRecord(HPROF_TAG_LOAD_CLASS, HPROF_TIME);
+ if (err != 0) {
+ return err;
}
- return 0;
+ // LOAD CLASS format:
+ // U4: class serial number (always > 0)
+ // ID: class object ID. We use the address of the class object structure as its ID.
+ // U4: stack trace serial number
+ // ID: class name string ID
+ rec->AddU4(nextSerialNumber++);
+ rec->AddId((HprofClassObjectId) clazz);
+ rec->AddU4(HPROF_NULL_STACK_TRACE);
+ rec->AddId(LookupClassNameId(clazz));
+ }
+
+ return 0;
}
} // namespace hprof
diff --git a/src/hprof/hprof_heap.cc b/src/hprof/hprof_heap.cc
index 84168e3..0b63e65 100644
--- a/src/hprof/hprof_heap.cc
+++ b/src/hprof/hprof_heap.cc
@@ -25,192 +25,172 @@
namespace hprof {
-/* Set DUMP_PRIM_DATA to 1 if you want to include the contents
- * of primitive arrays (byte arrays, character arrays, etc.)
- * in heap dumps. This can be a large amount of data.
- */
+// Set DUMP_PRIM_DATA to 1 if you want to include the contents
+// of primitive arrays (byte arrays, character arrays, etc.)
+// in heap dumps. This can be a large amount of data.
#define DUMP_PRIM_DATA 1
#define OBJECTS_PER_SEGMENT ((size_t)128)
#define BYTES_PER_SEGMENT ((size_t)4096)
-/* The static field-name for the synthetic object generated to account
- * for class Static overhead.
- */
+// The static field-name for the synthetic object generated to account
+// for class static overhead.
#define STATIC_OVERHEAD_NAME "$staticOverhead"
-/* The ID for the synthetic object generated to account for class
- * Static overhead.
- */
+// The ID for the synthetic object generated to account for class static overhead.
#define CLASS_STATICS_ID(clazz) ((HprofObjectId)(((uint32_t)(clazz)) | 1))
-static HprofBasicType signatureToBasicTypeAndSize(const char *sig, size_t *sizeOut)
-{
- char c = sig[0];
- HprofBasicType ret;
- size_t size;
+static HprofBasicType signatureToBasicTypeAndSize(const char *sig, size_t *sizeOut) {
+ char c = sig[0];
+ HprofBasicType ret;
+ size_t size;
- switch (c) {
- case '[':
- case 'L': ret = hprof_basic_object; size = 4; break;
- case 'Z': ret = hprof_basic_boolean; size = 1; break;
- case 'C': ret = hprof_basic_char; size = 2; break;
- case 'F': ret = hprof_basic_float; size = 4; break;
- case 'D': ret = hprof_basic_double; size = 8; break;
- case 'B': ret = hprof_basic_byte; size = 1; break;
- case 'S': ret = hprof_basic_short; size = 2; break;
- default: CHECK(false);
- case 'I': ret = hprof_basic_int; size = 4; break;
- case 'J': ret = hprof_basic_long; size = 8; break;
- }
+ switch (c) {
+ case '[':
+ case 'L': ret = hprof_basic_object; size = 4; break;
+ case 'Z': ret = hprof_basic_boolean; size = 1; break;
+ case 'C': ret = hprof_basic_char; size = 2; break;
+ case 'F': ret = hprof_basic_float; size = 4; break;
+ case 'D': ret = hprof_basic_double; size = 8; break;
+ case 'B': ret = hprof_basic_byte; size = 1; break;
+ case 'S': ret = hprof_basic_short; size = 2; break;
+ default: CHECK(false);
+ case 'I': ret = hprof_basic_int; size = 4; break;
+ case 'J': ret = hprof_basic_long; size = 8; break;
+ }
- if (sizeOut != NULL) {
- *sizeOut = size;
- }
+ if (sizeOut != NULL) {
+ *sizeOut = size;
+ }
- return ret;
+ return ret;
}
-static HprofBasicType primitiveToBasicTypeAndSize(Primitive::Type prim,
- size_t *sizeOut)
-{
- HprofBasicType ret;
- size_t size;
+static HprofBasicType primitiveToBasicTypeAndSize(Primitive::Type prim, size_t *sizeOut) {
+ HprofBasicType ret;
+ size_t size;
- switch (prim) {
- case Primitive::kPrimBoolean: ret = hprof_basic_boolean; size = 1; break;
- case Primitive::kPrimChar: ret = hprof_basic_char; size = 2; break;
- case Primitive::kPrimFloat: ret = hprof_basic_float; size = 4; break;
- case Primitive::kPrimDouble: ret = hprof_basic_double; size = 8; break;
- case Primitive::kPrimByte: ret = hprof_basic_byte; size = 1; break;
- case Primitive::kPrimShort: ret = hprof_basic_short; size = 2; break;
- default: CHECK(false);
- case Primitive::kPrimInt: ret = hprof_basic_int; size = 4; break;
- case Primitive::kPrimLong: ret = hprof_basic_long; size = 8; break;
- }
+ switch (prim) {
+ case Primitive::kPrimBoolean: ret = hprof_basic_boolean; size = 1; break;
+ case Primitive::kPrimChar: ret = hprof_basic_char; size = 2; break;
+ case Primitive::kPrimFloat: ret = hprof_basic_float; size = 4; break;
+ case Primitive::kPrimDouble: ret = hprof_basic_double; size = 8; break;
+ case Primitive::kPrimByte: ret = hprof_basic_byte; size = 1; break;
+ case Primitive::kPrimShort: ret = hprof_basic_short; size = 2; break;
+ default: CHECK(false);
+ case Primitive::kPrimInt: ret = hprof_basic_int; size = 4; break;
+ case Primitive::kPrimLong: ret = hprof_basic_long; size = 8; break;
+ }
- if (sizeOut != NULL) {
- *sizeOut = size;
- }
+ if (sizeOut != NULL) {
+ *sizeOut = size;
+ }
- return ret;
+ return ret;
}
-/* Always called when marking objects, but only does
- * something when ctx->gc_scan_state_ is non-zero, which is usually
- * only true when marking the root set or unreachable
- * objects. Used to add rootset references to obj.
- */
-int Hprof::MarkRootObject(const Object *obj, jobject jniObj)
-{
- HprofRecord *rec = ¤t_record_;
- int err; // TODO: we may return this uninitialized
- HprofHeapTag heapTag = (HprofHeapTag)gc_scan_state_;
+// Always called when marking objects, but only does
+// something when ctx->gc_scan_state_ is non-zero, which is usually
+// only true when marking the root set or unreachable
+// objects. Used to add rootset references to obj.
+int Hprof::MarkRootObject(const Object *obj, jobject jniObj) {
+ HprofRecord *rec = ¤t_record_;
+ int err; // TODO: we may return this uninitialized
+ HprofHeapTag heapTag = (HprofHeapTag)gc_scan_state_;
- if (heapTag == 0) {
- return 0;
- }
+ if (heapTag == 0) {
+ return 0;
+ }
- if (objects_in_segment_ >= OBJECTS_PER_SEGMENT || rec->length_ >= BYTES_PER_SEGMENT) {
- // This flushes the old segment and starts a new one.
- StartNewRecord(HPROF_TAG_HEAP_DUMP_SEGMENT, HPROF_TIME);
- objects_in_segment_ = 0;
- }
+ if (objects_in_segment_ >= OBJECTS_PER_SEGMENT || rec->length_ >= BYTES_PER_SEGMENT) {
+ // This flushes the old segment and starts a new one.
+ StartNewRecord(HPROF_TAG_HEAP_DUMP_SEGMENT, HPROF_TIME);
+ objects_in_segment_ = 0;
+ }
- switch (heapTag) {
- // ID: object ID
- case HPROF_ROOT_UNKNOWN:
- case HPROF_ROOT_STICKY_CLASS:
- case HPROF_ROOT_MONITOR_USED:
- case HPROF_ROOT_INTERNED_STRING:
- case HPROF_ROOT_FINALIZING:
- case HPROF_ROOT_DEBUGGER:
- case HPROF_ROOT_REFERENCE_CLEANUP:
- case HPROF_ROOT_VM_INTERNAL:
- rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
- break;
+ switch (heapTag) {
+ // ID: object ID
+ case HPROF_ROOT_UNKNOWN:
+ case HPROF_ROOT_STICKY_CLASS:
+ case HPROF_ROOT_MONITOR_USED:
+ case HPROF_ROOT_INTERNED_STRING:
+ case HPROF_ROOT_FINALIZING:
+ case HPROF_ROOT_DEBUGGER:
+ case HPROF_ROOT_REFERENCE_CLEANUP:
+ case HPROF_ROOT_VM_INTERNAL:
+ rec->AddU1(heapTag);
+ rec->AddId((HprofObjectId)obj);
+ break;
- /* ID: object ID
- * ID: JNI global ref ID
- */
- case HPROF_ROOT_JNI_GLOBAL:
- rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
- rec->AddId((HprofId)jniObj);
- break;
+ // ID: object ID
+ // ID: JNI global ref ID
+ case HPROF_ROOT_JNI_GLOBAL:
+ rec->AddU1(heapTag);
+ rec->AddId((HprofObjectId)obj);
+ rec->AddId((HprofId)jniObj);
+ break;
- /* ID: object ID
- * uint32_t: thread serial number
- * uint32_t: frame number in stack trace (-1 for empty)
- */
- case HPROF_ROOT_JNI_LOCAL:
- case HPROF_ROOT_JNI_MONITOR:
- case HPROF_ROOT_JAVA_FRAME:
- rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
- rec->AddU4(gc_thread_serial_number_);
- rec->AddU4((uint32_t)-1);
- break;
+ // ID: object ID
+ // U4: thread serial number
+ // U4: frame number in stack trace (-1 for empty)
+ case HPROF_ROOT_JNI_LOCAL:
+ case HPROF_ROOT_JNI_MONITOR:
+ case HPROF_ROOT_JAVA_FRAME:
+ rec->AddU1(heapTag);
+ rec->AddId((HprofObjectId)obj);
+ rec->AddU4(gc_thread_serial_number_);
+ rec->AddU4((uint32_t)-1);
+ break;
- /* ID: object ID
- * uint32_t: thread serial number
- */
- case HPROF_ROOT_NATIVE_STACK:
- case HPROF_ROOT_THREAD_BLOCK:
- rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
- rec->AddU4(gc_thread_serial_number_);
- break;
+ // ID: object ID
+ // U4: thread serial number
+ case HPROF_ROOT_NATIVE_STACK:
+ case HPROF_ROOT_THREAD_BLOCK:
+ rec->AddU1(heapTag);
+ rec->AddId((HprofObjectId)obj);
+ rec->AddU4(gc_thread_serial_number_);
+ break;
- /* ID: thread object ID
- * uint32_t: thread serial number
- * uint32_t: stack trace serial number
- */
- case HPROF_ROOT_THREAD_OBJECT:
- rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
- rec->AddU4(gc_thread_serial_number_);
- rec->AddU4((uint32_t)-1); //xxx
- break;
+ // ID: thread object ID
+ // U4: thread serial number
+ // U4: stack trace serial number
+ case HPROF_ROOT_THREAD_OBJECT:
+ rec->AddU1(heapTag);
+ rec->AddId((HprofObjectId)obj);
+ rec->AddU4(gc_thread_serial_number_);
+ rec->AddU4((uint32_t)-1); //xxx
+ break;
- default:
- err = 0;
- break;
- }
+ default:
+ err = 0;
+ break;
+ }
- objects_in_segment_++;
-
- return err;
+ objects_in_segment_++;
+ return err;
}
-static int stackTraceSerialNumber(const void *obj)
-{
- return HPROF_NULL_STACK_TRACE;
+static int stackTraceSerialNumber(const void *obj) {
+ return HPROF_NULL_STACK_TRACE;
}
int Hprof::DumpHeapObject(const Object* obj) {
- Class* clazz;
HprofRecord *rec = ¤t_record_;
-
HprofHeapId desiredHeap = false ? HPROF_HEAP_ZYGOTE : HPROF_HEAP_APP; // TODO: zygote objects?
if (objects_in_segment_ >= OBJECTS_PER_SEGMENT || rec->length_ >= BYTES_PER_SEGMENT) {
- /* This flushes the old segment and starts a new one.
- */
+ // This flushes the old segment and starts a new one.
StartNewRecord(HPROF_TAG_HEAP_DUMP_SEGMENT, HPROF_TIME);
objects_in_segment_ = 0;
- /* Starting a new HEAP_DUMP resets the heap to default.
- */
+ // Starting a new HEAP_DUMP resets the heap to default.
current_heap_ = HPROF_HEAP_DEFAULT;
}
if (desiredHeap != current_heap_) {
HprofStringId nameId;
- /* This object is in a different heap than the current one.
- * Emit a HEAP_DUMP_INFO tag to change heaps.
- */
+ // This object is in a different heap than the current one.
+ // Emit a HEAP_DUMP_INFO tag to change heaps.
rec->AddU1(HPROF_HEAP_DUMP_INFO);
rec->AddU4((uint32_t)desiredHeap); // uint32_t: heap id
switch (desiredHeap) {
@@ -221,7 +201,7 @@
nameId = LookupStringId("zygote");
break;
default:
- /* Internal error. */
+ // Internal error
LOG(ERROR) << "Unexpected desiredHeap";
nameId = LookupStringId("<ILLEGAL>");
break;
@@ -230,25 +210,21 @@
current_heap_ = desiredHeap;
}
- clazz = obj->GetClass();
-
+ Class* clazz = obj->GetClass();
if (clazz == NULL) {
- /* This object will bother HprofReader, because it has a NULL
- * class, so just don't dump it. It could be
- * gDvm.unlinkedJavaLangClass or it could be an object just
- * allocated which hasn't been initialized yet.
- */
+ // This object will bother HprofReader, because it has a NULL
+ // class, so just don't dump it. It could be
+ // gDvm.unlinkedJavaLangClass or it could be an object just
+ // allocated which hasn't been initialized yet.
} else {
if (obj->IsClass()) {
Class* thisClass = (Class*)obj;
- /* obj is a ClassObject.
- */
+ // obj is a ClassObject.
size_t sFieldCount = thisClass->NumStaticFields();
if (sFieldCount != 0) {
int byteLength = sFieldCount*sizeof(JValue); // TODO bogus; fields are packed
- /* Create a byte array to reflect the allocation of the
- * StaticField array at the end of this class.
- */
+ // Create a byte array to reflect the allocation of the
+ // StaticField array at the end of this class.
rec->AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
rec->AddId(CLASS_STATICS_ID(obj));
rec->AddU4(stackTraceSerialNumber(obj));
@@ -269,9 +245,8 @@
rec->AddId((HprofId)0); // reserved
rec->AddId((HprofId)0); // reserved
if (obj->IsClassClass()) {
- // ClassObjects have their static fields appended, so
- // aren't all the same size. But they're at least this
- // size.
+ // ClassObjects have their static fields appended, so aren't all the same size.
+ // But they're at least this size.
rec->AddU4(sizeof(Class)); // instance size
} else if (thisClass->IsArrayClass() || thisClass->IsPrimitive()) {
rec->AddU4(0);
@@ -279,10 +254,9 @@
rec->AddU4(thisClass->GetObjectSize()); // instance size
}
- rec->AddU2(0); // empty const pool
+ rec->AddU2(0); // empty const pool
- /* Static fields
- */
+ // Static fields
if (sFieldCount == 0) {
rec->AddU2((uint16_t)0);
} else {
@@ -312,8 +286,7 @@
}
}
- /* Instance fields for this class (no superclass fields)
- */
+ // Instance fields for this class (no superclass fields)
int iFieldCount = thisClass->IsObjectClass() ? 0 : thisClass->NumInstanceFields();
rec->AddU2((uint16_t)iFieldCount);
for (int i = 0; i < iFieldCount; ++i) {
@@ -327,8 +300,7 @@
uint32_t length = aobj->GetLength();
if (obj->IsObjectArray()) {
- /* obj is an object array.
- */
+ // obj is an object array.
rec->AddU1(HPROF_OBJECT_ARRAY_DUMP);
rec->AddId((HprofObjectId)obj);
@@ -336,15 +308,13 @@
rec->AddU4(length);
rec->AddId(LookupClassId(clazz));
- /* Dump the elements, which are always objects or NULL.
- */
+ // Dump the elements, which are always objects or NULL.
rec->AddIdList((const HprofObjectId *)aobj->GetRawData(), length);
} else {
size_t size;
HprofBasicType t = primitiveToBasicTypeAndSize(clazz->GetComponentType()->GetPrimitiveType(), &size);
- /* obj is a primitive array.
- */
+ // obj is a primitive array.
#if DUMP_PRIM_DATA
rec->AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
#else
@@ -357,8 +327,7 @@
rec->AddU1(t);
#if DUMP_PRIM_DATA
- /* Dump the raw, packed element values.
- */
+ // Dump the raw, packed element values.
if (size == 1) {
rec->AddU1List((const uint8_t *)aobj->GetRawData(), length);
} else if (size == 2) {
@@ -372,24 +341,19 @@
}
} else {
- /* obj is an instance object.
- */
+ // obj is an instance object.
rec->AddU1(HPROF_INSTANCE_DUMP);
rec->AddId((HprofObjectId)obj);
rec->AddU4(stackTraceSerialNumber(obj));
rec->AddId(LookupClassId(clazz));
- /* Reserve some space for the length of the instance
- * data, which we won't know until we're done writing
- * it.
- */
+ // Reserve some space for the length of the instance data, which we won't
+ // know until we're done writing it.
size_t sizePatchOffset = rec->length_;
rec->AddU4(0x77777777);
- /* Write the instance data; fields for this
- * class, followed by super class fields, and so on.
- * Don't write the klass or monitor fields of Object.class.
- */
+ // Write the instance data; fields for this class, followed by super class fields,
+ // and so on. Don't write the klass or monitor fields of Object.class.
const Class* sclass = clazz;
while (!sclass->IsObjectClass()) {
int ifieldCount = sclass->NumInstanceFields();
@@ -413,8 +377,7 @@
sclass = sclass->GetSuperClass();
}
- /* Patch the instance field length.
- */
+ // Patch the instance field length.
size_t savedLen = rec->length_;
rec->length_ = sizePatchOffset;
rec->AddU4(savedLen - (sizePatchOffset + 4));
@@ -423,7 +386,6 @@
}
objects_in_segment_++;
-
return 0;
}
diff --git a/src/hprof/hprof_output.cc b/src/hprof/hprof_output.cc
index 012bfdd..3e26468 100644
--- a/src/hprof/hprof_output.cc
+++ b/src/hprof/hprof_output.cc
@@ -81,255 +81,211 @@
classes_lock_("hprof classes"),
next_string_id_(0x400000),
strings_lock_("hprof strings") {
- /*
- * Have to do this here, because it must happen after we
- * memset the struct (want to treat file_data_ptr_/file_data_size_
- * as read-only while the file is open).
- */
- FILE *fp = open_memstream(&file_data_ptr_, &file_data_size_);
- if (fp == NULL) {
- /* not expected */
- LOG(ERROR) << StringPrintf("hprof: open_memstream failed: %s", strerror(errno));
- CHECK(false);
+ // Have to do this here, because it must happen after we
+ // memset the struct (want to treat file_data_ptr_/file_data_size_
+ // as read-only while the file is open).
+ FILE *fp = open_memstream(&file_data_ptr_, &file_data_size_);
+ if (fp == NULL) {
+ // not expected
+ LOG(ERROR) << StringPrintf("hprof: open_memstream failed: %s", strerror(errno));
+ CHECK(false);
+ }
+
+ direct_to_ddms_ = directToDdms;
+ file_name_ = strdup(outputFileName);
+ mem_fp_ = fp;
+ fd_ = fd;
+
+ current_record_.alloc_length_ = 128;
+ current_record_.body_ = (unsigned char *)malloc(current_record_.alloc_length_);
+ // TODO check for/return an error
+
+ if (writeHeader) {
+ char magic[] = HPROF_MAGIC_STRING;
+ unsigned char buf[4];
+
+ // Write the file header.
+ // U1: NUL-terminated magic string.
+ fwrite(magic, 1, sizeof(magic), fp);
+
+ // U4: size of identifiers. We're using addresses as IDs, so make sure a pointer fits.
+ U4_TO_BUF_BE(buf, 0, sizeof(void *));
+ fwrite(buf, 1, sizeof(uint32_t), fp);
+
+ // The current time, in milliseconds since 0:00 GMT, 1/1/70.
+ struct timeval now;
+ uint64_t nowMs;
+ if (gettimeofday(&now, NULL) < 0) {
+ nowMs = 0;
+ } else {
+ nowMs = (uint64_t)now.tv_sec * 1000 + now.tv_usec / 1000;
}
- direct_to_ddms_ = directToDdms;
- file_name_ = strdup(outputFileName);
- mem_fp_ = fp;
- fd_ = fd;
+ // U4: high word of the 64-bit time.
+ U4_TO_BUF_BE(buf, 0, (uint32_t)(nowMs >> 32));
+ fwrite(buf, 1, sizeof(uint32_t), fp);
- current_record_.alloc_length_ = 128;
- current_record_.body_ = (unsigned char *)malloc(current_record_.alloc_length_);
-//xxx check for/return an error
+ // U4: low word of the 64-bit time.
+ U4_TO_BUF_BE(buf, 0, (uint32_t)(nowMs & 0xffffffffULL));
+ fwrite(buf, 1, sizeof(uint32_t), fp); //xxx fix the time
+ }
+}
- if (writeHeader) {
- char magic[] = HPROF_MAGIC_STRING;
- unsigned char buf[4];
- struct timeval now;
- uint64_t nowMs;
+int HprofRecord::Flush(FILE *fp) {
+ if (dirty_) {
+ unsigned char headBuf[sizeof (uint8_t) + 2 * sizeof (uint32_t)];
- /* Write the file header.
- *
- * [uint8_t]*: NUL-terminated magic string.
- */
- fwrite(magic, 1, sizeof(magic), fp);
+ headBuf[0] = tag_;
+ U4_TO_BUF_BE(headBuf, 1, time_);
+ U4_TO_BUF_BE(headBuf, 5, length_);
- /* uint32_t: size of identifiers. We're using addresses
- * as IDs, so make sure a pointer fits.
- */
- U4_TO_BUF_BE(buf, 0, sizeof(void *));
- fwrite(buf, 1, sizeof(uint32_t), fp);
-
- /* The current time, in milliseconds since 0:00 GMT, 1/1/70.
- */
- if (gettimeofday(&now, NULL) < 0) {
- nowMs = 0;
- } else {
- nowMs = (uint64_t)now.tv_sec * 1000 + now.tv_usec / 1000;
- }
-
- /* uint32_t: high word of the 64-bit time.
- */
- U4_TO_BUF_BE(buf, 0, (uint32_t)(nowMs >> 32));
- fwrite(buf, 1, sizeof(uint32_t), fp);
-
- /* uint32_t: low word of the 64-bit time.
- */
- U4_TO_BUF_BE(buf, 0, (uint32_t)(nowMs & 0xffffffffULL));
- fwrite(buf, 1, sizeof(uint32_t), fp); //xxx fix the time
+ int nb = fwrite(headBuf, 1, sizeof(headBuf), fp);
+ if (nb != sizeof(headBuf)) {
+ return UNIQUE_ERROR();
}
-}
-
-int HprofRecord::Flush(FILE *fp)
-{
- if (dirty_) {
- unsigned char headBuf[sizeof (uint8_t) + 2 * sizeof (uint32_t)];
- int nb;
-
- headBuf[0] = tag_;
- U4_TO_BUF_BE(headBuf, 1, time_);
- U4_TO_BUF_BE(headBuf, 5, length_);
-
- nb = fwrite(headBuf, 1, sizeof(headBuf), fp);
- if (nb != sizeof(headBuf)) {
- return UNIQUE_ERROR();
- }
- nb = fwrite(body_, 1, length_, fp);
- if (nb != (int)length_) {
- return UNIQUE_ERROR();
- }
-
- dirty_ = false;
- }
-//xxx if we used less than half (or whatever) of allocLen, shrink the buffer.
-
- return 0;
-}
-
-int Hprof::FlushCurrentRecord()
-{
- return current_record_.Flush(mem_fp_);
-}
-
-int Hprof::StartNewRecord(uint8_t tag, uint32_t time)
-{
- HprofRecord *rec = ¤t_record_;
-
- int err = rec->Flush(mem_fp_);
- if (err != 0) {
- return err;
- } else if (rec->dirty_) {
- return UNIQUE_ERROR();
+ nb = fwrite(body_, 1, length_, fp);
+ if (nb != (int)length_) {
+ return UNIQUE_ERROR();
}
- rec->dirty_ = true;
- rec->tag_ = tag;
- rec->time_ = time;
- rec->length_ = 0;
-
- return 0;
+ dirty_ = false;
+ }
+ // TODO if we used less than half (or whatever) of allocLen, shrink the buffer.
+ return 0;
}
-static inline int guaranteeRecordAppend(HprofRecord *rec, size_t nmore)
-{
- size_t minSize;
+int Hprof::FlushCurrentRecord() {
+ return current_record_.Flush(mem_fp_);
+}
- minSize = rec->length_ + nmore;
- if (minSize > rec->alloc_length_) {
- unsigned char *newBody;
- size_t newAllocLen;
+int Hprof::StartNewRecord(uint8_t tag, uint32_t time) {
+ HprofRecord *rec = ¤t_record_;
- newAllocLen = rec->alloc_length_ * 2;
- if (newAllocLen < minSize) {
- newAllocLen = rec->alloc_length_ + nmore + nmore/2;
- }
- newBody = (unsigned char *)realloc(rec->body_, newAllocLen);
- if (newBody != NULL) {
- rec->body_ = newBody;
- rec->alloc_length_ = newAllocLen;
- } else {
-//TODO: set an error flag so future ops will fail
- return UNIQUE_ERROR();
- }
+ int err = rec->Flush(mem_fp_);
+ if (err != 0) {
+ return err;
+ } else if (rec->dirty_) {
+ return UNIQUE_ERROR();
+ }
+
+ rec->dirty_ = true;
+ rec->tag_ = tag;
+ rec->time_ = time;
+ rec->length_ = 0;
+ return 0;
+}
+
+static inline int guaranteeRecordAppend(HprofRecord *rec, size_t nmore) {
+ size_t minSize = rec->length_ + nmore;
+ if (minSize > rec->alloc_length_) {
+ size_t newAllocLen = rec->alloc_length_ * 2;
+ if (newAllocLen < minSize) {
+ newAllocLen = rec->alloc_length_ + nmore + nmore/2;
}
-
- CHECK_LE(rec->length_ + nmore, rec->alloc_length_);
- return 0;
-}
-
-int HprofRecord::AddU1List(const uint8_t *values, size_t numValues)
-{
- int err = guaranteeRecordAppend(this, numValues);
- if (err != 0) {
- return err;
+ unsigned char *newBody = (unsigned char *)realloc(rec->body_, newAllocLen);
+ if (newBody != NULL) {
+ rec->body_ = newBody;
+ rec->alloc_length_ = newAllocLen;
+ } else {
+ // TODO: set an error flag so future ops will fail
+ return UNIQUE_ERROR();
}
+ }
- memcpy(body_ + length_, values, numValues);
- length_ += numValues;
-
- return 0;
+ CHECK_LE(rec->length_ + nmore, rec->alloc_length_);
+ return 0;
}
-int HprofRecord::AddU1(uint8_t value)
-{
- int err = guaranteeRecordAppend(this, 1);
- if (err != 0) {
- return err;
- }
+int HprofRecord::AddU1List(const uint8_t *values, size_t numValues) {
+ int err = guaranteeRecordAppend(this, numValues);
+ if (err != 0) {
+ return err;
+ }
- body_[length_++] = value;
+ memcpy(body_ + length_, values, numValues);
+ length_ += numValues;
- return 0;
+ return 0;
}
-int HprofRecord::AddUtf8String(const char *str)
-{
- /* The terminating NUL character is NOT written.
- */
-//xxx don't do a strlen; add and grow as necessary, until NUL
- return AddU1List((const uint8_t *)str, strlen(str));
+int HprofRecord::AddU1(uint8_t value) {
+ int err = guaranteeRecordAppend(this, 1);
+ if (err != 0) {
+ return err;
+ }
+
+ body_[length_++] = value;
+ return 0;
}
-int HprofRecord::AddU2List(const uint16_t *values, size_t numValues)
-{
- int err = guaranteeRecordAppend(this, numValues * 2);
- if (err != 0) {
- return err;
- }
-
-//xxx this can be way smarter
-//xxx also, don't do this bytewise if aligned and on a matching-endian arch
- unsigned char *insert = body_ + length_;
- for (size_t i = 0; i < numValues; i++) {
- U2_TO_BUF_BE(insert, 0, *values++);
- insert += sizeof(*values);
- }
- length_ += numValues * 2;
-
- return 0;
+int HprofRecord::AddUtf8String(const char *str) {
+ // The terminating NUL character is NOT written.
+ return AddU1List((const uint8_t *)str, strlen(str));
}
-int HprofRecord::AddU2(uint16_t value)
-{
- return AddU2List(&value, 1);
+int HprofRecord::AddU2List(const uint16_t *values, size_t numValues) {
+ int err = guaranteeRecordAppend(this, numValues * 2);
+ if (err != 0) {
+ return err;
+ }
+
+ unsigned char *insert = body_ + length_;
+ for (size_t i = 0; i < numValues; i++) {
+ U2_TO_BUF_BE(insert, 0, *values++);
+ insert += sizeof(*values);
+ }
+ length_ += numValues * 2;
+ return 0;
}
-int HprofRecord::AddIdList(const HprofObjectId *values, size_t numValues)
-{
- return AddU4List((const uint32_t*) values, numValues);
+int HprofRecord::AddU2(uint16_t value) {
+ return AddU2List(&value, 1);
}
-int HprofRecord::AddU4List(const uint32_t *values, size_t numValues)
-{
- int err = guaranteeRecordAppend(this, numValues * 4);
- if (err != 0) {
- return err;
- }
-
-//xxx this can be way smarter
-//xxx also, don't do this bytewise if aligned and on a matching-endian arch
- unsigned char *insert = body_ + length_;
- for (size_t i = 0; i < numValues; i++) {
- U4_TO_BUF_BE(insert, 0, *values++);
- insert += sizeof(*values);
- }
- length_ += numValues * 4;
-
- return 0;
+int HprofRecord::AddIdList(const HprofObjectId *values, size_t numValues) {
+ return AddU4List((const uint32_t*) values, numValues);
}
-int HprofRecord::AddU4(uint32_t value)
-{
- return AddU4List(&value, 1);
+int HprofRecord::AddU4List(const uint32_t *values, size_t numValues) {
+ int err = guaranteeRecordAppend(this, numValues * 4);
+ if (err != 0) {
+ return err;
+ }
+
+ unsigned char *insert = body_ + length_;
+ for (size_t i = 0; i < numValues; i++) {
+ U4_TO_BUF_BE(insert, 0, *values++);
+ insert += sizeof(*values);
+ }
+ length_ += numValues * 4;
+ return 0;
}
-int HprofRecord::AddId(HprofObjectId value)
-{
- return AddU4((uint32_t) value);
+int HprofRecord::AddU4(uint32_t value) {
+ return AddU4List(&value, 1);
}
-int HprofRecord::AddU8List(const uint64_t *values, size_t numValues)
-{
- int err = guaranteeRecordAppend(this, numValues * 8);
- if (err != 0) {
- return err;
- }
-
-//xxx this can be way smarter
-//xxx also, don't do this bytewise if aligned and on a matching-endian arch
- unsigned char *insert = body_ + length_;
- for (size_t i = 0; i < numValues; i++) {
- U8_TO_BUF_BE(insert, 0, *values++);
- insert += sizeof(*values);
- }
- length_ += numValues * 8;
-
- return 0;
+int HprofRecord::AddId(HprofObjectId value) {
+ return AddU4((uint32_t) value);
}
-int HprofRecord::AddU8(uint64_t value)
-{
- return AddU8List(&value, 1);
+int HprofRecord::AddU8List(const uint64_t *values, size_t numValues) {
+ int err = guaranteeRecordAppend(this, numValues * 8);
+ if (err != 0) {
+ return err;
+ }
+
+ unsigned char *insert = body_ + length_;
+ for (size_t i = 0; i < numValues; i++) {
+ U8_TO_BUF_BE(insert, 0, *values++);
+ insert += sizeof(*values);
+ }
+ length_ += numValues * 8;
+ return 0;
+}
+
+int HprofRecord::AddU8(uint64_t value) {
+ return AddU8List(&value, 1);
}
} // namespace hprof
diff --git a/src/hprof/hprof_string.cc b/src/hprof/hprof_string.cc
index ab205e7..96acaf3 100644
--- a/src/hprof/hprof_string.cc
+++ b/src/hprof/hprof_string.cc
@@ -26,54 +26,50 @@
namespace hprof {
HprofStringId Hprof::LookupStringId(String* string) {
- return LookupStringId(string->ToModifiedUtf8());
+ return LookupStringId(string->ToModifiedUtf8());
}
HprofStringId Hprof::LookupStringId(const char* string) {
- return LookupStringId(std::string(string));
+ return LookupStringId(std::string(string));
}
HprofStringId Hprof::LookupStringId(std::string string) {
- MutexLock mu(strings_lock_);
- if (strings_.find(string) == strings_.end()) {
- strings_[string] = next_string_id_++;
- }
- return strings_[string];
+ MutexLock mu(strings_lock_);
+ if (strings_.find(string) == strings_.end()) {
+ strings_[string] = next_string_id_++;
+ }
+ return strings_[string];
}
int Hprof::DumpStrings() {
- MutexLock mu(strings_lock_);
+ MutexLock mu(strings_lock_);
- HprofRecord *rec = ¤t_record_;
+ HprofRecord *rec = ¤t_record_;
- for (StringMapIterator it = strings_.begin(); it != strings_.end(); ++it) {
- std::string string = (*it).first;
- size_t id = (*it).second;
+ for (StringMapIterator it = strings_.begin(); it != strings_.end(); ++it) {
+ std::string string = (*it).first;
+ size_t id = (*it).second;
- int err = StartNewRecord(HPROF_TAG_STRING, HPROF_TIME);
- if (err != 0) {
- return err;
- }
-
- /* STRING format:
- *
- * ID: ID for this string
- * [uint8_t]*: UTF8 characters for string (NOT NULL terminated)
- * (the record format encodes the length)
- *
- * We use the address of the string data as its ID.
- */
- err = rec->AddU4(id);
- if (err != 0) {
- return err;
- }
- err = rec->AddUtf8String(string.c_str());
- if (err != 0) {
- return err;
- }
+ int err = StartNewRecord(HPROF_TAG_STRING, HPROF_TIME);
+ if (err != 0) {
+ return err;
}
- return 0;
+ // STRING format:
+ // ID: ID for this string
+ // U1*: UTF8 characters for string (NOT NULL terminated)
+ // (the record format encodes the length)
+ err = rec->AddU4(id);
+ if (err != 0) {
+ return err;
+ }
+ err = rec->AddUtf8String(string.c_str());
+ if (err != 0) {
+ return err;
+ }
+ }
+
+ return 0;
}
} // namespace hprof