summaryrefslogtreecommitdiffstats
path: root/runtime/hprof
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2014-01-06 12:55:46 -0800
committerIan Rogers <irogers@google.com>2014-02-06 23:20:27 -0800
commitef7d42fca18c16fbaf103822ad16f23246e2905d (patch)
treec67eea52a349c2ea7f2c3bdda8e73933c05531a8 /runtime/hprof
parent822115a225185d2896607eb08d70ce5c7099adef (diff)
downloadart-ef7d42fca18c16fbaf103822ad16f23246e2905d.tar.gz
art-ef7d42fca18c16fbaf103822ad16f23246e2905d.tar.bz2
art-ef7d42fca18c16fbaf103822ad16f23246e2905d.zip
Object model changes to support 64bit.
Modify mirror objects so that references between them use an ObjectReference value type rather than an Object* so that functionality to compress larger references can be captured in the ObjectRefererence implementation. ObjectReferences are 32bit and all other aspects of object layout remain as they are currently. Expand fields in objects holding pointers so they can hold 64bit pointers. Its expected the size of these will come down by improving where we hold compiler meta-data. Stub out x86_64 architecture specific runtime implementation. Modify OutputStream so that reads and writes are of unsigned quantities. Make the use of portable or quick code more explicit. Templatize AtomicInteger to support more than just int32_t as a type. Add missing, and fix issues relating to, missing annotalysis information on the mutator lock. Refactor and share implementations for array copy between System and uses elsewhere in the runtime. Fix numerous 64bit build issues. Change-Id: I1a5694c251a42c9eff71084dfdd4b51fff716822
Diffstat (limited to 'runtime/hprof')
-rw-r--r--runtime/hprof/hprof.cc180
1 files changed, 96 insertions, 84 deletions
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index 9f899e87a3..24d403d634 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -167,14 +167,8 @@ enum HprofBasicType {
hprof_basic_long = 11,
};
-typedef uint32_t HprofId;
-typedef HprofId HprofStringId;
-typedef HprofId HprofObjectId;
-typedef HprofId HprofClassObjectId;
-typedef std::set<mirror::Class*> ClassSet;
-typedef std::set<mirror::Class*>::iterator ClassSetIterator;
-typedef SafeMap<std::string, size_t> StringMap;
-typedef SafeMap<std::string, size_t>::iterator StringMapIterator;
+typedef uint32_t HprofStringId;
+typedef uint32_t HprofClassObjectId;
// Represents a top-level hprof record, whose serialized format is:
// U1 TAG: denoting the type of the record
@@ -183,11 +177,8 @@ typedef SafeMap<std::string, size_t>::iterator StringMapIterator;
// U1* BODY: as many bytes as specified in the above uint32_t field
class HprofRecord {
public:
- HprofRecord() {
- dirty_ = false;
- alloc_length_ = 128;
+ HprofRecord() : alloc_length_(128), fp_(nullptr), tag_(0), time_(0), length_(0), dirty_(false) {
body_ = reinterpret_cast<unsigned char*>(malloc(alloc_length_));
- fp_ = NULL;
}
~HprofRecord() {
@@ -233,7 +224,7 @@ class HprofRecord {
int AddU1(uint8_t value) {
int err = GuaranteeRecordAppend(1);
- if (err != 0) {
+ if (UNLIKELY(err != 0)) {
return err;
}
@@ -253,13 +244,30 @@ class HprofRecord {
return AddU8List(&value, 1);
}
- int AddId(HprofObjectId value) {
- return AddU4((uint32_t) value);
+ int AddObjectId(const mirror::Object* value) {
+ return AddU4(PointerToLowMemUInt32(value));
+ }
+
+ // The ID for the synthetic object generated to account for class static overhead.
+ int AddClassStaticsId(const mirror::Class* value) {
+ return AddU4(1 | PointerToLowMemUInt32(value));
+ }
+
+ int AddJniGlobalRefId(jobject value) {
+ return AddU4(PointerToLowMemUInt32(value));
+ }
+
+ int AddClassId(HprofClassObjectId value) {
+ return AddU4(value);
+ }
+
+ int AddStringId(HprofStringId value) {
+ return AddU4(value);
}
int AddU1List(const uint8_t* values, size_t numValues) {
int err = GuaranteeRecordAppend(numValues);
- if (err != 0) {
+ if (UNLIKELY(err != 0)) {
return err;
}
@@ -270,7 +278,7 @@ class HprofRecord {
int AddU2List(const uint16_t* values, size_t numValues) {
int err = GuaranteeRecordAppend(numValues * 2);
- if (err != 0) {
+ if (UNLIKELY(err != 0)) {
return err;
}
@@ -285,7 +293,7 @@ class HprofRecord {
int AddU4List(const uint32_t* values, size_t numValues) {
int err = GuaranteeRecordAppend(numValues * 4);
- if (err != 0) {
+ if (UNLIKELY(err != 0)) {
return err;
}
@@ -317,8 +325,16 @@ class HprofRecord {
return 0;
}
- int AddIdList(const HprofObjectId* values, size_t numValues) {
- return AddU4List((const uint32_t*) values, numValues);
+ int AddIdList(mirror::ObjectArray<mirror::Object>* values)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ int32_t length = values->GetLength();
+ for (int32_t i = 0; i < length; ++i) {
+ int err = AddObjectId(values->GetWithoutChecks(i));
+ if (UNLIKELY(err != 0)) {
+ return err;
+ }
+ }
+ return 0;
}
int AddUtf8String(const char* str) {
@@ -510,12 +526,11 @@ class Hprof {
HprofRecord* rec = &current_record_;
uint32_t nextSerialNumber = 1;
- for (ClassSetIterator it = classes_.begin(); it != classes_.end(); ++it) {
- const mirror::Class* c = *it;
- CHECK(c != NULL);
+ for (mirror::Class* c : classes_) {
+ CHECK(c != nullptr);
int err = current_record_.StartNewRecord(header_fp_, HPROF_TAG_LOAD_CLASS, HPROF_TIME);
- if (err != 0) {
+ if (UNLIKELY(err != 0)) {
return err;
}
@@ -525,9 +540,9 @@ class Hprof {
// U4: stack trace serial number
// ID: class name string ID
rec->AddU4(nextSerialNumber++);
- rec->AddId((HprofClassObjectId) c);
+ rec->AddObjectId(c);
rec->AddU4(HPROF_NULL_STACK_TRACE);
- rec->AddId(LookupClassNameId(c));
+ rec->AddStringId(LookupClassNameId(c));
}
return 0;
@@ -536,9 +551,9 @@ class Hprof {
int WriteStringTable() {
HprofRecord* rec = &current_record_;
- for (StringMapIterator it = strings_.begin(); it != strings_.end(); ++it) {
- const std::string& string = (*it).first;
- size_t id = (*it).second;
+ for (std::pair<std::string, HprofStringId> p : strings_) {
+ const std::string& string = p.first;
+ size_t id = p.second;
int err = current_record_.StartNewRecord(header_fp_, HPROF_TAG_STRING, HPROF_TIME);
if (err != 0) {
@@ -573,24 +588,26 @@ class Hprof {
int MarkRootObject(const mirror::Object* obj, jobject jniObj);
- HprofClassObjectId LookupClassId(mirror::Class* c)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (c == NULL) {
- // c is the superclass of java.lang.Object or a primitive
- return (HprofClassObjectId)0;
+ HprofClassObjectId LookupClassId(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (c == nullptr) {
+ // c is the superclass of java.lang.Object or a primitive.
+ return 0;
}
- std::pair<ClassSetIterator, bool> result = classes_.insert(c);
- const mirror::Class* present = *result.first;
+ {
+ auto result = classes_.insert(c);
+ const mirror::Class* present = *result.first;
+ CHECK_EQ(present, c);
+ }
// Make sure that we've assigned a string ID for this class' name
LookupClassNameId(c);
- CHECK_EQ(present, c);
- return (HprofStringId) present;
+ HprofClassObjectId result = PointerToLowMemUInt32(c);
+ return result;
}
- HprofStringId LookupStringId(mirror::String* string) {
+ HprofStringId LookupStringId(mirror::String* string) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return LookupStringId(string->ToModifiedUtf8());
}
@@ -599,7 +616,7 @@ class Hprof {
}
HprofStringId LookupStringId(const std::string& string) {
- StringMapIterator it = strings_.find(string);
+ auto it = strings_.find(string);
if (it != strings_.end()) {
return it->second;
}
@@ -608,8 +625,7 @@ class Hprof {
return id;
}
- HprofStringId LookupClassNameId(const mirror::Class* c)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ HprofStringId LookupClassNameId(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return LookupStringId(PrettyDescriptor(c));
}
@@ -675,9 +691,9 @@ class Hprof {
char* body_data_ptr_;
size_t body_data_size_;
- ClassSet classes_;
- size_t next_string_id_;
- StringMap strings_;
+ std::set<mirror::Class*> classes_;
+ HprofStringId next_string_id_;
+ SafeMap<std::string, HprofStringId> strings_;
DISALLOW_COPY_AND_ASSIGN(Hprof);
};
@@ -685,11 +701,8 @@ class Hprof {
#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.
-#define CLASS_STATICS_ID(c) ((HprofObjectId)(((uint32_t)(c)) | 1))
static HprofBasicType SignatureToBasicTypeAndSize(const char* sig, size_t* sizeOut) {
char c = sig[0];
@@ -765,15 +778,15 @@ int Hprof::MarkRootObject(const mirror::Object* obj, jobject jniObj) {
case HPROF_ROOT_DEBUGGER:
case HPROF_ROOT_VM_INTERNAL:
rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(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);
+ rec->AddObjectId(obj);
+ rec->AddJniGlobalRefId(jniObj);
break;
// ID: object ID
@@ -783,7 +796,7 @@ int Hprof::MarkRootObject(const mirror::Object* obj, jobject jniObj) {
case HPROF_ROOT_JNI_MONITOR:
case HPROF_ROOT_JAVA_FRAME:
rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(gc_thread_serial_number_);
rec->AddU4((uint32_t)-1);
break;
@@ -793,7 +806,7 @@ int Hprof::MarkRootObject(const mirror::Object* obj, jobject jniObj) {
case HPROF_ROOT_NATIVE_STACK:
case HPROF_ROOT_THREAD_BLOCK:
rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(gc_thread_serial_number_);
break;
@@ -802,7 +815,7 @@ int Hprof::MarkRootObject(const mirror::Object* obj, jobject jniObj) {
// U4: stack trace serial number
case HPROF_ROOT_THREAD_OBJECT:
rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(gc_thread_serial_number_);
rec->AddU4((uint32_t)-1); // xxx
break;
@@ -859,7 +872,7 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
nameId = LookupStringId("<ILLEGAL>");
break;
}
- rec->AddId(nameId);
+ rec->AddStringId(nameId);
current_heap_ = desiredHeap;
}
@@ -875,11 +888,11 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
// obj is a ClassObject.
size_t sFieldCount = thisClass->NumStaticFields();
if (sFieldCount != 0) {
- int byteLength = sFieldCount*sizeof(JValue); // TODO bogus; fields are packed
+ 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.
rec->AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
- rec->AddId(CLASS_STATICS_ID(obj));
+ rec->AddClassStaticsId(thisClass);
rec->AddU4(StackTraceSerialNumber(obj));
rec->AddU4(byteLength);
rec->AddU1(hprof_basic_byte);
@@ -889,14 +902,14 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
}
rec->AddU1(HPROF_CLASS_DUMP);
- rec->AddId(LookupClassId(thisClass));
+ rec->AddClassId(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
+ rec->AddClassId(LookupClassId(thisClass->GetSuperClass()));
+ rec->AddObjectId(thisClass->GetClassLoader());
+ rec->AddObjectId(nullptr); // no signer
+ rec->AddObjectId(nullptr); // no prot domain
+ rec->AddObjectId(nullptr); // reserved
+ rec->AddObjectId(nullptr); // reserved
if (thisClass->IsClassClass()) {
// ClassObjects have their static fields appended, so aren't all the same size.
// But they're at least this size.
@@ -916,9 +929,9 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
rec->AddU2((uint16_t)0);
} else {
rec->AddU2((uint16_t)(sFieldCount+1));
- rec->AddId(LookupStringId(STATIC_OVERHEAD_NAME));
+ rec->AddStringId(LookupStringId(STATIC_OVERHEAD_NAME));
rec->AddU1(hprof_basic_object);
- rec->AddId(CLASS_STATICS_ID(obj));
+ rec->AddClassStaticsId(thisClass);
for (size_t i = 0; i < sFieldCount; ++i) {
mirror::ArtField* f = thisClass->GetStaticField(i);
@@ -926,7 +939,7 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
size_t size;
HprofBasicType t = SignatureToBasicTypeAndSize(fh.GetTypeDescriptor(), &size);
- rec->AddId(LookupStringId(fh.GetName()));
+ rec->AddStringId(LookupStringId(fh.GetName()));
rec->AddU1(t);
if (size == 1) {
rec->AddU1(static_cast<uint8_t>(f->Get32(thisClass)));
@@ -949,24 +962,24 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
mirror::ArtField* f = thisClass->GetInstanceField(i);
fh.ChangeField(f);
HprofBasicType t = SignatureToBasicTypeAndSize(fh.GetTypeDescriptor(), NULL);
- rec->AddId(LookupStringId(fh.GetName()));
+ rec->AddStringId(LookupStringId(fh.GetName()));
rec->AddU1(t);
}
} else if (c->IsArrayClass()) {
- const mirror::Array* aobj = obj->AsArray();
+ mirror::Array* aobj = obj->AsArray();
uint32_t length = aobj->GetLength();
if (obj->IsObjectArray()) {
// obj is an object array.
rec->AddU1(HPROF_OBJECT_ARRAY_DUMP);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(StackTraceSerialNumber(obj));
rec->AddU4(length);
- rec->AddId(LookupClassId(c));
+ rec->AddClassId(LookupClassId(c));
// Dump the elements, which are always objects or NULL.
- rec->AddIdList((const HprofObjectId*)aobj->GetRawData(sizeof(mirror::Object*)), length);
+ rec->AddIdList(aobj->AsObjectArray<mirror::Object>());
} else {
size_t size;
HprofBasicType t = PrimitiveToBasicTypeAndSize(c->GetComponentType()->GetPrimitiveType(), &size);
@@ -974,28 +987,28 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
// obj is a primitive array.
rec->AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(StackTraceSerialNumber(obj));
rec->AddU4(length);
rec->AddU1(t);
// Dump the raw, packed element values.
if (size == 1) {
- rec->AddU1List((const uint8_t*)aobj->GetRawData(sizeof(uint8_t)), length);
+ rec->AddU1List((const uint8_t*)aobj->GetRawData(sizeof(uint8_t), 0), length);
} else if (size == 2) {
- rec->AddU2List((const uint16_t*)aobj->GetRawData(sizeof(uint16_t)), length);
+ rec->AddU2List((const uint16_t*)aobj->GetRawData(sizeof(uint16_t), 0), length);
} else if (size == 4) {
- rec->AddU4List((const uint32_t*)aobj->GetRawData(sizeof(uint32_t)), length);
+ rec->AddU4List((const uint32_t*)aobj->GetRawData(sizeof(uint32_t), 0), length);
} else if (size == 8) {
- rec->AddU8List((const uint64_t*)aobj->GetRawData(sizeof(uint64_t)), length);
+ rec->AddU8List((const uint64_t*)aobj->GetRawData(sizeof(uint64_t), 0), length);
}
}
} else {
// obj is an instance object.
rec->AddU1(HPROF_INSTANCE_DUMP);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(StackTraceSerialNumber(obj));
- rec->AddId(LookupClassId(c));
+ rec->AddClassId(LookupClassId(c));
// Reserve some space for the length of the instance data, which we won't
// know until we're done writing it.
@@ -1004,7 +1017,7 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
// 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 mirror::Class* sclass = c;
+ mirror::Class* sclass = c;
FieldHelper fh;
while (!sclass->IsObjectClass()) {
int ifieldCount = sclass->NumInstanceFields();
@@ -1019,10 +1032,9 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
rec->AddU2(f->Get32(obj));
} else if (size == 4) {
rec->AddU4(f->Get32(obj));
- } else if (size == 8) {
- rec->AddU8(f->Get64(obj));
} else {
- CHECK(false);
+ CHECK_EQ(size, 8U);
+ rec->AddU8(f->Get64(obj));
}
}