16
16
#include " java_bytecode_convert_method.h"
17
17
#include " java_bytecode_convert_method_class.h"
18
18
#include " bytecode_info.h"
19
+ #include " java_static_initializers.h"
19
20
#include " java_string_library_preprocess.h"
20
21
#include " java_types.h"
21
22
#include " java_utils.h"
@@ -930,156 +931,6 @@ void java_bytecode_convert_methodt::check_static_field_stub(
930
931
}
931
932
}
932
933
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
-
1083
934
// / Each static access to classname should be prefixed with a check for
1084
935
// / necessary static init; this returns a call implementing that check.
1085
936
// / \param classname: Class name
@@ -1088,12 +939,17 @@ exprt java_bytecode_convert_methodt::get_or_create_clinit_wrapper(
1088
939
codet java_bytecode_convert_methodt::get_clinit_call (
1089
940
const irep_idt &classname)
1090
941
{
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 ())
1093
944
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
+ }
1097
953
}
1098
954
1099
955
static unsigned get_bytecode_type_width (const typet &ty)
0 commit comments