@@ -263,12 +263,28 @@ stack_entry_t *execute(method_t *method,
263263
264264 /* the method to be called */
265265 char * method_name , * method_descriptor , * class_name ;
266- class_name = find_method_info_from_index (index , clazz , & method_name ,
267- & method_descriptor );
266+ method_t * own_method = NULL ;
267+ class_file_t * target_class = NULL ;
268+ 269+ /* recursively find method from child to parent */
270+ while (!own_method ) {
271+ if (!target_class )
272+ class_name = find_method_info_from_index (
273+ index , clazz , & method_name , & method_descriptor );
274+ else
275+ class_name = find_class_name_from_index (
276+ target_class -> info -> super_class , target_class );
277+ find_or_add_class_to_heap (class_name , prefix , & target_class );
278+ assert (target_class &&
279+ "Failed to load class in i_invokestatic" );
280+ own_method =
281+ find_method (method_name , method_descriptor , target_class );
282+ }
268283
269- class_file_t * target_class ;
270- if (find_or_add_class_to_heap (class_name , prefix , & target_class )) {
271- /* Call static initialization */
284+ /* call static initialization. Only the class that contains this
285+ * method should do static initialization */
286+ if (!target_class -> initialized ) {
287+ target_class -> initialized = true;
272288 method_t * method = find_method ("<clinit>" , "()V" , target_class );
273289 if (method ) {
274290 local_variable_t own_locals [method -> code .max_locals ];
@@ -279,10 +295,7 @@ stack_entry_t *execute(method_t *method,
279295 free (exec_res );
280296 }
281297 }
282- assert (target_class && "Failed to load class in invokestatic" );
283298
284- method_t * own_method =
285- find_method (method_name , method_descriptor , target_class );
286299 uint16_t num_params = get_number_of_parameters (own_method );
287300 local_variable_t own_locals [own_method -> code .max_locals ];
288301 for (int i = num_params - 1 ; i >= 0 ; i -- )
@@ -794,19 +807,33 @@ stack_entry_t *execute(method_t *method,
794807 uint16_t index = ((param1 << 8 ) | param2 );
795808
796809 char * field_name , * field_descriptor , * class_name ;
810+ field_t * field = NULL ;
811+ class_file_t * target_class = NULL ;
812+ 797813 class_name = find_field_info_from_index (index , clazz , & field_name ,
798814 & field_descriptor );
799- 800815 /* skip java.lang.System in order to support java print
801816 * method */
802817 if (!strcmp (class_name , "java/lang/System" )) {
803818 pc += 3 ;
804819 break ;
805820 }
806821
807- class_file_t * target_class ;
808- if (find_or_add_class_to_heap (class_name , prefix , & target_class )) {
809- /* Call static initialization */
822+ while (!field ) {
823+ if (target_class )
824+ class_name = find_class_name_from_index (
825+ target_class -> info -> super_class , target_class );
826+ 827+ find_or_add_class_to_heap (class_name , prefix , & target_class );
828+ assert (target_class && "Failed to load class in i_getstatic" );
829+ 830+ field = find_field (field_name , field_descriptor , target_class );
831+ }
832+ 833+ /* call static initialization. Only the class that contains this
834+ * field should do static initialization */
835+ if (!target_class -> initialized ) {
836+ target_class -> initialized = true;
810837 method_t * method = find_method ("<clinit>" , "()V" , target_class );
811838 if (method ) {
812839 local_variable_t own_locals [method -> code .max_locals ];
@@ -818,9 +845,6 @@ stack_entry_t *execute(method_t *method,
818845 }
819846 }
820847
821- field_t * field =
822- find_field (field_name , field_descriptor , target_class );
823- 824848 switch (field_descriptor [0 ]) {
825849 case 'B' :
826850 /* signed byte */
@@ -866,12 +890,33 @@ stack_entry_t *execute(method_t *method,
866890 uint16_t index = ((param1 << 8 ) | param2 );
867891
868892 char * field_name , * field_descriptor , * class_name ;
893+ field_t * field = NULL ;
894+ class_file_t * target_class = NULL ;
869895 class_name = find_field_info_from_index (index , clazz , & field_name ,
870896 & field_descriptor );
871897
872- class_file_t * target_class ;
873- if (find_or_add_class_to_heap (class_name , prefix , & target_class )) {
874- /* Call static initialization */
898+ /* skip java.lang.System in order to support java print
899+ * method */
900+ if (!strcmp (class_name , "java/lang/System" )) {
901+ pc += 3 ;
902+ break ;
903+ }
904+ 905+ while (!field ) {
906+ if (target_class )
907+ class_name = find_class_name_from_index (
908+ target_class -> info -> super_class , target_class );
909+ 910+ find_or_add_class_to_heap (class_name , prefix , & target_class );
911+ assert (target_class && "Failed to load class in i_putstatic" );
912+ 913+ field = find_field (field_name , field_descriptor , target_class );
914+ }
915+ 916+ /* call static initialization. Only the class that contains this
917+ * field should do static initialization */
918+ if (!target_class -> initialized ) {
919+ target_class -> initialized = true;
875920 method_t * method = find_method ("<clinit>" , "()V" , target_class );
876921 if (method ) {
877922 local_variable_t own_locals [method -> code .max_locals ];
@@ -882,8 +927,6 @@ stack_entry_t *execute(method_t *method,
882927 free (exec_res );
883928 }
884929 }
885- field_t * field =
886- find_field (field_name , field_descriptor , target_class );
887930
888931 switch (field_descriptor [0 ]) {
889932 case 'B' :
@@ -938,6 +981,9 @@ stack_entry_t *execute(method_t *method,
938981
939982 /* the method to be called */
940983 char * method_name , * method_descriptor , * class_name ;
984+ class_file_t * target_class = NULL ;
985+ method_t * method = NULL ;
986+ 941987 class_name = find_method_info_from_index (index , clazz , & method_name ,
942988 & method_descriptor );
943989
@@ -964,9 +1010,22 @@ stack_entry_t *execute(method_t *method,
9641010 }
9651011
9661012 /* FIXME: consider method modifier */
967- class_file_t * target_class ;
968- if (find_or_add_class_to_heap (class_name , prefix , & target_class )) {
969- /* Call static initialization */
1013+ /* recursively find method from child to parent */
1014+ while (!method ) {
1015+ if (target_class )
1016+ class_name = find_class_name_from_index (
1017+ target_class -> info -> super_class , target_class );
1018+ find_or_add_class_to_heap (class_name , prefix , & target_class );
1019+ assert (target_class &&
1020+ "Failed to load class in i_invokevirtual" );
1021+ method =
1022+ find_method (method_name , method_descriptor , target_class );
1023+ }
1024+ 1025+ /* call static initialization. Only the class that contains this
1026+ * method should do static initialization */
1027+ if (!target_class -> initialized ) {
1028+ target_class -> initialized = true;
9701029 method_t * method = find_method ("<clinit>" , "()V" , target_class );
9711030 if (method ) {
9721031 local_variable_t own_locals [method -> code .max_locals ];
@@ -977,8 +1036,7 @@ stack_entry_t *execute(method_t *method,
9771036 free (exec_res );
9781037 }
9791038 }
980- method_t * method =
981- find_method (method_name , method_descriptor , target_class );
1039+ 9821040 uint16_t num_params = get_number_of_parameters (method );
9831041 local_variable_t own_locals [method -> code .max_locals ];
9841042 memset (own_locals , 0 , sizeof (own_locals ));
@@ -1138,8 +1196,26 @@ stack_entry_t *execute(method_t *method,
11381196
11391197 char * class_name = find_class_name_from_index (index , clazz );
11401198 class_file_t * target_class ;
1141- if (find_or_add_class_to_heap (class_name , prefix , & target_class )) {
1142- /* Call static initialization */
1199+ 1200+ /* FIXME: use linked list to prevent wasted space */
1201+ class_file_t * * stack = malloc (sizeof (class_file_t * ) * 100 );
1202+ size_t count = 0 ;
1203+ while (true) {
1204+ find_or_add_class_to_heap (class_name , prefix , & target_class );
1205+ assert (target_class && "Failed to load class in i_new" );
1206+ stack [count ++ ] = target_class ;
1207+ class_name = find_class_name_from_index (
1208+ target_class -> info -> super_class , target_class );
1209+ if (!strcmp (class_name , "java/lang/Object" ))
1210+ break ;
1211+ }
1212+ 1213+ /* call static initialization */
1214+ while (count ) {
1215+ target_class = stack [-- count ];
1216+ if (target_class -> initialized )
1217+ continue ;
1218+ target_class -> initialized = true;
11431219 method_t * method = find_method ("<clinit>" , "()V" , target_class );
11441220 if (method ) {
11451221 local_variable_t own_locals [method -> code .max_locals ];
@@ -1150,7 +1226,7 @@ stack_entry_t *execute(method_t *method,
11501226 free (exec_res );
11511227 }
11521228 }
1153- assert ( target_class && "Failed to load class in new" );
1229+ free ( stack );
11541230
11551231 object_t * object = create_object (target_class );
11561232 push_ref (op_stack , object );
@@ -1178,8 +1254,12 @@ stack_entry_t *execute(method_t *method,
11781254 }
11791255
11801256 class_file_t * target_class ;
1181- if (find_or_add_class_to_heap (class_name , prefix , & target_class )) {
1182- /* Call static initialization */
1257+ find_or_add_class_to_heap (class_name , prefix , & target_class );
1258+ assert (target_class && "Failed to load class in i_invokespecial" );
1259+ 1260+ /* call static initialization */
1261+ if (!target_class -> initialized ) {
1262+ target_class -> initialized = true;
11831263 method_t * method = find_method ("<clinit>" , "()V" , target_class );
11841264 if (method ) {
11851265 local_variable_t own_locals [method -> code .max_locals ];
@@ -1190,7 +1270,6 @@ stack_entry_t *execute(method_t *method,
11901270 free (exec_res );
11911271 }
11921272 }
1193- assert (target_class && "Failed to load class in i_invokespecial" );
11941273
11951274 /* find constructor method from class */
11961275 method_t * constructor =
@@ -1254,15 +1333,6 @@ int main(int argc, char *argv[])
12541333 prefix [match - argv [1 ] + 1 ] = '0円' ;
12551334 }
12561335
1257- method_t * method = find_method ("<clinit>" , "()V" , clazz );
1258- if (method ) {
1259- local_variable_t own_locals [method -> code .max_locals ];
1260- stack_entry_t * exec_res = execute (method , own_locals , clazz );
1261- assert (exec_res -> type == STACK_ENTRY_NONE &&
1262- "<clinit> must not return a value" );
1263- free (exec_res );
1264- }
1265- 12661336 /* execute the main method if found */
12671337 method_t * main_method =
12681338 find_method ("main" , "([Ljava/lang/String;)V" , clazz );
0 commit comments