Hprof code cleanup.
This replaces a bunch of structs+functions with C++ objects
and member functions. It shortens names where unambiguous and
reduces visibility where plausible.
The main two changes are to create Hprof and HprofRecord classes
(from the hprof_record_t and hprof_context_t structs) and moves
functions into the classes. It uses stack allocation for the Hprof
object, which saves a few allocation-failure checks. And it uses
constructors and destructors rather than functions that do those
things.
This change should not alter behavior.
Change-Id: I62ce97fae3c1ba6e2ea89fdfdca915b013072868
diff --git a/src/hprof/hprof.cc b/src/hprof/hprof.cc
index 20fc426..e285307 100644
--- a/src/hprof/hprof.cc
+++ b/src/hprof/hprof.cc
@@ -43,26 +43,6 @@
#define kHeadSuffix "-hptemp"
-hprof_context_t* hprofStartup(const char *outputFileName, int fd,
- bool directToDdms)
-{
- hprofStartup_String();
- hprofStartup_Class();
-
- hprof_context_t *ctx = (hprof_context_t *)malloc(sizeof(*ctx));
- if (ctx == NULL) {
- LOG(ERROR) << "hprof: can't allocate context.";
- return NULL;
- }
-
- /* pass in name or descriptor of the output file */
- hprofContextInit(ctx, strdup(outputFileName), fd, false, directToDdms);
-
- CHECK(ctx->memFp != NULL);
-
- return ctx;
-}
-
// TODO: use File::WriteFully
int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg)
{
@@ -86,127 +66,108 @@
/*
* Finish up the hprof dump. Returns true on success.
*/
-bool hprofShutdown(hprof_context_t *tailCtx)
+bool Hprof::Finish()
{
/* flush the "tail" portion of the output */
- hprofFlushCurrentRecord(tailCtx);
+ StartNewRecord(HPROF_TAG_HEAP_DUMP_END, HPROF_TIME);
+ FlushCurrentRecord();
- /*
- * Create a new context struct for the start of the file. We
- * heap-allocate it so we can share the "free" function.
- */
- hprof_context_t *headCtx = (hprof_context_t *)malloc(sizeof(*headCtx));
- if (headCtx == NULL) {
- LOG(ERROR) << "hprof: can't allocate context.";
- hprofFreeContext(tailCtx);
- return false;
- }
- hprofContextInit(headCtx, strdup(tailCtx->fileName), tailCtx->fd, true,
- tailCtx->directToDdms);
+ // 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\".", tailCtx->fileName);
- hprofDumpStrings(headCtx);
- hprofDumpClasses(headCtx);
+ 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.
*/
- hprofStartNewRecord(headCtx, HPROF_TAG_STACK_TRACE, HPROF_TIME);
- hprofAddU4ToRecord(&headCtx->curRec, HPROF_NULL_STACK_TRACE);
- hprofAddU4ToRecord(&headCtx->curRec, HPROF_NULL_THREAD);
- hprofAddU4ToRecord(&headCtx->curRec, 0); // no frames
+ 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
- hprofFlushCurrentRecord(headCtx);
-
- hprofShutdown_Class();
- hprofShutdown_String();
+ headCtx.FlushCurrentRecord();
/* flush to ensure memstream pointer and size are updated */
- fflush(headCtx->memFp);
- fflush(tailCtx->memFp);
+ fflush(headCtx.mem_fp_);
+ fflush(mem_fp_);
- if (tailCtx->directToDdms) {
+ if (direct_to_ddms_) {
/* send the data off to DDMS */
struct iovec iov[2];
- iov[0].iov_base = headCtx->fileDataPtr;
- iov[0].iov_len = headCtx->fileDataSize;
- iov[1].iov_base = tailCtx->fileDataPtr;
- iov[1].iov_len = tailCtx->fileDataSize;
+ 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(headCtx->fd == tailCtx->fd);
+ CHECK_EQ(headCtx.fd_, fd_);
int outFd;
- if (headCtx->fd >= 0) {
- outFd = dup(headCtx->fd);
+ if (headCtx.fd_ >= 0) {
+ outFd = dup(headCtx.fd_);
if (outFd < 0) {
- LOG(ERROR) << StringPrintf("dup(%d) failed: %s", headCtx->fd, strerror(errno));
+ LOG(ERROR) << StringPrintf("dup(%d) failed: %s", headCtx.fd_, strerror(errno));
/* continue to fail-handler below */
}
} else {
- outFd = open(tailCtx->fileName, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ outFd = open(file_name_, O_WRONLY|O_CREAT|O_TRUNC, 0644);
if (outFd < 0) {
- LOG(ERROR) << StringPrintf("can't open %s: %s", headCtx->fileName, strerror(errno));
+ LOG(ERROR) << StringPrintf("can't open %s: %s", headCtx.file_name_, strerror(errno));
/* continue to fail-handler below */
}
}
if (outFd < 0) {
- hprofFreeContext(headCtx);
- hprofFreeContext(tailCtx);
return false;
}
- int result;
- result = sysWriteFully(outFd, headCtx->fileDataPtr,
- headCtx->fileDataSize, "hprof-head");
- result |= sysWriteFully(outFd, tailCtx->fileDataPtr,
- tailCtx->fileDataSize, "hprof-tail");
+ 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) {
- hprofFreeContext(headCtx);
- hprofFreeContext(tailCtx);
return false;
}
}
/* throw out a log message for the benefit of "runhat" */
LOG(INFO) << StringPrintf("hprof: heap dump completed (%dKB)",
- (headCtx->fileDataSize + tailCtx->fileDataSize + 1023) / 1024);
-
- hprofFreeContext(headCtx);
- hprofFreeContext(tailCtx);
+ (headCtx.file_data_size_ + file_data_size_ + 1023) / 1024);
return true;
}
-/*
- * Free any heap-allocated items in "ctx", and then free "ctx" itself.
- */
-void hprofFreeContext(hprof_context_t *ctx)
-{
- CHECK(ctx != NULL);
+Hprof::~Hprof() {
+ /* we don't own ctx->fd_, do not close */
- /* we don't own ctx->fd, do not close */
-
- if (ctx->memFp != NULL)
- fclose(ctx->memFp);
- free(ctx->curRec.body);
- free(ctx->fileName);
- free(ctx->fileDataPtr);
- free(ctx);
+ 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);
+}
+
+void Hprof::VisitRoot(const Object* obj) {
uint32_t threadId = 0; // TODO
/*RootType */ size_t type = 0; // TODO
- static const hprof_heap_tag_t xlate[] = {
+ static const HprofHeapTag xlate[] = {
HPROF_ROOT_UNKNOWN,
HPROF_ROOT_JNI_GLOBAL,
HPROF_ROOT_JNI_LOCAL,
@@ -223,19 +184,16 @@
HPROF_ROOT_VM_INTERNAL,
HPROF_ROOT_JNI_MONITOR,
};
- hprof_context_t *ctx;
- CHECK(arg != NULL);
- CHECK(type < (sizeof(xlate) / sizeof(hprof_heap_tag_t)));
+ CHECK_LT(type, sizeof(xlate) / sizeof(HprofHeapTag));
if (obj == NULL) {
return;
}
- ctx = (hprof_context_t *)arg;
- ctx->gcScanState = xlate[type];
- ctx->gcThreadSerialNumber = threadId;
- hprofMarkRootObject(ctx, obj, 0);
- ctx->gcScanState = 0;
- ctx->gcThreadSerialNumber = 0;
+ gc_scan_state_ = xlate[type];
+ gc_thread_serial_number_ = threadId;
+ MarkRootObject(obj, 0);
+ gc_scan_state_ = 0;
+ gc_thread_serial_number_ = 0;
}
/*
@@ -246,8 +204,8 @@
{
CHECK(obj != NULL);
CHECK(arg != NULL);
- hprof_context_t *ctx = (hprof_context_t *)arg;
- DumpHeapObject(ctx, obj);
+ Hprof *hprof = (Hprof*)arg;
+ hprof->DumpHeapObject(obj);
}
/*
@@ -255,18 +213,15 @@
* file.
*
* If "fd" is >= 0, the output will be written to that file descriptor.
- * Otherwise, "fileName" is used to create an output file.
+ * Otherwise, "file_name_" is used to create an output file.
*
- * If "directToDdms" is set, the other arguments are ignored, and data is
+ * If "direct_to_ddms_" is set, the other arguments are ignored, and data is
* sent directly to DDMS.
*
* Returns 0 on success, or an error code on failure.
*/
int DumpHeap(const char* fileName, int fd, bool directToDdms)
{
- hprof_context_t *ctx;
- int success;
-
CHECK(fileName != NULL);
ScopedHeapLock lock;
ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
@@ -274,15 +229,11 @@
ThreadList* thread_list = Runtime::Current()->GetThreadList();
thread_list->SuspendAll();
- ctx = hprofStartup(fileName, fd, directToDdms);
- if (ctx == NULL) {
- return -1;
- }
- Runtime::Current()->VisitRoots(HprofRootVisitor, ctx);
- Heap::GetLiveBits()->Walk(HprofBitmapCallback, ctx);
- hprofFinishHeapDump(ctx);
+ Hprof hprof(fileName, fd, false, directToDdms);
+ Runtime::Current()->VisitRoots(HprofRootVisitor, &hprof);
+ Heap::GetLiveBits()->Walk(HprofBitmapCallback, &hprof);
//TODO: write a HEAP_SUMMARY record
- success = hprofShutdown(ctx) ? 0 : -1;
+ int success = hprof.Finish() ? 0 : -1;
thread_list->ResumeAll();
return success;
}
diff --git a/src/hprof/hprof.h b/src/hprof/hprof.h
index e26e2cf..94852bc 100644
--- a/src/hprof/hprof.h
+++ b/src/hprof/hprof.h
@@ -20,6 +20,8 @@
#include "globals.h"
#include "file.h"
#include "object.h"
+#include "unordered_map.h"
+#include "unordered_set.h"
namespace art {
@@ -34,12 +36,16 @@
#define HPROF_NULL_STACK_TRACE 0
#define HPROF_NULL_THREAD 0
-typedef uint32_t hprof_id;
-typedef hprof_id hprof_string_id;
-typedef hprof_id hprof_object_id;
-typedef hprof_id hprof_class_object_id;
+typedef uint32_t HprofId;
+typedef HprofId HprofStringId;
+typedef HprofId HprofObjectId;
+typedef HprofId HprofClassObjectId;
+typedef std::tr1::unordered_set<Class*, ObjectIdentityHash> ClassSet;
+typedef std::tr1::unordered_set<Class*, ObjectIdentityHash>::iterator ClassSetIterator;
+typedef std::tr1::unordered_map<std::string, size_t> StringMap;
+typedef std::tr1::unordered_map<std::string, size_t>::iterator StringMapIterator;
-enum hprof_basic_type {
+enum HprofBasicType {
hprof_basic_object = 2,
hprof_basic_boolean = 4,
hprof_basic_char = 5,
@@ -51,7 +57,7 @@
hprof_basic_long = 11,
};
-enum hprof_tag_t {
+enum HprofTag {
HPROF_TAG_STRING = 0x01,
HPROF_TAG_LOAD_CLASS = 0x02,
HPROF_TAG_UNLOAD_CLASS = 0x03,
@@ -72,7 +78,7 @@
* HEAP_DUMP and HEAP_DUMP_SEGMENT
* records:
*/
-enum hprof_heap_tag_t {
+enum HprofHeapTag {
/* standard */
HPROF_ROOT_UNKNOWN = 0xFF,
HPROF_ROOT_JNI_GLOBAL = 0x01,
@@ -104,18 +110,32 @@
* 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
+ * 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
*/
-struct hprof_record_t {
- unsigned char *body;
- uint32_t time;
- uint32_t length;
- size_t allocLen;
- uint8_t tag;
- bool dirty;
+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);
+
+ unsigned char *body_;
+ uint32_t time_;
+ uint32_t length_;
+ size_t alloc_length_;
+ uint8_t tag_;
+ bool dirty_;
};
enum HprofHeapId {
@@ -124,90 +144,57 @@
HPROF_HEAP_APP = 'A'
};
-struct hprof_context_t {
- /* curRec *must* be first so that we
+class 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();
+
+ 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.
*/
- hprof_record_t curRec;
+ HprofRecord current_record_;
- uint32_t gcThreadSerialNumber;
- uint8_t gcScanState;
- HprofHeapId currentHeap; // which heap we're currently emitting
- uint32_t stackTraceSerialNumber;
- size_t objectsInSegment;
+ 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 directToDdms is set, "fileName" and "fd" will be ignored.
- * Otherwise, "fileName" must be valid, though if "fd" >= 0 it will
+ * 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 directToDdms;
- char *fileName;
- char *fileDataPtr; // for open_memstream
- size_t fileDataSize; // for open_memstream
- FILE *memFp;
- int fd;
+ 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_;
+
+ size_t next_string_id_;
+ mutable Mutex strings_lock_;
+ StringMap strings_;
};
-hprof_string_id hprofLookupStringId(String* string);
-hprof_string_id hprofLookupStringId(const char* string);
-hprof_string_id hprofLookupStringId(std::string string);
-
-int hprofDumpStrings(hprof_context_t *ctx);
-
-int hprofStartup_String(void);
-int hprofShutdown_String(void);
-
-hprof_class_object_id hprofLookupClassId(Class* clazz);
-
-int hprofDumpClasses(hprof_context_t *ctx);
-
-int hprofStartup_Class(void);
-int hprofShutdown_Class(void);
-
-int hprofStartHeapDump(hprof_context_t *ctx);
-int hprofFinishHeapDump(hprof_context_t *ctx);
-
-int hprofSetGcScanState(hprof_context_t *ctx,
- hprof_heap_tag_t state, uint32_t threadSerialNumber);
-int hprofMarkRootObject(hprof_context_t *ctx,
- const Object *obj, jobject jniObj);
-
-int DumpHeapObject(hprof_context_t *ctx, const Object *obj);
-
-void hprofContextInit(hprof_context_t *ctx, char *fileName, int fd,
- bool writeHeader, bool directToDdms);
-
-int hprofFlushRecord(hprof_record_t *rec, FILE *fp);
-int hprofFlushCurrentRecord(hprof_context_t *ctx);
-int hprofStartNewRecord(hprof_context_t *ctx, uint8_t tag, uint32_t time);
-
-int hprofAddU1ToRecord(hprof_record_t *rec, uint8_t value);
-int hprofAddU1ListToRecord(hprof_record_t *rec,
- const uint8_t *values, size_t numValues);
-
-int hprofAddUtf8StringToRecord(hprof_record_t *rec, const char *str);
-
-int hprofAddU2ToRecord(hprof_record_t *rec, uint16_t value);
-int hprofAddU2ListToRecord(hprof_record_t *rec,
- const uint16_t *values, size_t numValues);
-
-int hprofAddU4ToRecord(hprof_record_t *rec, uint32_t value);
-int hprofAddU4ListToRecord(hprof_record_t *rec,
- const uint32_t *values, size_t numValues);
-
-int hprofAddU8ToRecord(hprof_record_t *rec, uint64_t value);
-int hprofAddU8ListToRecord(hprof_record_t *rec,
- const uint64_t *values, size_t numValues);
-
-#define hprofAddIdToRecord(rec, id) hprofAddU4ToRecord((rec), (uint32_t)(id))
-#define hprofAddIdListToRecord(rec, values, numValues) \
- hprofAddU4ListToRecord((rec), (const uint32_t *)(values), (numValues))
-
-hprof_context_t* hprofStartup(const char *outputFileName, int fd,
- bool directToDdms);
-bool hprofShutdown(hprof_context_t *ctx);
-void hprofFreeContext(hprof_context_t *ctx);
int DumpHeap(const char* fileName, int fd, bool directToDdms);
} // namespace hprof
diff --git a/src/hprof/hprof_class.cc b/src/hprof/hprof_class.cc
index e601e91..ebedc2d 100644
--- a/src/hprof/hprof_class.cc
+++ b/src/hprof/hprof_class.cc
@@ -26,29 +26,16 @@
namespace hprof {
-typedef std::tr1::unordered_set<Class*, ObjectIdentityHash> ClassSet;
-typedef std::tr1::unordered_set<Class*, ObjectIdentityHash>::iterator ClassSetIterator;
-static Mutex classes_lock_("hprof classes");
-static ClassSet classes_;
-
-int hprofStartup_Class() {
- return 0;
+HprofStringId Hprof::LookupClassNameId(Class* clazz) {
+ return LookupStringId(PrettyDescriptor(clazz->GetDescriptor()));
}
-int hprofShutdown_Class() {
- return 0;
-}
-
-static int getPrettyClassNameId(Class* clazz) {
- return hprofLookupStringId(PrettyDescriptor(clazz->GetDescriptor()));
-}
-
-hprof_class_object_id hprofLookupClassId(Class* clazz) {
+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 (hprof_class_object_id)0;
+ return (HprofClassObjectId)0;
}
MutexLock mu(classes_lock_);
@@ -56,21 +43,17 @@
std::pair<ClassSetIterator, bool> result = classes_.insert(clazz);
Class* present = *result.first;
- /* Make sure that the class's name is in the string table.
- * This is a bunch of extra work that we only have to do
- * because of the order of tables in the output file
- * (strings need to be dumped before classes).
- */
- getPrettyClassNameId(clazz);
+ // Make sure that we've assigned a string ID for this class' name
+ LookupClassNameId(clazz);
- CHECK(present == clazz);
- return (hprof_string_id) present;
+ CHECK_EQ(present, clazz);
+ return (HprofStringId) present;
}
-int hprofDumpClasses(hprof_context_t *ctx) {
+int Hprof::DumpClasses() {
MutexLock mu(classes_lock_);
- hprof_record_t *rec = &ctx->curRec;
+ HprofRecord *rec = ¤t_record_;
uint32_t nextSerialNumber = 1;
@@ -78,7 +61,7 @@
Class* clazz = *it;
CHECK(clazz != NULL);
- int err = hprofStartNewRecord(ctx, HPROF_TAG_LOAD_CLASS, HPROF_TIME);
+ int err = StartNewRecord(HPROF_TAG_LOAD_CLASS, HPROF_TIME);
if (err != 0) {
return err;
}
@@ -92,10 +75,10 @@
*
* We use the address of the class object structure as its ID.
*/
- hprofAddU4ToRecord(rec, nextSerialNumber++);
- hprofAddIdToRecord(rec, (hprof_class_object_id) clazz);
- hprofAddU4ToRecord(rec, HPROF_NULL_STACK_TRACE);
- hprofAddIdToRecord(rec, getPrettyClassNameId(clazz));
+ rec->AddU4(nextSerialNumber++);
+ rec->AddId((HprofClassObjectId) clazz);
+ rec->AddU4(HPROF_NULL_STACK_TRACE);
+ rec->AddId(LookupClassNameId(clazz));
}
return 0;
diff --git a/src/hprof/hprof_heap.cc b/src/hprof/hprof_heap.cc
index 5c23bbb..84168e3 100644
--- a/src/hprof/hprof_heap.cc
+++ b/src/hprof/hprof_heap.cc
@@ -41,36 +41,12 @@
/* The ID for the synthetic object generated to account for class
* Static overhead.
*/
-#define CLASS_STATICS_ID(clazz) ((hprof_object_id)(((uint32_t)(clazz)) | 1))
+#define CLASS_STATICS_ID(clazz) ((HprofObjectId)(((uint32_t)(clazz)) | 1))
-int hprofStartHeapDump(hprof_context_t *ctx)
-{
- ctx->objectsInSegment = OBJECTS_PER_SEGMENT;
- ctx->currentHeap = HPROF_HEAP_DEFAULT;
- return 0;
-}
-
-int hprofFinishHeapDump(hprof_context_t *ctx)
-{
- return hprofStartNewRecord(ctx, HPROF_TAG_HEAP_DUMP_END, HPROF_TIME);
-}
-
-int hprofSetGcScanState(hprof_context_t *ctx,
- hprof_heap_tag_t state,
- uint32_t threadSerialNumber)
-{
- /* Used by hprofMarkRootObject()
- */
- ctx->gcScanState = state;
- ctx->gcThreadSerialNumber = threadSerialNumber;
- return 0;
-}
-
-static hprof_basic_type signatureToBasicTypeAndSize(const char *sig,
- size_t *sizeOut)
+static HprofBasicType signatureToBasicTypeAndSize(const char *sig, size_t *sizeOut)
{
char c = sig[0];
- hprof_basic_type ret;
+ HprofBasicType ret;
size_t size;
switch (c) {
@@ -94,10 +70,10 @@
return ret;
}
-static hprof_basic_type primitiveToBasicTypeAndSize(Primitive::Type prim,
+static HprofBasicType primitiveToBasicTypeAndSize(Primitive::Type prim,
size_t *sizeOut)
{
- hprof_basic_type ret;
+ HprofBasicType ret;
size_t size;
switch (prim) {
@@ -120,32 +96,28 @@
}
/* Always called when marking objects, but only does
- * something when ctx->gcScanState is non-zero, which is usually
+ * 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 hprofMarkRootObject(hprof_context_t *ctx, const Object *obj, jobject jniObj)
+int Hprof::MarkRootObject(const Object *obj, jobject jniObj)
{
- hprof_record_t *rec = &ctx->curRec;
- int err;
- hprof_heap_tag_t heapTag = (hprof_heap_tag_t)ctx->gcScanState;
+ HprofRecord *rec = ¤t_record_;
+ int err; // TODO: we may return this uninitialized
+ HprofHeapTag heapTag = (HprofHeapTag)gc_scan_state_;
if (heapTag == 0) {
return 0;
}
- if (ctx->objectsInSegment >= OBJECTS_PER_SEGMENT ||
- rec->length >= BYTES_PER_SEGMENT)
- {
- /* This flushes the old segment and starts a new one.
- */
- hprofStartNewRecord(ctx, HPROF_TAG_HEAP_DUMP_SEGMENT, HPROF_TIME);
- ctx->objectsInSegment = 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
- */
+ // ID: object ID
case HPROF_ROOT_UNKNOWN:
case HPROF_ROOT_STICKY_CLASS:
case HPROF_ROOT_MONITOR_USED:
@@ -154,17 +126,17 @@
case HPROF_ROOT_DEBUGGER:
case HPROF_ROOT_REFERENCE_CLEANUP:
case HPROF_ROOT_VM_INTERNAL:
- hprofAddU1ToRecord(rec, heapTag);
- hprofAddIdToRecord(rec, (hprof_object_id)obj);
+ rec->AddU1(heapTag);
+ rec->AddId((HprofObjectId)obj);
break;
/* ID: object ID
* ID: JNI global ref ID
*/
case HPROF_ROOT_JNI_GLOBAL:
- hprofAddU1ToRecord(rec, heapTag);
- hprofAddIdToRecord(rec, (hprof_object_id)obj);
- hprofAddIdToRecord(rec, (hprof_id)jniObj);
+ rec->AddU1(heapTag);
+ rec->AddId((HprofObjectId)obj);
+ rec->AddId((HprofId)jniObj);
break;
/* ID: object ID
@@ -174,10 +146,10 @@
case HPROF_ROOT_JNI_LOCAL:
case HPROF_ROOT_JNI_MONITOR:
case HPROF_ROOT_JAVA_FRAME:
- hprofAddU1ToRecord(rec, heapTag);
- hprofAddIdToRecord(rec, (hprof_object_id)obj);
- hprofAddU4ToRecord(rec, ctx->gcThreadSerialNumber);
- hprofAddU4ToRecord(rec, (uint32_t)-1);
+ rec->AddU1(heapTag);
+ rec->AddId((HprofObjectId)obj);
+ rec->AddU4(gc_thread_serial_number_);
+ rec->AddU4((uint32_t)-1);
break;
/* ID: object ID
@@ -185,9 +157,9 @@
*/
case HPROF_ROOT_NATIVE_STACK:
case HPROF_ROOT_THREAD_BLOCK:
- hprofAddU1ToRecord(rec, heapTag);
- hprofAddIdToRecord(rec, (hprof_object_id)obj);
- hprofAddU4ToRecord(rec, ctx->gcThreadSerialNumber);
+ rec->AddU1(heapTag);
+ rec->AddId((HprofObjectId)obj);
+ rec->AddU4(gc_thread_serial_number_);
break;
/* ID: thread object ID
@@ -195,10 +167,10 @@
* uint32_t: stack trace serial number
*/
case HPROF_ROOT_THREAD_OBJECT:
- hprofAddU1ToRecord(rec, heapTag);
- hprofAddIdToRecord(rec, (hprof_object_id)obj);
- hprofAddU4ToRecord(rec, ctx->gcThreadSerialNumber);
- hprofAddU4ToRecord(rec, (uint32_t)-1); //xxx
+ rec->AddU1(heapTag);
+ rec->AddId((HprofObjectId)obj);
+ rec->AddU4(gc_thread_serial_number_);
+ rec->AddU4((uint32_t)-1); //xxx
break;
default:
@@ -206,7 +178,7 @@
break;
}
- ctx->objectsInSegment++;
+ objects_in_segment_++;
return err;
}
@@ -216,46 +188,46 @@
return HPROF_NULL_STACK_TRACE;
}
-int DumpHeapObject(hprof_context_t* ctx, const Object* obj) {
+int Hprof::DumpHeapObject(const Object* obj) {
Class* clazz;
- hprof_record_t *rec = &ctx->curRec;
+ HprofRecord *rec = ¤t_record_;
HprofHeapId desiredHeap = false ? HPROF_HEAP_ZYGOTE : HPROF_HEAP_APP; // TODO: zygote objects?
- if (ctx->objectsInSegment >= OBJECTS_PER_SEGMENT || rec->length >= BYTES_PER_SEGMENT) {
+ if (objects_in_segment_ >= OBJECTS_PER_SEGMENT || rec->length_ >= BYTES_PER_SEGMENT) {
/* This flushes the old segment and starts a new one.
*/
- hprofStartNewRecord(ctx, HPROF_TAG_HEAP_DUMP_SEGMENT, HPROF_TIME);
- ctx->objectsInSegment = 0;
+ StartNewRecord(HPROF_TAG_HEAP_DUMP_SEGMENT, HPROF_TIME);
+ objects_in_segment_ = 0;
/* Starting a new HEAP_DUMP resets the heap to default.
*/
- ctx->currentHeap = HPROF_HEAP_DEFAULT;
+ current_heap_ = HPROF_HEAP_DEFAULT;
}
- if (desiredHeap != ctx->currentHeap) {
- hprof_string_id nameId;
+ 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.
*/
- hprofAddU1ToRecord(rec, HPROF_HEAP_DUMP_INFO);
- hprofAddU4ToRecord(rec, (uint32_t)desiredHeap); // uint32_t: heap id
+ rec->AddU1(HPROF_HEAP_DUMP_INFO);
+ rec->AddU4((uint32_t)desiredHeap); // uint32_t: heap id
switch (desiredHeap) {
case HPROF_HEAP_APP:
- nameId = hprofLookupStringId("app");
+ nameId = LookupStringId("app");
break;
case HPROF_HEAP_ZYGOTE:
- nameId = hprofLookupStringId("zygote");
+ nameId = LookupStringId("zygote");
break;
default:
/* Internal error. */
LOG(ERROR) << "Unexpected desiredHeap";
- nameId = hprofLookupStringId("<ILLEGAL>");
+ nameId = LookupStringId("<ILLEGAL>");
break;
}
- hprofAddIdToRecord(rec, nameId);
- ctx->currentHeap = desiredHeap;
+ rec->AddId(nameId);
+ current_heap_ = desiredHeap;
}
clazz = obj->GetClass();
@@ -277,63 +249,63 @@
/* Create a byte array to reflect the allocation of the
* StaticField array at the end of this class.
*/
- hprofAddU1ToRecord(rec, HPROF_PRIMITIVE_ARRAY_DUMP);
- hprofAddIdToRecord(rec, CLASS_STATICS_ID(obj));
- hprofAddU4ToRecord(rec, stackTraceSerialNumber(obj));
- hprofAddU4ToRecord(rec, byteLength);
- hprofAddU1ToRecord(rec, hprof_basic_byte);
+ rec->AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
+ rec->AddId(CLASS_STATICS_ID(obj));
+ rec->AddU4(stackTraceSerialNumber(obj));
+ rec->AddU4(byteLength);
+ rec->AddU1(hprof_basic_byte);
for (int i = 0; i < byteLength; i++) {
- hprofAddU1ToRecord(rec, 0);
+ rec->AddU1(0);
}
}
- hprofAddU1ToRecord(rec, HPROF_CLASS_DUMP);
- hprofAddIdToRecord(rec, hprofLookupClassId(thisClass));
- hprofAddU4ToRecord(rec, stackTraceSerialNumber(thisClass));
- hprofAddIdToRecord(rec, hprofLookupClassId(thisClass->GetSuperClass()));
- hprofAddIdToRecord(rec, (hprof_object_id)thisClass->GetClassLoader());
- hprofAddIdToRecord(rec, (hprof_object_id)0); // no signer
- hprofAddIdToRecord(rec, (hprof_object_id)0); // no prot domain
- hprofAddIdToRecord(rec, (hprof_id)0); // reserved
- hprofAddIdToRecord(rec, (hprof_id)0); // reserved
+ rec->AddU1(HPROF_CLASS_DUMP);
+ rec->AddId(LookupClassId(thisClass));
+ rec->AddU4(stackTraceSerialNumber(thisClass));
+ rec->AddId(LookupClassId(thisClass->GetSuperClass()));
+ rec->AddId((HprofObjectId)thisClass->GetClassLoader());
+ rec->AddId((HprofObjectId)0); // no signer
+ rec->AddId((HprofObjectId)0); // no prot domain
+ 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.
- hprofAddU4ToRecord(rec, sizeof(Class)); // instance size
+ rec->AddU4(sizeof(Class)); // instance size
} else if (thisClass->IsArrayClass() || thisClass->IsPrimitive()) {
- hprofAddU4ToRecord(rec, 0);
+ rec->AddU4(0);
} else {
- hprofAddU4ToRecord(rec, thisClass->GetObjectSize()); // instance size
+ rec->AddU4(thisClass->GetObjectSize()); // instance size
}
- hprofAddU2ToRecord(rec, 0); // empty const pool
+ rec->AddU2(0); // empty const pool
/* Static fields
*/
if (sFieldCount == 0) {
- hprofAddU2ToRecord(rec, (uint16_t)0);
+ rec->AddU2((uint16_t)0);
} else {
- hprofAddU2ToRecord(rec, (uint16_t)(sFieldCount+1));
- hprofAddIdToRecord(rec, hprofLookupStringId(STATIC_OVERHEAD_NAME));
- hprofAddU1ToRecord(rec, hprof_basic_object);
- hprofAddIdToRecord(rec, CLASS_STATICS_ID(obj));
+ rec->AddU2((uint16_t)(sFieldCount+1));
+ rec->AddId(LookupStringId(STATIC_OVERHEAD_NAME));
+ rec->AddU1(hprof_basic_object);
+ rec->AddId(CLASS_STATICS_ID(obj));
for (size_t i = 0; i < sFieldCount; ++i) {
Field* f = thisClass->GetStaticField(i);
size_t size;
- hprof_basic_type t = signatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size);
- hprofAddIdToRecord(rec, hprofLookupStringId(f->GetName()));
- hprofAddU1ToRecord(rec, t);
+ HprofBasicType t = signatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size);
+ rec->AddId(LookupStringId(f->GetName()));
+ rec->AddU1(t);
if (size == 1) {
- hprofAddU1ToRecord(rec, static_cast<uint8_t>(f->Get32(NULL)));
+ rec->AddU1(static_cast<uint8_t>(f->Get32(NULL)));
} else if (size == 2) {
- hprofAddU2ToRecord(rec, static_cast<uint16_t>(f->Get32(NULL)));
+ rec->AddU2(static_cast<uint16_t>(f->Get32(NULL)));
} else if (size == 4) {
- hprofAddU4ToRecord(rec, f->Get32(NULL));
+ rec->AddU4(f->Get32(NULL));
} else if (size == 8) {
- hprofAddU8ToRecord(rec, f->Get64(NULL));
+ rec->AddU8(f->Get64(NULL));
} else {
CHECK(false);
}
@@ -343,12 +315,12 @@
/* Instance fields for this class (no superclass fields)
*/
int iFieldCount = thisClass->IsObjectClass() ? 0 : thisClass->NumInstanceFields();
- hprofAddU2ToRecord(rec, (uint16_t)iFieldCount);
+ rec->AddU2((uint16_t)iFieldCount);
for (int i = 0; i < iFieldCount; ++i) {
Field* f = thisClass->GetInstanceField(i);
- hprof_basic_type t = signatureToBasicTypeAndSize(f->GetTypeDescriptor(), NULL);
- hprofAddIdToRecord(rec, hprofLookupStringId(f->GetName()));
- hprofAddU1ToRecord(rec, t);
+ HprofBasicType t = signatureToBasicTypeAndSize(f->GetTypeDescriptor(), NULL);
+ rec->AddId(LookupStringId(f->GetName()));
+ rec->AddU1(t);
}
} else if (clazz->IsArrayClass()) {
Array *aobj = (Array *)obj;
@@ -357,44 +329,44 @@
if (obj->IsObjectArray()) {
/* obj is an object array.
*/
- hprofAddU1ToRecord(rec, HPROF_OBJECT_ARRAY_DUMP);
+ rec->AddU1(HPROF_OBJECT_ARRAY_DUMP);
- hprofAddIdToRecord(rec, (hprof_object_id)obj);
- hprofAddU4ToRecord(rec, stackTraceSerialNumber(obj));
- hprofAddU4ToRecord(rec, length);
- hprofAddIdToRecord(rec, hprofLookupClassId(clazz));
+ rec->AddId((HprofObjectId)obj);
+ rec->AddU4(stackTraceSerialNumber(obj));
+ rec->AddU4(length);
+ rec->AddId(LookupClassId(clazz));
/* Dump the elements, which are always objects or NULL.
*/
- hprofAddIdListToRecord(rec, (const hprof_object_id *)aobj->GetRawData(), length);
+ rec->AddIdList((const HprofObjectId *)aobj->GetRawData(), length);
} else {
size_t size;
- hprof_basic_type t = primitiveToBasicTypeAndSize(clazz->GetComponentType()->GetPrimitiveType(), &size);
+ HprofBasicType t = primitiveToBasicTypeAndSize(clazz->GetComponentType()->GetPrimitiveType(), &size);
/* obj is a primitive array.
*/
#if DUMP_PRIM_DATA
- hprofAddU1ToRecord(rec, HPROF_PRIMITIVE_ARRAY_DUMP);
+ rec->AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
#else
- hprofAddU1ToRecord(rec, HPROF_PRIMITIVE_ARRAY_NODATA_DUMP);
+ rec->AddU1(HPROF_PRIMITIVE_ARRAY_NODATA_DUMP);
#endif
- hprofAddIdToRecord(rec, (hprof_object_id)obj);
- hprofAddU4ToRecord(rec, stackTraceSerialNumber(obj));
- hprofAddU4ToRecord(rec, length);
- hprofAddU1ToRecord(rec, t);
+ rec->AddId((HprofObjectId)obj);
+ rec->AddU4(stackTraceSerialNumber(obj));
+ rec->AddU4(length);
+ rec->AddU1(t);
#if DUMP_PRIM_DATA
/* Dump the raw, packed element values.
*/
if (size == 1) {
- hprofAddU1ListToRecord(rec, (const uint8_t *)aobj->GetRawData(), length);
+ rec->AddU1List((const uint8_t *)aobj->GetRawData(), length);
} else if (size == 2) {
- hprofAddU2ListToRecord(rec, (const uint16_t *)(void *)aobj->GetRawData(), length);
+ rec->AddU2List((const uint16_t *)(void *)aobj->GetRawData(), length);
} else if (size == 4) {
- hprofAddU4ListToRecord(rec, (const uint32_t *)(void *)aobj->GetRawData(), length);
+ rec->AddU4List((const uint32_t *)(void *)aobj->GetRawData(), length);
} else if (size == 8) {
- hprofAddU8ListToRecord(rec, (const uint64_t *)aobj->GetRawData(), length);
+ rec->AddU8List((const uint64_t *)aobj->GetRawData(), length);
}
#endif
}
@@ -402,17 +374,17 @@
/* obj is an instance object.
*/
- hprofAddU1ToRecord(rec, HPROF_INSTANCE_DUMP);
- hprofAddIdToRecord(rec, (hprof_object_id)obj);
- hprofAddU4ToRecord(rec, stackTraceSerialNumber(obj));
- hprofAddIdToRecord(rec, hprofLookupClassId(clazz));
+ 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.
*/
- size_t sizePatchOffset = rec->length;
- hprofAddU4ToRecord(rec, 0x77777777);
+ size_t sizePatchOffset = rec->length_;
+ rec->AddU4(0x77777777);
/* Write the instance data; fields for this
* class, followed by super class fields, and so on.
@@ -426,13 +398,13 @@
size_t size;
signatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size);
if (size == 1) {
- hprofAddU1ToRecord(rec, f->Get32(obj));
+ rec->AddU1(f->Get32(obj));
} else if (size == 2) {
- hprofAddU2ToRecord(rec, f->Get32(obj));
+ rec->AddU2(f->Get32(obj));
} else if (size == 4) {
- hprofAddU4ToRecord(rec, f->Get32(obj));
+ rec->AddU4(f->Get32(obj));
} else if (size == 8) {
- hprofAddU8ToRecord(rec, f->Get64(obj));
+ rec->AddU8(f->Get64(obj));
} else {
CHECK(false);
}
@@ -443,14 +415,14 @@
/* Patch the instance field length.
*/
- size_t savedLen = rec->length;
- rec->length = sizePatchOffset;
- hprofAddU4ToRecord(rec, savedLen - (sizePatchOffset + 4));
- rec->length = savedLen;
+ size_t savedLen = rec->length_;
+ rec->length_ = sizePatchOffset;
+ rec->AddU4(savedLen - (sizePatchOffset + 4));
+ rec->length_ = savedLen;
}
}
- ctx->objectsInSegment++;
+ objects_in_segment_++;
return 0;
}
diff --git a/src/hprof/hprof_output.cc b/src/hprof/hprof_output.cc
index 5dfdb31..012bfdd 100644
--- a/src/hprof/hprof_output.cc
+++ b/src/hprof/hprof_output.cc
@@ -64,34 +64,42 @@
} while (0)
/*
- * Initialize an hprof context struct.
- *
- * This will take ownership of "fileName".
+ * Initialize an Hprof.
*/
-void hprofContextInit(hprof_context_t *ctx, char *fileName, int fd,
- bool writeHeader, bool directToDdms)
-{
- memset(ctx, 0, sizeof (*ctx));
-
+Hprof::Hprof(const char *outputFileName, int fd, bool writeHeader, bool directToDdms)
+ : current_record_(),
+ gc_thread_serial_number_(0),
+ gc_scan_state_(0),
+ current_heap_(HPROF_HEAP_DEFAULT),
+ objects_in_segment_(0),
+ direct_to_ddms_(0),
+ file_name_(NULL),
+ file_data_ptr_(NULL),
+ file_data_size_(0),
+ mem_fp_(NULL),
+ fd_(0),
+ 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 fileDataPtr/fileDataSize
+ * memset the struct (want to treat file_data_ptr_/file_data_size_
* as read-only while the file is open).
*/
- FILE *fp = open_memstream(&ctx->fileDataPtr, &ctx->fileDataSize);
+ 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);
}
- ctx->directToDdms = directToDdms;
- ctx->fileName = fileName;
- ctx->memFp = fp;
- ctx->fd = fd;
+ direct_to_ddms_ = directToDdms;
+ file_name_ = strdup(outputFileName);
+ mem_fp_ = fp;
+ fd_ = fd;
- ctx->curRec.allocLen = 128;
- ctx->curRec.body = (unsigned char *)malloc(ctx->curRec.allocLen);
+ current_record_.alloc_length_ = 128;
+ current_record_.body_ = (unsigned char *)malloc(current_record_.alloc_length_);
//xxx check for/return an error
if (writeHeader) {
@@ -132,195 +140,196 @@
}
}
-int hprofFlushRecord(hprof_record_t *rec, FILE *fp)
+int HprofRecord::Flush(FILE *fp)
{
- if (rec->dirty) {
+ if (dirty_) {
unsigned char headBuf[sizeof (uint8_t) + 2 * sizeof (uint32_t)];
int nb;
- headBuf[0] = rec->tag;
- U4_TO_BUF_BE(headBuf, 1, rec->time);
- U4_TO_BUF_BE(headBuf, 5, rec->length);
+ 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(rec->body, 1, rec->length, fp);
- if (nb != (int)rec->length) {
+ nb = fwrite(body_, 1, length_, fp);
+ if (nb != (int)length_) {
return UNIQUE_ERROR();
}
- rec->dirty = false;
+ dirty_ = false;
}
//xxx if we used less than half (or whatever) of allocLen, shrink the buffer.
return 0;
}
-int hprofFlushCurrentRecord(hprof_context_t *ctx)
+int Hprof::FlushCurrentRecord()
{
- return hprofFlushRecord(&ctx->curRec, ctx->memFp);
+ return current_record_.Flush(mem_fp_);
}
-int hprofStartNewRecord(hprof_context_t *ctx, uint8_t tag, uint32_t time)
+int Hprof::StartNewRecord(uint8_t tag, uint32_t time)
{
- hprof_record_t *rec = &ctx->curRec;
- int err;
+ HprofRecord *rec = ¤t_record_;
- err = hprofFlushRecord(rec, ctx->memFp);
+ int err = rec->Flush(mem_fp_);
if (err != 0) {
return err;
- } else if (rec->dirty) {
+ } else if (rec->dirty_) {
return UNIQUE_ERROR();
}
- rec->dirty = true;
- rec->tag = tag;
- rec->time = time;
- rec->length = 0;
+ rec->dirty_ = true;
+ rec->tag_ = tag;
+ rec->time_ = time;
+ rec->length_ = 0;
return 0;
}
-static inline int guaranteeRecordAppend(hprof_record_t *rec, size_t nmore)
+static inline int guaranteeRecordAppend(HprofRecord *rec, size_t nmore)
{
size_t minSize;
- minSize = rec->length + nmore;
- if (minSize > rec->allocLen) {
+ minSize = rec->length_ + nmore;
+ if (minSize > rec->alloc_length_) {
unsigned char *newBody;
size_t newAllocLen;
- newAllocLen = rec->allocLen * 2;
+ newAllocLen = rec->alloc_length_ * 2;
if (newAllocLen < minSize) {
- newAllocLen = rec->allocLen + nmore + nmore/2;
+ newAllocLen = rec->alloc_length_ + nmore + nmore/2;
}
- newBody = (unsigned char *)realloc(rec->body, newAllocLen);
+ newBody = (unsigned char *)realloc(rec->body_, newAllocLen);
if (newBody != NULL) {
- rec->body = newBody;
- rec->allocLen = newAllocLen;
+ rec->body_ = newBody;
+ rec->alloc_length_ = newAllocLen;
} else {
//TODO: set an error flag so future ops will fail
return UNIQUE_ERROR();
}
}
- CHECK(rec->length + nmore <= rec->allocLen);
+ CHECK_LE(rec->length_ + nmore, rec->alloc_length_);
return 0;
}
-int hprofAddU1ListToRecord(hprof_record_t *rec, const uint8_t *values,
- size_t numValues)
+int HprofRecord::AddU1List(const uint8_t *values, size_t numValues)
{
- int err;
-
- err = guaranteeRecordAppend(rec, numValues);
+ int err = guaranteeRecordAppend(this, numValues);
if (err != 0) {
return err;
}
- memcpy(rec->body + rec->length, values, numValues);
- rec->length += numValues;
+ memcpy(body_ + length_, values, numValues);
+ length_ += numValues;
return 0;
}
-int hprofAddU1ToRecord(hprof_record_t *rec, uint8_t value)
+int HprofRecord::AddU1(uint8_t value)
{
- int err;
-
- err = guaranteeRecordAppend(rec, 1);
+ int err = guaranteeRecordAppend(this, 1);
if (err != 0) {
return err;
}
- rec->body[rec->length++] = value;
+ body_[length_++] = value;
return 0;
}
-int hprofAddUtf8StringToRecord(hprof_record_t *rec, const char *str)
+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 hprofAddU1ListToRecord(rec, (const uint8_t *)str, strlen(str));
+ return AddU1List((const uint8_t *)str, strlen(str));
}
-int hprofAddU2ListToRecord(hprof_record_t *rec, const uint16_t *values,
- size_t numValues)
+int HprofRecord::AddU2List(const uint16_t *values, size_t numValues)
{
- int err = guaranteeRecordAppend(rec, numValues * 2);
+ 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 = rec->body + rec->length;
+ unsigned char *insert = body_ + length_;
for (size_t i = 0; i < numValues; i++) {
U2_TO_BUF_BE(insert, 0, *values++);
insert += sizeof(*values);
}
- rec->length += numValues * 2;
+ length_ += numValues * 2;
return 0;
}
-int hprofAddU2ToRecord(hprof_record_t *rec, uint16_t value)
+int HprofRecord::AddU2(uint16_t value)
{
- return hprofAddU2ListToRecord(rec, &value, 1);
+ return AddU2List(&value, 1);
}
-int hprofAddU4ListToRecord(hprof_record_t *rec, const uint32_t *values,
- size_t numValues)
+int HprofRecord::AddIdList(const HprofObjectId *values, size_t numValues)
{
- int err = guaranteeRecordAppend(rec, numValues * 4);
+ return AddU4List((const uint32_t*) values, numValues);
+}
+
+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 = rec->body + rec->length;
+ unsigned char *insert = body_ + length_;
for (size_t i = 0; i < numValues; i++) {
U4_TO_BUF_BE(insert, 0, *values++);
insert += sizeof(*values);
}
- rec->length += numValues * 4;
+ length_ += numValues * 4;
return 0;
}
-int hprofAddU4ToRecord(hprof_record_t *rec, uint32_t value)
+int HprofRecord::AddU4(uint32_t value)
{
- return hprofAddU4ListToRecord(rec, &value, 1);
+ return AddU4List(&value, 1);
}
-int hprofAddU8ListToRecord(hprof_record_t *rec, const uint64_t *values,
- size_t numValues)
+int HprofRecord::AddId(HprofObjectId value)
{
- int err = guaranteeRecordAppend(rec, numValues * 8);
+ return AddU4((uint32_t) value);
+}
+
+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 = rec->body + rec->length;
+ unsigned char *insert = body_ + length_;
for (size_t i = 0; i < numValues; i++) {
U8_TO_BUF_BE(insert, 0, *values++);
insert += sizeof(*values);
}
- rec->length += numValues * 8;
+ length_ += numValues * 8;
return 0;
}
-int hprofAddU8ToRecord(hprof_record_t *rec, uint64_t value)
+int HprofRecord::AddU8(uint64_t value)
{
- return hprofAddU8ListToRecord(rec, &value, 1);
+ return AddU8List(&value, 1);
}
} // namespace hprof
diff --git a/src/hprof/hprof_string.cc b/src/hprof/hprof_string.cc
index bc1caf2..ab205e7 100644
--- a/src/hprof/hprof_string.cc
+++ b/src/hprof/hprof_string.cc
@@ -25,29 +25,15 @@
namespace hprof {
-size_t next_string_id_ = 0x400000;
-typedef std::tr1::unordered_map<std::string, size_t> StringMap;
-typedef std::tr1::unordered_map<std::string, size_t>::iterator StringMapIterator;
-static Mutex strings_lock_("hprof strings");
-static StringMap strings_;
-
-int hprofStartup_String() {
- return 0;
+HprofStringId Hprof::LookupStringId(String* string) {
+ return LookupStringId(string->ToModifiedUtf8());
}
-int hprofShutdown_String() {
- return 0;
+HprofStringId Hprof::LookupStringId(const char* string) {
+ return LookupStringId(std::string(string));
}
-hprof_string_id hprofLookupStringId(String* string) {
- return hprofLookupStringId(string->ToModifiedUtf8());
-}
-
-hprof_string_id hprofLookupStringId(const char* string) {
- return hprofLookupStringId(std::string(string));
-}
-
-hprof_string_id hprofLookupStringId(std::string string) {
+HprofStringId Hprof::LookupStringId(std::string string) {
MutexLock mu(strings_lock_);
if (strings_.find(string) == strings_.end()) {
strings_[string] = next_string_id_++;
@@ -55,16 +41,16 @@
return strings_[string];
}
-int hprofDumpStrings(hprof_context_t *ctx) {
+int Hprof::DumpStrings() {
MutexLock mu(strings_lock_);
- hprof_record_t *rec = &ctx->curRec;
+ HprofRecord *rec = ¤t_record_;
for (StringMapIterator it = strings_.begin(); it != strings_.end(); ++it) {
std::string string = (*it).first;
size_t id = (*it).second;
- int err = hprofStartNewRecord(ctx, HPROF_TAG_STRING, HPROF_TIME);
+ int err = StartNewRecord(HPROF_TAG_STRING, HPROF_TIME);
if (err != 0) {
return err;
}
@@ -77,11 +63,11 @@
*
* We use the address of the string data as its ID.
*/
- err = hprofAddU4ToRecord(rec, id);
+ err = rec->AddU4(id);
if (err != 0) {
return err;
}
- err = hprofAddUtf8StringToRecord(rec, string.c_str());
+ err = rec->AddUtf8String(string.c_str());
if (err != 0) {
return err;
}