Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit fecdde2

Browse files
authored
Merge pull request #7 from hankluo6/object_heap
Implement object heap
2 parents 3181bc7 + 54662e2 commit fecdde2

File tree

12 files changed

+463
-57
lines changed

12 files changed

+463
-57
lines changed

‎Makefile‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ OBJS = \
77
stack.o \
88
constant-pool.o \
99
classfile.o \
10-
class-heap.o
10+
class-heap.o \
11+
object-heap.o
1112

1213
deps := $(OBJS:%.o=.%.o.d)
1314

@@ -43,8 +44,9 @@ TESTS = \
4344
Primes \
4445
Recursion \
4546
Long \
46-
Caller
47-
47+
Caller \
48+
Constructor
49+
4850
check: $(addprefix tests/,$(TESTS:=-result.out))
4951

5052
ifneq (, $(shell which valgrind))

‎class-heap.c‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,52 @@ class_file_t *find_class_from_heap(char *value)
3535
return NULL;
3636
}
3737

38+
class_file_t *find_or_add_class_to_heap(char *class_name, char *prefix)
39+
{
40+
class_file_t *target_class = find_class_from_heap(class_name);
41+
42+
/* if class is not found, adding specific class path and finding
43+
* again. This can be removed by recording path infomation in class
44+
* heap
45+
*/
46+
if (!target_class && prefix) {
47+
char *tmp = malloc(strlen(class_name) + strlen(prefix) + 1);
48+
strcpy(tmp, prefix);
49+
strcat(tmp, class_name);
50+
target_class = find_class_from_heap(tmp);
51+
52+
free(tmp);
53+
}
54+
55+
/* if class is still not found, meaning that this class is not
56+
* loaded in class heap, so add it to the class heap. */
57+
if (!target_class) {
58+
char *tmp;
59+
if (prefix) {
60+
tmp = malloc(
61+
(strlen(class_name) + strlen(".class") + strlen(prefix) + 1));
62+
strcpy(tmp, prefix);
63+
strcat(tmp, class_name);
64+
} else {
65+
tmp = malloc(strlen(class_name) + strlen(".class") + 1);
66+
strcpy(tmp, class_name);
67+
}
68+
/* attempt to read given class file */
69+
FILE *class_file = fopen(strcat(tmp, ".class"), "r");
70+
assert(class_file && "Failed to open file");
71+
72+
/* parse the class file */
73+
target_class = malloc(sizeof(class_file_t));
74+
*target_class = get_class(class_file);
75+
int error = fclose(class_file);
76+
assert(!error && "Failed to close file");
77+
add_class(target_class, tmp);
78+
free(tmp);
79+
}
80+
81+
return target_class;
82+
}
83+
3884
void free_class_heap()
3985
{
4086
for (int i = 0; i < class_heap.length; ++i) {
@@ -45,6 +91,7 @@ void free_class_heap()
4591
free(constant->info);
4692
}
4793
free(class_heap.class_info[i]->clazz->constant_pool.constant_pool);
94+
free(class_heap.class_info[i]->clazz->fields);
4895

4996
for (method_t *method = class_heap.class_info[i]->clazz->methods;
5097
method->name; method++) {

‎class-heap.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ void init_class_heap();
1111
void free_class_heap();
1212
void add_class(class_file_t *clazz, char *name);
1313
class_file_t *find_class_from_heap(char *value);
14+
class_file_t *find_or_add_class_to_heap(char *class_name, char *prefix);
1415
char *find_method_info_from_index(uint16_t idx,
1516
class_file_t *clazz,
1617
char **name_info,

‎classfile.c‎

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ class_info_t get_class_info(FILE *class_file)
1818
};
1919
u2 interfaces_count = read_u2(class_file);
2020
assert(!interfaces_count && "This VM does not support interfaces.");
21-
u2 fields_count = read_u2(class_file);
22-
assert(!fields_count && "This VM does not support fields.");
2321
return info;
2422
}
2523

@@ -92,6 +90,75 @@ char *find_method_info_from_index(uint16_t idx,
9290
return (char *) class_name->info;
9391
}
9492

93+
CONSTANT_FieldOrMethodRef_info *get_fieldref(constant_pool_t *cp, u2 idx)
94+
{
95+
const_pool_info *field = get_constant(cp, idx);
96+
assert(field->tag == CONSTANT_FieldRef && "Expected a FieldRef");
97+
return (CONSTANT_FieldOrMethodRef_info *) field->info;
98+
}
99+
100+
/**
101+
* Find the field info corresponding to the given constant pool index.
102+
*
103+
* @param index the constant pool index of the Methodref to call
104+
* @param clazz the parsed class file
105+
* @param name_info the pointer that will contain method name on return
106+
* @param descriptor_info the pointer that will contain method infomation on
107+
* return
108+
* @return the class name which has this field
109+
*/
110+
char *find_field_info_from_index(uint16_t idx,
111+
class_file_t *clazz,
112+
char **name_info,
113+
char **descriptor_info)
114+
{
115+
CONSTANT_FieldOrMethodRef_info *field_ref =
116+
get_fieldref(&clazz->constant_pool, idx);
117+
const_pool_info *name_and_type =
118+
get_constant(&clazz->constant_pool, field_ref->name_and_type_index);
119+
assert(name_and_type->tag == CONSTANT_NameAndType &&
120+
"Expected a NameAndType");
121+
const_pool_info *name = get_constant(
122+
&clazz->constant_pool,
123+
((CONSTANT_NameAndType_info *) name_and_type->info)->name_index);
124+
assert(name->tag == CONSTANT_Utf8 && "Expected a UTF8");
125+
const_pool_info *descriptor = get_constant(
126+
&clazz->constant_pool,
127+
((CONSTANT_NameAndType_info *) name_and_type->info)->descriptor_index);
128+
assert(descriptor->tag == CONSTANT_Utf8 && "Expected a UTF8");
129+
CONSTANT_Class_info *class_info =
130+
get_class_name(&clazz->constant_pool, field_ref->class_index);
131+
const_pool_info *class_name =
132+
get_constant(&clazz->constant_pool, class_info->string_index);
133+
*name_info = (char *) name->info;
134+
*descriptor_info = (char *) descriptor->info;
135+
136+
return (char *) class_name->info;
137+
}
138+
139+
char *find_class_name_from_index(uint16_t idx, class_file_t *clazz)
140+
{
141+
CONSTANT_Class_info *class = get_class_name(&clazz->constant_pool, idx);
142+
143+
const_pool_info *name =
144+
get_constant(&clazz->constant_pool, class->string_index);
145+
assert(name->tag == CONSTANT_Utf8 && "Expected a UTF8");
146+
return (char *) name->info;
147+
}
148+
149+
void read_field_attributes(FILE *class_file, field_info *info)
150+
{
151+
for (u2 i = 0; i < info->attributes_count; i++) {
152+
attribute_info ainfo = {
153+
.attribute_name_index = read_u2(class_file),
154+
.attribute_length = read_u4(class_file),
155+
};
156+
long attribute_end = ftell(class_file) + ainfo.attribute_length;
157+
/* Skip all the attribute */
158+
fseek(class_file, attribute_end, SEEK_SET);
159+
}
160+
}
161+
95162
void read_method_attributes(FILE *class_file,
96163
method_info *info,
97164
code_t *code,
@@ -129,6 +196,37 @@ void read_method_attributes(FILE *class_file,
129196

130197
#define IS_STATIC 0x0008
131198

199+
field_t *get_fields(FILE *class_file, constant_pool_t *cp, class_file_t *clazz)
200+
{
201+
u2 fields_count = read_u2(class_file);
202+
clazz->fields_count = fields_count;
203+
field_t *fields = malloc(sizeof(*fields) * (fields_count + 1));
204+
assert(fields && "Failed to allocate methods");
205+
206+
field_t *field = fields;
207+
for (u2 i = 0; i < fields_count; i++, field++) {
208+
field_info info = {
209+
.access_flags = read_u2(class_file),
210+
.name_index = read_u2(class_file),
211+
.descriptor_index = read_u2(class_file),
212+
.attributes_count = read_u2(class_file),
213+
};
214+
215+
const_pool_info *name = get_constant(cp, info.name_index);
216+
assert(name->tag == CONSTANT_Utf8 && "Expected a UTF8");
217+
field->name = (char *) name->info;
218+
const_pool_info *descriptor = get_constant(cp, info.descriptor_index);
219+
assert(descriptor->tag == CONSTANT_Utf8 && "Expected a UTF8");
220+
field->descriptor = (char *) descriptor->info;
221+
222+
read_field_attributes(class_file, &info);
223+
}
224+
225+
/* Mark end of array with NULL name */
226+
field->name = NULL;
227+
return fields;
228+
}
229+
132230
method_t *get_methods(FILE *class_file, constant_pool_t *cp)
133231
{
134232
u2 method_count = read_u2(class_file);
@@ -184,6 +282,9 @@ class_file_t get_class(FILE *class_file)
184282
/* Read information about the class that was compiled. */
185283
get_class_info(class_file);
186284

285+
/* Read the list of fields */
286+
clazz.fields = get_fields(class_file, &clazz.constant_pool, &clazz);
287+
187288
/* Read the list of static methods */
188289
clazz.methods = get_methods(class_file, &clazz.constant_pool);
189290
return clazz;

‎classfile.h‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ typedef struct {
2222
u2 attributes_count;
2323
} method_info;
2424

25+
typedef struct {
26+
u2 access_flags;
27+
u2 name_index;
28+
u2 descriptor_index;
29+
u2 attributes_count;
30+
} field_info;
31+
2532
typedef struct {
2633
u2 attribute_name_index;
2734
u4 attribute_length;
@@ -40,9 +47,17 @@ typedef struct {
4047
code_t code;
4148
} method_t;
4249

50+
typedef struct {
51+
char *class_name;
52+
char *name;
53+
char *descriptor;
54+
} field_t;
55+
4356
typedef struct {
4457
constant_pool_t constant_pool;
4558
method_t *methods;
59+
field_t *fields;
60+
u2 fields_count;
4661
} class_file_t;
4762

4863
typedef struct {
@@ -60,4 +75,12 @@ void read_method_attributes(FILE *class_file,
6075
uint16_t get_number_of_parameters(method_t *method);
6176
method_t *find_method(const char *name, const char *desc, class_file_t *clazz);
6277
method_t *find_method_from_index(uint16_t idx, class_file_t *clazz);
63-
class_file_t get_class(FILE *class_file);
78+
class_file_t get_class(FILE *class_file);
79+
char *find_class_name_from_index(uint16_t idx, class_file_t *clazz);
80+
CONSTANT_FieldOrMethodRef_info *get_fieldref(constant_pool_t *cp, u2 idx);
81+
char *find_field_info_from_index(uint16_t idx,
82+
class_file_t *clazz,
83+
char **name_info,
84+
char **descriptor_info);
85+
void read_field_attributes(FILE *class_file, field_info *info);
86+
field_t *get_fields(FILE *class_file, constant_pool_t *cp, class_file_t *clazz);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /