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 7d71178

Browse files
committed
Implement getstatic and putstatic
Add a new test script: "Static.java"
1 parent 0d95b5c commit 7d71178

File tree

6 files changed

+171
-3
lines changed

6 files changed

+171
-3
lines changed

‎Makefile‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ TESTS = \
4646
Long \
4747
Caller \
4848
Constructor \
49-
Field
49+
Field \
50+
Static
5051

5152
check: $(addprefix tests/,$(TESTS:=-result.out))
5253

‎class-heap.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ void free_class_heap()
9191
free(constant->info);
9292
}
9393
free(class_heap.class_info[i]->clazz->constant_pool.constant_pool);
94+
95+
field_t *field = class_heap.class_info[i]->clazz->fields;
96+
for (u2 j = 0; j < class_heap.class_info[i]->clazz->fields_count;
97+
j++, field++)
98+
free(field->static_var);
9499
free(class_heap.class_info[i]->clazz->fields);
95100

96101
for (method_t *method = class_heap.class_info[i]->clazz->methods;

‎classfile.c‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,27 @@ uint16_t get_number_of_parameters(method_t *method)
3131
return strlen(method->descriptor) - 3;
3232
}
3333

34+
/**
35+
* Find the field with the given name and signature.
36+
* The difference between `find_field` and `object_heap:find_field_addr`
37+
* is that `find_field` is used to find class level field (i.e. static field),
38+
* and `find_field_addr` is used to find object level field.
39+
*
40+
* @param name the field name
41+
* @param desc the field descriptor string, e.g. "(I)I"
42+
* @param clazz the parsed class file
43+
* @return the field if it was found, or NULL
44+
*/
45+
field_t *find_field(const char *name, const char *desc, class_file_t *clazz)
46+
{
47+
field_t *field = clazz->fields;
48+
for (u2 i = 0; i < clazz->fields_count; ++i, field++) {
49+
if (!(strcmp(name, field->name) || strcmp(desc, field->descriptor)))
50+
return field;
51+
}
52+
return NULL;
53+
}
54+
3455
/**
3556
* Find the method with the given name and signature.
3657
* The descriptor is necessary because Java allows method overloading.
@@ -218,6 +239,7 @@ field_t *get_fields(FILE *class_file, constant_pool_t *cp, class_file_t *clazz)
218239
const_pool_info *descriptor = get_constant(cp, info.descriptor_index);
219240
assert(descriptor->tag == CONSTANT_Utf8 && "Expected a UTF8");
220241
field->descriptor = (char *) descriptor->info;
242+
field->static_var = malloc(sizeof(variable_t));
221243

222244
read_field_attributes(class_file, &info);
223245
}

‎classfile.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ typedef struct {
5151
char *class_name;
5252
char *name;
5353
char *descriptor;
54+
variable_t *static_var; /* store static fields in the class */
5455
} field_t;
5556

5657
typedef struct {
@@ -73,6 +74,7 @@ void read_method_attributes(FILE *class_file,
7374
code_t *code,
7475
constant_pool_t *cp);
7576
uint16_t get_number_of_parameters(method_t *method);
77+
field_t *find_field(const char *name, const char *desc, class_file_t *clazz);
7678
method_t *find_method(const char *name, const char *desc, class_file_t *clazz);
7779
method_t *find_method_from_index(uint16_t idx, class_file_t *clazz);
7880
class_file_t get_class(FILE *class_file);

‎jvm.c‎

Lines changed: 117 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ typedef enum {
9494
i_areturn = 0xb0,
9595
i_return = 0xb1,
9696
i_getstatic = 0xb2,
97+
i_putstatic = 0xb3,
9798
i_getfield = 0xb4,
9899
i_putfield = 0xb5,
99100
i_invokevirtual = 0xb6,
@@ -785,10 +786,124 @@ stack_entry_t *execute(method_t *method,
785786
break;
786787

787788
/* Get static field from class */
788-
case i_getstatic:
789-
/* FIXME: unimplemented */
789+
case i_getstatic: {
790+
uint8_t param1 = code_buf[pc + 1], param2 = code_buf[pc + 2];
791+
uint16_t index = ((param1 << 8) | param2);
792+
793+
char *field_name, *field_descriptor, *class_name;
794+
class_name = find_field_info_from_index(index, clazz, &field_name,
795+
&field_descriptor);
796+
797+
/* skip java.lang.System in order to support java print
798+
* method */
799+
if (!strcmp(class_name, "java/lang/System")) {
800+
pc += 3;
801+
break;
802+
}
803+
804+
class_file_t *target_class =
805+
find_or_add_class_to_heap(class_name, prefix);
806+
field_t *field =
807+
find_field(field_name, field_descriptor, target_class);
808+
809+
switch (field_descriptor[0]) {
810+
case 'B':
811+
/* signed byte */
812+
push_byte(op_stack, field->static_var->value.char_value);
813+
break;
814+
case 'C':
815+
/* FIXME: complete Unicode handling */
816+
/* unicode character code */
817+
push_short(op_stack, field->static_var->value.short_value);
818+
break;
819+
case 'I':
820+
/* integer */
821+
push_int(op_stack, field->static_var->value.int_value);
822+
break;
823+
case 'J':
824+
/* long integer */
825+
push_long(op_stack, field->static_var->value.long_value);
826+
break;
827+
case 'S':
828+
/* signed short */
829+
push_short(op_stack, field->static_var->value.short_value);
830+
break;
831+
case 'Z':
832+
/* true or false */
833+
push_byte(op_stack, field->static_var->value.char_value);
834+
break;
835+
case 'L':
836+
/* an instance of class */
837+
push_ref(op_stack, field->static_var->value.ptr_value);
838+
break;
839+
default:
840+
fprintf(stderr, "Unknown field descriptor %c\n",
841+
field_descriptor[0]);
842+
exit(1);
843+
}
790844
pc += 3;
791845
break;
846+
}
847+
848+
/* Put static field to class */
849+
case i_putstatic: {
850+
uint8_t param1 = code_buf[pc + 1], param2 = code_buf[pc + 2];
851+
uint16_t index = ((param1 << 8) | param2);
852+
853+
char *field_name, *field_descriptor, *class_name;
854+
class_name = find_field_info_from_index(index, clazz, &field_name,
855+
&field_descriptor);
856+
857+
class_file_t *target_class =
858+
find_or_add_class_to_heap(class_name, prefix);
859+
field_t *field =
860+
find_field(field_name, field_descriptor, target_class);
861+
862+
switch (field_descriptor[0]) {
863+
case 'B':
864+
/* signed byte */
865+
field->static_var->value.char_value = (u1) pop_int(op_stack);
866+
field->static_var->type = VAR_BYTE;
867+
break;
868+
case 'C':
869+
/* FIXME: complete Unicode handling */
870+
/* unicode character code */
871+
field->static_var->value.char_value = (u2) pop_int(op_stack);
872+
field->static_var->type = VAR_SHORT;
873+
break;
874+
case 'I':
875+
/* integer */
876+
field->static_var->value.int_value = (u4) pop_int(op_stack);
877+
field->static_var->type = VAR_INT;
878+
break;
879+
case 'J':
880+
/* long integer */
881+
field->static_var->value.long_value = (u8) pop_int(op_stack);
882+
field->static_var->type = VAR_LONG;
883+
break;
884+
case 'S':
885+
/* signed short */
886+
field->static_var->value.short_value = (u2) pop_int(op_stack);
887+
field->static_var->type = VAR_SHORT;
888+
break;
889+
case 'Z':
890+
/* true or false */
891+
field->static_var->value.char_value = (u1) pop_int(op_stack);
892+
field->static_var->type = VAR_BYTE;
893+
break;
894+
case 'L':
895+
/* an instance of class ClassName */
896+
field->static_var->value.ptr_value = pop_ref(op_stack);
897+
field->static_var->type = VAR_PTR;
898+
break;
899+
default:
900+
fprintf(stderr, "Unknown field descriptor %c\n",
901+
field_descriptor[0]);
902+
exit(1);
903+
}
904+
pc += 3;
905+
break;
906+
}
792907

793908
/* Invoke instance method; dispatch based on class */
794909
case i_invokevirtual:

‎tests/Static.java‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
public class Static {
2+
static int x, y, z;
3+
public static void main(String[] args) {
4+
x = 3;
5+
y = 4;
6+
z = 5;
7+
StaticA.x = 1;
8+
StaticB.x = Static.x + StaticA.x;
9+
System.out.println(Static.x);
10+
System.out.println(Static.y);
11+
System.out.println(Static.z);
12+
System.out.println(StaticA.x);
13+
System.out.println(StaticB.x);
14+
}
15+
}
16+
17+
class StaticA {
18+
static int x;
19+
}
20+
21+
class StaticB {
22+
static int x;
23+
}

0 commit comments

Comments
(0)

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