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 715481e

Browse files
authored
Merge pull request #9 from hankluo6/virtual
Implement invokevirtual opcode
2 parents 6c5646a + b51624b commit 715481e

File tree

5 files changed

+119
-23
lines changed

5 files changed

+119
-23
lines changed

‎Makefile‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ TESTS = \
4747
Caller \
4848
Constructor \
4949
Field \
50-
Static
50+
Static \
51+
Invokevirtual
5152

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

‎classfile.c‎

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,16 @@ class_info_t get_class_info(FILE *class_file)
2727
*/
2828
uint16_t get_number_of_parameters(method_t *method)
2929
{
30-
/* Type descriptors have the length ( + #params + ) + return type */
31-
return strlen(method->descriptor) - 3;
30+
uint16_t num_param = 0;
31+
for (size_t i = 1; method->descriptor[i] != ')'; ++i) {
32+
/* if type is reference, skip class name */
33+
if (method->descriptor[i] == 'L') {
34+
while (method->descriptor[++i] != ';')
35+
;
36+
}
37+
num_param++;
38+
}
39+
return num_param;
3240
}
3341

3442
/**
@@ -271,13 +279,6 @@ method_t *get_methods(FILE *class_file, constant_pool_t *cp)
271279
assert(descriptor->tag == CONSTANT_Utf8 && "Expected a UTF8");
272280
method->descriptor = (char *) descriptor->info;
273281

274-
/* FIXME: this VM can only execute static methods, while every class
275-
* has a constructor method <init>
276-
*/
277-
if (strcmp(method->name, "<init>"))
278-
assert((info.access_flags & IS_STATIC) &&
279-
"Only static methods are supported by this VM.");
280-
281282
read_method_attributes(class_file, &info, &method->code, cp);
282283
}
283284

‎jvm.c‎

Lines changed: 75 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -172,14 +172,6 @@ static inline void ineg(stack_frame_t *op_stack)
172172
push_int(op_stack, -op1);
173173
}
174174

175-
static inline void invokevirtual(stack_frame_t *op_stack)
176-
{
177-
int64_t op = pop_int(op_stack);
178-
179-
/* FIXME: the implement is not correct. */
180-
printf("%" PRId64 "\n", op);
181-
}
182-
183175
static inline void iconst(stack_frame_t *op_stack, uint8_t current)
184176
{
185177
push_int(op_stack, current - i_iconst_0);
@@ -906,10 +898,83 @@ stack_entry_t *execute(method_t *method,
906898
}
907899

908900
/* Invoke instance method; dispatch based on class */
909-
case i_invokevirtual:
910-
invokevirtual(op_stack);
901+
case i_invokevirtual: {
902+
uint8_t param1 = code_buf[pc + 1], param2 = code_buf[pc + 2];
903+
uint16_t index = ((param1 << 8) | param2);
904+
905+
/* the method to be called */
906+
char *method_name, *method_descriptor, *class_name;
907+
class_name = find_method_info_from_index(index, clazz, &method_name,
908+
&method_descriptor);
909+
910+
/* to handle print method */
911+
if (!strcmp(class_name, "java/io/PrintStream")) {
912+
stack_entry_t element = top(op_stack);
913+
914+
switch (element.type) {
915+
/* integer */
916+
case STACK_ENTRY_INT:
917+
case STACK_ENTRY_SHORT:
918+
case STACK_ENTRY_BYTE:
919+
case STACK_ENTRY_LONG: {
920+
int64_t op = pop_int(op_stack);
921+
printf("%ld\n", op);
922+
break;
923+
}
924+
default:
925+
printf("print type (%d) is not supported\n", element.type);
926+
break;
927+
}
928+
pc += 3;
929+
break;
930+
}
931+
932+
/* FIXME: consider method modifier */
933+
class_file_t *target_class =
934+
find_or_add_class_to_heap(class_name, prefix);
935+
936+
method_t *method =
937+
find_method(method_name, method_descriptor, target_class);
938+
uint16_t num_params = get_number_of_parameters(method);
939+
local_variable_t own_locals[method->code.max_locals];
940+
memset(own_locals, 0, sizeof(own_locals));
941+
for (int i = num_params; i >= 1; i--) {
942+
pop_to_local(op_stack, &own_locals[i]);
943+
}
944+
object_t *obj = pop_ref(op_stack);
945+
946+
/* first argument is this pointer */
947+
own_locals[0].entry.ptr_value = obj;
948+
own_locals[0].type = STACK_ENTRY_REF;
949+
950+
stack_entry_t *exec_res = execute(method, own_locals, target_class);
951+
switch (exec_res->type) {
952+
case STACK_ENTRY_BYTE:
953+
push_int(op_stack, exec_res->entry.char_value);
954+
break;
955+
case STACK_ENTRY_SHORT:
956+
push_int(op_stack, exec_res->entry.short_value);
957+
break;
958+
case STACK_ENTRY_INT:
959+
push_int(op_stack, exec_res->entry.int_value);
960+
break;
961+
case STACK_ENTRY_LONG:
962+
push_long(op_stack, exec_res->entry.long_value);
963+
break;
964+
case STACK_ENTRY_REF:
965+
push_ref(op_stack, exec_res->entry.ptr_value);
966+
break;
967+
case STACK_ENTRY_NONE:
968+
/* nothing */
969+
break;
970+
default:
971+
assert(0 && "unknown return type");
972+
}
973+
974+
free(exec_res);
911975
pc += 3;
912976
break;
977+
}
913978

914979
/* Push int constant */
915980
case i_iconst_m1:

‎stack.c‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,13 @@ void *pop_ref(stack_frame_t *stack)
8686
void pop_to_local(stack_frame_t *stack, local_variable_t *locals)
8787
{
8888
stack_entry_type_t type = stack->store[stack->size - 1].type;
89-
/* convert to integer */
89+
/* push value from stack to locals */
9090
if (type >= STACK_ENTRY_BYTE && type <= STACK_ENTRY_LONG) {
91-
int64_t value = pop_int(stack);
92-
locals->entry.long_value = value;
91+
locals->entry.long_value = pop_int(stack);
9392
locals->type = STACK_ENTRY_LONG;
93+
} else if (type == STACK_ENTRY_REF) {
94+
locals->entry.ptr_value = pop_ref(stack);
95+
locals->type = STACK_ENTRY_REF;
9496
}
9597
}
9698

‎tests/Invokevirtual.java‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
class InvokevirtualA {
2+
void print(int val) {
3+
System.out.println(val);
4+
}
5+
}
6+
7+
class InvokevirtualB {
8+
void print(InvokevirtualA obj, int val) {
9+
obj.print(val);
10+
}
11+
}
12+
13+
class Invokevirtual {
14+
int a;
15+
public void print() {
16+
System.out.println(a);
17+
}
18+
public static void main(String args[]) {
19+
Invokevirtual x = new Invokevirtual();
20+
InvokevirtualA obj1 = new InvokevirtualA();
21+
InvokevirtualB obj2 = new InvokevirtualB();
22+
x.a = 3;
23+
x.print();
24+
obj1.print(2);
25+
obj2.print(obj1, 3);
26+
}
27+
}

0 commit comments

Comments
(0)

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