@@ -16,6 +16,7 @@ Author: Daniel Kroening, kroening@kroening.com
1616#include  " java_bytecode_convert_method.h" 
1717#include  " java_bytecode_convert_method_class.h" 
1818#include  " bytecode_info.h" 
19+ #include  " java_static_initializers.h" 
1920#include  " java_string_library_preprocess.h" 
2021#include  " java_types.h" 
2122#include  " java_utils.h" 
@@ -930,156 +931,6 @@ void java_bytecode_convert_methodt::check_static_field_stub(
930931  }
931932}
932933
933- // / Determine whether a `new` or static access against `classname` should be
934- // / prefixed with a static initialization check.
935- // / \param classname: Class name
936- // / \return Returns true if the given class or one of its parents has a static
937- // /   initializer
938- bool  java_bytecode_convert_methodt::class_needs_clinit (
939-   const  irep_idt &classname)
940- {
941-   auto  findit_any=any_superclass_has_clinit_method.insert ({classname, false });
942-   if (!findit_any.second )
943-     return  findit_any.first ->second ;
944- 
945-   auto  findit_here=class_has_clinit_method.insert ({classname, false });
946-   if (findit_here.second )
947-   {
948-     const  irep_idt &clinit_name=id2string (classname)+" .<clinit>:()V"  ;
949-     findit_here.first ->second =symbol_table.symbols .count (clinit_name);
950-   }
951-   if (findit_here.first ->second )
952-   {
953-     findit_any.first ->second =true ;
954-     return  true ;
955-   }
956-   const  auto  maybe_symbol=symbol_table.lookup (classname);
957-   //  Stub class?
958-   if (!maybe_symbol)
959-   {
960-     warning () << " SKIPPED: "   << classname << eom;
961-     return  false ;
962-   }
963-   const  symbolt &class_symbol=*maybe_symbol;
964-   for (const  auto  &base : to_class_type (class_symbol.type ).bases ())
965-   {
966-     if (class_needs_clinit (to_symbol_type (base.type ()).get_identifier ()))
967-     {
968-       findit_any.first ->second =true ;
969-       return  true ;
970-     }
971-   }
972-   return  false ;
973- }
974- 
975- // / Create a ::clinit_wrapper the first time a static initializer might be
976- // / called. The wrapper method checks whether static init has already taken
977- // / place, calls the actual <clinit> method if not, and initializes super-
978- // / classes and interfaces.
979- // / \param classname: Class name
980- // / \return Returns a symbol_exprt pointing to the given class' clinit wrapper
981- // /   if one is required, or nil otherwise.
982- exprt java_bytecode_convert_methodt::get_or_create_clinit_wrapper (
983-   const  irep_idt &classname)
984- {
985-   if (!class_needs_clinit (classname))
986-     return  static_cast <const  exprt &>(get_nil_irep ());
987- 
988-   //  if the symbol table already contains the clinit_wrapper() function, return
989-   //  it
990-   const  irep_idt &clinit_wrapper_name=
991-     id2string (classname)+" ::clinit_wrapper"  ;
992-   auto  findit=symbol_table.symbols .find (clinit_wrapper_name);
993-   if (findit!=symbol_table.symbols .end ())
994-     return  findit->second .symbol_expr ();
995- 
996-   //  Otherwise, assume that class C extends class C' and implements interfaces
997-   //  I1, ..., In. We now create the following function (possibly recursively
998-   //  creating the clinit_wrapper functions for C' and I1, ..., In):
999-   // 
1000-   //  java::C::clinit_wrapper()
1001-   //  {
1002-   //    if (java::C::clinit_already_run == false)
1003-   //    {
1004-   //      java::C::clinit_already_run = true; // before recursive calls!
1005-   // 
1006-   //      java::C'::clinit_wrapper();
1007-   //      java::I1::clinit_wrapper();
1008-   //      java::I2::clinit_wrapper();
1009-   //      // ...
1010-   //      java::In::clinit_wrapper();
1011-   // 
1012-   //      java::C::<clinit>();
1013-   //    }
1014-   //  }
1015-   const  irep_idt &already_run_name=
1016-     id2string (classname)+" ::clinit_already_run"  ;
1017-   symbolt already_run_symbol;
1018-   already_run_symbol.name =already_run_name;
1019-   already_run_symbol.pretty_name =already_run_name;
1020-   already_run_symbol.base_name =" clinit_already_run"  ;
1021-   already_run_symbol.type =bool_typet ();
1022-   already_run_symbol.value =false_exprt ();
1023-   already_run_symbol.is_lvalue =true ;
1024-   already_run_symbol.is_state_var =true ;
1025-   already_run_symbol.is_static_lifetime =true ;
1026-   already_run_symbol.mode =ID_java;
1027-   symbol_table.add (already_run_symbol);
1028- 
1029-   equal_exprt check_already_run (
1030-     already_run_symbol.symbol_expr (),
1031-     false_exprt ());
1032- 
1033-   //  the entire body of the function is an if-then-else
1034-   code_ifthenelset wrapper_body;
1035- 
1036-   //  add the condition to the if
1037-   wrapper_body.cond ()=check_already_run;
1038- 
1039-   //  add the "already-run = false" statement
1040-   code_blockt init_body;
1041-   code_assignt set_already_run (already_run_symbol.symbol_expr (), true_exprt ());
1042-   init_body.move_to_operands (set_already_run);
1043- 
1044-   //  iterate through the base types and add recursive calls to the
1045-   //  clinit_wrapper()
1046-   const  symbolt &class_symbol=*symbol_table.lookup (classname);
1047-   for (const  auto  &base : to_class_type (class_symbol.type ).bases ())
1048-   {
1049-     const  auto  base_name=to_symbol_type (base.type ()).get_identifier ();
1050-     exprt base_init_routine=get_or_create_clinit_wrapper (base_name);
1051-     if (base_init_routine.is_nil ())
1052-       continue ;
1053-     code_function_callt call_base;
1054-     call_base.function ()=base_init_routine;
1055-     init_body.move_to_operands (call_base);
1056-   }
1057- 
1058-   //  call java::C::<clinit>(), if the class has one static initializer
1059-   const  irep_idt &real_clinit_name=id2string (classname)+" .<clinit>:()V"  ;
1060-   auto  find_sym_it=symbol_table.symbols .find (real_clinit_name);
1061-   if (find_sym_it!=symbol_table.symbols .end ())
1062-   {
1063-     code_function_callt call_real_init;
1064-     call_real_init.function ()=find_sym_it->second .symbol_expr ();
1065-     init_body.move_to_operands (call_real_init);
1066-   }
1067-   wrapper_body.then_case ()=init_body;
1068- 
1069-   //  insert symbol in the symbol table
1070-   symbolt wrapper_method_symbol;
1071-   code_typet wrapper_method_type;
1072-   wrapper_method_type.return_type ()=void_typet ();
1073-   wrapper_method_symbol.name =clinit_wrapper_name;
1074-   wrapper_method_symbol.pretty_name =clinit_wrapper_name;
1075-   wrapper_method_symbol.base_name =" clinit_wrapper"  ;
1076-   wrapper_method_symbol.type =wrapper_method_type;
1077-   wrapper_method_symbol.value =wrapper_body;
1078-   wrapper_method_symbol.mode =ID_java;
1079-   symbol_table.add (wrapper_method_symbol);
1080-   return  wrapper_method_symbol.symbol_expr ();
1081- }
1082- 
1083934// / Each static access to classname should be prefixed with a check for
1084935// / necessary static init; this returns a call implementing that check.
1085936// / \param classname: Class name
@@ -1088,12 +939,17 @@ exprt java_bytecode_convert_methodt::get_or_create_clinit_wrapper(
1088939codet java_bytecode_convert_methodt::get_clinit_call (
1089940  const  irep_idt &classname)
1090941{
1091-   exprt callee= get_or_create_clinit_wrapper ( classname);
1092-   if (callee. is_nil ())
942+   auto  findit = symbol_table. symbols . find ( clinit_wrapper_name ( classname) );
943+   if (findit == symbol_table. symbols . end ())
1093944    return  code_skipt ();
1094-   code_function_callt ret;
1095-   ret.function ()=callee;
1096-   return  ret;
945+   else 
946+   {
947+     code_function_callt ret;
948+     ret.function () = findit->second .symbol_expr ();
949+     if (needed_lazy_methods)
950+       needed_lazy_methods->add_needed_method (findit->second .name );
951+     return  ret;
952+   }
1097953}
1098954
1099955static  unsigned  get_bytecode_type_width (const  typet &ty)
0 commit comments