@@ -30,6 +30,7 @@ typedef enum {
30
30
i_ldc2_w = 0x14 ,
31
31
i_iload = 0x15 ,
32
32
i_lload = 0x16 ,
33
+ i_aload = 0x19 ,
33
34
i_iload_0 = 0x1a ,
34
35
i_iload_1 = 0x1b ,
35
36
i_iload_2 = 0x1c ,
@@ -38,8 +39,13 @@ typedef enum {
38
39
i_lload_1 = 0x1f ,
39
40
i_lload_2 = 0x20 ,
40
41
i_lload_3 = 0x21 ,
42
+ i_aload_0 = 0x2a ,
43
+ i_aload_1 = 0x2b ,
44
+ i_aload_2 = 0x2c ,
45
+ i_aload_3 = 0x2d ,
41
46
i_istore = 0x36 ,
42
47
i_lstore = 0x37 ,
48
+ i_astore = 0x3a ,
43
49
i_istore_0 = 0x3b ,
44
50
i_istore_1 = 0x3c ,
45
51
i_istore_2 = 0x3d ,
@@ -48,6 +54,12 @@ typedef enum {
48
54
i_lstore_1 = 0x40 ,
49
55
i_lstore_2 = 0x41 ,
50
56
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 ,
51
63
i_iadd = 0x60 ,
52
64
i_ladd = 0x61 ,
53
65
i_isub = 0x64 ,
@@ -78,10 +90,13 @@ typedef enum {
78
90
i_goto = 0xa7 ,
79
91
i_ireturn = 0xac ,
80
92
i_lreturn = 0xad ,
93
+ i_areturn = 0xb0 ,
81
94
i_return = 0xb1 ,
82
95
i_getstatic = 0xb2 ,
83
96
i_invokevirtual = 0xb6 ,
97
+ i_invokespecial = 0xb7 ,
84
98
i_invokestatic = 0xb8 ,
99
+ i_new = 0xbb ,
85
100
} jvm_opcode_t ;
86
101
87
102
/* TODO: add -cp arg to achieve class path select */
@@ -222,6 +237,18 @@ stack_entry_t *execute(method_t *method,
222
237
return ret ;
223
238
}
224
239
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
+
225
252
/* Return void from method */
226
253
case i_return : {
227
254
stack_entry_t * ret = malloc (sizeof (stack_entry_t ));
@@ -242,47 +269,9 @@ stack_entry_t *execute(method_t *method,
242
269
char * method_name , * method_descriptor , * class_name ;
243
270
class_name = find_method_info_from_index (index , clazz , & method_name ,
244
271
& 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
- }
285
272
273
+ class_file_t * target_class =
274
+ find_or_add_class_to_heap (class_name , prefix );
286
275
assert (target_class && "Failed to load class in invokestatic" );
287
276
288
277
method_t * own_method =
@@ -301,6 +290,9 @@ stack_entry_t *execute(method_t *method,
301
290
case STACK_ENTRY_LONG :
302
291
push_long (op_stack , exec_res -> entry .long_value );
303
292
break ;
293
+ case STACK_ENTRY_REF :
294
+ push_ref (op_stack , exec_res -> entry .ptr_value );
295
+ break ;
304
296
case STACK_ENTRY_NONE :
305
297
/* nothing */
306
298
break ;
@@ -547,6 +539,18 @@ stack_entry_t *execute(method_t *method,
547
539
break ;
548
540
}
549
541
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
+
550
554
/* Load int from local variable */
551
555
case i_iload_0 :
552
556
case i_iload_1 :
@@ -584,6 +588,15 @@ stack_entry_t *execute(method_t *method,
584
588
break ;
585
589
}
586
590
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
+
587
600
/* Store long into local variable */
588
601
case i_lstore_0 :
589
602
case i_lstore_1 :
@@ -621,6 +634,34 @@ stack_entry_t *execute(method_t *method,
621
634
break ;
622
635
}
623
636
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
+
624
665
/* Increment local variable by constant */
625
666
case i_iinc : {
626
667
uint8_t i = code_buf [pc + 1 ];
@@ -778,6 +819,71 @@ stack_entry_t *execute(method_t *method,
778
819
pc += 3 ;
779
820
break ;
780
821
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
+
781
887
default :
782
888
fprintf (stderr , "Unknown instruction %x\n" , current );
783
889
exit (1 );
0 commit comments