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 54662e2

Browse files
committed
Add object related opcodes
This patch add some opcodes about java objects. Pitifulvm supports object constructor and static methods of objects now. New opcodes: * aload, astore * dup * invokespecial * new * pop Add a new test script: "Constructor.java"
1 parent 1236eda commit 54662e2

File tree

7 files changed

+251
-42
lines changed

7 files changed

+251
-42
lines changed

‎Makefile‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ TESTS = \
4444
Primes \
4545
Recursion \
4646
Long \
47-
Caller
48-
47+
Caller \
48+
Constructor
49+
4950
check: $(addprefix tests/,$(TESTS:=-result.out))
5051

5152
ifneq (, $(shell which valgrind))

‎class-heap.c‎

Lines changed: 46 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) {

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

‎jvm.c‎

Lines changed: 146 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ typedef enum {
3030
i_ldc2_w = 0x14,
3131
i_iload = 0x15,
3232
i_lload = 0x16,
33+
i_aload = 0x19,
3334
i_iload_0 = 0x1a,
3435
i_iload_1 = 0x1b,
3536
i_iload_2 = 0x1c,
@@ -38,8 +39,13 @@ typedef enum {
3839
i_lload_1 = 0x1f,
3940
i_lload_2 = 0x20,
4041
i_lload_3 = 0x21,
42+
i_aload_0 = 0x2a,
43+
i_aload_1 = 0x2b,
44+
i_aload_2 = 0x2c,
45+
i_aload_3 = 0x2d,
4146
i_istore = 0x36,
4247
i_lstore = 0x37,
48+
i_astore = 0x3a,
4349
i_istore_0 = 0x3b,
4450
i_istore_1 = 0x3c,
4551
i_istore_2 = 0x3d,
@@ -48,6 +54,12 @@ typedef enum {
4854
i_lstore_1 = 0x40,
4955
i_lstore_2 = 0x41,
5056
i_lstore_3 = 0x42,
57+
i_astore_0 = 0x4b,
58+
i_astore_1 = 0x4c,
59+
i_astore_2 = 0x4d,
60+
i_astore_3 = 0x4e,
61+
i_pop = 0x57,
62+
i_dup = 0x59,
5163
i_iadd = 0x60,
5264
i_ladd = 0x61,
5365
i_isub = 0x64,
@@ -78,10 +90,13 @@ typedef enum {
7890
i_goto = 0xa7,
7991
i_ireturn = 0xac,
8092
i_lreturn = 0xad,
93+
i_areturn = 0xb0,
8194
i_return = 0xb1,
8295
i_getstatic = 0xb2,
8396
i_invokevirtual = 0xb6,
97+
i_invokespecial = 0xb7,
8498
i_invokestatic = 0xb8,
99+
i_new = 0xbb,
85100
} jvm_opcode_t;
86101

87102
/* TODO: add -cp arg to achieve class path select */
@@ -222,6 +237,18 @@ stack_entry_t *execute(method_t *method,
222237
return ret;
223238
}
224239

240+
/* Return long from method */
241+
case i_areturn: {
242+
stack_entry_t *ret = malloc(sizeof(stack_entry_t));
243+
ret->entry.ptr_value = pop_ref(op_stack);
244+
ret->type = STACK_ENTRY_REF;
245+
246+
free(op_stack->store);
247+
free(op_stack);
248+
249+
return ret;
250+
}
251+
225252
/* Return void from method */
226253
case i_return: {
227254
stack_entry_t *ret = malloc(sizeof(stack_entry_t));
@@ -242,47 +269,9 @@ stack_entry_t *execute(method_t *method,
242269
char *method_name, *method_descriptor, *class_name;
243270
class_name = find_method_info_from_index(index, clazz, &method_name,
244271
&method_descriptor);
245-
class_file_t *target_class = find_class_from_heap(class_name);
246-
247-
/* if class is not found, adding specific class path and finding
248-
* again. This can be removed by recording path infomation in class
249-
* heap
250-
*/
251-
if (!target_class && prefix) {
252-
char *tmp = malloc(strlen(class_name) + strlen(prefix) + 1);
253-
strcpy(tmp, prefix);
254-
strcat(tmp, class_name);
255-
target_class = find_class_from_heap(tmp);
256-
257-
free(tmp);
258-
}
259-
260-
/* if class is still not found, meaning that this class is not
261-
* loaded in class heap, so add it to the class heap. */
262-
if (!target_class) {
263-
char *tmp;
264-
if (prefix) {
265-
tmp = malloc((strlen(class_name) + strlen(".class") +
266-
strlen(prefix) + 1));
267-
strcpy(tmp, prefix);
268-
strcat(tmp, class_name);
269-
} else {
270-
tmp = malloc(strlen(class_name) + strlen(".class") + 1);
271-
strcpy(tmp, class_name);
272-
}
273-
/* attempt to read given class file */
274-
FILE *class_file = fopen(strcat(tmp, ".class"), "r");
275-
assert(class_file && "Failed to open file");
276-
277-
/* parse the class file */
278-
target_class = malloc(sizeof(class_file_t));
279-
*target_class = get_class(class_file);
280-
int error = fclose(class_file);
281-
assert(!error && "Failed to close file");
282-
add_class(target_class, tmp);
283-
free(tmp);
284-
}
285272

273+
class_file_t *target_class =
274+
find_or_add_class_to_heap(class_name, prefix);
286275
assert(target_class && "Failed to load class in invokestatic");
287276

288277
method_t *own_method =
@@ -301,6 +290,9 @@ stack_entry_t *execute(method_t *method,
301290
case STACK_ENTRY_LONG:
302291
push_long(op_stack, exec_res->entry.long_value);
303292
break;
293+
case STACK_ENTRY_REF:
294+
push_ref(op_stack, exec_res->entry.ptr_value);
295+
break;
304296
case STACK_ENTRY_NONE:
305297
/* nothing */
306298
break;
@@ -547,6 +539,18 @@ stack_entry_t *execute(method_t *method,
547539
break;
548540
}
549541

542+
/* Load object from local variable */
543+
case i_aload_0:
544+
case i_aload_1:
545+
case i_aload_2:
546+
case i_aload_3: {
547+
int32_t param = current - i_aload_0;
548+
object_t *obj = locals[param].entry.ptr_value;
549+
push_ref(op_stack, obj);
550+
pc += 1;
551+
break;
552+
}
553+
550554
/* Load int from local variable */
551555
case i_iload_0:
552556
case i_iload_1:
@@ -584,6 +588,15 @@ stack_entry_t *execute(method_t *method,
584588
break;
585589
}
586590

591+
/* Store object from local variable */
592+
case i_astore: {
593+
int32_t param = code_buf[pc + 1];
594+
locals[param].entry.ptr_value = pop_ref(op_stack);
595+
locals[param].type = STACK_ENTRY_REF;
596+
pc += 2;
597+
break;
598+
}
599+
587600
/* Store long into local variable */
588601
case i_lstore_0:
589602
case i_lstore_1:
@@ -621,6 +634,34 @@ stack_entry_t *execute(method_t *method,
621634
break;
622635
}
623636

637+
/* Store object from local variable */
638+
case i_astore_0:
639+
case i_astore_1:
640+
case i_astore_2:
641+
case i_astore_3: {
642+
int32_t param = current - i_astore_0;
643+
locals[param].entry.ptr_value = pop_ref(op_stack);
644+
locals[param].type = STACK_ENTRY_REF;
645+
pc += 1;
646+
break;
647+
}
648+
649+
/* discard the top value on the stack */
650+
case i_pop: {
651+
op_stack->size--;
652+
pc += 1;
653+
break;
654+
}
655+
656+
/* duplicate the value on top of the stack */
657+
case i_dup: {
658+
op_stack->store[op_stack->size] =
659+
op_stack->store[op_stack->size - 1];
660+
op_stack->size++;
661+
pc += 1;
662+
break;
663+
}
664+
624665
/* Increment local variable by constant */
625666
case i_iinc: {
626667
uint8_t i = code_buf[pc + 1];
@@ -778,6 +819,71 @@ stack_entry_t *execute(method_t *method,
778819
pc += 3;
779820
break;
780821

822+
/* create new object */
823+
case i_new: {
824+
uint8_t param1 = code_buf[pc + 1], param2 = code_buf[pc + 2];
825+
uint16_t index = ((param1 << 8) | param2);
826+
827+
char *class_name = find_class_name_from_index(index, clazz);
828+
class_file_t *target_class =
829+
find_or_add_class_to_heap(class_name, prefix);
830+
assert(target_class && "Failed to load class in new");
831+
832+
object_t *object = create_object(target_class);
833+
push_ref(op_stack, object);
834+
835+
pc += 3;
836+
break;
837+
}
838+
839+
/* Invoke object constructor method */
840+
case i_invokespecial: {
841+
uint8_t param1 = code_buf[pc + 1], param2 = code_buf[pc + 2];
842+
uint16_t index = ((param1 << 8) | param2);
843+
844+
/* the method to be called */
845+
char *method_name, *method_descriptor, *class_name;
846+
class_name = find_method_info_from_index(index, clazz, &method_name,
847+
&method_descriptor);
848+
849+
/* java.lang.Object is the parent for every object, so every object
850+
* will finally call java.lang.Object's constructor */
851+
if (!strcmp(class_name, "java/lang/Object")) {
852+
pop_ref(op_stack);
853+
pc += 3;
854+
break;
855+
}
856+
857+
class_file_t *target_class =
858+
find_or_add_class_to_heap(class_name, prefix);
859+
assert(target_class && "Failed to load class in i_invokespecial");
860+
861+
/* find constructor method from class */
862+
method_t *constructor =
863+
find_method(method_name, method_descriptor, target_class);
864+
865+
/* prepare local variables */
866+
uint16_t num_params = get_number_of_parameters(constructor);
867+
local_variable_t own_locals[constructor->code.max_locals];
868+
for (int i = num_params; i >= 1; i--) {
869+
pop_to_local(op_stack, &own_locals[i]);
870+
}
871+
872+
/* first argument must be object itself */
873+
object_t *obj = pop_ref(op_stack);
874+
own_locals[0].entry.ptr_value = obj;
875+
own_locals[0].type = STACK_ENTRY_REF;
876+
877+
stack_entry_t *exec_res =
878+
execute(constructor, own_locals, target_class);
879+
assert(exec_res->type == STACK_ENTRY_NONE &&
880+
"A constructor must not return a value.");
881+
free(exec_res);
882+
883+
pc += 3;
884+
break;
885+
}
886+
781887
default:
782888
fprintf(stderr, "Unknown instruction %x\n", current);
783889
exit(1);

‎stack.c‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ void push_long(stack_frame_t *stack, int64_t value)
3636
stack->size++;
3737
}
3838

39+
void push_ref(stack_frame_t *stack, void *addr)
40+
{
41+
stack->store[stack->size].entry.ptr_value = addr;
42+
stack->store[stack->size].type = STACK_ENTRY_REF;
43+
stack->size++;
44+
}
45+
3946
/* pop top of stack value and convert to 64 bits integer */
4047
int64_t stack_to_int(value_t *entry, size_t size)
4148
{
@@ -66,6 +73,11 @@ int64_t pop_int(stack_frame_t *stack)
6673
return value;
6774
}
6875

76+
void *pop_ref(stack_frame_t *stack)
77+
{
78+
return stack->store[--stack->size].entry.ptr_value;
79+
}
80+
6981
void pop_to_local(stack_frame_t *stack, local_variable_t *locals)
7082
{
7183
stack_entry_type_t type = stack->store[stack->size - 1].type;

‎stack.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ void push_byte(stack_frame_t *stack, int8_t value);
3838
void push_short(stack_frame_t *stack, int16_t value);
3939
void push_int(stack_frame_t *stack, int32_t value);
4040
void push_long(stack_frame_t *stack, int64_t value);
41+
void push_ref(stack_frame_t *stack, void *addr);
4142
int64_t pop_int(stack_frame_t *stack);
43+
void *pop_ref(stack_frame_t *stack);
4244
void pop_to_local(stack_frame_t *stack, local_variable_t *locals);
4345
size_t get_type_size(stack_entry_type_t type);
4446
int64_t stack_to_int(value_t *entry, size_t size);

0 commit comments

Comments
(0)

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