cprover
java_static_initializers.cpp File Reference
+ Include dependency graph for java_static_initializers.cpp:

Go to the source code of this file.

Enumerations

enum  clinit_statest { clinit_statest::NOT_INIT, clinit_statest::IN_PROGRESS, clinit_statest::INIT_COMPLETE }
 The three states in which a <clinit> method for a class can be before, after, and during static class initialization. More...
 

Functions

static typet clinit_states_type ()
 
irep_idt clinit_wrapper_name (const irep_idt &class_name)
 Get the Java static initializer wrapper name for a given class (the wrapper checks if static initialization has already been done before invoking the real static initializer if not). More...
 
bool is_clinit_wrapper_function (const irep_idt &function_id)
 Check if function_id is a clinit wrapper. More...
 
static symbolt add_new_variable_symbol (symbol_table_baset &symbol_table, const irep_idt &name, const typet &type, const exprt &value, const bool is_thread_local, const bool is_static_lifetime)
 Add a new symbol to the symbol table. More...
 
static irep_idt clinit_already_run_variable_name (const irep_idt &class_name)
 Get name of the static-initialization-already-done global variable for a given class. More...
 
static irep_idt clinit_function_name (const irep_idt &class_name)
 Get name of the real static initializer for a given class. More...
 
static irep_idt clinit_state_var_name (const irep_idt &class_name)
 Get name of the static-initialization-state global variable for a given class. More...
 
static irep_idt clinit_thread_local_state_var_name (const irep_idt &class_name)
 Get name of the static-initialization-state local state variable for a given class. More...
 
static irep_idt clinit_local_init_complete_var_name (const irep_idt &class_name)
 Get name of the static-initialization local variable for a given class. More...
 
static code_assignt gen_clinit_assign (const exprt &expr, const clinit_statest state)
 Generates a code_assignt for clinit_statest /param expr: expression to be used as the LHS of generated assignment. More...
 
static equal_exprt gen_clinit_eqexpr (const exprt &expr, const clinit_statest state)
 Generates an equal_exprt for clinit_statest /param expr: expression to be used as the LHS of generated eqaul exprt. More...
 
static void clinit_wrapper_do_recursive_calls (symbol_table_baset &symbol_table, const irep_idt &class_name, code_blockt &init_body, const bool nondet_static, const java_object_factory_parameterst &object_factory_parameters, const select_pointer_typet &pointer_type_selector)
 Generates codet that iterates through the base types of the class specified by class_name, C, and recursively adds calls to their clinit wrapper. More...
 
static bool needs_clinit_wrapper (const irep_idt &class_name, const symbol_tablet &symbol_table)
 Checks whether a static initializer wrapper is needed for a given class, i.e. More...
 
static void create_clinit_wrapper_symbols (const irep_idt &class_name, symbol_tablet &symbol_table, synthetic_methods_mapt &synthetic_methods, const bool thread_safe)
 Creates a static initializer wrapper symbol for the given class, along with a global boolean that tracks if it has been run already. More...
 
code_blockt get_thread_safe_clinit_wrapper_body (const irep_idt &function_id, symbol_table_baset &symbol_table, const bool nondet_static, const java_object_factory_parameterst &object_factory_parameters, const select_pointer_typet &pointer_type_selector)
 Thread safe version of the static initializer. More...
 
code_ifthenelset get_clinit_wrapper_body (const irep_idt &function_id, symbol_table_baset &symbol_table, const bool nondet_static, const java_object_factory_parameterst &object_factory_parameters, const select_pointer_typet &pointer_type_selector)
 Produces the static initializer wrapper body for the given function. More...
 
void create_static_initializer_wrappers (symbol_tablet &symbol_table, synthetic_methods_mapt &synthetic_methods, const bool thread_safe)
 Create static initializer wrappers for all classes that need them. More...
 
template<class itertype >
static itertype advance_to_next_key (itertype in, itertype end)
 Advance map iterator to next distinct key. More...
 

Variables

const std::string clinit_wrapper_suffix = "::clinit_wrapper"
 
const std::string clinit_function_suffix = ".<clinit>:()V"
 

Enumeration Type Documentation

◆ clinit_statest

enum clinit_statest
strong

The three states in which a <clinit> method for a class can be before, after, and during static class initialization.

These states are only used when the thread safe version of the clinit wrapper is generated.

According to the JVM Spec document (section 5.5), the JVM needs to maintain, for every class initializer, a state indicating whether the initializer has been executed, is being executed, or has raised errors. The spec mandates that the JVM consider 4 different states (not initialized, being initialized, ready for use, and initialization error). The clinit_statet is a simplification of those 4 states where:

NOT_INIT corresponds to "not initialized" IN_PROGRESS corresponds to "some thread is currently running the `<clinit>` and no other thread should run it" INIT_COMPLETE corresponds to "the `<clinit>` has been executed and the class is ready to be used, or it has errored"

The last state corresponds to a fusion of the two original states "ready for use" and "initialization error". The basis for fusing these states is that for simplification reasons both implementations of the clinit wrapper do not handle exceptions, hence the error state is not possible.

Enumerator
NOT_INIT 
IN_PROGRESS 
INIT_COMPLETE 

Definition at line 40 of file java_static_initializers.cpp.

Function Documentation

◆ add_new_variable_symbol()

static symbolt add_new_variable_symbol ( symbol_table_baset symbol_table,
const irep_idt name,
const typet type,
const exprt value,
const bool  is_thread_local,
const bool  is_static_lifetime 
)
static

Add a new symbol to the symbol table.

Note: assumes that a symbol with this name does not exist. /param name: name of the symbol to be generated /param type: type of the symbol to be generated /param value: initial value of the symbol to be generated /param is_thread_local: if true this symbol will be set as thread local /param is_static_lifetime: if true this symbol will be set as static /return returns new symbol.

Definition at line 84 of file java_static_initializers.cpp.

◆ advance_to_next_key()

template<class itertype >
static itertype advance_to_next_key ( itertype  in,
itertype  end 
)
static

Advance map iterator to next distinct key.

Parameters
initerator to advance
endend of container iterator

Definition at line 731 of file java_static_initializers.cpp.

◆ clinit_already_run_variable_name()

static irep_idt clinit_already_run_variable_name ( const irep_idt class_name)
static

Get name of the static-initialization-already-done global variable for a given class.

Parameters
class_nameclass symbol name
Returns
static initializer wrapper-already run global name

Definition at line 112 of file java_static_initializers.cpp.

◆ clinit_function_name()

static irep_idt clinit_function_name ( const irep_idt class_name)
static

Get name of the real static initializer for a given class.

Doesn't check if a static initializer actually exists.

Parameters
class_nameclass symbol name
Returns
Static initializer symbol name

Definition at line 121 of file java_static_initializers.cpp.

◆ clinit_local_init_complete_var_name()

static irep_idt clinit_local_init_complete_var_name ( const irep_idt class_name)
static

Get name of the static-initialization local variable for a given class.

Parameters
class_nameclass symbol name
Returns
static initializer wrapper-state local variable

Definition at line 147 of file java_static_initializers.cpp.

◆ clinit_state_var_name()

static irep_idt clinit_state_var_name ( const irep_idt class_name)
static

Get name of the static-initialization-state global variable for a given class.

Parameters
class_nameclass symbol name
Returns
static initializer wrapper-state variable global name

Definition at line 130 of file java_static_initializers.cpp.

◆ clinit_states_type()

static typet clinit_states_type ( )
static

Definition at line 47 of file java_static_initializers.cpp.

◆ clinit_thread_local_state_var_name()

static irep_idt clinit_thread_local_state_var_name ( const irep_idt class_name)
static

Get name of the static-initialization-state local state variable for a given class.

Parameters
class_nameclass symbol name
Returns
static initializer wrapper-state local state variable name

Definition at line 139 of file java_static_initializers.cpp.

◆ clinit_wrapper_do_recursive_calls()

static void clinit_wrapper_do_recursive_calls ( symbol_table_baset symbol_table,
const irep_idt class_name,
code_blockt init_body,
const bool  nondet_static,
const java_object_factory_parameterst object_factory_parameters,
const select_pointer_typet pointer_type_selector 
)
static

Generates codet that iterates through the base types of the class specified by class_name, C, and recursively adds calls to their clinit wrapper.

Finally a call to the clinit of C is made. If nondet-static option was given then all static variables that are not constants (i.e. final) are then re-assigned to a nondet value.

Parameters
symbol_tablesymbol table
class_namename of the class to generate clinit wrapper calls for
[out]init_bodyappended with calls to clinit wrapper
nondet_statictrue if nondet-static option was given
object_factory_parametersobject factory parameters used to populate nondet-initialized globals and objects reachable from them (only needed if nondet-static is true)
pointer_type_selectorused to choose concrete types for abstract- typed globals and fields (only needed if nondet-static is true)

Definition at line 198 of file java_static_initializers.cpp.

◆ clinit_wrapper_name()

irep_idt clinit_wrapper_name ( const irep_idt class_name)

Get the Java static initializer wrapper name for a given class (the wrapper checks if static initialization has already been done before invoking the real static initializer if not).

Doesn't check whether the symbol actually exists

Parameters
class_nameclass symbol name
Returns
static initializer wrapper name

Definition at line 63 of file java_static_initializers.cpp.

◆ create_clinit_wrapper_symbols()

static void create_clinit_wrapper_symbols ( const irep_idt class_name,
symbol_tablet symbol_table,
synthetic_methods_mapt synthetic_methods,
const bool  thread_safe 
)
static

Creates a static initializer wrapper symbol for the given class, along with a global boolean that tracks if it has been run already.

Parameters
class_nameclass symbol name
symbol_tableglobal symbol table; will gain a clinit_wrapper symbol and a corresponding has-run-already global.
synthetic_methodssynthetic method type map. The new clinit wrapper symbol will be recorded, such that we get a callback to produce its body if and when required.
thread_safeif true state variables required to make the clinit_wrapper thread safe will be created.

Definition at line 309 of file java_static_initializers.cpp.

◆ create_static_initializer_wrappers()

void create_static_initializer_wrappers ( symbol_tablet symbol_table,
synthetic_methods_mapt synthetic_methods,
const bool  thread_safe 
)

Create static initializer wrappers for all classes that need them.

Parameters
symbol_tableglobal symbol table
synthetic_methodssynthetic methods map. Will be extended noting that any wrapper belongs to this code, and so get_clinit_wrapper_body should be used to produce the method body when required.
thread_safeif true state variables required to make the clinit_wrapper thread safe will be created.

Definition at line 703 of file java_static_initializers.cpp.

◆ gen_clinit_assign()

static code_assignt gen_clinit_assign ( const exprt expr,
const clinit_statest  state 
)
static

Generates a code_assignt for clinit_statest /param expr: expression to be used as the LHS of generated assignment.

/param state: execution state of the clint_wrapper, used as the RHS of the generated assignment. /return returns a code_assignt, assigning expr to the integer representation of state

Definition at line 161 of file java_static_initializers.cpp.

◆ gen_clinit_eqexpr()

static equal_exprt gen_clinit_eqexpr ( const exprt expr,
const clinit_statest  state 
)
static

Generates an equal_exprt for clinit_statest /param expr: expression to be used as the LHS of generated eqaul exprt.

/param state: execution state of the clint_wrapper, used as the RHS of the generated equal exprt. /return returns a equal_exprt, equating expr to the integer representation of state

Definition at line 177 of file java_static_initializers.cpp.

◆ get_clinit_wrapper_body()

code_ifthenelset get_clinit_wrapper_body ( const irep_idt function_id,
symbol_table_baset symbol_table,
const bool  nondet_static,
const java_object_factory_parameterst object_factory_parameters,
const select_pointer_typet pointer_type_selector 
)

Produces the static initializer wrapper body for the given function.

Note: this version of the clinit wrapper is not thread safe.

Parameters
function_idclinit wrapper function id (the wrapper_method_symbol name created by create_clinit_wrapper_symbols)
symbol_tableglobal symbol table
nondet_statictrue if nondet-static option was given
object_factory_parametersobject factory parameters used to populate nondet-initialized globals and objects reachable from them (only needed if nondet-static is true)
pointer_type_selectorused to choose concrete types for abstract- typed globals and fields (only needed if nondet-static is true)
Returns
the body of the static initializer wrapper

Definition at line 641 of file java_static_initializers.cpp.

◆ get_thread_safe_clinit_wrapper_body()

code_blockt get_thread_safe_clinit_wrapper_body ( const irep_idt function_id,
symbol_table_baset symbol_table,
const bool  nondet_static,
const java_object_factory_parameterst object_factory_parameters,
const select_pointer_typet pointer_type_selector 
)

Thread safe version of the static initializer.

Produces the static initializer wrapper body for the given function. This static initializer implements (a simplification of) the algorithm defined in Section 5.5 of the JVM Specs. This function, or wrapper, checks whether static init has already taken place, calls the actual <clinit> method if not, and possibly recursively initializes super-classes and interfaces. Assume that C is the class to be initialized and that C extends C' and implements interfaces I1 ... In, then the algorithm is as follows:

bool init_complete;
if(java::C::__CPROVER_PREFIX_clinit_thread_local_state == INIT_COMPLETE)
{
return;
}
java::C::__CPROVER_PREFIX_clinit_thread_local_state = INIT_COMPLETE;
// This thread atomically checks and sets the global variable
// 'clinit_state' in order to ensure that only this thread runs the
// static initializer. The assume() statement below will prevent the SAT
// solver from producing a thread schedule where more than 1 thread is
// running the initializer. At the end of this function the only
// thread that runs the static initializer will update the variable.
// Alternatively we could have done a busy wait / spin-lock, but that
// would achieve the same effect and blow up the size of the SAT formula.
assume(java::C::__CPROVER_PREFIX_clinit_state != IN_PROGRESS)
if(java::C::__CPROVER_PREFIX_clinit_state == NOT_INIT)
{
java::C::__CPROVER_PREFIX_clinit_state = IN_PROGRESS
init_complete = false;
}
else if(java::C::__CPROVER_PREFIX_clinit_state == INIT_COMPLETE)
{
init_complete = true;
}
if(init_complete)
return;
java::C'::clinit_wrapper();
java::I1::clinit_wrapper();
java::I2::clinit_wrapper();
// ...
java::In::clinit_wrapper();
java::C::<clinit>(); // or nondet-initialization of all static
// variables of C if nondet-static is true
// Setting this variable to INIT_COMPLETE will let other threads "cross"
// beyond the assume() statement above in this function.
ATOMIC_START
C::__CPROVER_PREFIX_clinit_state = INIT_COMPLETE;
ATOMIC_END
return;

Note: The current implementation does not deal with exceptions.

Parameters
function_idclinit wrapper function id (the wrapper_method_symbol name created by create_clinit_wrapper_symbols)
symbol_tableglobal symbol table
nondet_statictrue if nondet-static option was given
object_factory_parametersobject factory parameters used to populate nondet-initialized globals and objects reachable from them (only needed if nondet-static is true)
pointer_type_selectorused to choose concrete types for abstract- typed globals and fields (only needed if nondet-static is true)
Returns
the body of the static initializer wrapper

Definition at line 451 of file java_static_initializers.cpp.

◆ is_clinit_wrapper_function()

bool is_clinit_wrapper_function ( const irep_idt function_id)

Check if function_id is a clinit wrapper.

Parameters
function_idsome function identifier
Returns
true if the passed identifier is a clinit wrapper

Definition at line 71 of file java_static_initializers.cpp.

◆ needs_clinit_wrapper()

static bool needs_clinit_wrapper ( const irep_idt class_name,
const symbol_tablet symbol_table 
)
static

Checks whether a static initializer wrapper is needed for a given class, i.e.

if the given class or any superclass has a static initializer.

Parameters
class_nameclass symbol name
symbol_tableglobal symbol table
Returns
true if a static initializer wrapper is needed

Definition at line 278 of file java_static_initializers.cpp.

Variable Documentation

◆ clinit_function_suffix

const std::string clinit_function_suffix = ".<clinit>:()V"

Definition at line 55 of file java_static_initializers.cpp.

◆ clinit_wrapper_suffix

const std::string clinit_wrapper_suffix = "::clinit_wrapper"

Definition at line 54 of file java_static_initializers.cpp.