Move allocation of fields and methods to heap
Also make Object and subclasses constructors private to prevent
accidental non-heap allocation.
Change-Id: If9513967ba012748eb0d54c04e92df0f0944d385
diff --git a/src/class_linker.cc b/src/class_linker.cc
index a205a06..15c2e40 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -172,36 +172,42 @@
// Load static fields.
if (klass->num_sfields_ != 0) {
// TODO: allocate on the object heap.
- klass->sfields_ = new StaticField[klass->NumStaticFields()]();
+ klass->sfields_ = new StaticField*[klass->NumStaticFields()]();
uint32_t last_idx = 0;
for (size_t i = 0; i < klass->num_sfields_; ++i) {
RawDexFile::Field raw_field;
raw->dexReadClassDataField(&class_data, &raw_field, &last_idx);
- LoadField(klass, raw_field, &klass->sfields_[i]);
+ StaticField* sfield = Heap::AllocStaticField();
+ klass->sfields_[i] = sfield;
+ LoadField(klass, raw_field, sfield);
}
}
// Load instance fields.
if (klass->NumInstanceFields() != 0) {
// TODO: allocate on the object heap.
- klass->ifields_ = new InstanceField[klass->NumInstanceFields()]();
+ klass->ifields_ = new InstanceField*[klass->NumInstanceFields()]();
uint32_t last_idx = 0;
for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
RawDexFile::Field raw_field;
raw->dexReadClassDataField(&class_data, &raw_field, &last_idx);
- LoadField(klass, raw_field, klass->GetInstanceField(i));
+ InstanceField* ifield = Heap::AllocInstanceField();
+ klass->ifields_[i] = ifield;
+ LoadField(klass, raw_field, ifield);
}
}
// Load direct methods.
if (klass->NumDirectMethods() != 0) {
// TODO: append direct methods to class object
- klass->direct_methods_ = new Method[klass->NumDirectMethods()]();
+ klass->direct_methods_ = new Method*[klass->NumDirectMethods()]();
uint32_t last_idx = 0;
for (size_t i = 0; i < klass->NumDirectMethods(); ++i) {
RawDexFile::Method raw_method;
raw->dexReadClassDataMethod(&class_data, &raw_method, &last_idx);
- LoadMethod(klass, raw_method, klass->GetDirectMethod(i));
+ Method* meth = Heap::AllocMethod();
+ klass->direct_methods_[i] = meth;
+ LoadMethod(klass, raw_method, meth);
// TODO: register maps
}
}
@@ -209,12 +215,14 @@
// Load virtual methods.
if (klass->NumVirtualMethods() != 0) {
// TODO: append virtual methods to class object
- klass->virtual_methods_ = new Method[klass->NumVirtualMethods()]();
+ klass->virtual_methods_ = new Method*[klass->NumVirtualMethods()]();
uint32_t last_idx = 0;
for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
RawDexFile::Method raw_method;
raw->dexReadClassDataMethod(&class_data, &raw_method, &last_idx);
- LoadMethod(klass, raw_method, klass->GetVirtualMethod(i));
+ Method* meth = Heap::AllocMethod();
+ klass->virtual_methods_[i] = meth;
+ LoadMethod(klass, raw_method, meth);
// TODO: register maps
}
}
@@ -922,39 +930,28 @@
}
}
if (miranda_count != 0) {
- Method* newVirtualMethods;
- Method* meth;
- int oldMethodCount, oldVtableCount;
- if (klass->virtual_methods_ == NULL) {
- newVirtualMethods = new Method[klass->NumVirtualMethods() + miranda_count];
-
- } else {
- newVirtualMethods = new Method[klass->NumVirtualMethods() + miranda_count];
+ int oldMethodCount = klass->NumVirtualMethods();
+ int newMethodCount = oldMethodCount + miranda_count;
+ Method** newVirtualMethods = new Method*[newMethodCount];
+ if (klass->virtual_methods_ != NULL) {
memcpy(newVirtualMethods,
klass->virtual_methods_,
- klass->NumVirtualMethods() * sizeof(Method));
-
+ klass->NumVirtualMethods() * sizeof(Method*));
}
- if (newVirtualMethods != klass->virtual_methods_) {
- Method* meth = newVirtualMethods;
- for (size_t i = 0; i < klass->NumVirtualMethods(); i++, meth++) {
- klass->vtable_[meth->method_index_] = meth;
- }
- }
- oldMethodCount = klass->NumVirtualMethods();
klass->virtual_methods_ = newVirtualMethods;
- klass->num_virtual_methods_ += miranda_count;
+ klass->num_virtual_methods_ = newMethodCount;
CHECK(klass->vtable_ != NULL);
- oldVtableCount = klass->vtable_count_;
+ int oldVtableCount = klass->vtable_count_;
klass->vtable_count_ += miranda_count;
- meth = klass->virtual_methods_ + oldMethodCount;
- for (int i = 0; i < miranda_count; i++, meth++) {
+ for (int i = 0; i < miranda_count; i++) {
+ Method* meth = Heap::AllocMethod();
memcpy(meth, miranda_list[i], sizeof(Method));
meth->klass_ = klass;
meth->access_flags_ |= kAccMiranda;
meth->method_index_ = 0xFFFF & (oldVtableCount + i);
+ klass->virtual_methods_[oldMethodCount+i] = meth;
klass->vtable_[oldVtableCount + i] = meth;
}
}
@@ -980,17 +977,18 @@
// Move references to the front.
klass->num_reference_ifields_ = 0;
size_t i = 0;
- size_t j = klass->NumInstanceFields() - 1;
- for (size_t i = 0; i < klass->NumInstanceFields(); i++) {
+ for ( ; i < klass->NumInstanceFields(); i++) {
InstanceField* pField = klass->GetInstanceField(i);
char c = pField->GetType();
if (c != '[' && c != 'L') {
- while (j > i) {
- InstanceField* refField = klass->GetInstanceField(j--);
+ for (size_t j = klass->NumInstanceFields() - 1; j > i; j--) {
+ InstanceField* refField = klass->GetInstanceField(j);
char rc = refField->GetType();
if (rc == '[' || rc == 'L') {
- pField->Swap(refField);
+ klass->SetInstanceField(i, refField);
+ klass->SetInstanceField(j, pField);
+ pField = refField;
c = rc;
klass->num_reference_ifields_++;
break;
@@ -1023,12 +1021,13 @@
// Next field is 64-bit, so search for a 32-bit field we can
// swap into it.
bool found = false;
- j = klass->NumInstanceFields() - 1;
- while (j > i) {
- InstanceField* singleField = klass->GetInstanceField(j--);
+ for (size_t j = klass->NumInstanceFields() - 1; j > i; j--) {
+ InstanceField* singleField = klass->GetInstanceField(j);
char rc = singleField->GetType();
if (rc != 'J' && rc != 'D') {
- pField->Swap(singleField);
+ klass->SetInstanceField(i, singleField);
+ klass->SetInstanceField(j, pField);
+ pField = singleField;
pField->SetOffset(fieldOffset);
fieldOffset += sizeof(uint32_t);
found = true;
@@ -1045,16 +1044,17 @@
// Alignment is good, shuffle any double-wide fields forward, and
// finish assigning field offsets to all fields.
assert(i == klass->NumInstanceFields() || (fieldOffset & 0x04) == 0);
- j = klass->NumInstanceFields() - 1;
for ( ; i < klass->NumInstanceFields(); i++) {
InstanceField* pField = klass->GetInstanceField(i);
char c = pField->GetType();
if (c != 'D' && c != 'J') {
- while (j > i) {
- InstanceField* doubleField = klass->GetInstanceField(j--);
+ for (size_t j = klass->NumInstanceFields() - 1; j > i; j--) {
+ InstanceField* doubleField = klass->GetInstanceField(j);
char rc = doubleField->GetType();
if (rc == 'D' || rc == 'J') {
- pField->Swap(doubleField);
+ klass->SetInstanceField(i, doubleField);
+ klass->SetInstanceField(j, pField);
+ pField = doubleField;
c = rc;
break;
}
diff --git a/src/heap.h b/src/heap.h
index 7c679eb..b9f7937 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -26,6 +26,24 @@
return klass;
}
+ static StaticField* AllocStaticField() {
+ size_t size = sizeof(StaticField);
+ byte* raw = new byte[size]();
+ return reinterpret_cast<StaticField*>(raw);
+ }
+
+ static InstanceField* AllocInstanceField() {
+ size_t size = sizeof(InstanceField);
+ byte* raw = new byte[size]();
+ return reinterpret_cast<InstanceField*>(raw);
+ }
+
+ static Method* AllocMethod() {
+ size_t size = sizeof(Method);
+ byte* raw = new byte[size]();
+ return reinterpret_cast<Method*>(raw);
+ }
+
static CharArray* AllocCharArray(size_t length) {
size_t size = sizeof(Array) + length * sizeof(uint16_t);
byte* raw = new byte[size]();
diff --git a/src/object.h b/src/object.h
index ac42081..d7df9dc 100644
--- a/src/object.h
+++ b/src/object.h
@@ -156,6 +156,7 @@
Monitor* monitor_;
private:
+ Object();
DISALLOW_COPY_AND_ASSIGN(Object);
};
@@ -187,7 +188,7 @@
DISALLOW_COPY_AND_ASSIGN(ObjectLock);
};
-class Field {
+class Field : public Object {
public:
Class* GetClass() const {
return klass_;
@@ -206,6 +207,17 @@
}
public: // TODO: private
+#define FIELD_FIELD_SLOTS 1+6
+ // AccessibleObject #0 flag
+ // Field #0 declaringClass
+ // Field #1 genericType
+ // Field #2 genericTypesAreInitialized
+ // Field #3 name
+ // Field #4 slot
+ // Field #5 type
+ uint32_t instance_data_[FIELD_FIELD_SLOTS];
+#undef FIELD_FIELD_SLOTS
+
// The class in which this field is declared.
Class* klass_;
@@ -215,6 +227,9 @@
const char* signature_;
uint32_t access_flags_;
+
+ private:
+ Field();
};
// Instance fields.
@@ -228,16 +243,9 @@
offset_ = num_bytes;
}
- // TODO: stl::swap
- void Swap(InstanceField* that) {
- InstanceField tmp;
- memcpy(&tmp, this, sizeof(InstanceField));
- memcpy(this, that, sizeof(InstanceField));
- memcpy(that, &tmp, sizeof(InstanceField));
- }
-
private:
size_t offset_;
+ InstanceField();
};
// Static fields.
@@ -296,9 +304,10 @@
private:
JValue value_;
+ StaticField();
};
-class Method {
+class Method : public Object {
public:
// Returns the method name.
// TODO: example
@@ -374,6 +383,22 @@
bool HasSameArgumentTypes(const Method* that) const;
public: // TODO: private
+#define METHOD_FIELD_SLOTS 1+11
+ // AccessibleObject #0 flag
+ // Method #0 declaringClass
+ // Method #1 exceptionTypes
+ // Method #2 formalTypeParameters
+ // Method #3 genericExceptionTypes
+ // Method #4 genericParameterTypes
+ // Method #5 genericReturnType
+ // Method #6 genericTypesAreInitialized
+ // Method #7 name
+ // Method #8 parameterTypes
+ // Method #9 returnType
+ // Method #10 slot
+ uint32_t instance_data_[METHOD_FIELD_SLOTS];
+#undef METHOD_FIELD_SLOTS
+
// the class we are a part of
Class* klass_;
@@ -406,6 +431,9 @@
// A pointer to the memory-mapped DEX code.
const uint16_t* insns_;
+
+ private:
+ Method();
};
// Class objects.
@@ -533,7 +561,7 @@
}
Method* GetDirectMethod(uint32_t i) const {
- return &direct_methods_[i];
+ return direct_methods_[i];
}
// Returns the number of non-inherited virtual methods.
@@ -542,7 +570,7 @@
}
Method* GetVirtualMethod(uint32_t i) const {
- return &virtual_methods_[i];
+ return virtual_methods_[i];
}
size_t NumInstanceFields() const {
@@ -554,7 +582,11 @@
}
InstanceField* GetInstanceField(uint32_t i) { // TODO: uint16_t
- return &ifields_[i];
+ return ifields_[i];
+ }
+
+ void SetInstanceField(uint32_t i, InstanceField* f) { // TODO: uint16_t
+ ifields_[i] = f;
}
size_t NumStaticFields() const {
@@ -562,7 +594,7 @@
}
StaticField* GetStaticField(uint32_t i) { // TODO: uint16_t
- return &sfields_[i];
+ return sfields_[i];
}
uint32_t GetReferenceOffsets() const {
@@ -579,7 +611,8 @@
public: // TODO: private
// leave space for instance data; we could access fields directly if
// we freeze the definition of java/lang/Class
-#define CLASS_FIELD_SLOTS 4
+#define CLASS_FIELD_SLOTS 1
+ // Class.#0 name
uint32_t instance_data_[CLASS_FIELD_SLOTS];
#undef CLASS_FIELD_SLOTS
@@ -642,11 +675,11 @@
// static, private, and <init> methods
size_t num_direct_methods_;
- Method* direct_methods_;
+ Method** direct_methods_;
// virtual methods defined in this class; invoked through vtable
size_t num_virtual_methods_;
- Method* virtual_methods_;
+ Method** virtual_methods_;
// Virtual method table (vtable), for use by "invoke-virtual". The
// vtable from the superclass is copied in, and virtual methods from
@@ -690,7 +723,7 @@
// number of fields that are object refs
size_t num_reference_ifields_;
- InstanceField* ifields_;
+ InstanceField** ifields_;
// Bitmap of offsets of ifields.
uint32_t reference_offsets_;
@@ -700,13 +733,18 @@
// Static fields
size_t num_sfields_;
- StaticField* sfields_;
+ StaticField** sfields_;
+
+ private:
+ Class();
};
std::ostream& operator<<(std::ostream& os, const Class::Status& rhs);
class DataObject : public Object {
public:
uint32_t fields_[1];
+ private:
+ DataObject();
};
class Array : public Object {
@@ -718,9 +756,13 @@
private:
// The number of array elements.
uint32_t length_;
+ Array();
};
-class CharArray : public Array {};
+class CharArray : public Array {
+ private:
+ CharArray();
+};
class String : public Object {
public:
@@ -731,6 +773,9 @@
uint32_t offset_;
uint32_t count_;
+
+ private:
+ String();
};
class InterfaceEntry {