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 b51624b

Browse files
committed
Implement invokevirtual instruction
When `invokevirtual` is called, Jvm pops the reference from the stack and related arguments, then executes method. Add a new test script: "Invokevirtual.java"
1 parent e1d5def commit b51624b

File tree

4 files changed

+104
-18
lines changed

4 files changed

+104
-18
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: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -279,13 +279,6 @@ method_t *get_methods(FILE *class_file, constant_pool_t *cp)
279279
assert(descriptor->tag == CONSTANT_Utf8 && "Expected a UTF8");
280280
method->descriptor = (char *) descriptor->info;
281281

282-
/* FIXME: this VM can only execute static methods, while every class
283-
* has a constructor method <init>
284-
*/
285-
if (strcmp(method->name, "<init>"))
286-
assert((info.access_flags & IS_STATIC) &&
287-
"Only static methods are supported by this VM.");
288-
289282
read_method_attributes(class_file, &info, &method->code, cp);
290283
}
291284

‎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:

‎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 によって変換されたページ (->オリジナル) /