Signed-off-by: Vegard Nossum <vegard.nos...@gmail.com> --- include/vm/field.h | 4 +- vm/class.c | 135 +++++++++++++++++++++++++++++++++++++++++---------- vm/field.c | 11 +---- 3 files changed, 112 insertions(+), 38 deletions(-)
diff --git a/include/vm/field.h b/include/vm/field.h index 4a5a557..20bfc0f 100644 --- a/include/vm/field.h +++ b/include/vm/field.h @@ -25,8 +25,8 @@ struct vm_field { int vm_field_init(struct vm_field *vmf, struct vm_class *vmc, unsigned int field_index); -void vm_field_init_nonstatic(struct vm_field *vmf, unsigned int offset); -int vm_field_init_static(struct vm_field *vmf, unsigned int offset); +void vm_field_init_nonstatic(struct vm_field *vmf); +int vm_field_init_static(struct vm_field *vmf); static inline bool vm_field_is_static(const struct vm_field *vmf) { diff --git a/vm/class.c b/vm/class.c index 8cb6ebb..f35fba5 100644 --- a/vm/class.c +++ b/vm/class.c @@ -37,6 +37,8 @@ #include "cafebabe/method_info.h" #include "cafebabe/stream.h" +#include "lib/string.h" + #include "vm/class.h" #include "vm/classloader.h" #include "vm/die.h" @@ -46,8 +48,8 @@ #include "vm/itable.h" #include "vm/method.h" #include "vm/object.h" +#include "vm/stdlib.h" #include "vm/thread.h" -#include "lib/string.h" #include "vm/vm.h" #include "jit/exception.h" @@ -141,6 +143,64 @@ static int vm_class_link_common(struct vm_class *vmc) return 0; } +/* + * This is used for grouping fields by their type, so that we can: + * + * 1. put reference types first (improves GC) + * 2. sort the rest of the fields by size (improves object layout) + */ +struct field_bucket { + unsigned int nr; + struct vm_field **fields; +}; + +static void bucket_order_fields(struct field_bucket *bucket, + unsigned int size, unsigned int *offset) +{ + unsigned int tmp_offset = *offset; + + for (unsigned int i = 0; i < bucket->nr; ++i) { + struct vm_field *vmf = bucket->fields[i]; + + vmf->offset = tmp_offset; + tmp_offset += size; + } + + *offset = tmp_offset; +} + +static void buckets_order_fields(struct field_bucket buckets[VM_TYPE_MAX], + unsigned int *ref_size, unsigned int *size) +{ + unsigned int offset = *size; + + /* We need to align here, because offset might be non-zero from the + * parent class. */ + offset = ALIGN(offset, sizeof(void *)); + bucket_order_fields(&buckets[J_REFERENCE], sizeof(void *), &offset); + + /* Align with 8-byte boundary here. We don't need to align anything + * after this, since we _know_ e.g. that after 8-byte fields, we will + * always be 8-byte aligned, which is also always 4-byte aligned. */ + offset = ALIGN(offset, 8); + + bucket_order_fields(&buckets[J_DOUBLE], 8, &offset); + bucket_order_fields(&buckets[J_LONG], 8, &offset); + + bucket_order_fields(&buckets[J_FLOAT], 4, &offset); + bucket_order_fields(&buckets[J_INT], 4, &offset); + + /* XXX: Should be size = 2 */ + bucket_order_fields(&buckets[J_SHORT], 4, &offset); + bucket_order_fields(&buckets[J_CHAR], 4, &offset); + + /* XXX: Should be size = 1 */ + bucket_order_fields(&buckets[J_BYTE], 4, &offset); + bucket_order_fields(&buckets[J_BOOLEAN], 4, &offset); + + *size = offset; +} + int vm_class_link(struct vm_class *vmc, const struct cafebabe_class *class) { int err; @@ -254,55 +314,76 @@ int vm_class_link(struct vm_class *vmc, const struct cafebabe_class *class) return -1; } - unsigned int offset; - unsigned int static_offset; + for (uint16_t i = 0; i < class->fields_count; ++i) { + struct vm_field *vmf = &vmc->fields[i]; + + if (vm_field_init(vmf, vmc, i)) { + NOT_IMPLEMENTED; + return -1; + } + } if (vmc->super) { - offset = vmc->super->object_size; - static_offset = vmc->super->static_size; + vmc->static_size = vmc->super->static_size; + vmc->object_size = vmc->super->object_size; } else { - offset = 0; - static_offset = 0; + vmc->static_size = 0; + vmc->object_size = 0; } - unsigned int static_size = 0; - unsigned int object_size = 0; + struct field_bucket field_buckets[2][VM_TYPE_MAX]; + for (unsigned int i = 0; i < VM_TYPE_MAX; ++i) { + field_buckets[0][i].nr = 0; + field_buckets[1][i].nr = 0; + } + /* Count the number of fields for each bucket */ for (uint16_t i = 0; i < class->fields_count; ++i) { struct vm_field *vmf = &vmc->fields[i]; + unsigned int stat = vm_field_is_static(vmf) ? 0 : 1; + enum vm_type type = str_to_type(vmf->type); + struct field_bucket *bucket = &field_buckets[stat][type]; - if (vm_field_init(vmf, vmc, i)) { - NOT_IMPLEMENTED; - return -1; + ++bucket->nr; + } + + /* Allocate enough space in each bucket */ + for (unsigned int i = 0; i < VM_TYPE_MAX; ++i) { + for (unsigned int j = 0; j < 2; ++j) { + struct field_bucket *bucket = &field_buckets[j][i]; + + bucket->fields = malloc(bucket->nr * sizeof(*bucket->fields)); + bucket->nr = 0; } + } - if (vm_field_is_static(vmf)) - static_size += 8; - else - object_size += 8; + /* Place the fields in the buckets */ + for (uint16_t i = 0; i < class->fields_count; ++i) { + struct vm_field *vmf = &vmc->fields[i]; + unsigned int stat = vm_field_is_static(vmf) ? 0 : 1; + enum vm_type type = str_to_type(vmf->type); + struct field_bucket *bucket = &field_buckets[stat][type]; + + bucket->fields[bucket->nr++] = vmf; } - /* XXX: only static fields, right size, etc. */ - vmc->static_size = static_offset + static_size; - vmc->static_values = malloc(vmc->static_size); + unsigned int tmp; + buckets_order_fields(field_buckets[0], &tmp, &vmc->static_size); + buckets_order_fields(field_buckets[1], &tmp, &vmc->object_size); - vmc->object_size = offset + object_size; + /* XXX: only static fields, right size, etc. */ + vmc->static_values = zalloc(vmc->static_size); for (uint16_t i = 0; i < class->fields_count; ++i) { struct vm_field *vmf = &vmc->fields[i]; if (vm_field_is_static(vmf)) { - if (vm_field_init_static(vmf, static_offset)) { + if (vm_field_init_static(vmf)) { NOT_IMPLEMENTED; return -1; } - - /* XXX: Same as below */ - static_offset += 8; } else { - vm_field_init_nonstatic(vmf, offset); - /* XXX: Do field reordering and use the right sizes */ - offset += 8; + vm_field_init_nonstatic(vmf); } } diff --git a/vm/field.c b/vm/field.c index 2d012b6..babc286 100644 --- a/vm/field.c +++ b/vm/field.c @@ -54,24 +54,17 @@ int vm_field_init(struct vm_field *vmf, return 0; } -void vm_field_init_nonstatic(struct vm_field *vmf, unsigned int offset) +void vm_field_init_nonstatic(struct vm_field *vmf) { - vmf->offset = offset; } -int vm_field_init_static(struct vm_field *vmf, unsigned int offset) +int vm_field_init_static(struct vm_field *vmf) { - vmf->offset = offset; - const struct vm_class *vmc = vmf->class; const struct cafebabe_class *class = vmc->class; const struct cafebabe_field_info *field = &class->fields[vmf->field_index]; - /* XXX: Might have to change this when our fields have different - * sizes internally as well. */ - *(unsigned long *) &vmc->static_values[offset] = 0; - unsigned int constant_value_index = 0; if (cafebabe_attribute_array_get(&field->attributes, "ConstantValue", class, &constant_value_index)) -- 1.6.0.6 ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel