@@ -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 );
0 commit comments