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 0d95b5c

Browse files
committed
Implement getfield and putfield opcodes
Add a new test script: "Field.java"
1 parent 266e518 commit 0d95b5c

File tree

7 files changed

+122
-3
lines changed

7 files changed

+122
-3
lines changed

‎Makefile‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ TESTS = \
4545
Recursion \
4646
Long \
4747
Caller \
48-
Constructor
48+
Constructor \
49+
Field
4950

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

‎jvm.c‎

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ typedef enum {
9494
i_areturn = 0xb0,
9595
i_return = 0xb1,
9696
i_getstatic = 0xb2,
97+
i_getfield = 0xb4,
98+
i_putfield = 0xb5,
9799
i_invokevirtual = 0xb6,
98100
i_invokespecial = 0xb7,
99101
i_invokestatic = 0xb8,
@@ -820,6 +822,91 @@ stack_entry_t *execute(method_t *method,
820822
pc += 3;
821823
break;
822824

825+
/* Fetch field from object */
826+
case i_getfield: {
827+
uint8_t param1 = code_buf[pc + 1], param2 = code_buf[pc + 2];
828+
uint16_t index = ((param1 << 8) | param2);
829+
830+
object_t *obj = pop_ref(op_stack);
831+
char *field_name, *field_descriptor;
832+
find_field_info_from_index(index, clazz, &field_name,
833+
&field_descriptor);
834+
835+
variable_t *addr = find_field_addr(obj, field_name);
836+
837+
switch (field_descriptor[0]) {
838+
case 'I':
839+
push_int(op_stack, addr->value.int_value);
840+
break;
841+
case 'J':
842+
push_long(op_stack, addr->value.long_value);
843+
break;
844+
case 'L':
845+
push_ref(op_stack, addr->value.ptr_value);
846+
break;
847+
default:
848+
assert(0 && "Only support integer and reference field");
849+
break;
850+
}
851+
pc += 3;
852+
break;
853+
}
854+
855+
/* Set field in object */
856+
case i_putfield: {
857+
uint8_t param1 = code_buf[pc + 1], param2 = code_buf[pc + 2];
858+
uint16_t index = ((param1 << 8) | param2);
859+
int64_t value = 0;
860+
void *addr = NULL;
861+
862+
/* get prepared value from the stack */
863+
stack_entry_t element = top(op_stack);
864+
switch (element.type) {
865+
/* integer */
866+
case STACK_ENTRY_INT:
867+
case STACK_ENTRY_SHORT:
868+
case STACK_ENTRY_BYTE:
869+
case STACK_ENTRY_LONG:
870+
value = pop_int(op_stack);
871+
break;
872+
case STACK_ENTRY_REF:
873+
addr = pop_ref(op_stack);
874+
break;
875+
default:
876+
assert(0 && "Only support integer and reference field");
877+
break;
878+
}
879+
880+
object_t *obj = pop_ref(op_stack);
881+
882+
/* update value into object's field */
883+
char *field_name, *field_descriptor;
884+
find_field_info_from_index(index, clazz, &field_name,
885+
&field_descriptor);
886+
887+
variable_t *var = find_field_addr(obj, field_name);
888+
889+
switch (field_descriptor[0]) {
890+
case 'I':
891+
var->value.int_value = (int32_t) value;
892+
var->type = VAR_INT;
893+
break;
894+
case 'J':
895+
var->value.long_value = value;
896+
var->type = VAR_LONG;
897+
break;
898+
case 'L':
899+
var->value.ptr_value = addr;
900+
var->type = VAR_PTR;
901+
break;
902+
default:
903+
assert(0 && "Only support integer and reference field");
904+
break;
905+
}
906+
pc += 3;
907+
break;
908+
}
909+
823910
/* create new object */
824911
case i_new: {
825912
uint8_t param1 = code_buf[pc + 1], param2 = code_buf[pc + 2];

‎object-heap.c‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ object_t *create_object(class_file_t *clazz)
2626
return new_obj;
2727
}
2828

29+
variable_t *find_field_addr(object_t *obj, char *name)
30+
{
31+
field_t *field = obj->class->fields;
32+
for (u2 i = 0; i < obj->class->fields_count; i++, field++) {
33+
if (!strcmp(field->name, name)) {
34+
return &obj->value[i];
35+
}
36+
}
37+
assert(0 && "Can't find field in the object");
38+
return NULL;
39+
}
40+
2941
void free_object_heap()
3042
{
3143
for (int i = 0; i < object_heap.length; ++i) {

‎object-heap.h‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ typedef struct {
1515

1616
void init_object_heap();
1717
void free_object_heap();
18-
object_t *create_object(class_file_t *clazz);
18+
object_t *create_object(class_file_t *clazz);
19+
variable_t *find_field_addr(object_t *obj, char *name);

‎stack.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ void push_ref(stack_frame_t *stack, void *addr)
4343
stack->size++;
4444
}
4545

46+
stack_entry_t top(stack_frame_t *stack)
47+
{
48+
return stack->store[stack->size - 1];
49+
}
50+
4651
/* pop top of stack value and convert to 64 bits integer */
4752
int64_t stack_to_int(value_t *entry, size_t size)
4853
{

‎stack.h‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,5 @@ int64_t pop_int(stack_frame_t *stack);
4343
void *pop_ref(stack_frame_t *stack);
4444
void pop_to_local(stack_frame_t *stack, local_variable_t *locals);
4545
size_t get_type_size(stack_entry_type_t type);
46-
int64_t stack_to_int(value_t *entry, size_t size);
46+
int64_t stack_to_int(value_t *entry, size_t size);
47+
stack_entry_t top(stack_frame_t *stack);

‎tests/Field.java‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class Field {
2+
Field(int a, int b, int c) {
3+
x = a;
4+
y = b;
5+
z = c;
6+
}
7+
public static void main(String[] args) {
8+
Field f = new Field(1, 2, 3);
9+
System.out.println(f.x + f.y + f.z);
10+
}
11+
int x, y, z;
12+
}

0 commit comments

Comments
(0)

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